Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fbd4273ba | ||
|
|
f504a0f566 | ||
|
|
364f6bd8d0 | ||
|
|
6d7d4c7b28 | ||
|
|
40ea47a7c2 | ||
|
|
37430da4c9 | ||
|
|
abe5b16241 | ||
|
|
dcb528fa9f | ||
|
|
8c6c2f84ce | ||
|
|
f9098d8409 | ||
|
|
4216eb815f |
@@ -1,5 +1,29 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [0.1.8](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.7...v0.1.8) (2026-11-06)
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
|
||||||
|
* **deps:** set Renovate release age, PR limit and update groups (WealthLedger/main[#6](https://git.personal.ksv741.ru/WealthLedger/docs/issues/6)) ([#64](https://git.personal.ksv741.ru/WealthLedger/docs/issues/64)) ([6d7d4c7](https://git.personal.ksv741.ru/WealthLedger/docs/commit/6d7d4c7b286535b7338d7e398d2daf7d8137a501))
|
||||||
|
|
||||||
|
## [0.1.7](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.6...v0.1.7) (2026-11-01)
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
* describe all-account row grouping (WealthLedger/main[#47](https://git.personal.ksv741.ru/WealthLedger/docs/issues/47)) ([#59](https://git.personal.ksv741.ru/WealthLedger/docs/issues/59)) ([dcb528f](https://git.personal.ksv741.ru/WealthLedger/docs/commit/dcb528fa9f76f0d7aa98bd827cc7ee39024dbb13))
|
||||||
|
* describe concentration tab and stored instrument classification (WealthLedger/main[#48](https://git.personal.ksv741.ru/WealthLedger/docs/issues/48)) ([#60](https://git.personal.ksv741.ru/WealthLedger/docs/issues/60)) ([37430da](https://git.personal.ksv741.ru/WealthLedger/docs/commit/37430da4c99cb571ef5bc0676cad7b3a47bcb6f0))
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
|
||||||
|
* **deps:** resolve markdownlint audit advisory (WealthLedger/main[#49](https://git.personal.ksv741.ru/WealthLedger/docs/issues/49)) ([#61](https://git.personal.ksv741.ru/WealthLedger/docs/issues/61)) ([abe5b16](https://git.personal.ksv741.ru/WealthLedger/docs/commit/abe5b16241d3002baa5d39c2a12949f23a75b968))
|
||||||
|
|
||||||
|
## [0.1.6](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.5...v0.1.6) (2026-10-24)
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
|
||||||
|
* bump Node to 24.22.1 (WealthLedger/backend[#122](https://git.personal.ksv741.ru/WealthLedger/docs/issues/122)) ([4216eb8](https://git.personal.ksv741.ru/WealthLedger/docs/commit/4216eb815f59b7a284e679ccb1b725438da07882))
|
||||||
|
* **deps:** update non-major dependencies (WealthLedger/docs[#56](https://git.personal.ksv741.ru/WealthLedger/docs/issues/56)) ([f9098d8](https://git.personal.ksv741.ru/WealthLedger/docs/commit/f9098d84098467e41143bad5044085d6329099d9))
|
||||||
|
|
||||||
## [0.1.5](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.4...v0.1.5) (2026-10-18)
|
## [0.1.5](https://git.personal.ksv741.ru/WealthLedger/docs/compare/v0.1.4...v0.1.5) (2026-10-18)
|
||||||
|
|
||||||
### Documentation
|
### Documentation
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ WealthLedger помогает частному инвестору понимат
|
|||||||
| [Аутентификация](domains/authentication/overview.md) | Регистрация, вход, восстановление и завершение сессии |
|
| [Аутентификация](domains/authentication/overview.md) | Регистрация, вход, восстановление и завершение сессии |
|
||||||
| [Счета](domains/accounts/overview.md) | Доступные счета, сводки и состояния каждого счёта |
|
| [Счета](domains/accounts/overview.md) | Доступные счета, сводки и состояния каждого счёта |
|
||||||
| [Банковские карты](domains/cards/overview.md) | Ручные остатки, операции, категории, возвраты, месячные сводки и исправления |
|
| [Банковские карты](domains/cards/overview.md) | Ручные остатки, операции, категории, возвраты, месячные сводки и исправления |
|
||||||
| [Портфель](domains/portfolio/overview.md) | Позиции, остатки, суммы, структура и свежесть |
|
| [Портфель](domains/portfolio/overview.md) | Позиции, остатки, суммы, структура, [концентрация](domains/portfolio/concentration.md) и свежесть |
|
||||||
| [Все счета](domains/portfolio/all-accounts.md) | Общий портфель, происхождение строк и сводные разделы |
|
| [Все счета](domains/portfolio/all-accounts.md) | Общий портфель, происхождение строк и сводные разделы |
|
||||||
| [Операции](domains/operations/overview.md) | Исполненные операции, фильтры и пагинация |
|
| [Операции](domains/operations/overview.md) | Исполненные операции, фильтры и пагинация |
|
||||||
| [Доход](domains/income/overview.md) | Полученные купоны и дивиденды, периоды и состав расчёта |
|
| [Доход](domains/income/overview.md) | Полученные купоны и дивиденды, периоды и состав расчёта |
|
||||||
|
|||||||
@@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
**Status:** Accepted. Заменяет request-driven, manual-refresh и
|
**Status:** Accepted. Заменяет request-driven, manual-refresh и
|
||||||
no-periodic-walk части [ADR 017](017-local-tbank-reads-and-background-sync.md)
|
no-periodic-walk части [ADR 017](017-local-tbank-reads-and-background-sync.md)
|
||||||
и дополняет [ADR 018](018-minimal-runtime-coordination.md).
|
и дополняет [ADR 018](018-minimal-runtime-coordination.md). Правило «справочные
|
||||||
|
сведения запрашиваются онлайн» дополнено исключением для сектора и бренда
|
||||||
|
актива позиции — [ADR
|
||||||
|
022](022-stored-instrument-classification.md).
|
||||||
|
|
||||||
## Decision
|
## Decision
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
# 022. Хранимая классификация инструментов T-Bank
|
||||||
|
|
||||||
|
**Status:** Accepted. Дополняет [ADR
|
||||||
|
019](019-hourly-reads-and-online-instrument-reference.md) исключением из
|
||||||
|
правила «справочные сведения запрашиваются онлайн». Решение утверждено
|
||||||
|
владельцем в [Issue
|
||||||
|
WealthLedger/main#48](https://git.personal.ksv741.ru/WealthLedger/main/issues/48).
|
||||||
|
|
||||||
|
## Context
|
||||||
|
|
||||||
|
ADR 019 установил, что справочные сведения инструментов (detail, lookup,
|
||||||
|
каталоги) запрашиваются онлайн и не сохраняются как долговременный справочник:
|
||||||
|
«старые справочные строки не являются источником актуальности». Вкладка
|
||||||
|
«Концентрация» требует для каждой позиции её сектора и эмитента — бренда
|
||||||
|
актива по данным T-Bank. Сектор есть только в описаниях отдельных типов
|
||||||
|
инструментов (`share`, `bond`, `etf`), а эмитент — в описании актива по
|
||||||
|
`asset_uid` инструмента; из названия, тикера, ISIN или `logoName` его вывести
|
||||||
|
нельзя. Запрашивать эти поля онлайн при каждом открытии экрана нельзя:
|
||||||
|
ответ Portfolio не ждёт T-Bank, а разрезы должны считаться по уже сохранённому
|
||||||
|
снимку.
|
||||||
|
|
||||||
|
Существующий metadata-кэш (`TbankInstrument`) не подходит: общий ответ
|
||||||
|
`GetInstrumentBy` не содержит `sector`, а его `brand` — данные логотипа,
|
||||||
|
а не `{uid, name}` бренда актива.
|
||||||
|
|
||||||
|
## Decision
|
||||||
|
|
||||||
|
- Сектор и бренд актива позиции хранятся как последнее известное значение в
|
||||||
|
глобальной таблице `TbankInstrumentClassification` (провайдер, ключ
|
||||||
|
инструмента, сектор и время его получения, uid актива и uid/название бренда
|
||||||
|
с временем получения). Данные публичные, без привязки к пользователю или
|
||||||
|
подключению; ограждение по connection revision к ним не применяется, публикация
|
||||||
|
Snapshot ограждается как прежде.
|
||||||
|
- Каждое поле обновляется в часовом обходе при его первой попытке, начавшейся
|
||||||
|
не ранее чем через 24 часа после последнего успешного получения этого поля;
|
||||||
|
пока значение не получено, попытка повторяется в каждом обходе. Сектор и
|
||||||
|
бренд обновляются независимо.
|
||||||
|
- Неуспешное получение не мешает публикации Portfolio Snapshot и не влияет на
|
||||||
|
его свежесть; сохранённое значение остаётся доступным. Отказ token
|
||||||
|
обрабатывается как отказ token при обходе Portfolio. Ответ «инструмент не
|
||||||
|
найден» сохраняет прежнее значение и перезапускает отсчёт 24 часов.
|
||||||
|
- Классификация не входит в `meta.dependencies` Portfolio и не меняет
|
||||||
|
`isStale` и `lastSuccessfulAt`.
|
||||||
|
|
||||||
|
## Consequences
|
||||||
|
|
||||||
|
- Это первый долговременный справочник T-Bank в системе: ADR 019 теряет
|
||||||
|
характер «только онлайн» для этой области и дополняется, а не заменяется.
|
||||||
|
- Разрезы концентрации считаются по снимку без обращений к T-Bank; число
|
||||||
|
вызовов растёт ограниченно — не более одной попытки на поле в сутки на
|
||||||
|
позицию, при первом обходе после выката возможен разовый всплеск, сглаженный
|
||||||
|
общим лимитером и очередью.
|
||||||
|
- Значение может быть устаревшим до 24 часов; это приемлемо для группировки
|
||||||
|
позиций, но классификация не является источником актуальных данных брокера.
|
||||||
|
- Второй потребитель хранимой классификации — условие пересмотра решения
|
||||||
|
(выделение независимого процесса обновления, отдельные сроки).
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
# 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.** Пополнения и выводы в другой валюте не учитываются,
|
||||||
|
нерублёвые позиции отфильтрованы на входе; конвертация валют не
|
||||||
|
выполняется (WealthLedger/main#55).
|
||||||
|
- **Период** начинается с первого внешнего потока, не с открытия счёта.
|
||||||
|
Короче года — «за 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 бесплатно отдаёт данные «для ознакомления».
|
||||||
|
Приложение личное и локальное, данные не распространяются; источник
|
||||||
|
указывается в «Как считали».
|
||||||
|
- **Переводы между счетами.** Совпадение суммы и времени операций ещё не
|
||||||
|
доказывает внутренний перевод. Пока нет подтверждённой связи, такие счета
|
||||||
|
исключаются из рассчитанной части «Все счета» с явной причиной неполноты.
|
||||||
|
- **Несколько решений XIRR.** Процент не показывается: нельзя выбрать
|
||||||
|
произвольную ставку. Прибыль в рублях остаётся видна.
|
||||||
|
|
||||||
|
## 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)
|
||||||
@@ -26,3 +26,5 @@
|
|||||||
- [019 — Часовой обход и онлайн-справочник инструментов](019-hourly-reads-and-online-instrument-reference.md)
|
- [019 — Часовой обход и онлайн-справочник инструментов](019-hourly-reads-and-online-instrument-reference.md)
|
||||||
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
|
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
|
||||||
- [021 — Тихое чтение и редкие подтверждения](021-quiet-reading-and-rare-confirmations.md)
|
- [021 — Тихое чтение и редкие подтверждения](021-quiet-reading-and-rare-confirmations.md)
|
||||||
|
- [022 — Хранимая классификация инструментов T-Bank](022-stored-instrument-classification.md)
|
||||||
|
- [023 — Результат инвестирования относительно индекса Мосбиржи](023-investment-performance-vs-index.md)
|
||||||
|
|||||||
@@ -141,13 +141,18 @@ membership текущей revision перед каждым финансовым
|
|||||||
|
|
||||||
SQLite хранит полный последний portfolio, операции и их подтверждённые
|
SQLite хранит полный последний portfolio, операции и их подтверждённые
|
||||||
диапазоны, private прогнозы, сохранённые точки истории оценки, общие
|
диапазоны, private прогнозы, сохранённые точки истории оценки, общие
|
||||||
instrument/market sources и intent/staging.
|
instrument/market sources, классификацию инструментов (сектор и бренд актива
|
||||||
|
как последнее известное значение с временем каждого получения,
|
||||||
|
`TbankInstrumentClassification`) и intent/staging.
|
||||||
Нормализованные финансовые значения сохраняются decimal-строками. Полнота
|
Нормализованные финансовые значения сохраняются decimal-строками. Полнота
|
||||||
отделена от свежести и пагинации. Ответ не ждёт внешних RPC; обновлением
|
отделена от свежести и пагинации. Ответ не ждёт внешних RPC; обновлением
|
||||||
личных данных владеет часовой обход в том же backend process через
|
личных данных владеет часовой обход в том же backend process через
|
||||||
существующий лимитер, недостающие общие источники он же ставит в фоновую
|
существующий лимитер, недостающие общие источники он же ставит в фоновую
|
||||||
очередь. На startup обход начинает следующую попытку по обычному часовому
|
очередь. На startup обход начинает следующую попытку по обычному часовому
|
||||||
сроку; после нового подключения первая попытка начинается сразу.
|
сроку; после нового подключения первая попытка начинается сразу.
|
||||||
|
Классификация — публичные данные без привязки к пользователю и подключению;
|
||||||
|
её поля обновляются в том же обходе не чаще раза в сутки
|
||||||
|
([ADR 022](../adr/022-stored-instrument-classification.md)).
|
||||||
Подробности — [модель свежести](cross-cutting/data-freshness.md).
|
Подробности — [модель свежести](cross-cutting/data-freshness.md).
|
||||||
|
|
||||||
PUT подключения сначала проверяет token у T-Bank, затем одной транзакцией
|
PUT подключения сначала проверяет token у T-Bank, затем одной транзакцией
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ WealthLedger нормализует их для просмотра и сопос
|
|||||||
информацией об инструментах. [Интеграция T-Bank](../integrations/tbank.md)
|
информацией об инструментах. [Интеграция T-Bank](../integrations/tbank.md)
|
||||||
объясняет полномочия подключения и ограничения внешней зависимости.
|
объясняет полномочия подключения и ограничения внешней зависимости.
|
||||||
|
|
||||||
[MOEX ISS](../integrations/moex.md) поставляет публичные параметры и календарь выпусков облигаций.
|
[MOEX ISS](../integrations/moex.md) поставляет публичные параметры и календарь выпусков облигаций,
|
||||||
|
а также дневные закрытия индексов Мосбиржи для сравнения результата.
|
||||||
[Реестр НКР](../integrations/nkr.md) используется для поиска кредитного рейтинга конкретного выпуска;
|
[Реестр НКР](../integrations/nkr.md) используется для поиска кредитного рейтинга конкретного выпуска;
|
||||||
рейтинг эмитента не подставляется вместо него. Отсутствие подходящей записи
|
рейтинг эмитента не подставляется вместо него. Отсутствие подходящей записи
|
||||||
и недоступность источника имеют разный смысл. Правила интерпретации этих
|
и недоступность источника имеют разный смысл. Правила интерпретации этих
|
||||||
|
|||||||
@@ -8,8 +8,12 @@ T-Bank. Нормальным владельцем обновления служ
|
|||||||
простоя выполняется не более одна актуальная попытка, а перекрывающийся срок
|
простоя выполняется не более одна актуальная попытка, а перекрывающийся срок
|
||||||
пропускается, не ставится в очередь. Общие справочные данные инструментов
|
пропускается, не ставится в очередь. Общие справочные данные инструментов
|
||||||
запрашиваются онлайн, когда это требуется карточке; финансовый HTTP-ответ не
|
запрашиваются онлайн, когда это требуется карточке; финансовый HTTP-ответ не
|
||||||
ждёт T-Bank. Модель принята в
|
ждёт T-Bank. Единственное исключение — сектор и бренд актива позиции, которые
|
||||||
[ADR 019](../../adr/019-hourly-reads-and-online-instrument-reference.md).
|
хранятся как последнее известное значение с обновлением не чаще раза в сутки;
|
||||||
|
свежесть и полнота Portfolio от них не зависят. Модель принята в
|
||||||
|
[ADR 019](../../adr/019-hourly-reads-and-online-instrument-reference.md),
|
||||||
|
исключение — в
|
||||||
|
[ADR 022](../../adr/022-stored-instrument-classification.md).
|
||||||
|
|
||||||
## Клиентский и серверный снимки
|
## Клиентский и серверный снимки
|
||||||
|
|
||||||
@@ -18,7 +22,10 @@ T-Bank. Нормальным владельцем обновления служ
|
|||||||
HTTP-перечитывания в той же границе доступа. Это не серверный fallback и не
|
HTTP-перечитывания в той же границе доступа. Это не серверный fallback и не
|
||||||
состояние часового обхода. SQLite независимо от браузера хранит membership,
|
состояние часового обхода. SQLite независимо от браузера хранит membership,
|
||||||
последний полный portfolio, исполненные операции, прогнозы, общие сведения об
|
последний полный portfolio, исполненные операции, прогнозы, общие сведения об
|
||||||
инструментах, котировки, свечи и календари.
|
инструментах и классификацию инструментов (сектор и бренд актива как
|
||||||
|
последнее известное значение, [ADR
|
||||||
|
022](../../adr/022-stored-instrument-classification.md)), котировки, свечи и
|
||||||
|
календари.
|
||||||
|
|
||||||
[Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются.
|
[Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются.
|
||||||
Успешно проверенный пустой результат полон и доступен; последняя страница
|
Успешно проверенный пустой результат полон и доступен; последняя страница
|
||||||
|
|||||||
@@ -64,14 +64,23 @@ Envelope несовместим с прежними bare-array ответами:
|
|||||||
## Income analytics
|
## Income analytics
|
||||||
|
|
||||||
`GET /api/v1/brokerage-accounts/{accountId}/income-analytics` и общий маршрут
|
`GET /api/v1/brokerage-accounts/{accountId}/income-analytics` и общий маршрут
|
||||||
`all` возвращают результат только выбранного периода: итоги по исходным
|
`all` возвращают результат только выбранного периода: итоги в RUB, точные записи выплат, разбиение по инструментам и временные
|
||||||
валютам, точные записи выплат, разбиение по инструментам и временные
|
|
||||||
интервалы. Данных сравнения с предыдущим периодом или годом ранее в ответе
|
интервалы. Данных сравнения с предыдущим периодом или годом ранее в ответе
|
||||||
нет — ни в теле, ни среди зависимостей `meta.dependencies`, роль которых
|
нет — ни в теле, ни среди зависимостей `meta.dependencies`, роль которых
|
||||||
ограничена значением `selected`. Публичную машинную схему задаёт
|
ограничена значением `selected`. Публичную машинную схему задаёт
|
||||||
backend-generated OpenAPI; frontend получает её обновлённый snapshot отдельно.
|
backend-generated OpenAPI; frontend получает её обновлённый snapshot отдельно.
|
||||||
Точную семантику поведения описывает [доход](../domains/income/overview.md).
|
Точную семантику поведения описывает [доход](../domains/income/overview.md).
|
||||||
|
|
||||||
|
## Investment performance
|
||||||
|
|
||||||
|
`GET /api/v1/brokerage-accounts/{accountId}/performance` и общий маршрут
|
||||||
|
`all` возвращают [результат инвестирования](../domains/portfolio/investment-performance.md)
|
||||||
|
за всё время. Недоступность расчёта — не HTTP-ошибка: ответ `200` с
|
||||||
|
`data: null` и причинами в `meta.unavailable`. Неполная сводка «Все счета»
|
||||||
|
имеет `completeness: incomplete` и `excludedAccounts`. Доли передаются
|
||||||
|
десятичной строкой (`0.151` = 15,1 %), `return.basis` различает годовую
|
||||||
|
ставку и ставку за период. Схему задаёт backend-generated OpenAPI.
|
||||||
|
|
||||||
## Validation и identity
|
## Validation и identity
|
||||||
|
|
||||||
Backend преобразует и проверяет входные данные на общей HTTP-границе.
|
Backend преобразует и проверяет входные данные на общей HTTP-границе.
|
||||||
|
|||||||
+1
-1
@@ -66,7 +66,7 @@ compatibility re-exports `shared/theme` и `shared/ui` удалены.
|
|||||||
Фоновое обновление сохраняет доступные данные с локальным индикатором.
|
Фоновое обновление сохраняет доступные данные с локальным индикатором.
|
||||||
Подробные правила — в [состояниях интерфейса](../architecture/cross-cutting/ui-resilience.md).
|
Подробные правила — в [состояниях интерфейса](../architecture/cross-cutting/ui-resilience.md).
|
||||||
|
|
||||||
Финансовые значения сохраняют валюту, знак и различие между нулём и
|
Финансовые значения сохраняют валюту (RUB), знак и различие между нулём и
|
||||||
неизвестной суммой. Предметные представления раскрыты в
|
неизвестной суммой. Предметные представления раскрыты в
|
||||||
[портфеле](../domains/portfolio/overview.md), [операциях](../domains/operations/overview.md)
|
[портфеле](../domains/portfolio/overview.md), [операциях](../domains/operations/overview.md)
|
||||||
и [банковских картах](../domains/cards/overview.md).
|
и [банковских картах](../domains/cards/overview.md).
|
||||||
|
|||||||
@@ -33,12 +33,12 @@
|
|||||||
|
|
||||||
| Состояние `portfolioSummary` | Что оно означает |
|
| Состояние `portfolioSummary` | Что оно означает |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Доступные валютные итоги | Текущие стоимости позиций и деньги сложены точно в исходной валюте |
|
| Доступный итог | Текущие стоимости позиций и деньги сложены точно в RUB |
|
||||||
| Доступная сводка с пустыми итогами | Портфель получен, но валютных итогов нет; это не ошибка загрузки |
|
| Доступная сводка без итога | Портфель получен, но итоговой суммы нет; это не ошибка загрузки |
|
||||||
| `null` | Финансовая сводка этого счёта временно недоступна; метаданные и переход на счёт сохраняются |
|
| `null` | Финансовая сводка этого счёта временно недоступна; метаданные и переход на счёт сохраняются |
|
||||||
|
|
||||||
Валюты не конвертируются и не объединяются в общую сумму. Деньги уже входят
|
Позиции и деньги в валютах, отличных от RUB, не участвуют в итоге. Деньги уже входят
|
||||||
в валютный итог; они не образуют второй самостоятельный итог. Правила
|
в итог; они не образуют второй самостоятельный итог. Правила
|
||||||
неизвестных стоимостей совпадают со [справочником портфеля](../portfolio/data-reference.md).
|
неизвестных стоимостей совпадают со [справочником портфеля](../portfolio/data-reference.md).
|
||||||
|
|
||||||
Сводка также сообщает число ненулевых обычных позиций акций и облигаций
|
Сводка также сообщает число ненулевых обычных позиций акций и облигаций
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
- Неизвестная ошибка: то же состояние недоступности без действия повтора.
|
- Неизвестная ошибка: то же состояние недоступности без действия повтора.
|
||||||
- Успешный пустой ответ: штатное состояние отсутствия инвестиционных счетов.
|
- Успешный пустой ответ: штатное состояние отсутствия инвестиционных счетов.
|
||||||
|
|
||||||
Карточка ведёт на `/accounts/:accountId` по всей области и доступна с клавиатуры. Карточки расположены в одну колонку при любой ширине. Карточка показывает название, локализованный тип, крупный валютный итог и вторую валюту при наличии, число остальных валют, дату открытия без времени и видимое действие открытия. Отдельные цветные блоки «Акции» и «Облигации» показывают количество наименований бумаг. Недоступная или пустая сводка отображается локально; отсутствие сумм не скрывает известные количества бумаг, а недоступная сводка не подменяет их нулями. Наведение и видимый клавиатурный фокус подчёркивают переход; настройка уменьшения движения отключает анимацию.
|
Карточка ведёт на `/accounts/:accountId` по всей области и доступна с клавиатуры. Карточки расположены в одну колонку при любой ширине. Карточка показывает название, локализованный тип, крупный итог в RUB, дату открытия без времени и видимое действие открытия. Отдельные цветные блоки «Акции» и «Облигации» показывают количество наименований бумаг. Недоступная или пустая сводка отображается локально; отсутствие сумм не скрывает известные количества бумаг, а недоступная сводка не подменяет их нулями. Наведение и видимый клавиатурный фокус подчёркивают переход; настройка уменьшения движения отключает анимацию.
|
||||||
|
|
||||||
## Свежесть и границы
|
## Свежесть и границы
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
купонами и дивидендами за выбранный период». Пользователь открывает
|
купонами и дивидендами за выбранный период». Пользователь открывает
|
||||||
`/accounts/:accountId/income` из обзора счёта или
|
`/accounts/:accountId/income` из обзора счёта или
|
||||||
[общий доход](../portfolio/all-accounts.md) по доступным счетам.
|
[общий доход](../portfolio/all-accounts.md) по доступным счетам.
|
||||||
Экран показывает итоги по валютам и отдельную карточку каждой
|
Экран показывает итоги в RUB и отдельную карточку каждой
|
||||||
включённой выплаты. Источником служат [исполненные операции](../operations/overview.md),
|
включённой выплаты. Источником служат [исполненные операции](../operations/overview.md),
|
||||||
а не изменение цены портфеля и не календарь будущих выплат.
|
а не изменение цены портфеля и не календарь будущих выплат.
|
||||||
|
|
||||||
@@ -51,10 +51,10 @@
|
|||||||
## Какие выплаты входят в результат
|
## Какие выплаты входят в результат
|
||||||
|
|
||||||
- Backend проверяет доступ локально и читает сохранённые операции. Фоновая загрузка должна завершить все страницы; ошибка страницы или повреждённая цепочка курсоров не подтверждают полноту.
|
- Backend проверяет доступ локально и читает сохранённые операции. Фоновая загрузка должна завершить все страницы; ошибка страницы или повреждённая цепочка курсоров не подтверждают полноту.
|
||||||
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
|
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в RUB; отрицательные корректировки сохраняют знак. Выплаты в других валютах не участвуют. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
|
||||||
- Итоги, временные интервалы и разбиение по инструментам не смешивают валюты и не создают общий конвертированный итог. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
|
- Итоги, временные интервалы и разбиение по инструментам считаются только в RUB. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
|
||||||
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
|
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
|
||||||
- Раздел «Выплаты» показывает единый список карточек выплат в исходном порядке `entries`: одна карточка на каждую выплату. Внешних групп по инструментам или валютам, итогов и количества выплат инструмента нет. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой карточке; валюты разделены в итогах. Дополнительный запрос за составом не нужен.
|
- Раздел «Выплаты» показывает карточки выплат в исходном порядке `entries`. В отдельном счёте каждая выплата — отдельная карточка. В режиме «Все счета» выплаты одного инструмента, дня и точного типа образуют группу, если их две и более ([правила группировки](../operations/overview.md#группировка-в-режиме-все-счета)). Группа стоит на месте первой выплаты; каждая строка счёта показывает название счёта и свою сумму со знаком. Визуальный итог группы — точная сумма в RUB по показанным выплатам; он скрыт, если полнота периода не `complete`, или у выплаты нет суммы, или сумма равна нулю. Это клиентский расчёт и не заменяет серверные итоги аналитики дохода, которые по-прежнему приходят из ответа API и не пересчитываются. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой выплате. Дополнительный запрос за составом не нужен.
|
||||||
|
|
||||||
## Полнота и принадлежность выплат
|
## Полнота и принадлежность выплат
|
||||||
|
|
||||||
@@ -71,16 +71,16 @@
|
|||||||
Каждая запись `income-analytics.entries` содержит обязательный `instrumentKey`,
|
Каждая запись `income-analytics.entries` содержит обязательный `instrumentKey`,
|
||||||
равный `key` соответствующей строки `instruments`. Backend вычисляет этот ключ
|
равный `key` соответствующей строки `instruments`. Backend вычисляет этот ключ
|
||||||
один раз при подготовке записей дохода и использует его же для группировки.
|
один раз при подготовке записей дохода и использует его же для группировки.
|
||||||
Приоритет UID, FIGI, ticker/type и ID операции с разделением по валюте остаётся
|
Приоритет UID, FIGI, ticker/type и ID операции остаётся
|
||||||
серверным правилом; клиент воспринимает ключ как непрозрачную строку.
|
серверным правилом; клиент воспринимает ключ как непрозрачную строку.
|
||||||
Это поле принадлежит ответу аналитики; общий журнал операций его не требует.
|
Это поле принадлежит ответу аналитики; общий журнал операций его не требует.
|
||||||
|
|
||||||
Backend обеспечивает принадлежность выплат, валюту и receipt count при
|
Backend обеспечивает принадлежность выплат и receipt count при
|
||||||
построении entries и instrument groups из одного набора данных. Frontend
|
построении entries и instrument groups из одного набора данных. Frontend
|
||||||
доверяет типизированному contract, не восстанавливает формулу идентификации
|
доверяет типизированному contract, не восстанавливает формулу идентификации
|
||||||
и не выполняет второй consistency validator. Полностью пустой ответ допустим.
|
и не выполняет второй consistency validator. Полностью пустой ответ допустим.
|
||||||
Состав и исходный серверный порядок записей и знак сумм
|
Состав и исходный серверный порядок записей и знак сумм
|
||||||
сохраняются, frontend не пересчитывает денежные итоги. Стабильный ID в пределах подключения и счёта определяет одну операцию:
|
сохраняются; серверные денежные итоги frontend не пересчитывает (визуальный итог группы в режиме «Все счета» отдельный, см. выше). Стабильный ID в пределах подключения и счёта определяет одну операцию:
|
||||||
повторная сверка обновляет её без двойного учёта. Одинаковые ID разных счетов
|
повторная сверка обновляет её без двойного учёта. Одинаковые ID разных счетов
|
||||||
остаются разными выплатами. Изменение источника логотипа позволяет заново
|
остаются разными выплатами. Изменение источника логотипа позволяет заново
|
||||||
показать изображение после буквенной заглушки.
|
показать изображение после буквенной заглушки.
|
||||||
@@ -94,7 +94,7 @@ Backend обеспечивает принадлежность выплат, ва
|
|||||||
выбранного счёта и сохраняет прежнее поведение. Будущие выплаты
|
выбранного счёта и сохраняет прежнее поведение. Будущие выплаты
|
||||||
не включаются в итоги полученного дохода.
|
не включаются в итоги полученного дохода.
|
||||||
|
|
||||||
Аналитика читает сохранённую историю операций и не рассчитывает налоги, инвестиционную эффективность, доходность, валютную конвертацию или общий мультивалютный итог.
|
Аналитика читает сохранённую историю операций и не рассчитывает налоги, доходность (её показывает [результат инвестирования](../portfolio/investment-performance.md)), или итоги по нескольким валютам.
|
||||||
|
|
||||||
Основное проверяемое поведение — в [спецификации дохода](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-income-analytics/spec.md),
|
Основное проверяемое поведение — в [спецификации дохода](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-income-analytics/spec.md),
|
||||||
точная форма ответа — в [HTTP API](../../architecture/http-api.md).
|
точная форма ответа — в [HTTP API](../../architecture/http-api.md).
|
||||||
|
|||||||
@@ -56,8 +56,8 @@
|
|||||||
«сумма неизвестна» и не превращается в ноль или полученные деньги.
|
«сумма неизвестна» и не превращается в ноль или полученные деньги.
|
||||||
Дата дивиденда обозначена как дата реестра. Offer и погашение сохраняют своё
|
Дата дивиденда обозначена как дата реестра. Offer и погашение сохраняют своё
|
||||||
значение без суммы выплаты. У каждой строки видны тип,
|
значение без суммы выплаты. У каждой строки видны тип,
|
||||||
инструмент, дата и доступная сумма в исходной валюте. Список не имеет
|
инструмент, дата и доступная сумма в RUB. Список не имеет
|
||||||
пагинации и не конвертирует валюты. Пустой результат означает отсутствие
|
пагинации. Пустой результат означает отсутствие
|
||||||
известных поддерживаемых событий в выбранном окне, а не доказательство
|
известных поддерживаемых событий в выбранном окне, а не доказательство
|
||||||
отсутствия всех будущих выплат. Инструмент без поддерживаемых данных
|
отсутствия всех будущих выплат. Инструмент без поддерживаемых данных
|
||||||
не получает искусственную строку «нет данных».
|
не получает искусственную строку «нет данных».
|
||||||
@@ -70,8 +70,17 @@
|
|||||||
несуществующая дата дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`
|
несуществующая дата дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`
|
||||||
без замены периода и без запуска личной работы.
|
без замены периода и без запуска личной работы.
|
||||||
Фильтрация на сервере предшествует сортировке и вычислению
|
Фильтрация на сервере предшествует сортировке и вычислению
|
||||||
`incomeTotalsByCurrency`, включающего только купоны и дивиденды.
|
итога прогноза в RUB, включающего только купоны и дивиденды.
|
||||||
Итоги остаются в ответе API; полный экран показывает список без общего итога.
|
Итоги остаются в ответе API; полный экран показывает список без общего итога списка.
|
||||||
|
|
||||||
|
В режиме «Все счета» события одного инструмента, даты, точного типа и `dateKind` образуют
|
||||||
|
группу, если их две и более, в том числе одного счёта. Ключ дополнительно включает `dateKind`,
|
||||||
|
поэтому дата реестра дивиденда и иная дата того же инструмента не объединяются. Группа стоит на месте первого
|
||||||
|
события. Полный список группирует все полученные события; превью обзора сначала берёт пять
|
||||||
|
событий и группирует только их. Каждая строка счёта остаётся отдельной и показывает название
|
||||||
|
счёта и свою прогнозную сумму. Визуальный итог группы — точная сумма в RUB; он показывается
|
||||||
|
только если полнота прогноза `complete` и у каждого события группы известна прогнозная сумма.
|
||||||
|
Иначе итог скрыт, а строки остаются. Этот итог не равен итогам ответа API и не относится к полученному доходу.
|
||||||
|
|
||||||
## Получение и отказы
|
## Получение и отказы
|
||||||
|
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
завершённой дневной свечи до московской даты котировки; база ищется за 20 дней.
|
завершённой дневной свечи до московской даты котировки; база ищется за 20 дней.
|
||||||
Денежная оценка без НКД равна цене в процентах, умноженной на текущий номинал
|
Денежная оценка без НКД равна цене в процентах, умноженной на текущий номинал
|
||||||
и делённой на 100. Она округляется до девяти десятичных знаков. Оценка с НКД
|
и делённой на 100. Она округляется до девяти десятичных знаков. Оценка с НКД
|
||||||
добавляет текущий накопленный купонный доход только при совпадении валют.
|
добавляет текущий накопленный купонный доход.
|
||||||
Это ориентир без комиссии: котировка может быть старше текущего номинала и НКД.
|
Это ориентир без комиссии: котировка может быть старше текущего номинала и НКД.
|
||||||
FX-конвертация не выполняется, первоначальный номинал не заменяет текущий.
|
Первоначальный номинал не заменяет текущий.
|
||||||
|
|
||||||
Условия выпуска: текущий и первоначальный номинал, погашение, оферта,
|
Условия выпуска: текущий и первоначальный номинал, погашение, оферта,
|
||||||
количество купонов в год, лот. Отдельно отмечены плавающий купон,
|
количество купонов в год, лот. Отдельно отмечены плавающий купон,
|
||||||
@@ -49,7 +49,7 @@ FX-конвертация не выполняется, первоначальн
|
|||||||
Текущая купонная доходность — ближайший купон × 365 / длительность его периода
|
Текущая купонная доходность — ближайший купон × 365 / длительность его периода
|
||||||
в днях / денежная цена без НКД × 100 %. Decimal-расчёт округляется до четырёх
|
в днях / денежная цена без НКД × 100 %. Decimal-расчёт округляется до четырёх
|
||||||
знаков. Требуются известная неотрицательная выплата, положительные цена и
|
знаков. Требуются известная неотрицательная выплата, положительные цена и
|
||||||
период и одинаковая валюта выплаты и цены. Это годовая оценка при сохранении
|
период. Это годовая оценка при сохранении
|
||||||
размера купона и номинала, без налогов, комиссий и реинвестирования; она не
|
размера купона и номинала, без налогов, комиссий и реинвестирования; она не
|
||||||
является доходностью к погашению. Время котировки показывается отдельно.
|
является доходностью к погашению. Время котировки показывается отдельно.
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ HTML-источник, общий кэш и поведение при измен
|
|||||||
|
|
||||||
Позиция агрегирует только `BOND` с точным UID по доступным счетам, используя
|
Позиция агрегирует только `BOND` с точным UID по доступным счетам, используя
|
||||||
[снимок портфеля](../portfolio/overview.md) и decimal-арифметику. Средняя покупка взвешена
|
[снимок портфеля](../portfolio/overview.md) и decimal-арифметику. Средняя покупка взвешена
|
||||||
по количеству. Неполные или разновалютные суммы недоступны; общая средняя
|
по количеству. Неполные суммы недоступны; общая средняя
|
||||||
и процент доступны только при положительных включённых позициях. Для
|
и процент доступны только при положительных включённых позициях. Для
|
||||||
коротких позиций и сочетания длинных с короткими эти показатели не синтезируются.
|
коротких позиций и сочетания длинных с короткими эти показатели не синтезируются.
|
||||||
Результат открытой позиции не включает выплаченные купоны и продажи и не
|
Результат открытой позиции не включает выплаченные купоны и продажи и не
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: скринер
|
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: скринер
|
||||||
запускается кнопкой «Найти» с необязательным названием или тикером, сектором,
|
запускается кнопкой «Найти» с необязательным названием или тикером, сектором,
|
||||||
типом акции, валютой расчётов, площадкой, страной риска и максимальным размером
|
типом акции, площадкой, страной риска и максимальным размером
|
||||||
лота. Он использует полный полученный каталог и показывает только акции, для
|
лота. Он использует полный полученный каталог и показывает только акции, для
|
||||||
которых каталог подтверждает доступность покупки и торговли через API. Это не
|
которых каталог подтверждает доступность покупки и торговли через API. Это не
|
||||||
гарантирует, что конкретная заявка пользователя будет исполнена прямо сейчас.
|
гарантирует, что конкретная заявка пользователя будет исполнена прямо сейчас.
|
||||||
@@ -90,10 +90,10 @@ UID включён в ключ кэша и подпись общего курс
|
|||||||
восстанавливается переходом на первую страницу с повторным запросом.
|
восстанавливается переходом на первую страницу с повторным запросом.
|
||||||
|
|
||||||
[Портфель](../portfolio/overview.md) остаётся владельцем снимков и оценки позиций. Сводка
|
[Портфель](../portfolio/overview.md) остаётся владельцем снимков и оценки позиций. Сводка
|
||||||
фильтрует `STOCK` по точному UID и использует точную десятичную арифметику, без конвертации валют.
|
фильтрует `STOCK` по точному UID и использует точную десятичную арифметику, в RUB.
|
||||||
Средняя цена равна сумме количеств, умноженных на средние цены, делённой на
|
Средняя цена равна сумме количеств, умноженных на средние цены, делённой на
|
||||||
общее количество; она округляется сервером до девяти знаков, проценты — до шести.
|
общее количество; она округляется сервером до девяти знаков, проценты — до шести.
|
||||||
Неполные или разновалютные денежные итоги недоступны. Общая средняя и процент доступны только если все включённые позиции
|
Неполные денежные итоги недоступны. Общая средняя и процент доступны только если все включённые позиции
|
||||||
положительны; для нулевого количества, коротких позиций и сочетания
|
положительны; для нулевого количества, коротких позиций и сочетания
|
||||||
длинных с короткими они не синтезируются.
|
длинных с короткими они не синтезируются.
|
||||||
Результат открытой позиции исключает продажи и дивиденды и не называется полной
|
Результат открытой позиции исключает продажи и дивиденды и не называется полной
|
||||||
|
|||||||
@@ -13,9 +13,27 @@
|
|||||||
Исполненная операция содержит тип события, его категорию, описание,
|
Исполненная операция содержит тип события, его категорию, описание,
|
||||||
момент совершения, доступные сведения об инструменте и денежное движение.
|
момент совершения, доступные сведения об инструменте и денежное движение.
|
||||||
Запросы отменённых или ожидающих исполнения поручений не образуют этот журнал.
|
Запросы отменённых или ожидающих исполнения поручений не образуют этот журнал.
|
||||||
Суммы остаются точными десятичными строками в исходной валюте; frontend
|
Суммы остаются точными десятичными строками в RUB. Frontend
|
||||||
только форматирует их. Положительное и отрицательное движение сохраняют
|
форматирует их и считает визуальный итог группы по показанным записям
|
||||||
знак. Отсутствие `payment` означает «Без движения денег», а не нулевую сумму.
|
(см. [группировку](#группировка-в-режиме-все-счета)). Положительное и отрицательное
|
||||||
|
движение сохраняют знак. Отсутствие `payment` означает «Без движения денег», а не нулевую сумму.
|
||||||
|
|
||||||
|
## Группировка в режиме «Все счета»
|
||||||
|
|
||||||
|
Только в режиме `all` записи журнала и превью обзора, которые относятся к одному
|
||||||
|
дню экрана, одному инструменту и точному типу операции, объединяются в группу.
|
||||||
|
Ключом служат день, `instrumentUid` (иначе `figi`) и тип; группа образуется при
|
||||||
|
двух и более записях, в том числе одного счёта. Группа стоит на месте первой записи.
|
||||||
|
Каждая запись остаётся отдельной строкой с названием счёта простым текстом и своей суммой.
|
||||||
|
Одиночный счёт не группируется.
|
||||||
|
|
||||||
|
Группировка выполняется после лимита: превью обзора сначала берёт пять записей,
|
||||||
|
затем группирует только их. Полный журнал группирует страницу, уже загруженную
|
||||||
|
курсором; группы не переносятся между страницами. Курсор и порядок записей не меняются.
|
||||||
|
|
||||||
|
Итог группы — точная сумма в RUB. Он показывается только
|
||||||
|
если полнота журнала `complete`, у каждой записи группы есть `payment`, и ни одна сумма
|
||||||
|
не равна нулю. Иначе итог скрыт, а строки счетов остаются.
|
||||||
|
|
||||||
Категории объединяют разные события для фильтрации: сделка (`trade`),
|
Категории объединяют разные события для фильтрации: сделка (`trade`),
|
||||||
доход (`income`), налог (`tax`), комиссия (`fee`), перевод (`transfer`)
|
доход (`income`), налог (`tax`), комиссия (`fee`), перевод (`transfer`)
|
||||||
@@ -30,7 +48,7 @@
|
|||||||
но их недоступность не меняет финансовое событие.
|
но их недоступность не меняет финансовое событие.
|
||||||
|
|
||||||
Журнал не вычисляет остаток после операции, историческую стоимость портфеля,
|
Журнал не вычисляет остаток после операции, историческую стоимость портфеля,
|
||||||
совокупный налог или валютную конвертацию. Изменение рыночной цены не становится
|
совокупный налог. Изменение рыночной цены не становится
|
||||||
операцией. Переводы между счетами не схлопываются в одну запись; одинаковые
|
операцией. Переводы между счетами не схлопываются в одну запись; одинаковые
|
||||||
ID операций разных счетов не означают дубликат.
|
ID операций разных счетов не означают дубликат.
|
||||||
|
|
||||||
|
|||||||
@@ -30,12 +30,13 @@ Backend публикует статические маршруты под `/api/
|
|||||||
У них те же формы данных и фильтры, что у соответствующих разделов отдельного
|
У них те же формы данных и фильтры, что у соответствующих разделов отдельного
|
||||||
счёта. Позиции, операции (включая выплаты дохода) и события сохраняют источник
|
счёта. Позиции, операции (включая выплаты дохода) и события сохраняют источник
|
||||||
в поле `account: { id, name }`; в ответах одного счёта это поле отсутствует.
|
в поле `account: { id, name }`; в ответах одного счёта это поле отсутствует.
|
||||||
Валютные итоги и деньги агрегированы. Точную форму транспорта задаёт
|
Итоги и деньги агрегированы в RUB. Точную форму транспорта задаёт
|
||||||
[OpenAPI backend](../../architecture/http-api.md).
|
[OpenAPI backend](../../architecture/http-api.md).
|
||||||
|
|
||||||
- Портфель и доступные денежные остатки суммируются сервером точно, по исходной
|
- Портфель и доступные денежные остатки суммируются сервером точно, в RUB,
|
||||||
валюте, с точной десятичной арифметикой. FX-конвертации нет; правила
|
с точной десятичной арифметикой. Позиции и деньги в других валютах не
|
||||||
неизвестных значений и состава сумм наследуются от [портфеля](data-reference.md).
|
участвуют; правила неизвестных значений и состава сумм наследуются от
|
||||||
|
[портфеля](data-reference.md).
|
||||||
- Одинаковые бумаги разных счетов показаны одной карточкой с общим названием
|
- Одинаковые бумаги разных счетов показаны одной карточкой с общим названием
|
||||||
и идентификатором. Внутри всегда видны строки счетов: ссылка на портфель,
|
и идентификатором. Внутри всегда видны строки счетов: ссылка на портфель,
|
||||||
количество, доступная стоимость, результат, средняя цена и доля позиции.
|
количество, доступная стоимость, результат, средняя цена и доля позиции.
|
||||||
@@ -48,7 +49,7 @@ Backend публикует статические маршруты под `/api/
|
|||||||
API сохраняет позиции каждого счёта; объединяется только их представление.
|
API сохраняет позиции каждого счёта; объединяется только их представление.
|
||||||
Порядок карточек задаёт первое вхождение
|
Порядок карточек задаёт первое вхождение
|
||||||
бумаги; порядок счетов внутри карточки сохраняется. Одиночные позиции
|
бумаги; порядок счетов внутри карточки сохраняется. Одиночные позиции
|
||||||
используют прежнюю карточку. Доля относится к позициям той же валюты
|
используют прежнюю карточку. Доля относится к позициям
|
||||||
во всём показанном портфеле, без денежных остатков.
|
во всём показанном портфеле, без денежных остатков.
|
||||||
- Журнал объединяет операции по убыванию времени, при равном времени использует
|
- Журнал объединяет операции по убыванию времени, при равном времени использует
|
||||||
порядок идентификаторов счетов и операций. ID
|
порядок идентификаторов счетов и операций. ID
|
||||||
@@ -59,6 +60,12 @@ Backend публикует статические маршруты под `/api/
|
|||||||
состав счетов влияет только на фактические выплаты выбранного периода.
|
состав счетов влияет только на фактические выплаты выбранного периода.
|
||||||
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
|
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
|
||||||
Прогноз не включается в реализованные доходы.
|
Прогноз не включается в реализованные доходы.
|
||||||
|
- [Результат инвестирования](investment-performance.md) складывает потоки и
|
||||||
|
стоимость только рублёвых счетов с полной историей. Счёт с причиной
|
||||||
|
недоступности исключается, сводка помечается неполной. Похожие на перевод
|
||||||
|
между своими счетами операции без подтверждённой связи исключают оба счёта
|
||||||
|
(`UNCONFIRMED_TRANSFER`). Если оценки оставшихся счетов сделаны в разные
|
||||||
|
московские дни, сводка недоступна: стоимости разных дат не складываются.
|
||||||
|
|
||||||
## Полнота, свежесть и доступ
|
## Полнота, свежесть и доступ
|
||||||
|
|
||||||
@@ -81,6 +88,12 @@ Backend публикует статические маршруты под `/api/
|
|||||||
применённые фильтры. Coverage/status без изменения строк не ломают cursor.
|
применённые фильтры. Coverage/status без изменения строк не ломают cursor.
|
||||||
Продолжение не зависит от RAM-кэша или перезапуска.
|
Продолжение не зависит от RAM-кэша или перезапуска.
|
||||||
|
|
||||||
|
Визуальная группировка строк одного инструмента в общих списках выполняется только
|
||||||
|
в пределах уже полученного списка: в журнале — на загруженной странице, без переноса группы
|
||||||
|
на следующую; в полном списке будущих событий и выплатах дохода — по всем полученным строкам
|
||||||
|
периода. Группировка не меняет порядок, cursor или ответ API. Протокол курсора прежний.
|
||||||
|
Правила группировки — в [журнале](../operations/overview.md#группировка-в-режиме-все-счета).
|
||||||
|
|
||||||
Повторная сверка полного показанного периода публикует все счета и интервалы
|
Повторная сверка полного показанного периода публикует все счета и интервалы
|
||||||
одной транзакцией; успешное первое окно не смешивается с прежними остальными.
|
одной транзакцией; успешное первое окно не смешивается с прежними остальными.
|
||||||
Подробнее — [журнал](../operations/overview.md#получение-и-полнота).
|
Подробнее — [журнал](../operations/overview.md#получение-и-полнота).
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
# Концентрация портфеля
|
||||||
|
|
||||||
|
Вкладка «Концентрация» на странице счёта `/accounts/:accountId` показывает,
|
||||||
|
какие акции, облигации, секторы и эмитенты занимают наибольшую часть текущей
|
||||||
|
оценки Portfolio. Она отвечает на вопрос «где сконцентрированы деньги»,
|
||||||
|
который не решают карточки позиций и [структура
|
||||||
|
активов](overview.md#как-читать-экран). Точный смысл полей и долей — в
|
||||||
|
[справочнике данных](data-reference.md).
|
||||||
|
|
||||||
|
## Вкладка и разрезы
|
||||||
|
|
||||||
|
Вкладка есть только у отдельного счёта: в режиме [«Все счета»](all-accounts.md)
|
||||||
|
её нет. Появление вкладки не меняет вкладку, открытую по умолчанию («Позиции»),
|
||||||
|
и содержание остальных вкладок. Пока Portfolio загружается, при его ошибке или
|
||||||
|
штатном пустом составе вкладки нет; при Portfolio хотя бы с одной позицией или
|
||||||
|
денежным остатком вкладка показывается.
|
||||||
|
|
||||||
|
Вкладка содержит четыре разреза и показывает один из них одновременно:
|
||||||
|
|
||||||
|
| Разрез | Что ранжирует | Типы позиций |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| «Акции» | Пять крупнейших позиций акций | `STOCK` |
|
||||||
|
| «Облигации» | Пять крупнейших позиций облигаций | `BOND` |
|
||||||
|
| «Секторы» | Пять крупнейших секторов по данным T-Bank | `STOCK`, `BOND`, `FUND` |
|
||||||
|
| «Эмитенты» | Пять крупнейших эмитентов (брендов актива) | `STOCK`, `BOND` |
|
||||||
|
|
||||||
|
Фонды участвуют только в разрезе «Секторы»: их эмитент — управляющая компания,
|
||||||
|
а не компания внутри фонда. Позиции типов `CURRENCY`, `FUTURE`, `OPTION`,
|
||||||
|
`STRUCTURED_NOTE`, `DIGITAL_FINANCIAL_ASSET` и `OTHER` во вкладку не входят.
|
||||||
|
|
||||||
|
Позиции без сектора образуют явную группу «Сектор не указан», без бренда —
|
||||||
|
«Эмитент не указан»; обе группы показываются с видимой долей. Государственные
|
||||||
|
облигации определяются значением сектора T-Bank `government` с подписью
|
||||||
|
«Государственный сектор»; других собственных классификаций WealthLedger
|
||||||
|
не вводит. Название элемента в разрезе эмитентов — название бренда; если у
|
||||||
|
одного бренда разные названия, показывается название позиции с наибольшей
|
||||||
|
стоимостью.
|
||||||
|
|
||||||
|
## Топ-5 и «Прочее»
|
||||||
|
|
||||||
|
В каждом разрезе показаны пять крупнейших элементов по текущей денежной оценке,
|
||||||
|
каждый с суммой и долей. Рядом показан суммарный показатель «Топ-5 · N %».
|
||||||
|
Если в разрезе семь и более элементов, все остальные объединены в одну строку
|
||||||
|
«Прочее» с числом элементов, суммой и долей. При шести и меньшем числе
|
||||||
|
элементов каждый показан своей строкой. По нажатию на «Прочее» раскрывается
|
||||||
|
полный перечень остальных элементов, каждый со своей суммой и долей; топ-5
|
||||||
|
и диаграмма при этом не меняются.
|
||||||
|
|
||||||
|
Доли считаются от суммы стоимостей позиций разреза и
|
||||||
|
в сумме дают ровно 100 %; округление — до десятой доли процента, очень малые
|
||||||
|
доли показываются как «< 0,1 %». Отрицательные и нулевые стоимости, а также
|
||||||
|
позиции без оценки в разрез не входят.
|
||||||
|
|
||||||
|
## Диаграмма и неполные данные
|
||||||
|
|
||||||
|
Рядом с перечнем показана кольцевая диаграмма, согласованная с перечнем;
|
||||||
|
информация передаётся не только цветом, есть текстовый эквивалент. Если ответ
|
||||||
|
отмечен как неполный (`completeness: "incomplete"` — часть позиций не имеет
|
||||||
|
оценки), над разрезом появляется предупреждение «Данные неполные», а под
|
||||||
|
списком — сноска «Не учтено позиций: N» с числом позиций, не вошедших в разрез.
|
||||||
|
Пустой разрез (нет позиций с положительной оценкой)
|
||||||
|
показывает текстовое состояние вместо диаграммы.
|
||||||
|
|
||||||
|
## Откуда берутся сектор и эмитент
|
||||||
|
|
||||||
|
Сектор и эмитент — часть данных Portfolio: их получает backend в часовом
|
||||||
|
обходе и сохраняет в снимке вместе с остальными полями позиций
|
||||||
|
([поток загрузки](flows/portfolio-loading.md#обновление-сектора-и-эмитента),
|
||||||
|
[интеграция T-Bank](../../integrations/tbank.md)). Вкладка считается по уже
|
||||||
|
загруженному снимку и не обращается к T-Bank.
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
Деньги представлены значением Money: ISO-код валюты и десятичная строка,
|
Деньги представлены значением Money: ISO-код валюты и десятичная строка,
|
||||||
например `{ "currency": "RUB", "value": "12500.5" }` — условный пример.
|
например `{ "currency": "RUB", "value": "12500.5" }` — условный пример.
|
||||||
|
Валюта всегда `RUB`: система работает только с рублями.
|
||||||
Количества также передаются десятичными строками. Backend выполняет
|
Количества также передаются десятичными строками. Backend выполняет
|
||||||
десятичную арифметику без промежуточного `Number`, нормализует отрицательные
|
десятичную арифметику без промежуточного `Number`, нормализует отрицательные
|
||||||
целую и дробную части и убирает незначащие конечные нули. Экспоненциальной
|
целую и дробную части и убирает незначащие конечные нули. Экспоненциальной
|
||||||
@@ -18,7 +19,7 @@
|
|||||||
`null` означает, что показатель нельзя определить из доступных данных.
|
`null` означает, что показатель нельзя определить из доступных данных.
|
||||||
Это не ноль. Известная нулевая цена отличается от отсутствующей;
|
Это не ноль. Известная нулевая цена отличается от отсутствующей;
|
||||||
позиция с ненулевым количеством и неизвестной стоимостью остаётся в составе.
|
позиция с ненулевым количеством и неизвестной стоимостью остаётся в составе.
|
||||||
Несколько валют никогда не складываются в одну общую стоимость.
|
Позиции и деньги в валютах, отличных от RUB, отфильтровываются при получении из T-Bank и не участвуют ни в одном итоге.
|
||||||
|
|
||||||
## Состав и денежные показатели
|
## Состав и денежные показатели
|
||||||
|
|
||||||
@@ -26,23 +27,37 @@
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Позиция | Ненулевое количество обычного инструмента из `GetPortfolio.positions` | Виртуальные позиции не включаются; порядок источника сохраняется |
|
| Позиция | Ненулевое количество обычного инструмента из `GetPortfolio.positions` | Виртуальные позиции не включаются; порядок источника сохраняется |
|
||||||
| `quantity` | Количество из текущей позиции брокера | Допустимы дробные и отрицательные количества; это не число лотов |
|
| `quantity` | Количество из текущей позиции брокера | Допустимы дробные и отрицательные количества; это не число лотов |
|
||||||
| `currentValue` | Количество × текущая цена из `GetPortfolio` | `null`, если цена или её валюта недоступны |
|
| `currentValue` | Количество × текущая цена из `GetPortfolio` | `null`, если цена недоступна |
|
||||||
| `averagePurchasePrice` | Средняя цена позиции, переданная брокером | Это цена единицы, а не сумма затрат или рассчитанная приложением история покупок |
|
| `averagePurchasePrice` | Средняя цена позиции, переданная брокером | Это цена единицы, а не сумма затрат или рассчитанная приложением история покупок |
|
||||||
| `absoluteReturn` | Количество × (текущая цена − средняя цена) | Требует обеих цен в одной известной валюте; не включает продажи, купоны и дивиденды |
|
| `absoluteReturn` | Количество × (текущая цена − средняя цена) | Требует обеих цен; не включает продажи, купоны и дивиденды |
|
||||||
| Cash Balance | Суммы из `GetPositions.money`, объединённые по валюте | Заблокированные деньги не прибавляются; торгуемый инструмент `CURRENCY` остаётся позицией |
|
| Cash Balance | Суммы RUB из `GetPositions.money`, объединённые в один остаток | Заблокированные деньги не прибавляются; торгуемый инструмент `CURRENCY` остаётся позицией |
|
||||||
| `totalsByCurrency` | Стоимости позиций + доступные деньги той же валюты | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
|
| Итог Portfolio | Стоимости позиций + Cash Balance в RUB | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
|
||||||
| `lastSuccessfulAt` | Время формирования успешного снимка, UTC | Не является временем каждой котировки; запасной снимок сохраняет исходное время |
|
| `lastSuccessfulAt` | Время формирования успешного снимка, UTC | Не является временем каждой котировки; запасной снимок сохраняет исходное время |
|
||||||
| `isStale` | Истёк часовой срок свежести сохранённого portfolio source | Не описывает состояние клиентского кэша или ошибку фонового запроса |
|
| `isStale` | Истёк часовой срок свежести сохранённого portfolio source | Не описывает состояние клиентского кэша или ошибку фонового запроса |
|
||||||
|
| `sector` | Сектор инструмента в том виде, как его определяет T-Bank, с обрезанными пробелами | Только для позиций `STOCK`, `BOND` и `FUND`; значение из одних пробел считается отсутствующим. Во всех остальных случаях — `null` |
|
||||||
|
| `issuer` | Бренд актива инструмента по данным T-Bank: `{ id, name }` | Только для позиций `STOCK`, `BOND` и `FUND`, когда у актива известны uid и название бренда. Во всех остальных случаях — `null`. Не влияет на количество, стоимость и свежесть снимка; используется вкладкой [«Концентрация»](concentration.md) |
|
||||||
|
|
||||||
Ненулевые денежные остатки одной валюты суммируются. Позиции одинаковых
|
Ненулевые денежные остатки суммируются в один Cash Balance. Позиции одинаковых
|
||||||
инструментов в ответе отдельного счёта не объединяются; визуальная группировка
|
инструментов в ответе отдельного счёта не объединяются; визуальная группировка
|
||||||
между счетами описана [отдельно](all-accounts.md#данные-и-вычисления).
|
между счетами описана [отдельно](all-accounts.md#данные-и-вычисления).
|
||||||
Сводка уже включает Cash Balance: прибавление денег к ней второй раз неверно.
|
Сводка уже включает Cash Balance: прибавление денег к ней второй раз неверно.
|
||||||
|
|
||||||
При отсутствии вычислимой стоимости у части позиций известный итог остаётся
|
При отсутствии вычислимой стоимости у части позиций известный итог остаётся
|
||||||
полезен, но представляет только оценённую часть. Известные нулевые итоги
|
полезен, но представляет только оценённую часть. Известные нулевые итоги
|
||||||
отдельного счёта не создают валютные карточки. Если `totalsByCurrency` пуст,
|
отдельного счёта не создают отдельную итоговую карточку. Если итог Portfolio
|
||||||
но позиции или деньги присутствуют, это не пустой портфель.
|
отсутствует, но позиции или деньги присутствуют, это не пустой портфель.
|
||||||
|
|
||||||
|
## Результат инвестирования
|
||||||
|
|
||||||
|
| Поле | Смысл | Ограничение |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `netInvested`, `currentValue`, `profit` | Чистые внешние потоки, сумма RUB-оценок, их разность | Только RUB, копейки |
|
||||||
|
| `return.value` | Доля XIRR (`0.151` = 15,1 %) | `null` с `unavailableReason`; при `basis = period` — за весь период |
|
||||||
|
| `benchmark`, `reference` | Те же потоки в MCFTRR и IMOEX | IMOEX только справка |
|
||||||
|
| `outperformance` | Разница долей и стоимостей с MCFTRR | `null`, если любая сторона недоступна |
|
||||||
|
| `series` | Точки торговых дней MCFTRR | Пусто без истории индекса |
|
||||||
|
|
||||||
|
Подробнее — [результат инвестирования](investment-performance.md).
|
||||||
|
|
||||||
## Идентификация и оформление инструмента
|
## Идентификация и оформление инструмента
|
||||||
|
|
||||||
@@ -58,6 +73,8 @@ ISIN, тикер и `logoName` могут быть `null`. `logoName` — имя
|
|||||||
или метаданных не меняет количество, суммы и свежесть снимка и не скрывает
|
или метаданных не меняет количество, суммы и свежесть снимка и не скрывает
|
||||||
финансовые данные. Metadata обновляется независимо; отсутствие имени не задерживает выдачу
|
финансовые данные. Metadata обновляется независимо; отсутствие имени не задерживает выдачу
|
||||||
финансового снимка и оставляет доступный идентификатор.
|
финансового снимка и оставляет доступный идентификатор.
|
||||||
|
`logoName` не равен эмитенту из вкладки «Концентрация»: он берётся из metadata
|
||||||
|
инструмента, а эмитент — из [классификации инструмента](flows/portfolio-loading.md#обновление-сектора-и-эмитента).
|
||||||
|
|
||||||
## Структура и доли
|
## Структура и доли
|
||||||
|
|
||||||
@@ -65,33 +82,32 @@ ISIN, тикер и `logoName` могут быть `null`. `logoName` — имя
|
|||||||
облигации (`BOND`), прочие инструменты (`OTHER`) и деньги (`CASH`).
|
облигации (`BOND`), прочие инструменты (`OTHER`) и деньги (`CASH`).
|
||||||
Торгуемые валютные инструменты входят в `OTHER`; денежные остатки — в `CASH`.
|
Торгуемые валютные инструменты входят в `OTHER`; денежные остатки — в `CASH`.
|
||||||
Сервер строит структуру из позиций и денег, без повторного добавления
|
Сервер строит структуру из позиций и денег, без повторного добавления
|
||||||
`totalsByCurrency`.
|
итога Portfolio.
|
||||||
|
|
||||||
Доля категории — её стоимость / известная стоимость позиций и денег
|
Доля категории — её стоимость / известная стоимость позиций и денег
|
||||||
в выбранной валюте × 100. Backend округляет процент до шести знаков;
|
× 100. Backend округляет процент до шести знаков;
|
||||||
frontend показывает до сотых. Положительное значение меньше 0,01%
|
frontend показывает до сотых. Положительное значение меньше 0,01%
|
||||||
отображается как «< 0,01 %», если серверное округление не превратило его в ноль.
|
отображается как «< 0,01 %», если серверное округление не превратило его в ноль.
|
||||||
В геометрию диаграммы передаются только числовые проценты; суммы в списке
|
В геометрию диаграммы передаются только числовые проценты; суммы в списке
|
||||||
и подсказке форматируются из исходных точных строк.
|
и подсказке форматируются из исходных точных строк.
|
||||||
|
|
||||||
Доля на карточке отдельной позиции использует другой знаменатель:
|
Доля на карточке отдельной позиции использует другой знаменатель:
|
||||||
сумму стоимостей всех позиций той же валюты **без денег**. Это приблизительный
|
сумму стоимостей всех отображаемых позиций **без денег**. Это приблизительный
|
||||||
показатель для отображения, рассчитанный frontend. Он не изменяет Money.
|
показатель для отображения, рассчитанный frontend. Он не изменяет Money.
|
||||||
В режиме всех счетов знаменатель охватывает все показанные счета.
|
В режиме всех счетов знаменатель охватывает все показанные счета.
|
||||||
|
|
||||||
| Состояние | Доступное представление |
|
| Состояние | Доступное представление |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Все составляющие оценены, неотрицательны, итог положителен | Суммы, доли и кольцевая диаграмма выбранной валюты |
|
| Все составляющие оценены, неотрицательны, итог положителен | Суммы, доли и кольцевая диаграмма |
|
||||||
| Есть позиция без оценки | `unvaluedCategories` содержит её категорию и количество; суммы известной части остаются, доли и кольцо недоступны для всех валют |
|
| Есть позиция без оценки | `unvaluedCategories` содержит её категорию и количество; суммы известной части остаются, доли и кольцо недоступны |
|
||||||
| Есть отрицательная составляющая | Суммы со знаком остаются; доли и кольцо отключены для её валюты, даже если итог категории положителен |
|
| Есть отрицательная составляющая | Суммы со знаком остаются; доли и кольцо отключены, даже если итог категории положителен |
|
||||||
| Состав пуст или имеет нулевую стоимость | Текстовое состояние вместо кольца |
|
| Состав пуст или имеет нулевую стоимость | Текстовое состояние вместо кольца |
|
||||||
|
|
||||||
Неоценённой позиции нельзя достоверно назначить валюту по её стоимости,
|
В общем портфеле проверка
|
||||||
поэтому ограничение долей действует на все валюты. В общем портфеле проверка
|
|
||||||
отрицательных денег выполняется по остаткам счетов до взаимозачёта.
|
отрицательных денег выполняется по остаткам счетов до взаимозачёта.
|
||||||
|
|
||||||
Нормативные основы: [нормализованный состав](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-нормализованный-состав-portfolio)
|
Нормативные основы: [нормализованный состав](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-нормализованный-состав-portfolio)
|
||||||
и [точные значения и валютные агрегаты](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-точные-значения-и-валютные-агрегаты).
|
и [точные значения и итоговая сумма в RUB](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-точные-значения-и-итоговая-сумма-в-rub).
|
||||||
Структура и общий режим подтверждены реализацией и её проверками;
|
Структура и общий режим подтверждены реализацией и её проверками;
|
||||||
отдельных требований к ним в основной спецификации портфеля пока нет.
|
отдельных требований к ним в основной спецификации портфеля пока нет.
|
||||||
Поля транспорта следует сверять с [HTTP API](../../architecture/http-api.md),
|
Поля транспорта следует сверять с [HTTP API](../../architecture/http-api.md),
|
||||||
|
|||||||
@@ -11,9 +11,28 @@
|
|||||||
они не ждут и не вызывают T-Bank и не предлагают ручную синхронизацию. Часовой
|
они не ждут и не вызывают T-Bank и не предлагают ручную синхронизацию. Часовой
|
||||||
обход текущего подключения обновляет Portfolio независимо от экрана. Для нового
|
обход текущего подключения обновляет Portfolio независимо от экрана. Для нового
|
||||||
полного snapshot ему нужны оба финансовых ответа `GetPortfolio` и
|
полного snapshot ему нужны оба финансовых ответа `GetPortfolio` и
|
||||||
`GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента
|
`GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента и
|
||||||
дополняет представление независимо, с доступным UID/FIGI вместо имени до её
|
классификация (сектор и эмитент) дополняют представление независимо,
|
||||||
онлайн-загрузки.
|
с доступным UID/FIGI вместо имени до их загрузки.
|
||||||
|
|
||||||
|
## Обновление сектора и эмитента
|
||||||
|
|
||||||
|
Часовой обход также обновляет сектор и эмитента позиций типов `share`, `bond`
|
||||||
|
и `etf`. Значения хранятся как последнее известное ([ADR
|
||||||
|
022](../../../adr/022-stored-instrument-classification.md)): сектор — как его
|
||||||
|
определяет T-Bank, эмитент — бренд актива (`uid` и `name`). Каждое поле
|
||||||
|
обновляется при первом обходе, начавшемся не ранее чем через 24 часа после его
|
||||||
|
последнего успешного получения; пока значение не получено, попытка повторяется
|
||||||
|
в каждом обходе. Сектор и эмитент обновляются независимо.
|
||||||
|
|
||||||
|
Неуспешное получение не мешает публикации snapshot и не меняет
|
||||||
|
`lastSuccessfulAt` и `isStale`; сохранённое значение остаётся доступным.
|
||||||
|
Исключение — отказ token: он обрабатывается так же, как отказ token при
|
||||||
|
обходе Portfolio. Инструмент ищется по UID, затем по FIGI; ответ «не найдено»
|
||||||
|
сохраняет прежнее значение и отсчёт 24 часов начинается заново. Позиции без
|
||||||
|
полученных значений участвуют в разрезах вкладки
|
||||||
|
[«Концентрация»](../concentration.md) как «Сектор не указан» и
|
||||||
|
«Эмитент не указан».
|
||||||
|
|
||||||
Открытый экран выполняет локальное перечитывание не чаще одного раза в
|
Открытый экран выполняет локальное перечитывание не чаще одного раза в
|
||||||
30 минут; retry также повторяет только HTTP GET. `data: null` означает, что
|
30 минут; retry также повторяет только HTTP GET. `data: null` означает, что
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
базы для разбора не нужны; не переносите их в документацию или отчёт.
|
базы для разбора не нужны; не переносите их в документацию или отчёт.
|
||||||
|
|
||||||
1. **Определите предмет сравнения.** Запишите, открыт отдельный счёт или
|
1. **Определите предмет сравнения.** Запишите, открыт отдельный счёт или
|
||||||
«Все счета», какая валюта и какой показатель расходятся. Текущая стоимость,
|
«Все счета» и какой показатель расходится. Текущая стоимость,
|
||||||
свободные деньги, результат открытой позиции и полученный доход — разные
|
свободные деньги, результат открытой позиции и полученный доход — разные
|
||||||
величины. Убедитесь, что сравниваемые значения относятся к одному составу
|
величины. Убедитесь, что сравниваемые значения относятся к одному составу
|
||||||
счетов и инструменту. Название или тикер сами по себе не доказывают
|
счетов и инструменту. Название или тикер сами по себе не доказывают
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
автоматически, поэтому расхождение проверяйте по показанному состоянию
|
автоматически, поэтому расхождение проверяйте по показанному состоянию
|
||||||
источника, а не по результату ручного обновления. Перезагрузка backend
|
источника, а не по результату ручного обновления. Перезагрузка backend
|
||||||
сохраняет последний полный снимок в SQLite, но не создаёт историю стоимости.
|
сохраняет последний полный снимок в SQLite, но не создаёт историю стоимости.
|
||||||
3. **Проверьте состав суммы.** Для одной валюты итог складывается из
|
3. **Проверьте состав суммы.** Итог складывается из вычислимых стоимостей
|
||||||
вычислимых стоимостей позиций и доступных денег. Не добавляйте деньги
|
позиций и доступных денег в RUB. Не добавляйте деньги второй раз и не
|
||||||
второй раз, не складывайте валюты и не включайте заблокированные средства.
|
включайте заблокированные средства.
|
||||||
Ненулевая позиция с `currentValue: null` делает оценку неполной, но не
|
Ненулевая позиция с `currentValue: null` делает оценку неполной, но не
|
||||||
даёт нулевой вклад в смысле полной стоимости. `CURRENCY` участвует
|
даёт нулевой вклад в смысле полной стоимости. `CURRENCY` участвует
|
||||||
в суммах, хотя текущий интерфейс скрывает её карточку —
|
в суммах, хотя текущий интерфейс скрывает её карточку —
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Результат инвестирования
|
||||||
|
|
||||||
|
Вкладка «Результат» на странице брокерского счёта и в режиме
|
||||||
|
[«Все счета»](all-accounts.md) отвечает на два вопроса:
|
||||||
|
|
||||||
|
- сколько заработали вложенные деньги;
|
||||||
|
- обогнал ли пользователь рынок.
|
||||||
|
|
||||||
|
Результат считается за всё время истории счёта, только в рублях. Решение и
|
||||||
|
отклонённые альтернативы описаны в
|
||||||
|
[ADR 023](../../adr/023-investment-performance-vs-index.md).
|
||||||
|
|
||||||
|
## Показатели
|
||||||
|
|
||||||
|
| Показатель | Смысл |
|
||||||
|
| --- | --- |
|
||||||
|
| Вложено (нетто) | Сумма пополнений минус сумма выводов рублей |
|
||||||
|
| Прибыль | Текущая стоимость портфеля минус чистые вложения |
|
||||||
|
| Доходность | Ставка XIRR с учётом сумм и дат пополнений и выводов |
|
||||||
|
| Те же деньги в индексе Мосбиржи | Стоимость и доходность тех же пополнений и выводов, вложенных в индекс полной доходности MCFTRR (с дивидендами после налогов) |
|
||||||
|
| Опережение или отставание рынка | Разница доходностей в процентных пунктах и разница стоимостей в рублях |
|
||||||
|
|
||||||
|
Ценовой индекс IMOEX не учитывает дивиденды. Он показан на графике только
|
||||||
|
для справки и в сравнении не участвует.
|
||||||
|
|
||||||
|
Период начинается с первого пополнения, а не с открытия счёта. Если деньги
|
||||||
|
вложены меньше 365 дней, проценты показаны за фактическое число дней и не
|
||||||
|
пересчитываются в годовые.
|
||||||
|
|
||||||
|
## Какие операции считаются потоками
|
||||||
|
|
||||||
|
Внешние потоки — только пополнения и выводы рублей (типы T-Bank `INPUT`,
|
||||||
|
`INPUT_ACQUIRING`, `INPUT_SWIFT`, `INP_MULTI` и соответствующие `OUTPUT`).
|
||||||
|
Сделки, купоны, дивиденды, погашения, налоги и комиссии уже отражены в
|
||||||
|
текущей стоимости и потоками не являются. Учитываются только операции до
|
||||||
|
момента последней полной оценки портфеля.
|
||||||
|
|
||||||
|
## Когда результата нет
|
||||||
|
|
||||||
|
Число не подменяется нулём: вместо него показывается причина.
|
||||||
|
|
||||||
|
| Причина | Когда возникает |
|
||||||
|
| --- | --- |
|
||||||
|
| `HISTORY_START_UNKNOWN` | Неизвестна дата открытия счёта |
|
||||||
|
| `OPERATIONS_HISTORY_INCOMPLETE` | История операций не получена полностью до момента оценки |
|
||||||
|
| `PORTFOLIO_VALUATION_INCOMPLETE` | Нет полной оценки портфеля |
|
||||||
|
| `UNVALUED_SECURITIES_TRANSFER` | Бумаги введены или выведены без денежной оценки |
|
||||||
|
| `UNCONFIRMED_TRANSFER` | В «Все счета» есть похожие на перевод между своими счетами операции, связь которых источник не подтверждает |
|
||||||
|
| `ACCOUNT_VALUATION_DATES_DIFFER` | В «Все счета» последние оценки счетов сделаны в разные московские дни |
|
||||||
|
| `NO_SOLUTION` | Уравнение доходности не имеет решения; прибыль остаётся |
|
||||||
|
| `AMBIGUOUS_RETURN` | Потоки меняют знак больше одного раза, и единственность ставки не доказана; прибыль остаётся |
|
||||||
|
| `INDEX_HISTORY_UNAVAILABLE` | Нет истории индекса за период; прибыль и доходность остаются, сравнения нет |
|
||||||
|
|
||||||
|
В «Все счета» счёт с причиной исключается, а результат помечается
|
||||||
|
неполным со списком исключённых счетов. Если считать не по чему, результат
|
||||||
|
недоступен целиком.
|
||||||
|
|
||||||
|
## График
|
||||||
|
|
||||||
|
На графике показаны ступенчатая линия чистых вложений, стоимость тех же
|
||||||
|
денег в индексе по закрытиям торговых дней, справочная линия индекса без
|
||||||
|
дивидендов и отметка текущей стоимости портфеля на конец периода. Линии
|
||||||
|
прошлой стоимости портфеля нет: такая история пока не хранится.
|
||||||
|
|
||||||
|
Нормативное поведение задаёт change
|
||||||
|
`2026-11-07-investment-performance-vs-index` в репозитории specs, форму
|
||||||
|
ответа — [HTTP API](../../architecture/http-api.md#investment-performance).
|
||||||
@@ -10,9 +10,10 @@
|
|||||||
## Снимок и связанные области
|
## Снимок и связанные области
|
||||||
|
|
||||||
Снимок состоит из позиций по инструментам, доступных денежных остатков,
|
Снимок состоит из позиций по инструментам, доступных денежных остатков,
|
||||||
валютных итогов и структуры активов. Позиция означает ненулевое количество
|
итоговой суммы в RUB и структуры активов. Позиция означает ненулевое количество
|
||||||
обычного инструмента в брокерском портфеле. Торгуемая валютная позиция
|
обычного инструмента в брокерском портфеле. Торгуемая валютная позиция
|
||||||
`CURRENCY` и свободные деньги имеют разный смысл и передаются раздельно.
|
`CURRENCY` и свободные деньги имеют разный смысл и передаются раздельно;
|
||||||
|
в итоге учитываются только деньги в RUB.
|
||||||
Точный смысл сумм и неизвестных значений раскрыт в
|
Точный смысл сумм и неизвестных значений раскрыт в
|
||||||
[справочнике данных](data-reference.md).
|
[справочнике данных](data-reference.md).
|
||||||
|
|
||||||
@@ -29,21 +30,20 @@ Backend получает данные через серверную
|
|||||||
самостоятельно: его ошибка или отсутствие данных не скрывает основной
|
самостоятельно: его ошибка или отсутствие данных не скрывает основной
|
||||||
портфель. Полученные выплаты и прогноз не добавляются к текущей стоимости
|
портфель. Полученные выплаты и прогноз не добавляются к текущей стоимости
|
||||||
повторно и не превращают результат открытой позиции в полную доходность.
|
повторно и не превращают результат открытой позиции в полную доходность.
|
||||||
|
Полную доходность с учётом пополнений и выводов показывает вкладка
|
||||||
|
[«Результат»](investment-performance.md).
|
||||||
|
|
||||||
## Как читать экран
|
## Как читать экран
|
||||||
|
|
||||||
Валютная сводка показывает отдельную карточку для каждого полученного итога.
|
Сводка показывает одну карточку с итоговой суммой в RUB. Деньги уже включены
|
||||||
Деньги уже включены в итог своей валюты. RUB, USD и EUR обозначены ₽, $ и €;
|
в итог. Сумма обозначена ₽; вспомогательным технологиям доступны полное
|
||||||
другие валюты сохраняют ISO-код. Вспомогательным технологиям доступны полное
|
|
||||||
значение и название валюты. Суммы сохраняют все исходные цифры, знак и
|
значение и название валюты. Суммы сохраняют все исходные цифры, знак и
|
||||||
дробные позиции, включая `-0,5`; длинные значения переносятся без обрезания.
|
дробные позиции, включая `-0,5`; длинные значения переносятся без обрезания.
|
||||||
Карточки не интерактивны и занимают одну колонку на узком экране,
|
Карточка не интерактивна. Отсутствующая итоговая сумма не получает искусственный
|
||||||
две или три на широком. Отсутствующая валюта не получает искусственную
|
ноль. Пустой итог не скрывает доступный состав портфеля.
|
||||||
нулевую карточку. Пустые итоги не скрывают доступный состав портфеля.
|
|
||||||
|
|
||||||
Структура после сводки распределяет известную стоимость по акциям,
|
Структура после сводки распределяет известную стоимость по акциям,
|
||||||
облигациям, другим активам и свободным деньгам. При нескольких валютах
|
облигациям, другим активам и свободным деньгам в RUB.
|
||||||
пользователь выбирает одну; при одной отдельного переключателя нет.
|
|
||||||
Кольцевая диаграмма дополнена текстовым списком сумм и долей и подсказкой;
|
Кольцевая диаграмма дополнена текстовым списком сумм и долей и подсказкой;
|
||||||
на узком экране список расположен под ней. Неизвестная оценка, отрицательные
|
на узком экране список расположен под ней. Неизвестная оценка, отрицательные
|
||||||
составляющие или нулевой итог ограничивают возможность показать доли —
|
составляющие или нулевой итог ограничивают возможность показать доли —
|
||||||
@@ -64,17 +64,21 @@ Backend получает данные через серверную
|
|||||||
без логотипа и с подписью результата. Отсутствующие показатели скрываются,
|
без логотипа и с подписью результата. Отсутствующие показатели скрываются,
|
||||||
а не подменяются нулём или заглушкой.
|
а не подменяются нулём или заглушкой.
|
||||||
|
|
||||||
|
Рядом с вкладкой «Позиции» на странице отдельного счёта есть вкладка
|
||||||
|
[«Концентрация»](concentration.md): она показывает, где сконцентрированы
|
||||||
|
деньги — крупнейшие бумаги, секторы и эмитенты. В режиме «Все счета» её нет.
|
||||||
|
|
||||||
Существует расхождение: [согласованная спецификация представления позиций](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-представление-карточек-позиций-на-клиенте)
|
Существует расхождение: [согласованная спецификация представления позиций](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-представление-карточек-позиций-на-клиенте)
|
||||||
требует доступности всех иных типов в отдельной секции, а текущие frontend
|
требует доступности всех иных типов в отдельной секции, а текущие frontend
|
||||||
и его проверка исключают `CURRENCY` только из списка карточек. Такие позиции
|
и его проверка исключают `CURRENCY` только из списка карточек. Такие позиции
|
||||||
остаются в ответе, валютных итогах, структуре и знаменателе долей остальных
|
остаются в ответе, но не входят в итоговую сумму, структуру; их учёт в знаменателе
|
||||||
позиций. Это описание фактического ограничения; выбор между изменением
|
долей остальных позиций требует проверки. Выбор между изменением интерфейса и
|
||||||
интерфейса и согласованием требований остаётся отдельной задачей.
|
согласованием требований остаётся отдельной задачей.
|
||||||
|
|
||||||
## Свежесть и границы
|
## Свежесть и границы
|
||||||
|
|
||||||
При первом запросе экран показывает каркас заголовка, сводки и разделов.
|
При первом запросе экран показывает каркас заголовка, сводки и разделов.
|
||||||
Три формы валютных карточек в каркасе не обещают наличие трёх валют.
|
Каркас итоговой карточки не обещает наличие суммы.
|
||||||
Загрузка обозначена для вспомогательных технологий; декоративные элементы
|
Загрузка обозначена для вспомогательных технологий; декоративные элементы
|
||||||
не содержат данных и не получают фокус. При обычном фоновом обновлении
|
не содержат данных и не получают фокус. При обычном фоновом обновлении
|
||||||
сохраняются предыдущие суммы и время успешного получения в UTC.
|
сохраняются предыдущие суммы и время успешного получения в UTC.
|
||||||
@@ -89,10 +93,9 @@ Backend получает данные через серверную
|
|||||||
Правила времени и ошибок приведены в [потоке загрузки](flows/portfolio-loading.md).
|
Правила времени и ошибок приведены в [потоке загрузки](flows/portfolio-loading.md).
|
||||||
|
|
||||||
Отдельного чтения истории стоимости нет, но каждый полный снимок
|
Отдельного чтения истории стоимости нет, но каждый полный снимок
|
||||||
сохраняет точку оценки по счёту и валюте для будущих поддерживаемых
|
сохраняет точку оценки по счёту в RUB для будущих поддерживаемых
|
||||||
представлений; публичного графика в текущем решении нет. Нет также
|
представлений; публичного графика в текущем решении нет. Нет также
|
||||||
валютной конвертации, учёта виртуальных позиций или заблокированных
|
учёта виртуальных позиций или заблокированных средств. Последний полный снимок сохраняется после перезапуска;
|
||||||
средств. Последний полный снимок сохраняется после перезапуска;
|
|
||||||
обновлением личных данных владеет часовой обход, рассчитанный на один
|
обновлением личных данных владеет часовой обход, рассчитанный на один
|
||||||
экземпляр backend. Действие «Обновить» выполняет только локальное
|
экземпляр backend. Действие «Обновить» выполняет только локальное
|
||||||
перечитывание открытого экрана и не запускает работу с T-Bank.
|
перечитывание открытого экрана и не запускает работу с T-Bank.
|
||||||
|
|||||||
+93
-14
@@ -91,7 +91,7 @@ _Не использовать_: тип аккаунта T-Bank, protobuf type.
|
|||||||
## Portfolio
|
## Portfolio
|
||||||
|
|
||||||
Текущее нормализованное состояние инвестиций одного Brokerage Account,
|
Текущее нормализованное состояние инвестиций одного Brokerage Account,
|
||||||
включающее позиции, доступные денежные остатки и итоги по каждой валюте.
|
включающее позиции, доступный денежный остаток и итоговую сумму в RUB.
|
||||||
|
|
||||||
_Не использовать_: общий портфель, баланс счёта.
|
_Не использовать_: общий портфель, баланс счёта.
|
||||||
|
|
||||||
@@ -119,6 +119,46 @@ Instrument. Она остаётся в `positions` и не объединяет
|
|||||||
|
|
||||||
_Не использовать_: денежный остаток, cash balance.
|
_Не использовать_: денежный остаток, cash balance.
|
||||||
|
|
||||||
|
## Концентрация
|
||||||
|
|
||||||
|
Вкладка страницы одного Brokerage Account, показывающая, какие акции,
|
||||||
|
облигации, секторы и эмитенты занимают наибольшую часть текущей оценки
|
||||||
|
Portfolio в RUB. Отличается от [структуры
|
||||||
|
портфеля](domains/portfolio/data-reference.md#структура-и-доли): в её разрезах
|
||||||
|
деньги не входят в знаменатель долей.
|
||||||
|
|
||||||
|
_Не использовать_: структура портфеля, диверсификация.
|
||||||
|
|
||||||
|
## Разрез
|
||||||
|
|
||||||
|
Одна из четырёх группировок вкладки «Концентрация»: «Акции», «Облигации»,
|
||||||
|
«Секторы», «Эмитенты». Элемент разреза — единица ранжирования; сектор
|
||||||
|
агрегирует позиции `STOCK`, `BOND` и `FUND`, эмитенты — `STOCK` и `BOND`.
|
||||||
|
|
||||||
|
_Не использовать_: фильтр, категория структуры.
|
||||||
|
|
||||||
|
## Сектор
|
||||||
|
|
||||||
|
Значение сектора инструмента в том виде, как его определяет T-Bank, без
|
||||||
|
перекодирования и собственной классификации WealthLedger. Заполняется для
|
||||||
|
позиций `STOCK`, `BOND` и `FUND`; государственные облигации определяются
|
||||||
|
значением `government` с подписью «Государственный сектор». Позиция без
|
||||||
|
сектора попадает в явную группу «Сектор не указан».
|
||||||
|
|
||||||
|
_Не использовать_: отрасль, собственная классификация приложения.
|
||||||
|
|
||||||
|
## Эмитент
|
||||||
|
|
||||||
|
В разрезе «Эмитенты» вкладки «Концентрация» — бренд актива по данным T-Bank,
|
||||||
|
объединяющий акции и облигации одной компании; фонды в разрез не входят.
|
||||||
|
Название эмитента — название бренда. **Оговорка:** в этом разрезе слово
|
||||||
|
означает бренд актива T-Bank, а не юридического эмитента ценной бумаги;
|
||||||
|
[рейтинг выпуска](integrations/nkr.md) не подставляется вместо рейтинга
|
||||||
|
эмитента и наоборот. Позиция без бренда попадает в явную группу
|
||||||
|
«Эмитент не указан».
|
||||||
|
|
||||||
|
_Не использовать_: юридический эмитент, эмитент рейтинга.
|
||||||
|
|
||||||
## Instrument
|
## Instrument
|
||||||
|
|
||||||
Ценная бумага или иной торгуемый актив T-Bank, на который ссылается Portfolio
|
Ценная бумага или иной торгуемый актив T-Bank, на который ссылается Portfolio
|
||||||
@@ -148,8 +188,8 @@ _Не использовать_: аватар актива, иконка бум
|
|||||||
|
|
||||||
## Cash Balance
|
## Cash Balance
|
||||||
|
|
||||||
Ненулевой доступный денежный остаток Portfolio в одной валюте; не является
|
Ненулевой доступный денежный остаток Portfolio в RUB; не является
|
||||||
Portfolio Position и передаётся отдельно от `positions` в `cashBalances`.
|
Portfolio Position и передаётся отдельно от `positions`.
|
||||||
|
|
||||||
_Не использовать_: валютная позиция, заблокированные средства.
|
_Не использовать_: валютная позиция, заблокированные средства.
|
||||||
|
|
||||||
@@ -162,12 +202,13 @@ _Не использовать_: история портфеля, snapshot дл
|
|||||||
|
|
||||||
## Точка истории стоимости портфеля
|
## Точка истории стоимости портфеля
|
||||||
|
|
||||||
Полная оценка одного Brokerage Account в одной валюте на момент успешного
|
Полная оценка одного Brokerage Account в RUB на момент успешного
|
||||||
обновления Portfolio; последовательность таких точек описывает изменение
|
обновления Portfolio; последовательность таких точек описывает изменение
|
||||||
оценки во времени, включая неторговые дни. Не является Portfolio Snapshot
|
оценки во времени, включая неторговые дни. Не является Portfolio Snapshot
|
||||||
или инвестиционной доходностью; отсутствие цены позиции не приравнивается к нулю.
|
или [Результатом инвестирования](#результат-инвестирования); отсутствие цены
|
||||||
|
позиции не приравнивается к нулю.
|
||||||
|
|
||||||
_Не использовать_: снимок состава портфеля, доходность.
|
_Не использовать_: снимок состава портфеля.
|
||||||
|
|
||||||
## Client Cached Snapshot
|
## Client Cached Snapshot
|
||||||
|
|
||||||
@@ -252,8 +293,7 @@ _Не использовать_: активный refresh token, признак
|
|||||||
Прогнозируемое на ближайший период денежное или связанное корпоративное
|
Прогнозируемое на ближайший период денежное или связанное корпоративное
|
||||||
событие одного Brokerage Account, рассчитанное по текущей Portfolio Position;
|
событие одного Brokerage Account, рассчитанное по текущей Portfolio Position;
|
||||||
не является исполненной Ledger Entry. Прогнозная сумма события передаётся как
|
не является исполненной Ledger Entry. Прогнозная сумма события передаётся как
|
||||||
nullable Money: известные coupon, dividend и maturity содержат Money в исходной
|
nullable Money: известные coupon, dividend и maturity содержат Money в RUB, offer или неизвестные денежные условия передаются как `null`.
|
||||||
валюте, offer или неизвестные денежные условия передаются как `null`.
|
|
||||||
В публичном API прогноз доступен через маршруты `/events`; в доменной
|
В публичном API прогноз доступен через маршруты `/events`; в доменной
|
||||||
документации событие называется Future Cash Event.
|
документации событие называется Future Cash Event.
|
||||||
|
|
||||||
@@ -269,10 +309,49 @@ _Не использовать_: upstream dividend type, MOEX row name.
|
|||||||
## Realized Income Analytics
|
## Realized Income Analytics
|
||||||
|
|
||||||
Результат анализа исполненных купонов и дивидендов по счёту за календарный
|
Результат анализа исполненных купонов и дивидендов по счёту за календарный
|
||||||
период включительно в часовом поясе Europe/Moscow. Сохраняет исходные валюты
|
период включительно в часовом поясе Europe/Moscow. Сохраняет знаки денежных выплат,
|
||||||
и знаки денежных выплат, переданных брокером. Это не налоговый расчёт,
|
переданных брокером, в RUB. Это не налоговый расчёт,
|
||||||
прогноз или инвестиционная доходность; правила расчёта объясняет
|
прогноз или [Результат инвестирования](#результат-инвестирования); правила
|
||||||
[область дохода](domains/income/overview.md).
|
расчёта объясняет [область дохода](domains/income/overview.md).
|
||||||
|
|
||||||
_Не использовать_: доходность, общий доход в одной валюте, гарантированный
|
_Не использовать_: доходность выплат, общий доход в нескольких валютах,
|
||||||
доход.
|
гарантированный доход.
|
||||||
|
|
||||||
|
## Результат инвестирования
|
||||||
|
|
||||||
|
Прибыль, доходность и сравнение с индексом Мосбиржи для счёта или «Все
|
||||||
|
счета» за всё время в рублях. Правила описаны в
|
||||||
|
[результате инвестирования](domains/portfolio/investment-performance.md),
|
||||||
|
решение — в [ADR 023](adr/023-investment-performance-vs-index.md).
|
||||||
|
|
||||||
|
_Не использовать_: нереализованный результат, доход.
|
||||||
|
|
||||||
|
## Внешний денежный поток
|
||||||
|
|
||||||
|
Пополнение (положительный поток) или вывод (отрицательный поток) рублей со
|
||||||
|
счёта. Сделки, выплаты, налоги и комиссии внешними потоками не являются.
|
||||||
|
|
||||||
|
_Не использовать_: операция, выплата.
|
||||||
|
|
||||||
|
## Доходность (XIRR)
|
||||||
|
|
||||||
|
Годовая ставка, при которой дисконтированные по фактическим дням внешние
|
||||||
|
потоки и текущая стоимость в сумме дают ноль. При истории короче года
|
||||||
|
показывается доходность за период. Единственное значение термина
|
||||||
|
«доходность» для личного результата.
|
||||||
|
|
||||||
|
_Не использовать_: доходность к погашению, рост цены позиции.
|
||||||
|
|
||||||
|
## Те же деньги в индексе Мосбиржи
|
||||||
|
|
||||||
|
Стоимость и доходность тех же внешних потоков, вложенных в индекс полной
|
||||||
|
доходности MCFTRR по закрытию дня потока. Ценовой IMOEX — только справка.
|
||||||
|
|
||||||
|
_Не использовать_: бенчмарк IMOEX, теневой портфель (в интерфейсе).
|
||||||
|
|
||||||
|
## Опережение рынка
|
||||||
|
|
||||||
|
Разница доходности пользователя и тех же денег в индексе в процентных пунктах
|
||||||
|
и разница стоимостей в рублях; отрицательное значение называется отставанием.
|
||||||
|
|
||||||
|
_Не использовать_: альфа.
|
||||||
|
|||||||
+28
-1
@@ -1,6 +1,7 @@
|
|||||||
# Интеграция с MOEX ISS
|
# Интеграция с MOEX ISS
|
||||||
|
|
||||||
MOEX ISS дополняет данные T-Bank публичной информацией об облигациях.
|
MOEX ISS дополняет данные T-Bank публичной информацией об облигациях и
|
||||||
|
дневными закрытиями индексов Мосбиржи.
|
||||||
Backend получает её по HTTPS в JSON с `iss.moex.com`; запросы содержат
|
Backend получает её по HTTPS в JSON с `iss.moex.com`; запросы содержат
|
||||||
идентификаторы выпуска, без token T-Bank и идентификатора брокерского счёта.
|
идентификаторы выпуска, без token T-Bank и идентификатора брокерского счёта.
|
||||||
MOEX не определяет доступ пользователя к инвестициям и не подтверждает
|
MOEX не определяет доступ пользователя к инвестициям и не подтверждает
|
||||||
@@ -47,6 +48,32 @@ HTTP-запрос ограничен таймаутом. Сеть, неуспе
|
|||||||
[странице облигации](../domains/instruments/bonds.md#получение-данных-и-восстановление).
|
[странице облигации](../domains/instruments/bonds.md#получение-данных-и-восстановление).
|
||||||
Наличие успешного HTTP-ответа не гарантирует котировку без задержки.
|
Наличие успешного HTTP-ответа не гарантирует котировку без задержки.
|
||||||
|
|
||||||
|
## Индексы
|
||||||
|
|
||||||
|
Для [результата инвестирования](../domains/portfolio/investment-performance.md)
|
||||||
|
backend читает дневные закрытия MCFTRR (полная доходность после налогов) и
|
||||||
|
IMOEX (ценовой, справка) из
|
||||||
|
`/iss/history/engines/stock/markets/index/securities/{SECID}.json` с
|
||||||
|
`history.columns=TRADEDATE,CLOSE`, постранично по `history.cursor`.
|
||||||
|
Любая некорректная страница считается сбоем: частичная история не
|
||||||
|
сохраняется.
|
||||||
|
|
||||||
|
Закрытия и подтверждённый диапазон покрытия хранятся локально в SQLite
|
||||||
|
(исключение из ADR 019, см. [ADR 023](../adr/023-investment-performance-vs-index.md)).
|
||||||
|
Догрузка выполняется при чтении результата одной одновременной загрузкой на
|
||||||
|
индекс: расширение диапазона назад — сразу, проверка ещё не опубликованного
|
||||||
|
закрытия и повтор после сбоя — не чаще раза в час. Недоступность
|
||||||
|
MOEX не возвращается как HTTP-ошибка: при достаточной сохранённой истории
|
||||||
|
результат считается по ней, иначе сравнение помечается
|
||||||
|
`INDEX_HISTORY_UNAVAILABLE`. События лога —
|
||||||
|
`integration.moex.index_history.succeeded` и `.failed`, без данных
|
||||||
|
пользователя.
|
||||||
|
|
||||||
|
ISS бесплатно отдаёт данные для ознакомления; приложение личное и не
|
||||||
|
распространяет их, источник указан в пояснении «Как считали».
|
||||||
|
|
||||||
|
## Ссылки
|
||||||
|
|
||||||
Условия обработки источника в прогнозе закреплены в
|
Условия обработки источника в прогнозе закреплены в
|
||||||
[спецификации будущих событий](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-upcoming-events/spec.md#requirement-upcoming-events-use-complete-source-results).
|
[спецификации будущих событий](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/brokerage-account-upcoming-events/spec.md#requirement-upcoming-events-use-complete-source-results).
|
||||||
Точный механизм транспорта, разбора и сопоставления реализован в
|
Точный механизм транспорта, разбора и сопоставления реализован в
|
||||||
|
|||||||
+13
-2
@@ -11,11 +11,20 @@ WealthLedger обращается к Invest API на сервере по gRPC ov
|
|||||||
| Категория | Для чего используется |
|
| Категория | Для чего используется |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Открытые счета | Определить доступный состав счетов и проверить доступ к конкретному счёту |
|
| Открытые счета | Определить доступный состав счетов и проверить доступ к конкретному счёту |
|
||||||
| Портфель и денежные остатки | Показать текущий состав инвестиций и итоги по исходным валютам |
|
| Портфель и денежные остатки | Показать текущий состав инвестиций и итоговую сумму в RUB |
|
||||||
| Исполненные операции | Построить журнал и выделить полученные купоны и дивиденды |
|
| Исполненные операции | Построить журнал и выделить полученные купоны и дивиденды |
|
||||||
| Инструменты и рынок | Имена, идентификаторы, цены, свечи, параметры акций и облигаций |
|
| Инструменты и рынок | Имена, идентификаторы, цены, свечи, параметры акций и облигаций |
|
||||||
|
| Классификация инструментов | Сектор акций, облигаций и фондов и бренд актива для разрезов [концентрации](../domains/portfolio/concentration.md) |
|
||||||
| Купоны и дивиденды | Построить будущие события по текущим позициям и календарь инструмента |
|
| Купоны и дивиденды | Построить будущие события по текущим позициям и календарь инструмента |
|
||||||
|
|
||||||
|
Сектор получается из описаний инструмента (отдельные описания для акций,
|
||||||
|
облигаций и фондов, поиск по UID, затем по FIGI); эмитент — из описания актива
|
||||||
|
по `asset_uid` инструмента: его uid и название бренда. Эмитент не выводится из
|
||||||
|
названия, тикера или ISIN. Классификация хранится как последнее известное
|
||||||
|
значение с обновлением не чаще раза в сутки ([ADR
|
||||||
|
022](../adr/022-stored-instrument-classification.md)); все вызовы проходят
|
||||||
|
через общий лимитер запросов T-Bank.
|
||||||
|
|
||||||
T-Bank определяет исходные данные и права token. Backend проверяет локальную
|
T-Bank определяет исходные данные и права token. Backend проверяет локальную
|
||||||
сессию, выбирает подключение её пользователя и устанавливает доступ к счёту.
|
сессию, выбирает подключение её пользователя и устанавливает доступ к счёту.
|
||||||
Наличие идентификатора счёта в URL этого доступа не подтверждает.
|
Наличие идентификатора счёта в URL этого доступа не подтверждает.
|
||||||
@@ -41,7 +50,9 @@ Backend передаёт имя файла `logoName` из метаданных
|
|||||||
|
|
||||||
Логотипы используются в портфеле, операциях, будущих событиях, поиске и
|
Логотипы используются в портфеле, операциях, будущих событиях, поиске и
|
||||||
страницах инструментов. Отсутствующее имя или ошибка изображения оставляют
|
страницах инструментов. Отсутствующее имя или ошибка изображения оставляют
|
||||||
буквенную заглушку и не меняют финансовые значения. Правило построения URL
|
буквенную заглушку и не меняют финансовые значения. Логотип — это metadata
|
||||||
|
инструмента; он не равен эмитенту из [концентрации](../domains/portfolio/concentration.md),
|
||||||
|
который берётся из бренда актива. Правило построения URL
|
||||||
принадлежит [форматированию frontend](https://git.personal.ksv741.ru/WealthLedger/frontend/src/commit/9f7e342333b80bfacfd5bc394a2dcd0613d33ff3/src/shared/lib/display.ts).
|
принадлежит [форматированию frontend](https://git.personal.ksv741.ru/WealthLedger/frontend/src/commit/9f7e342333b80bfacfd5bc394a2dcd0613d33ff3/src/shared/lib/display.ts).
|
||||||
|
|
||||||
## Проверка и сохранение подключения
|
## Проверка и сохранение подключения
|
||||||
|
|||||||
+9
-6
@@ -19,7 +19,8 @@ WealthLedger — локальное приложение для частного
|
|||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Найти свой инвестиционный счёт | [Список счетов](domains/accounts/overview.md), их типы и доступные сводки |
|
| Найти свой инвестиционный счёт | [Список счетов](domains/accounts/overview.md), их типы и доступные сводки |
|
||||||
| Вести банковские карты | [Ручной учёт](domains/cards/overview.md): независимые балансы, расходы, пополнения, переводы, возвраты и месячные сводки |
|
| Вести банковские карты | [Ручной учёт](domains/cards/overview.md): независимые балансы, расходы, пополнения, переводы, возвраты и месячные сводки |
|
||||||
| Понять текущий состав инвестиций | [Портфель](domains/portfolio/overview.md): позиции, денежные остатки и итоги по валютам |
|
| Понять текущий состав инвестиций | [Портфель](domains/portfolio/overview.md): позиции, денежные остатки и итоговая сумма в RUB |
|
||||||
|
| Увидеть, где сконцентрированы деньги | [Концентрация](domains/portfolio/concentration.md): крупнейшие бумаги, секторы и эмитенты счёта |
|
||||||
| Разобрать уже совершённые движения | [Журнал операций](domains/operations/overview.md): исполненные операции с фильтрами и последовательной загрузкой истории |
|
| Разобрать уже совершённые движения | [Журнал операций](domains/operations/overview.md): исполненные операции с фильтрами и последовательной загрузкой истории |
|
||||||
| Посчитать полученные выплаты | [Пассивный доход](domains/income/overview.md): исполненные купоны и дивиденды за календарный период |
|
| Посчитать полученные выплаты | [Пассивный доход](domains/income/overview.md): исполненные купоны и дивиденды за календарный период |
|
||||||
| Посмотреть ожидаемые события | [Будущие выплаты](domains/income/upcoming-events.md): купоны, дивиденды, погашения и оферты по текущим позициям |
|
| Посмотреть ожидаемые события | [Будущие выплаты](domains/income/upcoming-events.md): купоны, дивиденды, погашения и оферты по текущим позициям |
|
||||||
@@ -40,12 +41,14 @@ WealthLedger — локальное приложение для частного
|
|||||||
|
|
||||||
Портфель отвечает на вопрос «что есть сейчас», журнал — «что исполнено»,
|
Портфель отвечает на вопрос «что есть сейчас», журнал — «что исполнено»,
|
||||||
аналитика дохода — «какие выплаты уже получены», будущие события — «что
|
аналитика дохода — «какие выплаты уже получены», будущие события — «что
|
||||||
ожидается». Прогноз не подтверждает фактическое зачисление. Полученные купоны
|
ожидается», [результат инвестирования](domains/portfolio/investment-performance.md) —
|
||||||
и дивиденды не равны инвестиционной доходности или результату после налогов.
|
«как сработали вложенные деньги и обогнал ли я индекс Мосбиржи». Прогноз не
|
||||||
|
подтверждает фактическое зачисление. Полученные купоны и дивиденды сами по
|
||||||
|
себе не равны доходности или результату после налогов.
|
||||||
|
|
||||||
Денежная сумма всегда относится к одной валюте. Недоступное значение
|
Система работает только с рублями (RUB): данные в других валютах отфильтровываются
|
||||||
отличается от нуля, а объединение счетов не означает автоматическую
|
при получении из T-Bank и MOEX и не участвуют в итогах. Недоступное значение
|
||||||
конвертацию всех валют. Краткие определения собраны в [глоссарии](glossary.md).
|
отличается от нуля, а объединение счетов не означает конвертацию. Краткие определения собраны в [глоссарии](glossary.md).
|
||||||
|
|
||||||
## Источники и границы продукта
|
## Источники и границы продукта
|
||||||
|
|
||||||
|
|||||||
Generated
+218
-711
File diff suppressed because it is too large
Load Diff
+16
-13
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"name": "wealth-ledger-docs",
|
"name": "wealth-ledger-docs",
|
||||||
"version": "0.1.5",
|
"version": "0.1.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "24.21.0"
|
"node": "24.22.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "markdownlint --dot --rules .markdownlint-rule-relative-links.cjs --ignore node_modules --ignore CHANGELOG.md -- \"**/*.md\" && markdownlint --config .markdownlint-changelog.json --rules .markdownlint-rule-relative-links.cjs -- CHANGELOG.md",
|
"lint": "markdownlint --dot --rules .markdownlint-rule-relative-links.cjs --ignore node_modules --ignore CHANGELOG.md -- \"**/*.md\" && markdownlint --config .markdownlint-changelog.json --rules .markdownlint-rule-relative-links.cjs -- CHANGELOG.md",
|
||||||
@@ -13,23 +13,26 @@
|
|||||||
"commitlint": "commitlint"
|
"commitlint": "commitlint"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "21.2.2",
|
"@commitlint/cli": "21.2.4",
|
||||||
"@commitlint/config-conventional": "21.2.2",
|
"@commitlint/config-conventional": "21.2.4",
|
||||||
"@release-it/conventional-changelog": "12.0.0",
|
"@release-it/conventional-changelog": "12.0.2",
|
||||||
"conventional-changelog-conventionalcommits": "10.4.0",
|
"conventional-changelog-conventionalcommits": "10.4.1",
|
||||||
"markdownlint-cli": "0.49.1",
|
"markdownlint-cli": "0.49.1",
|
||||||
"markdownlint-rule-relative-links": "5.1.3",
|
"markdownlint-rule-relative-links": "5.1.4",
|
||||||
"release-it": "21.0.2"
|
"release-it": "21.1.1"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"overrides": {
|
||||||
"katex": "0.19.0",
|
"fast-uri": "3.1.9",
|
||||||
|
"katex": "0.19.1",
|
||||||
"markdownlint-cli@0.49.1": {
|
"markdownlint-cli@0.49.1": {
|
||||||
"js-yaml": "5.4.2",
|
"js-yaml": "5.4.2",
|
||||||
"smol-toml": "1.9.0"
|
"minimatch": "11.0.2",
|
||||||
|
"smol-toml": "1.9.1"
|
||||||
},
|
},
|
||||||
"release-it": {
|
"release-it": {
|
||||||
"basic-ftp": "6.2.1",
|
"basic-ftp": "6.2.3",
|
||||||
"undici": "7.29.1"
|
"undici": "7.30.1"
|
||||||
}
|
},
|
||||||
|
"markdown-it": "15.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+30
-1
@@ -2,7 +2,8 @@
|
|||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": [
|
"extends": [
|
||||||
"config:recommended",
|
"config:recommended",
|
||||||
":semanticCommitTypeAll(chore)"
|
":semanticCommitTypeAll(chore)",
|
||||||
|
"security:minimumReleaseAgeNpm"
|
||||||
],
|
],
|
||||||
"timezone": "Europe/Moscow",
|
"timezone": "Europe/Moscow",
|
||||||
"labels": [
|
"labels": [
|
||||||
@@ -10,6 +11,13 @@
|
|||||||
],
|
],
|
||||||
"dependencyDashboard": true,
|
"dependencyDashboard": true,
|
||||||
"rangeStrategy": "pin",
|
"rangeStrategy": "pin",
|
||||||
|
"prConcurrentLimit": 5,
|
||||||
|
"lockFileMaintenance": {
|
||||||
|
"enabled": true,
|
||||||
|
"schedule": [
|
||||||
|
"before 4am on the first day of the month"
|
||||||
|
]
|
||||||
|
},
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": [
|
"matchUpdateTypes": [
|
||||||
@@ -18,6 +26,27 @@
|
|||||||
],
|
],
|
||||||
"groupName": "non-major dependencies"
|
"groupName": "non-major dependencies"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"github-actions"
|
||||||
|
],
|
||||||
|
"matchUpdateTypes": [
|
||||||
|
"minor",
|
||||||
|
"patch"
|
||||||
|
],
|
||||||
|
"groupName": "non-major github actions"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"matchManagers": [
|
||||||
|
"docker-compose",
|
||||||
|
"dockerfile"
|
||||||
|
],
|
||||||
|
"matchUpdateTypes": [
|
||||||
|
"minor",
|
||||||
|
"patch"
|
||||||
|
],
|
||||||
|
"groupName": "non-major container images"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"matchUpdateTypes": [
|
"matchUpdateTypes": [
|
||||||
"major"
|
"major"
|
||||||
|
|||||||
Reference in New Issue
Block a user