2 Commits
Author SHA1 Message Date
codex-bot 7fbd4273ba docs: describe RUB-only behavior (WealthLedger/main#55) (#68)
Docs security / security (push) Successful in 7s
Docs verify / verify (push) Successful in 13s
2026-11-11 09:19:49 +03:00
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
18 changed files with 89 additions and 105 deletions
+3 -3
View File
@@ -37,9 +37,9 @@
индексе Мосбиржи».
- **IMOEX — только справочный индекс.** Он показывается рядом, но не
участвует в «опережении» и не является базой сравнения.
- **Только RUB.** Счёт с потоками или стоимостью в другой валюте не
рассчитывается (причина `NON_RUB_ACTIVITY`); конвертация валют не
выполняется.
- **Только RUB.** Пополнения и выводы в другой валюте не учитываются,
нерублёвые позиции отфильтрованы на входе; конвертация валют не
выполняется (WealthLedger/main#55).
- **Период** начинается с первого внешнего потока, не с открытия счёта.
Короче года — «за N дн.» без annualization; `basis = annual` только если
деньги вложены от 365 дней.
+1 -2
View File
@@ -64,8 +64,7 @@ Envelope несовместим с прежними bare-array ответами:
## Income analytics
`GET /api/v1/brokerage-accounts/{accountId}/income-analytics` и общий маршрут
`all` возвращают результат только выбранного периода: итоги по исходным
валютам, точные записи выплат, разбиение по инструментам и временные
`all` возвращают результат только выбранного периода: итоги в RUB, точные записи выплат, разбиение по инструментам и временные
интервалы. Данных сравнения с предыдущим периодом или годом ранее в ответе
нет — ни в теле, ни среди зависимостей `meta.dependencies`, роль которых
ограничена значением `selected`. Публичную машинную схему задаёт
+1 -1
View File
@@ -66,7 +66,7 @@ compatibility re-exports `shared/theme` и `shared/ui` удалены.
Фоновое обновление сохраняет доступные данные с локальным индикатором.
Подробные правила — в [состояниях интерфейса](../architecture/cross-cutting/ui-resilience.md).
Финансовые значения сохраняют валюту, знак и различие между нулём и
Финансовые значения сохраняют валюту (RUB), знак и различие между нулём и
неизвестной суммой. Предметные представления раскрыты в
[портфеле](../domains/portfolio/overview.md), [операциях](../domains/operations/overview.md)
и [банковских картах](../domains/cards/overview.md).
+5 -5
View File
@@ -33,12 +33,12 @@
| Состояние `portfolioSummary` | Что оно означает |
| --- | --- |
| Доступные валютные итоги | Текущие стоимости позиций и деньги сложены точно в исходной валюте |
| Доступная сводка с пустыми итогами | Портфель получен, но валютных итогов нет; это не ошибка загрузки |
| Доступный итог | Текущие стоимости позиций и деньги сложены точно в RUB |
| Доступная сводка без итога | Портфель получен, но итоговой суммы нет; это не ошибка загрузки |
| `null` | Финансовая сводка этого счёта временно недоступна; метаданные и переход на счёт сохраняются |
Валюты не конвертируются и не объединяются в общую сумму. Деньги уже входят
в валютный итог; они не образуют второй самостоятельный итог. Правила
Позиции и деньги в валютах, отличных от RUB, не участвуют в итоге. Деньги уже входят
в итог; они не образуют второй самостоятельный итог. Правила
неизвестных стоимостей совпадают со [справочником портфеля](../portfolio/data-reference.md).
Сводка также сообщает число ненулевых обычных позиций акций и облигаций
@@ -66,7 +66,7 @@
- Неизвестная ошибка: то же состояние недоступности без действия повтора.
- Успешный пустой ответ: штатное состояние отсутствия инвестиционных счетов.
Карточка ведёт на `/accounts/:accountId` по всей области и доступна с клавиатуры. Карточки расположены в одну колонку при любой ширине. Карточка показывает название, локализованный тип, крупный валютный итог и вторую валюту при наличии, число остальных валют, дату открытия без времени и видимое действие открытия. Отдельные цветные блоки «Акции» и «Облигации» показывают количество наименований бумаг. Недоступная или пустая сводка отображается локально; отсутствие сумм не скрывает известные количества бумаг, а недоступная сводка не подменяет их нулями. Наведение и видимый клавиатурный фокус подчёркивают переход; настройка уменьшения движения отключает анимацию.
Карточка ведёт на `/accounts/:accountId` по всей области и доступна с клавиатуры. Карточки расположены в одну колонку при любой ширине. Карточка показывает название, локализованный тип, крупный итог в RUB, дату открытия без времени и видимое действие открытия. Отдельные цветные блоки «Акции» и «Облигации» показывают количество наименований бумаг. Недоступная или пустая сводка отображается локально; отсутствие сумм не скрывает известные количества бумаг, а недоступная сводка не подменяет их нулями. Наведение и видимый клавиатурный фокус подчёркивают переход; настройка уменьшения движения отключает анимацию.
## Свежесть и границы
+7 -7
View File
@@ -4,7 +4,7 @@
купонами и дивидендами за выбранный период». Пользователь открывает
`/accounts/:accountId/income` из обзора счёта или
[общий доход](../portfolio/all-accounts.md) по доступным счетам.
Экран показывает итоги по валютам и отдельную карточку каждой
Экран показывает итоги в RUB и отдельную карточку каждой
включённой выплаты. Источником служат [исполненные операции](../operations/overview.md),
а не изменение цены портфеля и не календарь будущих выплат.
@@ -51,10 +51,10 @@
## Какие выплаты входят в результат
- Backend проверяет доступ локально и читает сохранённые операции. Фоновая загрузка должна завершить все страницы; ошибка страницы или повреждённая цепочка курсоров не подтверждают полноту.
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в исходной валюте; отрицательные корректировки сохраняют знак. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
- Итоги, временные интервалы и разбиение по инструментам не смешивают валюты и не создают общий конвертированный итог. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
- Только точные типы купона и дивиденда источника формируют результат. Суммы остаются точными десятичными строками в RUB; отрицательные корректировки сохраняют знак. Выплаты в других валютах не участвуют. Налоги, комиссии, сделки, переводы, погашения и переводы дивидендов не входят в доход.
- Итоги, временные интервалы и разбиение по инструментам считаются только в RUB. Система не загружает другие периоды ради сравнения полученного дохода с выбранным.
- Временные интервалы по-прежнему приходят с backend: дни для 1–45 дней, недели для 46–180 и месяцы для более длинного периода, включая пустые интервалы. Страница дохода не строит из них график или текстовую динамику; ответ API не меняется.
- Раздел «Выплаты» показывает карточки выплат в исходном порядке `entries`. В отдельном счёте каждая выплата — отдельная карточка. В режиме «Все счета» выплаты одного инструмента, дня и точного типа образуют группу, если их две и более ([правила группировки](../operations/overview.md#группировка-в-режиме-все-счета)). Группа стоит на месте первой выплаты; каждая строка счёта показывает название счёта и свою сумму со знаком. Визуальный итог группы — точная сумма по валютам по показанным выплатам; он скрыт, если полнота периода не `complete`, или у выплаты нет суммы, или сумма равна нулю. Это клиентский расчёт и не заменяет серверные итоги аналитики дохода, которые по-прежнему приходят из ответа API и не пересчитываются. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой выплате. Дополнительный запрос за составом не нужен.
- Раздел «Выплаты» показывает карточки выплат в исходном порядке `entries`. В отдельном счёте каждая выплата — отдельная карточка. В режиме «Все счета» выплаты одного инструмента, дня и точного типа образуют группу, если их две и более ([правила группировки](../operations/overview.md#группировка-в-режиме-все-счета)). Группа стоит на месте первой выплаты; каждая строка счёта показывает название счёта и свою сумму со знаком. Визуальный итог группы — точная сумма в RUB по показанным выплатам; он скрыт, если полнота периода не `complete`, или у выплаты нет суммы, или сумма равна нулю. Это клиентский расчёт и не заменяет серверные итоги аналитики дохода, которые по-прежнему приходят из ответа API и не пересчитываются. Описание, дата, доступные идентификаторы инструмента и сумма со знаком видны в каждой выплате. Дополнительный запрос за составом не нужен.
## Полнота и принадлежность выплат
@@ -71,11 +71,11 @@
Каждая запись `income-analytics.entries` содержит обязательный `instrumentKey`,
равный `key` соответствующей строки `instruments`. Backend вычисляет этот ключ
один раз при подготовке записей дохода и использует его же для группировки.
Приоритет UID, FIGI, ticker/type и ID операции с разделением по валюте остаётся
Приоритет UID, FIGI, ticker/type и ID операции остаётся
серверным правилом; клиент воспринимает ключ как непрозрачную строку.
Это поле принадлежит ответу аналитики; общий журнал операций его не требует.
Backend обеспечивает принадлежность выплат, валюту и receipt count при
Backend обеспечивает принадлежность выплат и receipt count при
построении entries и instrument groups из одного набора данных. Frontend
доверяет типизированному contract, не восстанавливает формулу идентификации
и не выполняет второй consistency validator. Полностью пустой ответ допустим.
@@ -94,7 +94,7 @@ Backend обеспечивает принадлежность выплат, ва
выбранного счёта и сохраняет прежнее поведение. Будущие выплаты
не включаются в итоги полученного дохода.
Аналитика читает сохранённую историю операций и не рассчитывает налоги, доходность (её показывает [результат инвестирования](../portfolio/investment-performance.md)), валютную конвертацию или общий мультивалютный итог.
Аналитика читает сохранённую историю операций и не рассчитывает налоги, доходность (её показывает [результат инвестирования](../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).
+4 -4
View File
@@ -56,8 +56,8 @@
«сумма неизвестна» и не превращается в ноль или полученные деньги.
Дата дивиденда обозначена как дата реестра. Offer и погашение сохраняют своё
значение без суммы выплаты. У каждой строки видны тип,
инструмент, дата и доступная сумма в исходной валюте. Список не имеет
пагинации и не конвертирует валюты. Пустой результат означает отсутствие
инструмент, дата и доступная сумма в RUB. Список не имеет
пагинации. Пустой результат означает отсутствие
известных поддерживаемых событий в выбранном окне, а не доказательство
отсутствия всех будущих выплат. Инструмент без поддерживаемых данных
не получает искусственную строку «нет данных».
@@ -70,7 +70,7 @@
несуществующая дата дают `400`; обратный период — `400 INVALID_EVENTS_PERIOD`
без замены периода и без запуска личной работы.
Фильтрация на сервере предшествует сортировке и вычислению
`incomeTotalsByCurrency`, включающего только купоны и дивиденды.
итога прогноза в RUB, включающего только купоны и дивиденды.
Итоги остаются в ответе API; полный экран показывает список без общего итога списка.
В режиме «Все счета» события одного инструмента, даты, точного типа и `dateKind` образуют
@@ -78,7 +78,7 @@
поэтому дата реестра дивиденда и иная дата того же инструмента не объединяются. Группа стоит на месте первого
события. Полный список группирует все полученные события; превью обзора сначала берёт пять
событий и группирует только их. Каждая строка счёта остаётся отдельной и показывает название
счёта и свою прогнозную сумму. Визуальный итог группы — точная сумма по валютам; он показывается
счёта и свою прогнозную сумму. Визуальный итог группы — точная сумма в RUB; он показывается
только если полнота прогноза `complete` и у каждого события группы известна прогнозная сумма.
Иначе итог скрыт, а строки остаются. Этот итог не равен итогам ответа API и не относится к полученному доходу.
+4 -4
View File
@@ -31,9 +31,9 @@
завершённой дневной свечи до московской даты котировки; база ищется за 20 дней.
Денежная оценка без НКД равна цене в процентах, умноженной на текущий номинал
и делённой на 100. Она округляется до девяти десятичных знаков. Оценка с НКД
добавляет текущий накопленный купонный доход только при совпадении валют.
добавляет текущий накопленный купонный доход.
Это ориентир без комиссии: котировка может быть старше текущего номинала и НКД.
FX-конвертация не выполняется, первоначальный номинал не заменяет текущий.
Первоначальный номинал не заменяет текущий.
Условия выпуска: текущий и первоначальный номинал, погашение, оферта,
количество купонов в год, лот. Отдельно отмечены плавающий купон,
@@ -49,7 +49,7 @@ FX-конвертация не выполняется, первоначальн
Текущая купонная доходность — ближайший купон × 365 / длительность его периода
в днях / денежная цена без НКД × 100 %. Decimal-расчёт округляется до четырёх
знаков. Требуются известная неотрицательная выплата, положительные цена и
период и одинаковая валюта выплаты и цены. Это годовая оценка при сохранении
период. Это годовая оценка при сохранении
размера купона и номинала, без налогов, комиссий и реинвестирования; она не
является доходностью к погашению. Время котировки показывается отдельно.
@@ -79,7 +79,7 @@ HTML-источник, общий кэш и поведение при измен
Позиция агрегирует только `BOND` с точным UID по доступным счетам, используя
[снимок портфеля](../portfolio/overview.md) и decimal-арифметику. Средняя покупка взвешена
по количеству. Неполные или разновалютные суммы недоступны; общая средняя
по количеству. Неполные суммы недоступны; общая средняя
и процент доступны только при положительных включённых позициях. Для
коротких позиций и сочетания длинных с короткими эти показатели не синтезируются.
Результат открытой позиции не включает выплаченные купоны и продажи и не
+3 -3
View File
@@ -30,7 +30,7 @@
Раздел «Акции» в боковой и мобильной навигации ведёт на `/stocks`: скринер
запускается кнопкой «Найти» с необязательным названием или тикером, сектором,
типом акции, валютой расчётов, площадкой, страной риска и максимальным размером
типом акции, площадкой, страной риска и максимальным размером
лота. Он использует полный полученный каталог и показывает только акции, для
которых каталог подтверждает доступность покупки и торговли через API. Это не
гарантирует, что конкретная заявка пользователя будет исполнена прямо сейчас.
@@ -90,10 +90,10 @@ UID включён в ключ кэша и подпись общего курс
восстанавливается переходом на первую страницу с повторным запросом.
[Портфель](../portfolio/overview.md) остаётся владельцем снимков и оценки позиций. Сводка
фильтрует `STOCK` по точному UID и использует точную десятичную арифметику, без конвертации валют.
фильтрует `STOCK` по точному UID и использует точную десятичную арифметику, в RUB.
Средняя цена равна сумме количеств, умноженных на средние цены, делённой на
общее количество; она округляется сервером до девяти знаков, проценты — до шести.
Неполные или разновалютные денежные итоги недоступны. Общая средняя и процент доступны только если все включённые позиции
Неполные денежные итоги недоступны. Общая средняя и процент доступны только если все включённые позиции
положительны; для нулевого количества, коротких позиций и сочетания
длинных с короткими они не синтезируются.
Результат открытой позиции исключает продажи и дивиденды и не называется полной
+3 -3
View File
@@ -13,7 +13,7 @@
Исполненная операция содержит тип события, его категорию, описание,
момент совершения, доступные сведения об инструменте и денежное движение.
Запросы отменённых или ожидающих исполнения поручений не образуют этот журнал.
Суммы остаются точными десятичными строками в исходной валюте. Frontend
Суммы остаются точными десятичными строками в RUB. Frontend
форматирует их и считает визуальный итог группы по показанным записям
(см. [группировку](#группировка-в-режиме-все-счета)). Положительное и отрицательное
движение сохраняют знак. Отсутствие `payment` означает «Без движения денег», а не нулевую сумму.
@@ -31,7 +31,7 @@
затем группирует только их. Полный журнал группирует страницу, уже загруженную
курсором; группы не переносятся между страницами. Курсор и порядок записей не меняются.
Итог группы — точная сумма по каждой валюте, без конвертации. Он показывается только
Итог группы — точная сумма в RUB. Он показывается только
если полнота журнала `complete`, у каждой записи группы есть `payment`, и ни одна сумма
не равна нулю. Иначе итог скрыт, а строки счетов остаются.
@@ -48,7 +48,7 @@
но их недоступность не меняет финансовое событие.
Журнал не вычисляет остаток после операции, историческую стоимость портфеля,
совокупный налог или валютную конвертацию. Изменение рыночной цены не становится
совокупный налог. Изменение рыночной цены не становится
операцией. Переводы между счетами не схлопываются в одну запись; одинаковые
ID операций разных счетов не означают дубликат.
+6 -5
View File
@@ -30,12 +30,13 @@ Backend публикует статические маршруты под `/api/
У них те же формы данных и фильтры, что у соответствующих разделов отдельного
счёта. Позиции, операции (включая выплаты дохода) и события сохраняют источник
в поле `account: { id, name }`; в ответах одного счёта это поле отсутствует.
Валютные итоги и деньги агрегированы. Точную форму транспорта задаёт
Итоги и деньги агрегированы в RUB. Точную форму транспорта задаёт
[OpenAPI backend](../../architecture/http-api.md).
- Портфель и доступные денежные остатки суммируются сервером точно, по исходной
валюте, с точной десятичной арифметикой. FX-конвертации нет; правила
неизвестных значений и состава сумм наследуются от [портфеля](data-reference.md).
- Портфель и доступные денежные остатки суммируются сервером точно, в RUB,
с точной десятичной арифметикой. Позиции и деньги в других валютах не
участвуют; правила неизвестных значений и состава сумм наследуются от
[портфеля](data-reference.md).
- Одинаковые бумаги разных счетов показаны одной карточкой с общим названием
и идентификатором. Внутри всегда видны строки счетов: ссылка на портфель,
количество, доступная стоимость, результат, средняя цена и доля позиции.
@@ -48,7 +49,7 @@ Backend публикует статические маршруты под `/api/
API сохраняет позиции каждого счёта; объединяется только их представление.
Порядок карточек задаёт первое вхождение
бумаги; порядок счетов внутри карточки сохраняется. Одиночные позиции
используют прежнюю карточку. Доля относится к позициям той же валюты
используют прежнюю карточку. Доля относится к позициям
во всём показанном портфеле, без денежных остатков.
- Журнал объединяет операции по убыванию времени, при равном времени использует
порядок идентификаторов счетов и операций. ID
+3 -14
View File
@@ -46,21 +46,10 @@
полный перечень остальных элементов, каждый со своей суммой и долей; топ-5
и диаграмма при этом не меняются.
Доли считаются от суммы стоимостей позиций разреза в выбранной валюте и
Доли считаются от суммы стоимостей позиций разреза и
в сумме дают ровно 100 %; округление — до десятой доли процента, очень малые
доли показываются как «< 0,1 %». Отрицательные и нулевые стоимости, а также
позиции без оценки в разрез не входят. Конвертации валют нет: каждая позиция
входит только в валюту своей оценки.
## Валюта
У вкладки свой список валют — валюты оценок позиций акций, облигаций и фондов,
отсортированные по ISO-коду, — и свой выбор, независимый от «Структуры
портфеля». По умолчанию выбрана первая валюта списка. При одной валюте
переключатель не показывается. Общего итога по нескольким валютам нет.
Выбранные разрез и валюта сохраняются, пока пользователь остаётся на странице
счёта, включая переключение её вкладок, и сбрасываются при новом заходе и при
смене счёта.
позиции без оценки в разрез не входят.
## Диаграмма и неполные данные
@@ -69,7 +58,7 @@
отмечен как неполный (`completeness: "incomplete"` — часть позиций не имеет
оценки), над разрезом появляется предупреждение «Данные неполные», а под
списком — сноска «Не учтено позиций: N» с числом позиций, не вошедших в разрез.
Пустой разрез (нет позиций с положительной оценкой в выбранной валюте)
Пустой разрез (нет позиций с положительной оценкой)
показывает текстовое состояние вместо диаграммы.
## Откуда берутся сектор и эмитент
+17 -17
View File
@@ -9,6 +9,7 @@
Деньги представлены значением Money: ISO-код валюты и десятичная строка,
например `{ "currency": "RUB", "value": "12500.5" }` — условный пример.
Валюта всегда `RUB`: система работает только с рублями.
Количества также передаются десятичными строками. Backend выполняет
десятичную арифметику без промежуточного `Number`, нормализует отрицательные
целую и дробную части и убирает незначащие конечные нули. Экспоненциальной
@@ -18,7 +19,7 @@
`null` означает, что показатель нельзя определить из доступных данных.
Это не ноль. Известная нулевая цена отличается от отсутствующей;
позиция с ненулевым количеством и неизвестной стоимостью остаётся в составе.
Несколько валют никогда не складываются в одну общую стоимость.
Позиции и деньги в валютах, отличных от RUB, отфильтровываются при получении из T-Bank и не участвуют ни в одном итоге.
## Состав и денежные показатели
@@ -26,25 +27,25 @@
| --- | --- | --- |
| Позиция | Ненулевое количество обычного инструмента из `GetPortfolio.positions` | Виртуальные позиции не включаются; порядок источника сохраняется |
| `quantity` | Количество из текущей позиции брокера | Допустимы дробные и отрицательные количества; это не число лотов |
| `currentValue` | Количество × текущая цена из `GetPortfolio` | `null`, если цена или её валюта недоступны |
| `currentValue` | Количество × текущая цена из `GetPortfolio` | `null`, если цена недоступна |
| `averagePurchasePrice` | Средняя цена позиции, переданная брокером | Это цена единицы, а не сумма затрат или рассчитанная приложением история покупок |
| `absoluteReturn` | Количество × (текущая цена − средняя цена) | Требует обеих цен в одной известной валюте; не включает продажи, купоны и дивиденды |
| Cash Balance | Суммы из `GetPositions.money`, объединённые по валюте | Заблокированные деньги не прибавляются; торгуемый инструмент `CURRENCY` остаётся позицией |
| `totalsByCurrency` | Стоимости позиций + доступные деньги той же валюты | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
| `absoluteReturn` | Количество × (текущая цена − средняя цена) | Требует обеих цен; не включает продажи, купоны и дивиденды |
| Cash Balance | Суммы RUB из `GetPositions.money`, объединённые в один остаток | Заблокированные деньги не прибавляются; торгуемый инструмент `CURRENCY` остаётся позицией |
| Итог Portfolio | Стоимости позиций + Cash Balance в RUB | Не включает невычислимую стоимость; не обещает полную оценку портфеля |
| `lastSuccessfulAt` | Время формирования успешного снимка, UTC | Не является временем каждой котировки; запасной снимок сохраняет исходное время |
| `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#данные-и-вычисления).
Сводка уже включает Cash Balance: прибавление денег к ней второй раз неверно.
При отсутствии вычислимой стоимости у части позиций известный итог остаётся
полезен, но представляет только оценённую часть. Известные нулевые итоги
отдельного счёта не создают валютные карточки. Если `totalsByCurrency` пуст,
но позиции или деньги присутствуют, это не пустой портфель.
отдельного счёта не создают отдельную итоговую карточку. Если итог Portfolio
отсутствует, но позиции или деньги присутствуют, это не пустой портфель.
## Результат инвестирования
@@ -81,33 +82,32 @@ ISIN, тикер и `logoName` могут быть `null`. `logoName` — имя
облигации (`BOND`), прочие инструменты (`OTHER`) и деньги (`CASH`).
Торгуемые валютные инструменты входят в `OTHER`; денежные остатки — в `CASH`.
Сервер строит структуру из позиций и денег, без повторного добавления
`totalsByCurrency`.
итога Portfolio.
Доля категории — её стоимость / известная стоимость позиций и денег
в выбранной валюте × 100. Backend округляет процент до шести знаков;
× 100. Backend округляет процент до шести знаков;
frontend показывает до сотых. Положительное значение меньше 0,01%
отображается как «< 0,01 %», если серверное округление не превратило его в ноль.
В геометрию диаграммы передаются только числовые проценты; суммы в списке
и подсказке форматируются из исходных точных строк.
Доля на карточке отдельной позиции использует другой знаменатель:
сумму стоимостей всех позиций той же валюты **без денег**. Это приблизительный
сумму стоимостей всех отображаемых позиций **без денег**. Это приблизительный
показатель для отображения, рассчитанный 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-точные-значения-и-валютные-агрегаты).
и [точные значения и итоговая сумма в 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),
@@ -7,7 +7,7 @@
базы для разбора не нужны; не переносите их в документацию или отчёт.
1. **Определите предмет сравнения.** Запишите, открыт отдельный счёт или
«Все счета», какая валюта и какой показатель расходятся. Текущая стоимость,
«Все счета» и какой показатель расходится. Текущая стоимость,
свободные деньги, результат открытой позиции и полученный доход — разные
величины. Убедитесь, что сравниваемые значения относятся к одному составу
счетов и инструменту. Название или тикер сами по себе не доказывают
@@ -19,9 +19,9 @@
автоматически, поэтому расхождение проверяйте по показанному состоянию
источника, а не по результату ручного обновления. Перезагрузка backend
сохраняет последний полный снимок в SQLite, но не создаёт историю стоимости.
3. **Проверьте состав суммы.** Для одной валюты итог складывается из
вычислимых стоимостей позиций и доступных денег. Не добавляйте деньги
второй раз, не складывайте валюты и не включайте заблокированные средства.
3. **Проверьте состав суммы.** Итог складывается из вычислимых стоимостей
позиций и доступных денег в RUB. Не добавляйте деньги второй раз и не
включайте заблокированные средства.
Ненулевая позиция с `currentValue: null` делает оценку неполной, но не
даёт нулевой вклад в смысле полной стоимости. `CURRENCY` участвует
в суммах, хотя текущий интерфейс скрывает её карточку —
@@ -44,7 +44,6 @@
| `HISTORY_START_UNKNOWN` | Неизвестна дата открытия счёта |
| `OPERATIONS_HISTORY_INCOMPLETE` | История операций не получена полностью до момента оценки |
| `PORTFOLIO_VALUATION_INCOMPLETE` | Нет полной оценки портфеля |
| `NON_RUB_ACTIVITY` | Есть потоки или остатки не в рублях |
| `UNVALUED_SECURITIES_TRANSFER` | Бумаги введены или выведены без денежной оценки |
| `UNCONFIRMED_TRANSFER` | В «Все счета» есть похожие на перевод между своими счетами операции, связь которых источник не подтверждает |
| `ACCOUNT_VALUATION_DATES_DIFFER` | В «Все счета» последние оценки счетов сделаны в разные московские дни |
+14 -17
View File
@@ -10,9 +10,10 @@
## Снимок и связанные области
Снимок состоит из позиций по инструментам, доступных денежных остатков,
валютных итогов и структуры активов. Позиция означает ненулевое количество
итоговой суммы в RUB и структуры активов. Позиция означает ненулевое количество
обычного инструмента в брокерском портфеле. Торгуемая валютная позиция
`CURRENCY` и свободные деньги имеют разный смысл и передаются раздельно.
`CURRENCY` и свободные деньги имеют разный смысл и передаются раздельно;
в итоге учитываются только деньги в RUB.
Точный смысл сумм и неизвестных значений раскрыт в
[справочнике данных](data-reference.md).
@@ -34,18 +35,15 @@ Backend получает данные через серверную
## Как читать экран
Валютная сводка показывает отдельную карточку для каждого полученного итога.
Деньги уже включены в итог своей валюты. RUB, USD и EUR обозначены ₽, $ и €;
другие валюты сохраняют ISO-код. Вспомогательным технологиям доступны полное
Сводка показывает одну карточку с итоговой суммой в RUB. Деньги уже включены
в итог. Сумма обозначена ₽; вспомогательным технологиям доступны полное
значение и название валюты. Суммы сохраняют все исходные цифры, знак и
дробные позиции, включая `-0,5`; длинные значения переносятся без обрезания.
Карточки не интерактивны и занимают одну колонку на узком экране,
две или три на широком. Отсутствующая валюта не получает искусственную
нулевую карточку. Пустые итоги не скрывают доступный состав портфеля.
Карточка не интерактивна. Отсутствующая итоговая сумма не получает искусственный
ноль. Пустой итог не скрывает доступный состав портфеля.
Структура после сводки распределяет известную стоимость по акциям,
облигациям, другим активам и свободным деньгам. При нескольких валютах
пользователь выбирает одну; при одной отдельного переключателя нет.
облигациям, другим активам и свободным деньгам в RUB.
Кольцевая диаграмма дополнена текстовым списком сумм и долей и подсказкой;
на узком экране список расположен под ней. Неизвестная оценка, отрицательные
составляющие или нулевой итог ограничивают возможность показать доли —
@@ -73,14 +71,14 @@ Backend получает данные через серверную
Существует расхождение: [согласованная спецификация представления позиций](https://git.personal.ksv741.ru/WealthLedger/specs/src/commit/9e227a563dda67620f0ad78228aa8a4c18bf35a0/openspec/specs/portfolio-view/spec.md#requirement-представление-карточек-позиций-на-клиенте)
требует доступности всех иных типов в отдельной секции, а текущие frontend
и его проверка исключают `CURRENCY` только из списка карточек. Такие позиции
остаются в ответе, валютных итогах, структуре и знаменателе долей остальных
позиций. Это описание фактического ограничения; выбор между изменением
интерфейса и согласованием требований остаётся отдельной задачей.
остаются в ответе, но не входят в итоговую сумму, структуру; их учёт в знаменателе
долей остальных позиций требует проверки. Выбор между изменением интерфейса и
согласованием требований остаётся отдельной задачей.
## Свежесть и границы
При первом запросе экран показывает каркас заголовка, сводки и разделов.
Три формы валютных карточек в каркасе не обещают наличие трёх валют.
Каркас итоговой карточки не обещает наличие суммы.
Загрузка обозначена для вспомогательных технологий; декоративные элементы
не содержат данных и не получают фокус. При обычном фоновом обновлении
сохраняются предыдущие суммы и время успешного получения в UTC.
@@ -95,10 +93,9 @@ Backend получает данные через серверную
Правила времени и ошибок приведены в [потоке загрузки](flows/portfolio-loading.md).
Отдельного чтения истории стоимости нет, но каждый полный снимок
сохраняет точку оценки по счёту и валюте для будущих поддерживаемых
сохраняет точку оценки по счёту в RUB для будущих поддерживаемых
представлений; публичного графика в текущем решении нет. Нет также
валютной конвертации, учёта виртуальных позиций или заблокированных
средств. Последний полный снимок сохраняется после перезапуска;
учёта виртуальных позиций или заблокированных средств. Последний полный снимок сохраняется после перезапуска;
обновлением личных данных владеет часовой обход, рассчитанный на один
экземпляр backend. Действие «Обновить» выполняет только локальное
перечитывание открытого экрана и не запускает работу с T-Bank.
+9 -10
View File
@@ -91,7 +91,7 @@ _Не использовать_: тип аккаунта T-Bank, protobuf type.
## Portfolio
Текущее нормализованное состояние инвестиций одного Brokerage Account,
включающее позиции, доступные денежные остатки и итоги по каждой валюте.
включающее позиции, доступный денежный остаток и итоговую сумму в RUB.
_Не использовать_: общий портфель, баланс счёта.
@@ -123,7 +123,7 @@ _Не использовать_: денежный остаток, cash balance.
Вкладка страницы одного Brokerage Account, показывающая, какие акции,
облигации, секторы и эмитенты занимают наибольшую часть текущей оценки
Portfolio, без валютной конвертации. Отличается от [структуры
Portfolio в RUB. Отличается от [структуры
портфеля](domains/portfolio/data-reference.md#структура-и-доли): в её разрезах
деньги не входят в знаменатель долей.
@@ -188,8 +188,8 @@ _Не использовать_: аватар актива, иконка бум
## Cash Balance
Ненулевой доступный денежный остаток Portfolio в одной валюте; не является
Portfolio Position и передаётся отдельно от `positions` в `cashBalances`.
Ненулевой доступный денежный остаток Portfolio в RUB; не является
Portfolio Position и передаётся отдельно от `positions`.
_Не использовать_: валютная позиция, заблокированные средства.
@@ -202,7 +202,7 @@ _Не использовать_: история портфеля, snapshot дл
## Точка истории стоимости портфеля
Полная оценка одного Brokerage Account в одной валюте на момент успешного
Полная оценка одного Brokerage Account в RUB на момент успешного
обновления Portfolio; последовательность таких точек описывает изменение
оценки во времени, включая неторговые дни. Не является Portfolio Snapshot
или [Результатом инвестирования](#результат-инвестирования); отсутствие цены
@@ -293,8 +293,7 @@ _Не использовать_: активный refresh token, признак
Прогнозируемое на ближайший период денежное или связанное корпоративное
событие одного Brokerage Account, рассчитанное по текущей Portfolio Position;
не является исполненной Ledger Entry. Прогнозная сумма события передаётся как
nullable Money: известные coupon, dividend и maturity содержат Money в исходной
валюте, offer или неизвестные денежные условия передаются как `null`.
nullable Money: известные coupon, dividend и maturity содержат Money в RUB, offer или неизвестные денежные условия передаются как `null`.
В публичном API прогноз доступен через маршруты `/events`; в доменной
документации событие называется Future Cash Event.
@@ -310,12 +309,12 @@ _Не использовать_: upstream dividend type, MOEX row name.
## Realized Income Analytics
Результат анализа исполненных купонов и дивидендов по счёту за календарный
период включительно в часовом поясе Europe/Moscow. Сохраняет исходные валюты
и знаки денежных выплат, переданных брокером. Это не налоговый расчёт,
период включительно в часовом поясе Europe/Moscow. Сохраняет знаки денежных выплат,
переданных брокером, в RUB. Это не налоговый расчёт,
прогноз или [Результат инвестирования](#результат-инвестирования); правила
расчёта объясняет [область дохода](domains/income/overview.md).
_Не использовать_: доходность выплат, общий доход в одной валюте,
_Не использовать_: доходность выплат, общий доход в нескольких валютах,
гарантированный доход.
## Результат инвестирования
+1 -1
View File
@@ -11,7 +11,7 @@ WealthLedger обращается к Invest API на сервере по gRPC ov
| Категория | Для чего используется |
| --- | --- |
| Открытые счета | Определить доступный состав счетов и проверить доступ к конкретному счёту |
| Портфель и денежные остатки | Показать текущий состав инвестиций и итоги по исходным валютам |
| Портфель и денежные остатки | Показать текущий состав инвестиций и итоговую сумму в RUB |
| Исполненные операции | Построить журнал и выделить полученные купоны и дивиденды |
| Инструменты и рынок | Имена, идентификаторы, цены, свечи, параметры акций и облигаций |
| Классификация инструментов | Сектор акций, облигаций и фондов и бренд актива для разрезов [концентрации](../domains/portfolio/concentration.md) |
+4 -4
View File
@@ -19,7 +19,7 @@ WealthLedger — локальное приложение для частного
| --- | --- |
| Найти свой инвестиционный счёт | [Список счетов](domains/accounts/overview.md), их типы и доступные сводки |
| Вести банковские карты | [Ручной учёт](domains/cards/overview.md): независимые балансы, расходы, пополнения, переводы, возвраты и месячные сводки |
| Понять текущий состав инвестиций | [Портфель](domains/portfolio/overview.md): позиции, денежные остатки и итоги по валютам |
| Понять текущий состав инвестиций | [Портфель](domains/portfolio/overview.md): позиции, денежные остатки и итоговая сумма в RUB |
| Увидеть, где сконцентрированы деньги | [Концентрация](domains/portfolio/concentration.md): крупнейшие бумаги, секторы и эмитенты счёта |
| Разобрать уже совершённые движения | [Журнал операций](domains/operations/overview.md): исполненные операции с фильтрами и последовательной загрузкой истории |
| Посчитать полученные выплаты | [Пассивный доход](domains/income/overview.md): исполненные купоны и дивиденды за календарный период |
@@ -46,9 +46,9 @@ WealthLedger — локальное приложение для частного
подтверждает фактическое зачисление. Полученные купоны и дивиденды сами по
себе не равны доходности или результату после налогов.
Денежная сумма всегда относится к одной валюте. Недоступное значение
отличается от нуля, а объединение счетов не означает автоматическую
конвертацию всех валют. Краткие определения собраны в [глоссарии](glossary.md).
Система работает только с рублями (RUB): данные в других валютах отфильтровываются
при получении из T-Bank и MOEX и не участвуют в итогах. Недоступное значение
отличается от нуля, а объединение счетов не означает конвертацию. Краткие определения собраны в [глоссарии](glossary.md).
## Источники и границы продукта