docs: состояние фазы 2 после матчинга, корпдействий и бэкфилла цен
Три утверждения в разделе «Состояние» оказались неверны и стоили агентам времени на перепроверку. Пять расхождений позиций описаны как корпоративные действия — на деле корпоративное там только FIVE→X5, остальные четыре были отменёнными заявками. Причина тонкой истории цен — не «большинство облигаций куплено в апреле» (у них min(d) совпадает с днём первого владения), а четыре фонда и переезд с доски TQTF на TQBR. И сектор больше не пуст у всех инструментов. Добавлен порядок шагов пересчёта с объяснением, почему matching обязан идти после classify: это единственное место, где перестановка тихо отменяет результат.
This commit is contained in:
@@ -67,25 +67,47 @@ just revision "msg" # новая alembic-миграция из изме
|
|||||||
- `sources/tinvest` — 7 счетов, 2756 операций → `event`, маппер на все 67 `OperationType`;
|
- `sources/tinvest` — 7 счетов, 2756 операций → `event`, маппер на все 67 `OperationType`;
|
||||||
- `ledger/lots.py` + `rebuild.py` — FIFO, 804 лота, 672 закрытия, реализовано +1892 ₽;
|
- `ledger/lots.py` + `rebuild.py` — FIFO, 804 лота, 672 закрытия, реализовано +1892 ₽;
|
||||||
короткие позиции поддержаны, `qty_remaining` хранится со знаком;
|
короткие позиции поддержаны, `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:<id>`,
|
- `analytics/valuation` — дневная серия стоимости и холдинги по scope (`all`, `account:<id>`,
|
||||||
`portfolio:<id>`), сверка со снапшотами брокера; `analytics/returns` — XIRR и TWR по
|
`portfolio:<id>`), сверка со снапшотами брокера; `analytics/returns` — XIRR и TWR по
|
||||||
периодам (`1m 3m 6m ytd 1y 3y all`) плюс XIRR на инструмент; `pricing/prices.py` — цена на
|
периодам (`1m 3m 6m ytd 1y 3y all`) плюс XIRR на инструмент; `pricing/prices.py` — цена на
|
||||||
дату с протяжкой вперёд и порогом устаревания 10 дн.;
|
дату с протяжкой вперёд и порогом устаревания 10 дн.;
|
||||||
- `analytics/allocation` — разрезы по классу актива, сектору, стране и валюте; каждый
|
- `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}` и экраны «Портфель» (позиции +
|
- API `/analytics/*`, `/events`, `/instruments/{id}` и экраны «Портфель» (позиции +
|
||||||
аллокация) и карточка инструмента.
|
аллокация), карточка инструмента и «События».
|
||||||
|
|
||||||
Осталось: `ledger/matching.py` + `account_link`, корпоративные действия, бэкфилл истории
|
Осталось по фазе 2: API `/links/unmatched` и экран несматченных линков, эндпоинт
|
||||||
цен MOEX.
|
брокерских потоков, `price_manual` для двух бумаг без котировок.
|
||||||
|
|
||||||
Известные расхождения derived vs брокерский снапшот по позициям (5 шт, не ошибки разбора):
|
Порядок шагов пересчёта (`analytics/__init__.py:register_steps`):
|
||||||
редомициляция FIVE→X5, MGNT, HEAD, внебиржевая SIBN6P4. Без цен два инструмента — `SIBN6P4`
|
`fx → classify → matching → corpactions → lots → valuation → returns → allocation →
|
||||||
и `NDM_TBNK-PP-FIXPRCNT-08.25`, им нужен `price_manual`. По кэшу derived выше снапшота на
|
cashflow_broker → networth → cashflow → spending → runway → quality`. `matching` обязан
|
||||||
счетах 46, 48 и 52 (+6313, +56447, +146 ₽) — это неполнота леджера T-Invest, а не оценки:
|
идти после `classify`: тот пересчитывает `flow_type` с нуля и затёр бы результат линковки.
|
||||||
счёт 51 сходится точно. История цен тонкая (большинство облигаций — только с апреля 2026,
|
|
||||||
TBRU@ — с 14.09.2026), поэтому TWR пропускает 32 дня и сообщает об этом в
|
Известные расхождения derived vs брокерский снапшот по позициям (5 шт) объяснены. Четыре из
|
||||||
`metric_data_quality`. Сектор не заполнен ни у одного инструмента: `sources/tinvest` читает
|
пяти — не корпоративные действия, а отменённые заявки: `GetOperationsByCursor` отдаёт
|
||||||
`GetInstrumentBy`, в ответе которого этого поля нет — нужны потиповые `Shares`/`Bonds`.
|
операции с `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`.
|
План фаз — в `docs/ai/plan.md`.
|
||||||
|
|||||||
Reference in New Issue
Block a user