10 Commits
Author SHA1 Message Date
codex-bot f504a0f566 docs: investment performance vs Moscow Exchange index (WealthLedger/main#54) (#67)
Docs security / security (push) Successful in 7s
Docs verify / verify (push) Successful in 11s
2026-11-08 16:49:39 +03:00
ksv741 364f6bd8d0 chore(release): 0.1.8
Conventional commits / commits (pull_request) Successful in 10s
Docs security / security (pull_request) Successful in 6s
Docs verify / verify (pull_request) Successful in 9s
Docs security / security (push) Successful in 6s
Docs verify / verify (push) Successful in 10s
2026-11-06 07:47:24 +03:00
codex-bot 6d7d4c7b28 chore(deps): set Renovate release age, PR limit and update groups (WealthLedger/main#6) (#64)
Docs security / security (push) Successful in 6s
Docs verify / verify (push) Successful in 10s
2026-11-03 14:07:41 +03:00
ksv741 40ea47a7c2 chore(release): 0.1.7
Conventional commits / commits (pull_request) Successful in 10s
Docs security / security (pull_request) Successful in 7s
Docs verify / verify (pull_request) Successful in 12s
Docs security / security (push) Successful in 8s
Docs verify / verify (push) Successful in 11s
2026-11-01 19:33:26 +03:00
codex-bot 37430da4c9 docs: describe concentration tab and stored instrument classification (WealthLedger/main#48) (#60)
Docs security / security (push) Successful in 7s
Docs verify / verify (push) Successful in 11s
2026-11-01 19:29:01 +03:00
codex-bot abe5b16241 chore(deps): resolve markdownlint audit advisory (WealthLedger/main#49) (#61)
Docs security / security (push) Successful in 7s
Docs verify / verify (push) Successful in 11s
2026-11-01 19:13:01 +03:00
codex-bot dcb528fa9f docs: describe all-account row grouping (WealthLedger/main#47) (#59)
Docs security / security (push) Successful in 6s
Docs verify / verify (push) Successful in 9s
2026-10-30 07:28:25 +03:00
ksv741 8c6c2f84ce chore(release): 0.1.6
Conventional commits / commits (pull_request) Successful in 12s
Docs security / security (pull_request) Successful in 8s
Docs verify / verify (pull_request) Successful in 12s
Docs security / security (push) Successful in 7s
Docs verify / verify (push) Successful in 13s
2026-10-24 19:15:05 +03:00
renovate-bot f9098d8409 chore(deps): update non-major dependencies (WealthLedger/docs#56)
Docs security / security (push) Successful in 8s
Docs verify / verify (push) Successful in 12s
Co-authored-by: renovate-bot <renovate-bot@ksv741.ru>
2026-10-24 19:04:54 +03:00
codex-bot 4216eb815f chore: bump Node to 24.22.1 (WealthLedger/backend#122)
Docs security / security (push) Successful in 8s
Docs verify / verify (push) Successful in 13s
2026-10-23 16:20:01 +03:00
27 changed files with 843 additions and 753 deletions
+1 -1
View File
@@ -1 +1 @@
24.21.0
24.22.1
+24
View File
@@ -1,5 +1,29 @@
# 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)
### Documentation
+1 -1
View File
@@ -30,7 +30,7 @@ WealthLedger помогает частному инвестору понимат
| [Аутентификация](domains/authentication/overview.md) | Регистрация, вход, восстановление и завершение сессии |
| [Счета](domains/accounts/overview.md) | Доступные счета, сводки и состояния каждого счёта |
| [Банковские карты](domains/cards/overview.md) | Ручные остатки, операции, категории, возвраты, месячные сводки и исправления |
| [Портфель](domains/portfolio/overview.md) | Позиции, остатки, суммы, структура и свежесть |
| [Портфель](domains/portfolio/overview.md) | Позиции, остатки, суммы, структура, [концентрация](domains/portfolio/concentration.md) и свежесть |
| [Все счета](domains/portfolio/all-accounts.md) | Общий портфель, происхождение строк и сводные разделы |
| [Операции](domains/operations/overview.md) | Исполненные операции, фильтры и пагинация |
| [Доход](domains/income/overview.md) | Полученные купоны и дивиденды, периоды и состав расчёта |
@@ -2,7 +2,10 @@
**Status:** Accepted. Заменяет request-driven, manual-refresh и
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
@@ -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.** Счёт с потоками или стоимостью в другой валюте не
рассчитывается (причина `NON_RUB_ACTIVITY`); конвертация валют не
выполняется.
- **Период** начинается с первого внешнего потока, не с открытия счёта.
Короче года — «за N дн.» без annualization; `basis = annual` только если
деньги вложены от 365 дней.
- **Хранение закрытий индексов.** Пара (индекс, торговый день по Москве) →
CLOSE хранится локально с upsert. Это исключение из ADR 019: публичная
история индекса, не привязанная к пользователю или подключению, хранится
как долговременные данные. Остальные справочные сведения ADR 019 не
меняются.
### Отклонённые варианты
- **Простой ROI** (`стоимость / вложено − 1`): искажён моментами пополнений
и выводов, поэтому не сравнивается с индексом на тех же деньгах.
- **TWR (time-weighted return):** требует стоимости портфеля на каждую дату
потока; история оценок в системе отсутствует. Сохранение такой истории
вне этого решения.
- **Ценовой IMOEX как ориентир:** не учитывает дивиденды и купоны, поэтому
сравнение с портфелем, где они учтены, смещено.
- **Конвертация валют (FX):** потребовала бы исторических курсов и
отдельного решения о методике; не нужна для личного RUB-учёта.
## Consequences
- Результат зависит от сохранённых операций T-Bank и последнего полного
Portfolio: неполная история или неполная оценка дают `data: null` или
`completeness: incomplete` по правилам change, а не подменяются оценкой.
- Первая загрузка индекса догружает историю от `from − 10 дней`; при
недостатке закрытий появляется `INDEX_HISTORY_UNAVAILABLE`. Фоновая
синхронизация индексов не вводится.
- Исключение из ADR 019 ограничено закрытиями индексов MOEX.
### Оговорки и условия источника
- **Налоги.** MCFTRR при расчёте дивидендов и купонов использует ставки для
организаций, а не НДФЛ физического лица. Индекс — ориентир альтернативы,
а не точная модель налогов пользователя. Оговорка фиксируется в методике
(«Как считали»).
- **Данные MOEX ISS.** ISS бесплатно отдаёт данные «для ознакомления».
Приложение личное и локальное, данные не распространяются; источник
указывается в «Как считали».
- **Переводы между счетами.** Совпадение суммы и времени операций ещё не
доказывает внутренний перевод. Пока нет подтверждённой связи, такие счета
исключаются из рассчитанной части «Все счета» с явной причиной неполноты.
- **Несколько решений 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)
+2
View File
@@ -26,3 +26,5 @@
- [019 — Часовой обход и онлайн-справочник инструментов](019-hourly-reads-and-online-instrument-reference.md)
- [020 — Evidence for hourly sync read boundaries](020-hourly-sync-verification-evidence.md)
- [021 — Тихое чтение и редкие подтверждения](021-quiet-reading-and-rare-confirmations.md)
- [022 — Хранимая классификация инструментов T-Bank](022-stored-instrument-classification.md)
- [023 — Результат инвестирования относительно индекса Мосбиржи](023-investment-performance-vs-index.md)
+6 -1
View File
@@ -141,13 +141,18 @@ membership текущей revision перед каждым финансовым
SQLite хранит полный последний portfolio, операции и их подтверждённые
диапазоны, private прогнозы, сохранённые точки истории оценки, общие
instrument/market sources и intent/staging.
instrument/market sources, классификацию инструментов (сектор и бренд актива
как последнее известное значение с временем каждого получения,
`TbankInstrumentClassification`) и intent/staging.
Нормализованные финансовые значения сохраняются decimal-строками. Полнота
отделена от свежести и пагинации. Ответ не ждёт внешних RPC; обновлением
личных данных владеет часовой обход в том же backend process через
существующий лимитер, недостающие общие источники он же ставит в фоновую
очередь. На startup обход начинает следующую попытку по обычному часовому
сроку; после нового подключения первая попытка начинается сразу.
Классификация — публичные данные без привязки к пользователю и подключению;
её поля обновляются в том же обходе не чаще раза в сутки
([ADR 022](../adr/022-stored-instrument-classification.md)).
Подробности — [модель свежести](cross-cutting/data-freshness.md).
PUT подключения сначала проверяет token у T-Bank, затем одной транзакцией
+2 -1
View File
@@ -31,7 +31,8 @@ WealthLedger нормализует их для просмотра и сопос
информацией об инструментах. [Интеграция T-Bank](../integrations/tbank.md)
объясняет полномочия подключения и ограничения внешней зависимости.
[MOEX ISS](../integrations/moex.md) поставляет публичные параметры и календарь выпусков облигаций.
[MOEX ISS](../integrations/moex.md) поставляет публичные параметры и календарь выпусков облигаций,
а также дневные закрытия индексов Мосбиржи для сравнения результата.
[Реестр НКР](../integrations/nkr.md) используется для поиска кредитного рейтинга конкретного выпуска;
рейтинг эмитента не подставляется вместо него. Отсутствие подходящей записи
и недоступность источника имеют разный смысл. Правила интерпретации этих
+10 -3
View File
@@ -8,8 +8,12 @@ T-Bank. Нормальным владельцем обновления служ
простоя выполняется не более одна актуальная попытка, а перекрывающийся срок
пропускается, не ставится в очередь. Общие справочные данные инструментов
запрашиваются онлайн, когда это требуется карточке; финансовый HTTP-ответ не
ждёт T-Bank. Модель принята в
[ADR 019](../../adr/019-hourly-reads-and-online-instrument-reference.md).
ждёт T-Bank. Единственное исключение — сектор и бренд актива позиции, которые
хранятся как последнее известное значение с обновлением не чаще раза в сутки;
свежесть и полнота 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 и не
состояние часового обхода. SQLite независимо от браузера хранит membership,
последний полный portfolio, исполненные операции, прогнозы, общие сведения об
инструментах, котировки, свечи и календари.
инструментах и классификацию инструментов (сектор и бренд актива как
последнее известное значение, [ADR
022](../../adr/022-stored-instrument-classification.md)), котировки, свечи и
календари.
[Полнота периода](../../glossary.md#полнота-истории-счёта) и свежесть различаются.
Успешно проверенный пустой результат полон и доступен; последняя страница
+10
View File
@@ -72,6 +72,16 @@ Envelope несовместим с прежними bare-array ответами:
backend-generated OpenAPI; frontend получает её обновлённый snapshot отдельно.
Точную семантику поведения описывает [доход](../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
Backend преобразует и проверяет входные данные на общей HTTP-границе.
+3 -3
View File
@@ -54,7 +54,7 @@
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
- Итоги, временные интервалы и разбиение по инструментам не смешивают валюты и не создают общий конвертированный итог. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
- Раздел «Выплаты» показывает единый список карточек выплат в исходном порядке `entries`: одна карточка на каждую выплату. Внешних групп по инструментам или валютам, итогов и количества выплат инструмента нет. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой карточке; валюты разделены в итогах. Дополнительный запрос за составом не нужен.
- Раздел «Выплаты» показывает карточки выплат в исходном порядке `entries`. В отдельном счёте каждая выплата — отдельная карточка. В режиме «Все счета» выплаты одного инструмента, дня и точного типа образуют группу, если их две и более ([правила группировки](../operations/overview.md#группировка-в-режиме-все-счета)). Группа стоит на месте первой выплаты; каждая строка счёта показывает название счёта и свою сумму со знаком. Визуальный итог группы — точная сумма по валютам по показанным выплатам; он скрыт, если полнота периода не `complete`, или у выплаты нет суммы, или сумма равна нулю. Это клиентский расчёт и не заменяет серверные итоги аналитики дохода, которые по-прежнему приходят из ответа API и не пересчитываются. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой выплате. Дополнительный запрос за составом не нужен.
## Полнота и принадлежность выплат
@@ -80,7 +80,7 @@ Backend обеспечивает принадлежность выплат, ва
доверяет типизированному contract, не восстанавливает формулу идентификации
и не выполняет второй consistency validator. Полностью пустой ответ допустим.
Состав и исходный серверный порядок записей и знак сумм
сохраняются, frontend не пересчитывает денежные итоги. Стабильный ID в пределах подключения и счёта определяет одну операцию:
сохраняются; серверные денежные итоги frontend не пересчитывает (визуальный итог группы в режиме «Все счета» отдельный, см. выше). Стабильный 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),
точная форма ответа — в [HTTP API](../../architecture/http-api.md).
+10 -1
View File
@@ -71,7 +71,16 @@
без замены периода и без запуска личной работы.
Фильтрация на сервере предшествует сортировке и вычислению
`incomeTotalsByCurrency`, включающего только купоны и дивиденды.
Итоги остаются в ответе API; полный экран показывает список без общего итога.
Итоги остаются в ответе API; полный экран показывает список без общего итога списка.
В режиме «Все счета» события одного инструмента, даты, точного типа и `dateKind` образуют
группу, если их две и более, в том числе одного счёта. Ключ дополнительно включает `dateKind`,
поэтому дата реестра дивиденда и иная дата того же инструмента не объединяются. Группа стоит на месте первого
события. Полный список группирует все полученные события; превью обзора сначала берёт пять
событий и группирует только их. Каждая строка счёта остаётся отдельной и показывает название
счёта и свою прогнозную сумму. Визуальный итог группы — точная сумма по валютам; он показывается
только если полнота прогноза `complete` и у каждого события группы известна прогнозная сумма.
Иначе итог скрыт, а строки остаются. Этот итог не равен итогам ответа API и не относится к полученному доходу.
## Получение и отказы
+21 -3
View File
@@ -13,9 +13,27 @@
Исполненная операция содержит тип события, его категорию, описание,
момент совершения, доступные сведения об инструменте и денежное движение.
Запросы отменённых или ожидающих исполнения поручений не образуют этот журнал.
Суммы остаются точными десятичными строками в исходной валюте; frontend
только форматирует их. Положительное и отрицательное движение сохраняют
знак. Отсутствие `payment` означает «Без движения денег», а не нулевую сумму.
Суммы остаются точными десятичными строками в исходной валюте. Frontend
форматирует их и считает визуальный итог группы по показанным записям
(см. [группировку](#группировка-в-режиме-все-счета)). Положительное и отрицательное
движение сохраняют знак. Отсутствие `payment` означает «Без движения денег», а не нулевую сумму.
## Группировка в режиме «Все счета»
Только в режиме `all` записи журнала и превью обзора, которые относятся к одному
дню экрана, одному инструменту и точному типу операции, объединяются в группу.
Ключом служат день, `instrumentUid` (иначе `figi`) и тип; группа образуется при
двух и более записях, в том числе одного счёта. Группа стоит на месте первой записи.
Каждая запись остаётся отдельной строкой с названием счёта простым текстом и своей суммой.
Одиночный счёт не группируется.
Группировка выполняется после лимита: превью обзора сначала берёт пять записей,
затем группирует только их. Полный журнал группирует страницу, уже загруженную
курсором; группы не переносятся между страницами. Курсор и порядок записей не меняются.
Итог группы — точная сумма по каждой валюте, без конвертации. Он показывается только
если полнота журнала `complete`, у каждой записи группы есть `payment`, и ни одна сумма
не равна нулю. Иначе итог скрыт, а строки счетов остаются.
Категории объединяют разные события для фильтрации: сделка (`trade`),
доход (`income`), налог (`tax`), комиссия (`fee`), перевод (`transfer`)
+12
View File
@@ -59,6 +59,12 @@ Backend публикует статические маршруты под `/api/
состав счетов влияет только на фактические выплаты выбранного периода.
- Будущие события сортируются по дате и сохраняют отдельную строку каждого счёта.
Прогноз не включается в реализованные доходы.
- [Результат инвестирования](investment-performance.md) складывает потоки и
стоимость только рублёвых счетов с полной историей. Счёт с причиной
недоступности исключается, сводка помечается неполной. Похожие на перевод
между своими счетами операции без подтверждённой связи исключают оба счёта
(`UNCONFIRMED_TRANSFER`). Если оценки оставшихся счетов сделаны в разные
московские дни, сводка недоступна: стоимости разных дат не складываются.
## Полнота, свежесть и доступ
@@ -81,6 +87,12 @@ Backend публикует статические маршруты под `/api/
применённые фильтры. Coverage/status без изменения строк не ломают cursor.
Продолжение не зависит от RAM-кэша или перезапуска.
Визуальная группировка строк одного инструмента в общих списках выполняется только
в пределах уже полученного списка: в журнале — на загруженной странице, без переноса группы
на следующую; в полном списке будущих событий и выплатах дохода — по всем полученным строкам
периода. Группировка не меняет порядок, cursor или ответ API. Протокол курсора прежний.
Правила группировки — в [журнале](../operations/overview.md#группировка-в-режиме-все-счета).
Повторная сверка полного показанного периода публикует все счета и интервалы
одной транзакцией; успешное первое окно не смешивается с прежними остальными.
Подробнее — [журнал](../operations/overview.md#получение-и-полнота).
+81
View File
@@ -0,0 +1,81 @@
# Концентрация портфеля
Вкладка «Концентрация» на странице счёта `/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 %». Отрицательные и нулевые стоимости, а также
позиции без оценки в разрез не входят. Конвертации валют нет: каждая позиция
входит только в валюту своей оценки.
## Валюта
У вкладки свой список валют — валюты оценок позиций акций, облигаций и фондов,
отсортированные по ISO-коду, — и свой выбор, независимый от «Структуры
портфеля». По умолчанию выбрана первая валюта списка. При одной валюте
переключатель не показывается. Общего итога по нескольким валютам нет.
Выбранные разрез и валюта сохраняются, пока пользователь остаётся на странице
счёта, включая переключение её вкладок, и сбрасываются при новом заходе и при
смене счёта.
## Диаграмма и неполные данные
Рядом с перечнем показана кольцевая диаграмма, согласованная с перечнем;
информация передаётся не только цветом, есть текстовый эквивалент. Если ответ
отмечен как неполный (`completeness: "incomplete"` — часть позиций не имеет
оценки), над разрезом появляется предупреждение «Данные неполные», а под
списком — сноска «Не учтено позиций: N» с числом позиций, не вошедших в разрез.
Пустой разрез (нет позиций с положительной оценкой в выбранной валюте)
показывает текстовое состояние вместо диаграммы.
## Откуда берутся сектор и эмитент
Сектор и эмитент — часть данных Portfolio: их получает backend в часовом
обходе и сохраняет в снимке вместе с остальными полями позиций
([поток загрузки](flows/portfolio-loading.md#обновление-сектора-и-эмитента),
[интеграция T-Bank](../../integrations/tbank.md)). Вкладка считается по уже
загруженному снимку и не обращается к T-Bank.
+16
View File
@@ -33,6 +33,8 @@
| `totalsByCurrency` | Стоимости позиций + доступные деньги той же валюты | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
| `lastSuccessfulAt` | Время формирования успешного снимка, UTC | Не является временем каждой котировки; запасной снимок сохраняет исходное время |
| `isStale` | Истёк часовой срок свежести сохранённого portfolio source | Не описывает состояние клиентского кэша или ошибку фонового запроса |
| `sector` | Сектор инструмента в том виде, как его определяет T-Bank, с обрезанными пробелами | Только для позиций `STOCK`, `BOND` и `FUND`; значение из одних пробел считается отсутствующим. Во всех остальных случаях — `null` |
| `issuer` | Бренд актива инструмента по данным T-Bank: `{ id, name }` | Только для позиций `STOCK`, `BOND` и `FUND`, когда у актива известны uid и название бренда. Во всех остальных случаях — `null`. Не влияет на количество, стоимость и свежесть снимка; используется вкладкой [«Концентрация»](concentration.md) |
Ненулевые денежные остатки одной валюты суммируются. Позиции одинаковых
инструментов в ответе отдельного счёта не объединяются; визуальная группировка
@@ -44,6 +46,18 @@
отдельного счёта не создают валютные карточки. Если `totalsByCurrency` пуст,
но позиции или деньги присутствуют, это не пустой портфель.
## Результат инвестирования
| Поле | Смысл | Ограничение |
| --- | --- | --- |
| `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).
## Идентификация и оформление инструмента
UID определяет конкретный инструмент брокера и используется для перехода
@@ -58,6 +72,8 @@ ISIN, тикер и `logoName` могут быть `null`. `logoName` — имя
или метаданных не меняет количество, суммы и свежесть снимка и не скрывает
финансовые данные. Metadata обновляется независимо; отсутствие имени не задерживает выдачу
финансового снимка и оставляет доступный идентификатор.
`logoName` не равен эмитенту из вкладки «Концентрация»: он берётся из metadata
инструмента, а эмитент — из [классификации инструмента](flows/portfolio-loading.md#обновление-сектора-и-эмитента).
## Структура и доли
+22 -3
View File
@@ -11,9 +11,28 @@
они не ждут и не вызывают T-Bank и не предлагают ручную синхронизацию. Часовой
обход текущего подключения обновляет Portfolio независимо от экрана. Для нового
полного snapshot ему нужны оба финансовых ответа `GetPortfolio` и
`GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента
дополняет представление независимо, с доступным UID/FIGI вместо имени до её
онлайн-загрузки.
`GetPositions`; суммы и позиции публикуются вместе. Metadata инструмента и
классификация (сектор и эмитент) дополняют представление независимо,
с доступным 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` означает, что
@@ -0,0 +1,68 @@
# Результат инвестирования
Вкладка «Результат» на странице брокерского счёта и в режиме
[«Все счета»](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` | Нет полной оценки портфеля |
| `NON_RUB_ACTIVITY` | Есть потоки или остатки не в рублях |
| `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).
+6
View File
@@ -29,6 +29,8 @@ Backend получает данные через серверную
самостоятельно: его ошибка или отсутствие данных не скрывает основной
портфель. Полученные выплаты и прогноз не добавляются к текущей стоимости
повторно и не превращают результат открытой позиции в полную доходность.
Полную доходность с учётом пополнений и выводов показывает вкладка
[«Результат»](investment-performance.md).
## Как читать экран
@@ -64,6 +66,10 @@ Backend получает данные через серверную
без логотипа и с подписью результата. Отсутствующие показатели скрываются,
а не подменяются нулём или заглушкой.
Рядом с вкладкой «Позиции» на странице отдельного счёта есть вкладка
[«Концентрация»](concentration.md): она показывает, где сконцентрированы
деньги — крупнейшие бумаги, секторы и эмитенты. В режиме «Все счета» её нет.
Существует расхождение: [согласованная спецификация представления позиций](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-представление-карточек-позиций-на-клиенте)
требует доступности всех иных типов в отдельной секции, а текущие frontend
и его проверка исключают `CURRENCY` только из списка карточек. Такие позиции
+86 -6
View File
@@ -119,6 +119,46 @@ Instrument. Она остаётся в `positions` и не объединяет
_Не использовать_: денежный остаток, cash balance.
## Концентрация
Вкладка страницы одного Brokerage Account, показывающая, какие акции,
облигации, секторы и эмитенты занимают наибольшую часть текущей оценки
Portfolio, без валютной конвертации. Отличается от [структуры
портфеля](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
Ценная бумага или иной торгуемый актив T-Bank, на который ссылается Portfolio
@@ -165,9 +205,10 @@ _Не использовать_: история портфеля, snapshot дл
Полная оценка одного Brokerage Account в одной валюте на момент успешного
обновления Portfolio; последовательность таких точек описывает изменение
оценки во времени, включая неторговые дни. Не является Portfolio Snapshot
или инвестиционной доходностью; отсутствие цены позиции не приравнивается к нулю.
или [Результатом инвестирования](#результат-инвестирования); отсутствие цены
позиции не приравнивается к нулю.
_Не использовать_: снимок состава портфеля, доходность.
_Не использовать_: снимок состава портфеля.
## Client Cached Snapshot
@@ -271,8 +312,47 @@ _Не использовать_: upstream dividend type, MOEX row name.
Результат анализа исполненных купонов и дивидендов по счёту за календарный
период включительно в часовом поясе Europe/Moscow. Сохраняет исходные валюты
и знаки денежных выплат, переданных брокером. Это не налоговый расчёт,
прогноз или инвестиционная доходность; правила расчёта объясняет
[область дохода](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
View File
@@ -1,6 +1,7 @@
# Интеграция с MOEX ISS
MOEX ISS дополняет данные T-Bank публичной информацией об облигациях.
MOEX ISS дополняет данные T-Bank публичной информацией об облигациях и
дневными закрытиями индексов Мосбиржи.
Backend получает её по HTTPS в JSON с `iss.moex.com`; запросы содержат
идентификаторы выпуска, без token T-Bank и идентификатора брокерского счёта.
MOEX не определяет доступ пользователя к инвестициям и не подтверждает
@@ -47,6 +48,32 @@ HTTP-запрос ограничен таймаутом. Сеть, неуспе
[странице облигации](../domains/instruments/bonds.md#получение-данных-и-восстановление).
Наличие успешного 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).
Точный механизм транспорта, разбора и сопоставления реализован в
+12 -1
View File
@@ -14,8 +14,17 @@ WealthLedger обращается к Invest API на сервере по gRPC ov
| Портфель и денежные остатки | Показать текущий состав инвестиций и итоги по исходным валютам |
| Исполненные операции | Построить журнал и выделить полученные купоны и дивиденды |
| Инструменты и рынок | Имена, идентификаторы, цены, свечи, параметры акций и облигаций |
| Классификация инструментов | Сектор акций, облигаций и фондов и бренд актива для разрезов [концентрации](../domains/portfolio/concentration.md) |
| Купоны и дивиденды | Построить будущие события по текущим позициям и календарь инструмента |
Сектор получается из описаний инструмента (отдельные описания для акций,
облигаций и фондов, поиск по UID, затем по FIGI); эмитент — из описания актива
по `asset_uid` инструмента: его uid и название бренда. Эмитент не выводится из
названия, тикера или ISIN. Классификация хранится как последнее известное
значение с обновлением не чаще раза в сутки ([ADR
022](../adr/022-stored-instrument-classification.md)); все вызовы проходят
через общий лимитер запросов T-Bank.
T-Bank определяет исходные данные и права token. Backend проверяет локальную
сессию, выбирает подключение её пользователя и устанавливает доступ к счёту.
Наличие идентификатора счёта в 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).
## Проверка и сохранение подключения
+5 -2
View File
@@ -20,6 +20,7 @@ WealthLedger — локальное приложение для частного
| Найти свой инвестиционный счёт | [Список счетов](domains/accounts/overview.md), их типы и доступные сводки |
| Вести банковские карты | [Ручной учёт](domains/cards/overview.md): независимые балансы, расходы, пополнения, переводы, возвраты и месячные сводки |
| Понять текущий состав инвестиций | [Портфель](domains/portfolio/overview.md): позиции, денежные остатки и итоги по валютам |
| Увидеть, где сконцентрированы деньги | [Концентрация](domains/portfolio/concentration.md): крупнейшие бумаги, секторы и эмитенты счёта |
| Разобрать уже совершённые движения | [Журнал операций](domains/operations/overview.md): исполненные операции с фильтрами и последовательной загрузкой истории |
| Посчитать полученные выплаты | [Пассивный доход](domains/income/overview.md): исполненные купоны и дивиденды за календарный период |
| Посмотреть ожидаемые события | [Будущие выплаты](domains/income/upcoming-events.md): купоны, дивиденды, погашения и оферты по текущим позициям |
@@ -40,8 +41,10 @@ WealthLedger — локальное приложение для частного
Портфель отвечает на вопрос «что есть сейчас», журнал — «что исполнено»,
аналитика дохода — «какие выплаты уже получены», будущие события — «что
ожидается». Прогноз не подтверждает фактическое зачисление. Полученные купоны
и дивиденды не равны инвестиционной доходности или результату после налогов.
ожидается», [результат инвестирования](domains/portfolio/investment-performance.md) —
«как сработали вложенные деньги и обогнал ли я индекс Мосбиржи». Прогноз не
подтверждает фактическое зачисление. Полученные купоны и дивиденды сами по
себе не равны доходности или результату после налогов.
Денежная сумма всегда относится к одной валюте. Недоступное значение
отличается от нуля, а объединение счетов не означает автоматическую
+218 -711
View File
File diff suppressed because it is too large Load Diff
+16 -13
View File
@@ -1,9 +1,9 @@
{
"name": "wealth-ledger-docs",
"version": "0.1.5",
"version": "0.1.8",
"private": true,
"engines": {
"node": "24.21.0"
"node": "24.22.1"
},
"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",
@@ -13,23 +13,26 @@
"commitlint": "commitlint"
},
"devDependencies": {
"@commitlint/cli": "21.2.2",
"@commitlint/config-conventional": "21.2.2",
"@release-it/conventional-changelog": "12.0.0",
"conventional-changelog-conventionalcommits": "10.4.0",
"@commitlint/cli": "21.2.4",
"@commitlint/config-conventional": "21.2.4",
"@release-it/conventional-changelog": "12.0.2",
"conventional-changelog-conventionalcommits": "10.4.1",
"markdownlint-cli": "0.49.1",
"markdownlint-rule-relative-links": "5.1.3",
"release-it": "21.0.2"
"markdownlint-rule-relative-links": "5.1.4",
"release-it": "21.1.1"
},
"overrides": {
"katex": "0.19.0",
"fast-uri": "3.1.9",
"katex": "0.19.1",
"markdownlint-cli@0.49.1": {
"js-yaml": "5.4.2",
"smol-toml": "1.9.0"
"minimatch": "11.0.2",
"smol-toml": "1.9.1"
},
"release-it": {
"basic-ftp": "6.2.1",
"undici": "7.29.1"
}
"basic-ftp": "6.2.3",
"undici": "7.30.1"
},
"markdown-it": "15.0.3"
}
}
+30 -1
View File
@@ -2,7 +2,8 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:recommended",
":semanticCommitTypeAll(chore)"
":semanticCommitTypeAll(chore)",
"security:minimumReleaseAgeNpm"
],
"timezone": "Europe/Moscow",
"labels": [
@@ -10,6 +11,13 @@
],
"dependencyDashboard": true,
"rangeStrategy": "pin",
"prConcurrentLimit": 5,
"lockFileMaintenance": {
"enabled": true,
"schedule": [
"before 4am on the first day of the month"
]
},
"packageRules": [
{
"matchUpdateTypes": [
@@ -18,6 +26,27 @@
],
"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": [
"major"