diff --git a/AGENTS.md b/AGENTS.md index 2f9a5ab..8d6ce36 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -67,25 +67,47 @@ just revision "msg" # новая alembic-миграция из изме - `sources/tinvest` — 7 счетов, 2756 операций → `event`, маппер на все 67 `OperationType`; - `ledger/lots.py` + `rebuild.py` — FIFO, 804 лота, 672 закрытия, реализовано +1892 ₽; короткие позиции поддержаны, `qty_remaining` хранится со знаком; -- `sources/moex` — 77 инструментов, 31 154 дневные цены, `price_daily` / `price_last`; +- `sources/moex` — 77 инструментов, 33 380 дневных цен, `price_daily` / `price_last`; + бэкфилл ведётся по инструменту через `price_coverage`, а не по общему курсору источника, + и режет окно по доскам: фонды T-Bank переехали с TQTF на TQBR 22.06.2026, и до переезда + история отвечает только на старой доске; - `analytics/valuation` — дневная серия стоимости и холдинги по scope (`all`, `account:`, `portfolio:`), сверка со снапшотами брокера; `analytics/returns` — XIRR и TWR по периодам (`1m 3m 6m ytd 1y 3y all`) плюс XIRR на инструмент; `pricing/prices.py` — цена на дату с протяжкой вперёд и порогом устаревания 10 дн.; - `analytics/allocation` — разрезы по классу актива, сектору, стране и валюте; каждый покрывает один и тот же итог (бумаги + кэш), поэтому веса любого из них дают единицу; +- `ledger/matching.py` + `flow_link` — связывание перевода ZenMoney с брокерским + deposit/withdrawal (та же валюта, |Δ| ≤ max(1 ₽, 0,5 %), ≤ 3 рабочих дня, жадно 1:1); + связанная ZM-транзакция становится `internal_transfer`. Кандидаты берутся по + `mirror_of_account_id`, `account_link` и правилу `broker_target`; +- `ledger/corporate_actions.py` — сплиты, амортизации и погашения выводятся из леджера в + `corporate_action` до пересборки лотов; +- `analytics/cashflow_broker` — пополнения и выводы по scope и месяцу; читает `event` + заново, а не дневную сумму `external_flow_rub`: та неттит потоки внутри дня и прячет + 512 550 ₽ выводов; +- `sources/tinvest` — сектор берётся из потиповых `Shares`/`Bonds`/`Etfs` (в ответе + `GetInstrumentBy` его нет): 73 из 80 инструментов, аллокация по сектору — 9 бакетов; - API `/analytics/*`, `/events`, `/instruments/{id}` и экраны «Портфель» (позиции + - аллокация) и карточка инструмента. + аллокация), карточка инструмента и «События». -Осталось: `ledger/matching.py` + `account_link`, корпоративные действия, бэкфилл истории -цен MOEX. +Осталось по фазе 2: API `/links/unmatched` и экран несматченных линков, эндпоинт +брокерских потоков, `price_manual` для двух бумаг без котировок. -Известные расхождения derived vs брокерский снапшот по позициям (5 шт, не ошибки разбора): -редомициляция FIVE→X5, MGNT, HEAD, внебиржевая SIBN6P4. Без цен два инструмента — `SIBN6P4` -и `NDM_TBNK-PP-FIXPRCNT-08.25`, им нужен `price_manual`. По кэшу derived выше снапшота на -счетах 46, 48 и 52 (+6313, +56447, +146 ₽) — это неполнота леджера T-Invest, а не оценки: -счёт 51 сходится точно. История цен тонкая (большинство облигаций — только с апреля 2026, -TBRU@ — с 14.09.2026), поэтому TWR пропускает 32 дня и сообщает об этом в -`metric_data_quality`. Сектор не заполнен ни у одного инструмента: `sources/tinvest` читает -`GetInstrumentBy`, в ответе которого этого поля нет — нужны потиповые `Shares`/`Bonds`. +Порядок шагов пересчёта (`analytics/__init__.py:register_steps`): +`fx → classify → matching → corpactions → lots → valuation → returns → allocation → +cashflow_broker → networth → cashflow → spending → runway → quality`. `matching` обязан +идти после `classify`: тот пересчитывает `flow_type` с нуля и затёр бы результат линковки. + +Известные расхождения derived vs брокерский снапшот по позициям (5 шт) объяснены. Четыре из +пяти — не корпоративные действия, а отменённые заявки: `GetOperationsByCursor` отдаёт +операции с `state = OPERATION_STATE_CANCELED`, у них `quantity_done = 0` и нет платежа, +и покупка читалась как бесплатное приобретение (SIBN6P4 +5, HEAD +2, FIVE +2, MGNT −1). +`sync._is_executed` их теперь отсеивает и подчищает при перечитывании; уже импортированные +строки уходят только при повторном чтении того же окна. Пятое — редомициляция FIVE→X5: +зачисления X5 нет ни в одной операции ленты, лот невыводим из данных и требует ручного +`transfer_in`. Без цен два инструмента — `SIBN6P4` и `NDM_TBNK-PP-FIXPRCNT-08.25`, им нужен +`price_manual`. По кэшу derived выше снапшота на счетах 46, 48 и 52 (+6313, +56447, +146 ₽) +— вероятно та же отменённая заявка, отдельно не проверялось: счёт 51 сходится точно. +TWR пропускает 3 дня вместо прежних 32 — остаток держат две бумаги без котировок. План фаз — в `docs/ai/plan.md`.