Второй источник выплат: 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).
docs/ai — обзор проекта
Назначение
fin-tracker объединяет два мира личных финансов:
- ZenMoney — повседневные счета и транзакции (синкается с банками сам), читаем через
POST /v8/diff/; - брокеры — T-Invest по gRPC API, Сбер и ВТБ через загрузку отчётов, прочее вручную/CSV;
и считает поверх них то, за что раньше платили Snowball Income: позиции по всем брокерам, P&L, XIRR/TWR, аллокацию, календарь дивидендов и купонов с прогнозом, ребалансировку, бенчмарки, налоги — плюс net worth, cash flow и runway по ZenMoney.
Система в общих чертах
sources/* ──sync──▶ raw_* (JSONB, идемпотентно) ──map──▶ core (account, instrument, event, cash_txn…)
│
worker (APScheduler, advisory locks) ▼
ledger (лоты FIFO, дедуп, матчинг ZM↔брокер)
│
analytics (polars, pyxirr) ──▶ metric_* ──▶ api ──▶ Flutter
backend/src/fintracker/sources/— по одному пакету на источник, контракт вbase.py.worker/— планировщик и запуск синков (runner.run_source): lock,sync_run, курсор.api/— FastAPI,/api/v1, ошибки RFC 7807, деньги строками.app/— Flutter, клиент сгенерирован изopenapi/openapi.json.
Документы
- architecture.md — домен, модули, потоки данных, API.
- conventions.md — деньги, валюты, идемпотентность, стиль.
- plan.md — фазы и чек-листы проверки.
- ops.md — деплой на VPS, бэкапы, секреты.
- links.md — внешние API и референсы.