docs: investment performance vs Moscow Exchange index (WealthLedger/main#54) #67

Merged
codex-bot merged 2 commits from feature/54-investment-performance-vs-index into develop 2026-11-08 16:49:40 +03:00
2 changed files with 91 additions and 0 deletions
Showing only changes of commit e1981a24bf - Show all commits
@@ -0,0 +1,90 @@
# 023. Результат инвестирования относительно индекса Мосбиржи
**Status:** Accepted. **Date:** 2026-11-07. Дополняет [ADR
019](019-hourly-reads-and-online-instrument-reference.md) исключением для
публичной истории закрытий индексов MOEX (по образцу
[ADR 022](022-stored-instrument-classification.md)). Решение оформлено в
[Issue WealthLedger/main#54](https://git.personal.ksv741.ru/WealthLedger/main/issues/54)
и утверждённом change `specs/openspec/changes/2026-11-07-investment-performance-vs-index/`
в репозитории specs.
## Context
Вкладка «Результат» должна показать, как счёт или «Все счета» справились с
деньгами, которые в него внесли, и сравнить это с вложением тех же денег в
индекс. Простая доходность «стоимость / вложено − 1» искажает оценку, когда
пополнения и выводы распределены во времени. Доходность по времени (TWR)
требует истории стоимости на каждую дату потока, а её в системе нет: хранится
только последний Portfolio.
Сравнение с ценовым IMOEX не отвечает на вопрос пользователя: IMOEX не
включает дивиденды и купоны, а эталон должен учитывать их так же, как
портфель. ADR 019 запрещает хранить справочные данные как долговременный
источник; индексы — публичные временные ряды, для которых онлайн-запрос при
каждом открытии вкладки неприемлем по задержке и лимитам внешнего сервиса.
## Decision
- **«Доходность» для «Результата инвестирования» — money-weighted return (XIRR)**
по внешним денежным потокам счёта и текущей оценке Portfolio. Термин
«доходность» снимается с запрета только для этого понятия; прочие понятия
«не доходность» сохраняют прежний текст.
- **Сравнение — теневой портфель в индексе.** Те же внешние потоки
конвертируются в единицы индекса по закрытию дня потока (или ближайшего
предыдущего торгового дня) и оцениваются по закрытию на дату расчёта.
Эталон — полный доходный индекс MCFTRR; XIRR индекса считается на тех же
потоках. Это идея PME по Long–Nickels; в интерфейсе — «те же деньги в
индексе Мосбиржи».
- **IMOEX — только справочный индекс.** Он показывается рядом, но не
участвует в «опережении» и не является базой сравнения.
- **Только RUB.** Счёт с потоками или стоимостью в другой валюте не
рассчитывается (причина `NON_RUB_ACTIVITY`); конвертация валют не
выполняется.
- **Период короче года** показывается как «за N дн.» без annualization;
`basis = annual` только при истории от 365 дней.
- **Хранение закрытий индексов.** Пара (индекс, торговый день по Москве) →
CLOSE хранится локально с upsert. Это исключение из ADR 019: публичная
история индекса, не привязанная к пользователю или подключению, хранится
как долговременные данные. Остальные справочные сведения ADR 019 не
меняются.
### Отклонённые варианты
- **Простой ROI** (`стоимость / вложено − 1`): искажён моментами пополнений
и выводов, поэтому не сравнивается с индексом на тех же деньгах.
- **TWR (time-weighted return):** требует стоимости портфеля на каждую дату
потока; история оценок в системе отсутствует. Сохранение такой истории
вне этого решения.
- **Ценовой IMOEX как ориентир:** не учитывает дивиденды и купоны, поэтому
сравнение с портфелем, где они учтены, смещено.
- **Конвертация валют (FX):** потребовала бы исторических курсов и
отдельного решения о методике; не нужна для личного RUB-учёта.
## Consequences
- Результат зависит от сохранённых операций T-Bank и последнего полного
Portfolio: неполная история или неполная оценка дают `data: null` или
`completeness: incomplete` по правилам change, а не подменяются оценкой.
- Первая загрузка индекса догружает историю от `from − 10 дней`; при
недостатке закрытий появляется `INDEX_HISTORY_UNAVAILABLE`. Фоновая
синхронизация индексов не вводится.
- Исключение из ADR 019 ограничено закрытиями индексов MOEX.
### Оговорки и условия источника
- **Налоги.** MCFTRR при расчёте дивидендов и купонов использует ставки для
организаций, а не НДФЛ физического лица. Индекс — ориентир альтернативы,
а не точная модель налогов пользователя. Оговорка фиксируется в методике
(«Как считали»).
- **Данные MOEX ISS.** ISS бесплатно отдаёт данные «для ознакомления».
Приложение личное и локальное, данные не распространяются; источник
указывается в «Как считали».
- **Правило парности переводов** между своими счетами в «Все счета» пока
подтверждается на реальных данных; это открытый вопрос change, а не часть
решения.
## Links
- Issue: [WealthLedger/main#54](https://git.personal.ksv741.ru/WealthLedger/main/issues/54)
- Change: `specs/openspec/changes/2026-11-07-investment-performance-vs-index/`
(proposal, system-analysis «Расчёт» и «Индексы MOEX», design, Decisions backend 3, 5)
+1
View File
@@ -27,3 +27,4 @@
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
- [021 — Тихое чтение и редкие подтверждения](021-quiet-reading-and-rare-confirmations.md)
- [022 — Хранимая классификация инструментов T-Bank](022-stored-instrument-classification.md)
- [023 — Результат инвестирования относительно индекса Мосбиржи](023-investment-performance-vs-index.md)