[Bug] Кэш брокерского счёта дважды входит в totals/structure; неверный знак % у коротких позиций #140

Closed
opened 2026-10-28 07:53:06 +03:00 by codex-bot · 0 comments
Owner

Problem

  1. totalsByCurrency (tbank-portfolio.mapper.ts) суммирует cash из getPositions().money и все позиции портфеля, включая CURRENCY (RUB000UTSTOM, USD800UTSTOM), которые являются тем же кэшем. portfolioStructure кладёт CURRENCY в OTHER, а кэш — в CASH. Завышенные totals сохраняются в TbankPortfolioValuePoint и складываются в сводке «все счета».
    • dev.db, счёт 2197225275: фонд 120.24 + cash 1.25 → сохранено 122.74 вместо 121.49.
    • brokerage-accounts.service.ts уже исключает CURRENCY ("must not duplicate the separately returned cash balances"), totals/structure — нет.
  2. unrealizedReturnByCurrency.percent делит на cost basis avgPrice × quantity, который у короткой позиции отрицателен: qty −2, avg 100, current 110 → absolute −20, cost −200, percent +10 (убыток показан как прибыль). Лонг и шорт одной валюты взаимно гасят cost basis.

Acceptance Criteria

  • totalsByCurrency = сумма currentValue не-CURRENCY позиций + Cash Balance по валюте.
  • structure не содержит CURRENCY позиций в OTHER; кэш учитывается только в CASH.
  • percent = null, если в валюте есть позиция с quantity ≤ 0 (как в instrument-position.ts).
  • Regression-тесты: currency position + cash; короткая позиция.

Out of scope

  • Уже сохранённые точки TbankPortfolioValuePoint (решение отдельно).
  • Blocked cash, НКД, FX-конвертация.
  • Уточнение формулировки specs/portfolio-view («сумма позиций и Cash Balance») — follow-up в specs; связано с WealthLedger/frontend#59.
## Problem 1. `totalsByCurrency` (`tbank-portfolio.mapper.ts`) суммирует cash из `getPositions().money` **и** все позиции портфеля, включая `CURRENCY` (`RUB000UTSTOM`, `USD800UTSTOM`), которые являются тем же кэшем. `portfolioStructure` кладёт `CURRENCY` в `OTHER`, а кэш — в `CASH`. Завышенные totals сохраняются в `TbankPortfolioValuePoint` и складываются в сводке «все счета». - dev.db, счёт 2197225275: фонд 120.24 + cash 1.25 → сохранено 122.74 вместо 121.49. - `brokerage-accounts.service.ts` уже исключает `CURRENCY` ("must not duplicate the separately returned cash balances"), totals/structure — нет. 2. `unrealizedReturnByCurrency.percent` делит на cost basis `avgPrice × quantity`, который у короткой позиции отрицателен: qty −2, avg 100, current 110 → absolute −20, cost −200, percent `+10` (убыток показан как прибыль). Лонг и шорт одной валюты взаимно гасят cost basis. ## Acceptance Criteria - [ ] `totalsByCurrency` = сумма currentValue не-`CURRENCY` позиций + Cash Balance по валюте. - [ ] `structure` не содержит `CURRENCY` позиций в `OTHER`; кэш учитывается только в `CASH`. - [ ] `percent` = `null`, если в валюте есть позиция с quantity ≤ 0 (как в `instrument-position.ts`). - [ ] Regression-тесты: currency position + cash; короткая позиция. ## Out of scope - Уже сохранённые точки `TbankPortfolioValuePoint` (решение отдельно). - Blocked cash, НКД, FX-конвертация. - Уточнение формулировки `specs/portfolio-view` («сумма позиций и Cash Balance») — follow-up в specs; связано с WealthLedger/frontend#59.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: WealthLedger/backend#140