bootstrap
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user