Files
specs/openspec/changes/2026-11-07-investment-performance-vs-index/tasks.md
T
codex-bot 892800301b
Specs security / security (push) Successful in 8s
Specs verify / verify (push) Successful in 11s
spec: plan investment performance vs Moscow Exchange index (WealthLedger/main#54) (#85)
2026-11-08 16:30:32 +03:00

11 KiB
Raw Blame History

Tasks

Issue: WealthLedger/main#54. Ветки в каждом repo: feature/54-investment-performance-vs-index от актуального develop.

1. Backend: история индексов

  • 1.1 [backend] Хранилище дневных закрытий индексов и состояния догрузки (аддитивная миграция)
    • Covers: instruments/market-index-history — Дневная история индексов Мосбиржи
    • Source: design «Data / Storage Changes»
    • Verification: npx prisma migrate dev на одноразовой копии БД; npm run verify
    • Depends on: none
  • 1.2 [backend] MoexClient.indexHistory(secid, from, till): пагинация history.cursor, строгий разбор, сбой без частичных строк
    • Covers: instruments/market-index-history — Дневная история индексов Мосбиржи
    • Source: system-analysis «Contracts» (MOEX ISS), index-refresh.mmd; design backend 5
    • Verification: moex.client.spec.ts: несколько страниц, невалидная страница, таймаут, не-2xx
    • Depends on: none
  • 1.3 [backend] MarketIndexHistoryService: покрытие периода, догрузка не чаще раза в час, single-flight, upsert, лог integration.moex.index_history.*, сбой → недостаточно покрытия
    • Covers: instruments/market-index-history — Дневная история индексов Мосбиржи, Свежесть и недоступность истории индексов
    • Source: system-analysis «Индексы MOEX», «Error and Recovery Semantics»; design backend 5, «Cross-cutting Implementation»
    • Verification: unit-тесты сервиса (покрытие ±10 дн., час, параллельные вызовы, сбой с историей и без); npm run verify
    • Depends on: 1.1, 1.2

2. Backend: расчёт результата

  • 2.1 [backend] Вынести isCompleteValuation(snapshot) в portfolio domain и использовать его при записи истории оценки
    • Covers: portfolio/investment-performance — Недоступный и неполный результат
    • Source: design backend 2; qa-analysis «Regression Impact»
    • Verification: существующие тесты portfolio-value-history и новые unit-тесты функции проходят; npm run verify
    • Depends on: none
  • 2.2 [backend] Domain: маппинг типов операций → роли, внешние потоки по дате Europe/Moscow, отсечка по fetchedAt, кандидаты на переводы в all без автоматического подтверждения, причины недоступности в порядке приоритета
    • Covers: portfolio/investment-performance — Внешние денежные потоки, Недоступный и неполный результат
    • Source: system-analysis «Маппинг операций T-Bank», «Переводы между счетами в all», «Причины недоступности»; design backend 4, 7
    • Verification: unit-тесты: счёт A (130 000 / 10 000), UNCONFIRMED_TRANSFER при совпадении операций, перевод на исключённый счёт, бумаги без пары, USD, порядок причин
    • Depends on: none
  • 2.3 [backend] Domain: XIRR (Ньютон + бисекция, проверка знака), basis annual/period, теневой портфель MCFTRR/IMOEX, опережение, series
    • Covers: portfolio/investment-performance — Доходность с учётом сумм и дат потоков, Те же деньги в индексе Мосбиржи, Справочный индекс без дивидендов, График результата
    • Source: system-analysis «Расчёт»; design backend 3
    • Verification: unit-тесты с эталонными константами (LibreOffice/scipy, допуск 1e-6): 10 % за 730 дн., 110 000 ₽ по индексу, поток в выходной, NO_SOLUTION, AMBIGUOUS_RETURN, period basis, отставание
    • Depends on: none
  • 2.4 [backend] Модуль performance: маршруты GET /brokerage-accounts/{accountId|all}/performance, доступ, сборка ответа, DTO, UnavailableReason, лог performance.calculated
    • Covers: portfolio/investment-performance — Результат инвестирования выбранного счёта, Недоступный и неполный результат; instruments/market-index-history — Свежесть и недоступность истории индексов
    • Source: contract investment-performance.openapi.yaml, performance-read.mmd; design backend 1, 6
    • Verification: e2e на SQLite (npm run test:sqlite): 200 ready, data: null, all incomplete, 401/404/503, MOEX недоступен с историей и без; npm run verify
    • Depends on: 1.3, 2.1, 2.2, 2.3
  • 2.5 [backend] Обновить generated OpenAPI и сверить его с целевым контрактом
    • Covers: portfolio/investment-performance — Результат инвестирования выбранного счёта
    • Source: design «Contract Implementation»
    • Verification: npm run openapi:generate; npm run openapi:check; построчная сверка маршрутов, required, nullable, enum и форматов с investment-performance.openapi.yaml, результат — в описании PR
    • Depends on: 2.4

3. Frontend

  • 3.1 [frontend] Обновить OpenAPI snapshot и типы, entity performance с usePerformance(accountId)
    • Covers: portfolio/investment-performance — Результат инвестирования выбранного счёта
    • Source: design frontend 1, «Contract Implementation»
    • Verification: npm run openapi:generate; npm run openapi:check; npm run typecheck
    • Depends on: 2.5
  • 3.2 [frontend] Форматтеры formatSignedPercent, formatPercentagePoints (знак U+2212, 1 знак)
    • Covers: portfolio/investment-performance — Вкладка «Результат» на странице счёта
    • Source: design frontend 4
    • Verification: unit-тесты: положительное, отрицательное, ноль, округление
    • Depends on: none
  • 3.3 [frontend] Вкладка «Результат»: container, VM, view, KPI, alerts, недоступно, skeleton, ошибка секции, «Как считали», hint, строки portfolio.performance.*
    • Covers: portfolio/investment-performance — Вкладка «Результат» на странице счёта, Недоступный и неполный результат
    • Source: design frontend 2, 3, 6, 7, «UI/UX Package»; prototype вариант A
    • Verification: тесты VM и view (RTL + MSW): обгоняю, отстаю, меньше года, неполный, недоступно, неизвестная причина, загрузка, ошибка только во вкладке; npm run verify
    • Depends on: 3.1, 3.2
  • 3.4 [frontend] График результата: LineChart с тремя сериями и точкой текущей стоимости, tooltip, текстовая альтернатива, пояснение об отсутствии прошлой стоимости, состояние без series
    • Covers: portfolio/investment-performance — График результата, Справочный индекс без дивидендов
    • Source: design frontend 5, «UI/UX Package»
    • Verification: тесты view: серии, aria-label с итогами, отсутствие референсной линии, пустой series; browser-тест на 390px без горизонтальной прокрутки; npm run verify
    • Depends on: 3.3

4. Docs

  • 4.1 [docs] ADR 023 и строка в adr/README.md
    • Covers: N/A — документация решения
    • Source: docs-impact: docs/adr/023-investment-performance-vs-index.md, docs/adr/README.md
    • Verification: npm run verify
    • Depends on: none
  • 4.2 [docs] Страница domains/portfolio/investment-performance.md и обновления all-accounts.md, data-reference.md, portfolio/overview.md
    • Covers: N/A — документация текущего поведения
    • Source: docs-impact: соответствующие строки таблицы
    • Verification: npm run verify; сверка с реализованным поведением 2.4 и 3.3
    • Depends on: 2.4, 3.3, 4.1
  • 4.3 [docs] Глоссарий, overview.md, income/overview.md: новые термины и снятие конфликтующих запретов
    • Covers: N/A — терминология
    • Source: docs-impact: docs/glossary.md, docs/overview.md, docs/domains/income/overview.md
    • Verification: npm run verify; grep -rn "доходност" . — только новое значение или оговорки «не является»
    • Depends on: 4.1
  • 4.4 [docs] integrations/moex.md (раздел «Индексы»), architecture/context.md, architecture/http-api.md
    • Covers: N/A — документация интеграции и API
    • Source: docs-impact: соответствующие строки таблицы
    • Verification: npm run verify; сверка с generated OpenAPI из 2.5
    • Depends on: 2.5

5. Завершение

  • 5.1 [specs] Commit planning artifacts и прототипа; PR в develop
    • Covers: N/A — поставка planning artifacts
    • Source: engineering workflow
    • Verification: npm run validate; git diff --check
    • Depends on: none

Ручная приёмка на реальных данных Change Owner (парность переводов, правдоподобие результата) и semantic verify/archive выполняются по qa-analysis до закрытия Issue. Это не implementation task.