fix(portfolio): exclude closed (size-0) positions from the dashboard Overview - #2465
Conversation
…Overview
A closed position still has a portfolio account in its market (positionSize 0,
rendered "Flat", often holding idle capital), so `usePortfolio().positions`
returns it. The dashboard Overview counted/listed that raw array unfiltered, so
a market the user had closed kept showing as an active position — e.g.
"OPEN POSITIONS (2)" and "ACTIVE POSITIONS 2" with a Flat row for a closed
market.
The canonical open/flat split already exists elsewhere: PortfolioPositionsView
separates open positions from idle deposits via `account.positionSize !== 0n`,
and the site-wide PositionsBar filters the same way. The dashboard components
simply never applied it.
Fix: add a shared `isOpenPosition(pos)` helper in usePortfolio (keyed on
`account.positionSize !== 0n`, matching the existing canonical definition so all
open-position surfaces agree) and apply it in the four Overview components that
count or list positions:
- PositionSummary — the "Open Positions" list + count
- DashboardHeader — the "Active Positions" stat
- PnlChart — the "Across N positions" caption + empty-state gate
- StatsBar — stats + per-market fee readout + empty-state checks
(win/loss already ignored flat rows via the >0/<0 PnL test; this also
corrects the length-based cases and is memoized to stay referentially stable)
Filtering is done consumer-side, not at the hook, so surfaces that legitimately
need every account (idle deposits, my-markets) are unaffected. A funded-but-flat
account (idle deposit) is correctly treated as NOT open; an all-flat book now
shows the proper empty state.
Tested: tsc clean; new isOpenPosition unit suite (6 cases: open long/short,
closed size-0, funded-but-flat idle, missing account, mixed-book filter) green;
the one pre-existing AtRiskBanner test failure reproduces identically on the
untouched baseline (unrelated to this change).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@0x-SquidSol is attempting to deploy a commit to the Khubair Nasir's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Problem
A closed position still has a portfolio account in its market —
positionSize == 0, rendered Flat, and often still holding idle capital — sousePortfolio().positionsreturns it. The dashboard Overview consumed that raw array unfiltered, so a market the user had closed kept appearing as an active position:Flatrow for the closed market and its count was inflated ((2)with one real position).2.Repro: open a position, close it, open
/portfolio→ the closed market still shows under Open Positions withSize 0.Root cause
The canonical open/flat split already exists in the codebase —
PortfolioPositionsViewseparates open positions from idle deposits withaccount.positionSize !== 0n, and the site-widePositionsBarfilters the same way. The dashboard components just never applied it; they mapped/countedportfolio.positionsdirectly.Fix
Add a single shared helper in
usePortfolioand apply it everywhere the Overview counts or lists positions:Keyed on
account.positionSizeto match the existing canonical definition (PortfolioPositionsView,PositionsBar) so every open-position surface agrees — no third variant.Applied in the four Overview components:
PositionSummaryDashboardHeaderpositions.lengthPnlChartStatsBarDesign notes
StatsBar's win/loss already ignored flat rows via the>0/<0PnL test; this additionally corrects the length-based empty checks and per-market fee readout, and the filtered list is memoized to stay referentially stable.Testing
tsc --noEmitclean.isOpenPositionunit suite — 6/6: open long, open short, closed (size 0), funded-but-flat idle deposit, missing account, and a mixed-book filter.PORT-007: AtRiskBanner) reproduces identically on the untouched baseline, so it's pre-existing and unrelated to this change.PortfolioPositionsView/PositionsBarbehavior.🤖 Generated with Claude Code