feat(analytics): доходы, ребалансировка, налоги, бенчмарки и цели — фаза 4
Второй источник выплат: sources/tinvest/sync_events.py (GetDividends, GetBondCoupons, GetBondEvents) и sources/moex/payouts.py (ISS bondization + dividends). Приоритет между ними — pricing/payouts.resolve_payouts, решается на чтении, а не на записи: corporate_action уникален по (instrument_id, kind, source, source_id), обе версии сосуществуют, и правило можно поменять без ресинка истории. Амортизация от MOEX идёт в bond_nominal_schedule, а не в corporate_action — этим типом безраздельно владеет ledger/corporate_actions.py. analytics/income.py — metric_income_monthly (факт) и metric_income_calendar (прошлое и прогноз) с basis paid/announced/history на каждой строке, три источника числа не смешиваются. analytics/rebalance.py — сделки по portfolio_target пропорционально внутри бакета, лоты только вниз, покупки не занимают у ещё не свершившихся продаж. analytics/tax.py — оценка, не замена справки брокера: дивиденды/купоны gross, реализованный результат из lot_disposal с переоценкой каждой ноги на свою дату. analytics/benchmarks.py — TWR индекса на сетке портфеля, kind (price/total_return) не скрывается. analytics/goals.py — прогресс цели и нужный взнос по trailing XIRR. Четыре шага зарегистрированы в register_steps: benchmarks после returns (общая сетка дат), rebalance после allocation (её веса, не пересчитывает), income и tax после lots (нужен lot_disposal).
This commit is contained in:
@@ -103,14 +103,18 @@ def register_steps() -> None:
|
||||
|
||||
from fintracker.analytics import (
|
||||
allocation,
|
||||
benchmarks,
|
||||
cashflow,
|
||||
cashflow_broker,
|
||||
classify,
|
||||
income,
|
||||
networth,
|
||||
quality,
|
||||
rebalance,
|
||||
returns,
|
||||
runway,
|
||||
spending,
|
||||
tax,
|
||||
valuation,
|
||||
)
|
||||
from fintracker.ledger.corporate_actions import rebuild_corporate_actions
|
||||
@@ -132,8 +136,15 @@ def register_steps() -> None:
|
||||
# valuation prices the positions the lots describe; returns reads the series it writes
|
||||
register_step("valuation", valuation.rebuild_valuation)
|
||||
register_step("returns", returns.rebuild_returns)
|
||||
# benchmarks reads metric_returns to sit on the same date grid
|
||||
register_step("benchmarks", benchmarks.rebuild_benchmark_returns)
|
||||
register_step("allocation", allocation.rebuild_allocation)
|
||||
# rebalance reads metric_allocation, never re-derives a weight itself
|
||||
register_step("rebalance", rebalance.rebuild_rebalance)
|
||||
register_step("cashflow_broker", cashflow_broker.rebuild_cash_flow_broker)
|
||||
# income and tax both read event/corporate_action/lot_disposal, all written by now
|
||||
register_step("income", income.rebuild_income)
|
||||
register_step("tax", tax.rebuild_tax_year)
|
||||
register_step("networth", networth.rebuild_net_worth_daily)
|
||||
register_step("cashflow", cashflow.rebuild_cash_flow_monthly)
|
||||
register_step("spending", spending.rebuild_spending_by_category)
|
||||
|
||||
Reference in New Issue
Block a user