spec: ignore non-RUB flows in performance (WealthLedger/main#55)
Conventional commits / commits (pull_request) Successful in 10s
Specs security / security (pull_request) Successful in 12s
Specs verify / verify (pull_request) Successful in 12s

This commit is contained in:
2026-11-11 09:00:25 +03:00
parent 6d977e585c
commit d4492282c2
4 changed files with 8 additions and 13 deletions
@@ -33,7 +33,7 @@ Issue: WealthLedger/main#54
| Индекс: отставание | Счёт со стоимостью ниже теневой: отрицательные `percentagePoints` и `money`, в UI «Отставание от рынка» |
| Справочный индекс недоступен | IMOEX нет, MCFTRR есть: `reference.unavailableReason` задан, `benchmark` и `outperformance` есть, в UI нет пунктирной линии |
| Недоступно: неизвестная дата открытия | Счёт с `historyBoundary = unknown`: `data: null`, `HISTORY_START_UNKNOWN`; в UI «Доходность недоступна», нет нулей |
| Недоступно: USD в `all` | 3 счёта, один с USD: `completeness = incomplete`, `excludedAccounts` содержит счёт и `NON_RUB_ACTIVITY`; в UI предупреждение |
| USD-поток игнорируется | Счёт с пополнением в USD: результат считается по рублёвым потокам, `excludedAccounts` пуст |
| Недоступно: даты оценок в `all` различаются | Последние оценки A и B в разные московские дни → `data: null`, `ACCOUNT_VALUATION_DATES_DIFFER`; стоимость не складывается |
| Недоступно: индекс недоступен | MOEX заблокирован и истории нет: `profit` есть, `benchmark.unavailableReason = INDEX_HISTORY_UNAVAILABLE`, `series = []` |
| Недоступно: остальные причины | Перевод бумаг без пары → `UNVALUED_SECURITIES_TRANSFER`; позиция без цены → `PORTFOLIO_VALUATION_INCOMPLETE`; незавершённая синхронизация → `OPERATIONS_HISTORY_INCOMPLETE` |
@@ -15,7 +15,7 @@
- **THEN** система не раскрывает никаких значений результата этого счёта
### Requirement: Внешние денежные потоки
Внешним денежным потоком MUST считаться только пополнение счёта рублями (положительный поток) и вывод рублей со счёта (отрицательный поток) на дату исполнения. Сделки, купоны, дивиденды, погашения, амортизация, налоги и комиссии MUST NOT считаться внешними потоками: их влияние входит в текущую стоимость. В режиме `all` переводы денег и бумаг между счетами, входящими в результат, MUST NOT считаться внешними потоками. Чистые внешние вложения MUST равняться точной сумме внешних потоков периода. Прибыль MUST равняться точной разности текущей стоимости и чистых внешних вложений.
Внешним денежным потоком MUST считаться только пополнение счёта рублями (положительный поток) и вывод рублей со счёта (отрицательный поток) на дату исполнения. Пополнения и выводы не в RUB MUST NOT учитываться и MUST NOT делать результат недоступным: система поддерживает только RUB и не конвертирует валюты. Сделки, купоны, дивиденды, погашения, амортизация, налоги и комиссии MUST NOT считаться внешними потоками: их влияние входит в текущую стоимость. В режиме `all` переводы денег и бумаг между счетами, входящими в результат, MUST NOT считаться внешними потоками. Чистые внешние вложения MUST равняться точной сумме внешних потоков периода. Прибыль MUST равняться точной разности текущей стоимости и чистых внешних вложений.
#### Scenario: Пополнения, вывод и дивиденды
- **WHEN** на счёт внесено 100 000 RUB и 50 000 RUB, выведено 20 000 RUB, получены дивиденды 3 000 RUB, а текущая стоимость Portfolio 140 000 RUB
@@ -81,7 +81,6 @@
### Requirement: Недоступный и неполный результат
Система MUST NOT возвращать числовой результат, выдаваемый за доходность, если его нельзя рассчитать честно. Для одного счёта результат MUST быть недоступным с машиночитаемой причиной, если:
- начало истории операций неизвестно;
- есть поток или позиция не в RUB;
- есть ввод или вывод ценных бумаг без денежной оценки, а в режиме `all` — неподтверждённый кандидат на перевод между своими счетами;
- текущая оценка Portfolio неполная;
- история операций не получена полностью.
@@ -92,9 +91,9 @@
- **WHEN** у счёта неизвестно начало истории операций
- **THEN** результат счёта недоступен с причиной «начало истории неизвестно», и ни одно значение не показывается как ноль
#### Scenario: Счёт с операциями в USD в режиме «Все счета»
- **WHEN** в режиме `all` один из трёх счетов содержит пополнение в USD
- **THEN** результат рассчитывается по двум оставшимся счетам и помечается как неполный с указанием исключённого счёта и причины «операции не в рублях»
#### Scenario: Пополнение в USD не учитывается
- **WHEN** у рублёвого счёта есть пополнение в USD
- **THEN** результат рассчитывается только по рублёвым пополнениям и выводам, без причины недоступности
#### Scenario: Счета оценены в разные московские дни
- **WHEN** в режиме `all` последние полные оценки включённых счетов относятся к разным московским календарным дням
@@ -84,9 +84,7 @@ Issue: WealthLedger/main#54
| `INPUT_SECURITIES`, `OUTPUT_SECURITIES`, `TRANS_IIS_BS`, `TRANS_BS_BS` | Перевод бумаг: у отдельного счёта всегда `UNVALUED_SECURITIES_TRANSFER`; в `all` — см. ниже |
| Сделки, купоны, дивиденды, погашения, амортизация, налоги, комиссии (включая `OUT_FEE`, `OUTPUT_PENALTY`), прочие | Внутренние, в потоки не входят |
- Поток в валюте, отличной от RUB, даёт счёту `NON_RUB_ACTIVITY`.
- `totalsByCurrency` последнего Portfolio с ненулевым значением в другой
валюте тоже даёт `NON_RUB_ACTIVITY`.
- Поток в валюте, отличной от RUB, не учитывается (RUB-only, WealthLedger/main#55).
- Учитываются только операции с `occurredAt ≤ fetchedAt` Portfolio этого
счёта. Иначе пополнение после оценки исказит результат.
- Дата потока — календарный день `occurredAt` в Europe/Moscow.
@@ -119,9 +117,8 @@ T-Bank не передаёт в операции счёт-контрагента
2. `OPERATIONS_HISTORY_INCOMPLETE`: покрытие не `complete`.
3. `PORTFOLIO_VALUATION_INCOMPLETE`: нет Portfolio или у ненулевой позиции
нет вычислимой стоимости (то же правило, что у `portfolio-value-history`).
4. `NON_RUB_ACTIVITY`.
5. `UNVALUED_SECURITIES_TRANSFER`.
6. `UNCONFIRMED_TRANSFER` (только `all`, когда есть кандидат на внутренний
4. `UNVALUED_SECURITIES_TRANSFER`.
5. `UNCONFIRMED_TRANSFER` (только `all`, когда есть кандидат на внутренний
перевод без доказанной связи).
Как причины попадают в ответ:
@@ -58,7 +58,6 @@ components:
enum:
- HISTORY_START_UNKNOWN
- OPERATIONS_HISTORY_INCOMPLETE
- NON_RUB_ACTIVITY
- UNVALUED_SECURITIES_TRANSFER
- UNCONFIRMED_TRANSFER
- ACCOUNT_VALUATION_DATES_DIFFER