Files
nifodea/engine/scenarios.py
T
2026-07-12 19:46:07 +03:00

88 lines
2.7 KiB
Python

from copy import deepcopy
from cashflow_model import FinancialModel, ForecastScenario
from engine.forecast import ForecastService
class ScenarioError(Exception):
pass
DEFAULT_SCENARIOS = {
"baseline": ForecastScenario(
name="baseline",
income_multiplier=1.0,
expense_multiplier=1.0,
growth_multiplier=1.0,
description="Базовый сценарий без изменений",
),
"optimistic": ForecastScenario(
name="optimistic",
income_multiplier=1.15,
expense_multiplier=0.95,
growth_multiplier=1.2,
description="Оптимистичный: доход +15%, расход -5%, рост активов +20%",
),
"pessimistic": ForecastScenario(
name="pessimistic",
income_multiplier=0.85,
expense_multiplier=1.1,
growth_multiplier=0.8,
description="Пессимистичный: доход -15%, расход +10%, рост активов -20%",
),
}
class ScenarioService:
def __init__(self, model: FinancialModel):
self.model = deepcopy(model)
def apply(self, scenario: ForecastScenario, months: int = 12) -> dict:
model = deepcopy(self.model)
for t in model.transactions:
if t.amount > 0:
t.amount *= scenario.income_multiplier
else:
t.amount *= scenario.expense_multiplier
for r in model.recurring:
if r.category == "income":
r.amount *= scenario.income_multiplier
else:
r.amount *= scenario.expense_multiplier
for a in model.assets:
a.growth_rate *= scenario.growth_multiplier
service = ForecastService(model)
result = service.summary(months)
result["scenario"] = scenario.name
result["scenario_description"] = scenario.description
return result
def compare(self, months: int = 12) -> dict:
results = {}
for name, scenario in DEFAULT_SCENARIOS.items():
results[name] = self.apply(scenario, months)
return results
def what_if(
self,
income_mult: float = 1.0,
expense_mult: float = 1.0,
growth_mult: float = 1.0,
months: int = 12,
) -> dict:
scenario = ForecastScenario(
name="what-if",
income_multiplier=income_mult,
expense_multiplier=expense_mult,
growth_multiplier=growth_mult,
description=(
f"What-if: income x{income_mult}, "
f"expense x{expense_mult}, growth x{growth_mult}"
),
)
return self.apply(scenario, months)