docs: describe RUB-only behavior (WealthLedger/main#55)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -46,21 +46,10 @@
|
||||
полный перечень остальных элементов, каждый со своей суммой и долей; топ-5
|
||||
и диаграмма при этом не меняются.
|
||||
|
||||
Доли считаются от суммы стоимостей позиций разреза в выбранной валюте и
|
||||
Доли считаются от суммы стоимостей позиций разреза и
|
||||
в сумме дают ровно 100 %; округление — до десятой доли процента, очень малые
|
||||
доли показываются как «< 0,1 %». Отрицательные и нулевые стоимости, а также
|
||||
позиции без оценки в разрез не входят. Конвертации валют нет: каждая позиция
|
||||
входит только в валюту своей оценки.
|
||||
|
||||
## Валюта
|
||||
|
||||
У вкладки свой список валют — валюты оценок позиций акций, облигаций и фондов,
|
||||
отсортированные по ISO-коду, — и свой выбор, независимый от «Структуры
|
||||
портфеля». По умолчанию выбрана первая валюта списка. При одной валюте
|
||||
переключатель не показывается. Общего итога по нескольким валютам нет.
|
||||
Выбранные разрез и валюта сохраняются, пока пользователь остаётся на странице
|
||||
счёта, включая переключение её вкладок, и сбрасываются при новом заходе и при
|
||||
смене счёта.
|
||||
позиции без оценки в разрез не входят.
|
||||
|
||||
## Диаграмма и неполные данные
|
||||
|
||||
@@ -69,7 +58,7 @@
|
||||
отмечен как неполный (`completeness: "incomplete"` — часть позиций не имеет
|
||||
оценки), над разрезом появляется предупреждение «Данные неполные», а под
|
||||
списком — сноска «Не учтено позиций: N» с числом позиций, не вошедших в разрез.
|
||||
Пустой разрез (нет позиций с положительной оценкой в выбранной валюте)
|
||||
Пустой разрез (нет позиций с положительной оценкой)
|
||||
показывает текстовое состояние вместо диаграммы.
|
||||
|
||||
## Откуда берутся сектор и эмитент
|
||||
|
||||
@@ -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` | В «Все счета» последние оценки счетов сделаны в разные московские дни |
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user