diff --git a/openspec/changes/2026-11-07-investment-performance-vs-index/qa-analysis.md b/openspec/changes/2026-11-07-investment-performance-vs-index/qa-analysis.md index bb8baac..476406c 100644 --- a/openspec/changes/2026-11-07-investment-performance-vs-index/qa-analysis.md +++ b/openspec/changes/2026-11-07-investment-performance-vs-index/qa-analysis.md @@ -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` | diff --git a/openspec/changes/2026-11-07-investment-performance-vs-index/specs/portfolio/investment-performance/spec.md b/openspec/changes/2026-11-07-investment-performance-vs-index/specs/portfolio/investment-performance/spec.md index c6b8bbc..8481bc9 100644 --- a/openspec/changes/2026-11-07-investment-performance-vs-index/specs/portfolio/investment-performance/spec.md +++ b/openspec/changes/2026-11-07-investment-performance-vs-index/specs/portfolio/investment-performance/spec.md @@ -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` последние полные оценки включённых счетов относятся к разным московским календарным дням diff --git a/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/analysis.md b/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/analysis.md index d38255a..647df71 100644 --- a/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/analysis.md +++ b/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/analysis.md @@ -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`, когда есть кандидат на внутренний перевод без доказанной связи). Как причины попадают в ответ: diff --git a/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/contracts/investment-performance.openapi.yaml b/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/contracts/investment-performance.openapi.yaml index 5acc862..25f4d24 100644 --- a/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/contracts/investment-performance.openapi.yaml +++ b/openspec/changes/2026-11-07-investment-performance-vs-index/system-analysis/contracts/investment-performance.openapi.yaml @@ -58,7 +58,6 @@ components: enum: - HISTORY_START_UNKNOWN - OPERATIONS_HISTORY_INCOMPLETE - - NON_RUB_ACTIVITY - UNVALUED_SECURITIES_TRANSFER - UNCONFIRMED_TRANSFER - ACCOUNT_VALUATION_DATES_DIFFER