StackTrading Docs

SRS: Dashboard - Common — Overview (UC 4.2.1–4.2.5)

FieldValue
BA in ChargeTrang Nguyen
Date Created2026-08-08
Versionv9
Document ReferencesRFQ_ Stack Trading Prop Tech V7.pdf (§3.2 Calculations and Endpoints for our Dashboard, §Risk Metrics Logic Definitions, §Risk Metrics Endpoints) · RFQ_ Website and Dashboard Implementation V7.pdf (§Part C: Trader Dashboard Implementation, Key Features)

UC Index

UC_IDUse Case NameBusiness Description
UC_4.2.1Position Monitor TableLive grid of the trader's open positions (Symbol, Side, Net Position, Unrealized/Realized/Total PnL, Forex-only Est. Swap) streamed via thePOSITION_METRICS WebSocket event.
UC_4.2.2The PulseA 0–100 discipline score that rewards risk-reducing behavior and penalizes averaging-down/erratic sizing, reset every trading session.
UC_4.2.3Equity CurveA time-series chart of the trader's Net Equity (absolute value = Initial Starting Capital + Realized + Unrealized PnL), filterable by 1D/1W/1M timeframe.[CR] (Source: CR-20260831-001).
UC_4.2.4Profit factorThe ratio of gross profit to gross loss across the trader's closed trades at their current level.
UC_4.2.5Win RateWin-rate statistics for a selectable lookback window (10/30/50/100 trades), including a per-trade win/loss dot grid.

Note on UC_4.3 relationship

UC_4.3 ("12 Performance Metrics", Ref: UC_4.3) documents 5 dedicated Performance-screen widgets (Sharpe Ratio, Sortino Ratio, Avg. Win vs. Loss, Holding Time Analysis, Trade Efficiency Matrix). The Pulse (BR_4.2.2.1), Equity Curve (BR_4.2.3.x), Profit factor (BR_4.2.4.1), and Win Rate (UC_4.2.5 §7 Screen Description row 3) each carry their own formula inline in this UC — there is no cross-UC canonical-formula dependency between this UC and UC_4.3.


Overview — Performance Widgets

UC_4.2.1 — Position Monitor Table

1. Overview

FieldContent
IDUC_4.2.1
Use CasePosition Monitor Table
DescriptionReal-time grid of the trader's currently open positions on the Overview screen — Symbol, Side, Net Position, Unrealized/Realized/Total PnL, and a conditional Forex-only Est. Swap column — streamed via thePOSITION_METRICS WebSocket event. Same UC for both SIM and LIVE account types (Ref: UC_4.1.1 §2 Screen Description).
Zapier Flow
Zapier Table
3rd Party

Dashboard.png Overview screen — Position Monitor Table (top-right panel), populated state. Dashboard - Day 0.png Overview screen — Position Monitor Table, empty state (no open positions).

Motion reference: UC_4.2.1 motion clips

2. Trigger

The Overview screen (Ref: UC_4.1.1) has rendered.

3. Pre-conditions

4. Post-conditions

  • The table displays the trader's current open positions and updates live as fills, partial fills, or closes occur.

5. Basic Flow

  1. On Overview screen load — including a page reload/F5 — frontend subscribes to the POSITION_METRICS WebSocket event, and the table renders immediately from the Backend's latest held snapshot of the user's open positions rather than appearing empty while waiting for the next event (Ref: BR_4.2.1.3).
  2. As fills, partial fills, or closes occur, Backend sends updated data for only the affected position(s), keyed by position_id (the position identifier), throttled to 1 evaluation/second (Source: RFQ_ Stack Trading Prop Tech V7.pdf §3.2 for the payload fields; Ref: BR_4.2.1.3 for the snapshot/delta mechanism and position_id keying, which supersedes a full-array re-send on every event).
  3. Frontend uses position_id to identify the corresponding row and maps/updates only the changed data into that row; each row updates independently — the table does NOT wait for a synchronized batch update across all positions (Ref: BR_4.2.1.1).
  4. If a position closes entirely, Backend flags the closure on that position's update and Frontend removes the row from the table (Ref: BR_4.2.1.3).
  5. If the user has no open positions, the table shows the empty state instead of rows (Ref: BR_4.2.1.2).

6. Exceptional Flow

  • WebSocket connection drops, market is closed, or page reload (F5): the table continues displaying the latest successfully captured snapshot rather than becoming empty — it does not reset to empty or zero simply because no new real-time events are arriving. This snapshot/reconnection resiliency behavior is shared across all real-time Dashboard widgets fed by WebSocket events (Ref: CR-14).

7. Business Rules

BR_4.2.1.1: Est. Swap — Forex-Only Visibility Window, Asynchronous Streaming

The Est. Swap column is visible only for Forex positions — it is hidden entirely (not shown as $0, the column itself does not render) for Futures positions. For Forex positions, the column follows this visibility window:

  • Animates into view exactly 60 minutes before the Forex daily rollover.
  • Disappears 1 minute after the rollover completes.
  • If the column is visible but the backend has not yet pushed a swap estimate for a given position, the cell shows a neutral placeholder ($0) until the first est_swap value arrives.
  • Whenever the backend receives an updated swap estimate from the execution gateway, it pushes the new est_swap value via the standard POSITION_METRICS WebSocket channel (subject to the same 1 evaluation/second throttle) — the frontend table updates each row independently as data arrives, it does NOT wait for a synchronized batch calculation across all active positions.

Rollover time — DST-aware (America/New_York timezone), not a fixed UTC offset: the Forex daily rollover is always 5:00 PM Eastern Time, which is a wall-clock anchor, not a fixed UTC time. Because the US observes Daylight Saving Time, the equivalent UTC time shifts twice a year:

  • EDT (roughly mid-March → early November): 5:00 PM ET = 21:00 UTC.
  • EST (roughly early November → mid-March): 5:00 PM ET = 22:00 UTC.

The timekeeper must resolve the rollover trigger (and therefore the column's 60-minutes-before / 1-minute-after visibility window) from the US Eastern Time DST calendar, not from a hardcoded UTC offset — otherwise the 60-minute pre-rollover animation and the column's disappearance would fire at the wrong wall-clock time on the two DST transition days each year, breaking the UI timer.

BR_4.2.1.2: Empty State

When the trader has no open positions, the table displays a centered empty-state indicator (icon + text) reading "No open positions" instead of any rows. (Source: BA confirmation, 2026-08-08, QnA_init_docs.md A-04; visual per wireframe Dashboard - Day 0.png.)

BR_4.2.1.3: Snapshot Persistence, Delta Update by Position Identifier, and Row Removal on Close

Backend snapshot persistence (reload/F5): Backend maintains and holds the latest POSITION_METRICS snapshot (the current set of open positions and their latest field values) for the user, independent of any single WebSocket connection. On Overview screen load — including a page reload/F5 — the table is restored from this held snapshot immediately, so it does not appear empty while waiting for the next WebSocket event. This is the Position-Monitor-specific application of the shared snapshot rule (Ref: CR-14).

Delta update by position identifier (position_id): after the initial snapshot render, each subsequent POSITION_METRICS WebSocket event carries only the updated data for the position(s) affected by that fill/partial-fill/close — not a full re-send of every open position. position_id is the position identifier: Frontend uses it to find the matching row already on screen and maps/updates only the changed fields (net_pos, unrealized_pnl, realized_pnl, total_pnl, est_swap) into that row, leaving every other row untouched. symbol remains a display-only field on the row (the traded instrument) and is not used to key the update, since a trader can hold more than one open position on the same symbol (e.g. positions opened at different times or on different strategies) — position_id is what disambiguates them. This confirms and supersedes any full-array-per-event or symbol-keyed reading of §3.2 — the existing snapshot render plus this row-level delta, keyed by position_id, is the update mechanism (Source: User instruction (BA session), 2026-08-31).

Row removal on full close: when a position closes out entirely (net_pos reaches 0 for that position_id), the affected-position update carries a closed flag for that position_id. Frontend removes the corresponding row from the table on that event, rather than leaving a stale zero-quantity row on screen. If this was the trader's last open position, the table then shows the empty state (Ref: BR_4.2.1.2).

Market closed / connection drop: while the market is closed or the WebSocket connection is temporarily unavailable, the table continues showing the latest snapshot/delta-updated state rather than resetting to empty (Ref: CR-14).

8. Screen Description

No.Field NameField TypeDisplaying rule / Behaviour rule
1SymbolLabelDisplaying rule:- The traded instrument symbol.- Overflow: Truncate with tooltip Ref: CR-10 if it exceeds the column width.Behaviour rule:- Read-only, display field. The row itself is keyed by position_id (not shown on screen), used to route each POSITION_METRICS delta update to its row and to remove the row on full close (Ref: BR_4.2.1.1, BR_4.2.1.3).
2SideBadgeDisplaying rule:- Possible values: Long, Short.
3Net PosLabelDisplaying rule:- Net position size (integer, signed) for this symbol.
4Unrealized PNLLabelDisplaying rule:- Formula: Σ((Current Price − Avg Entry Price) × Position Size × Tick Value) for this position (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Logic Definitions "PnL Breakdown").- Monetary value display: Ref: CR-11.
5Realized PNLLabelDisplaying rule:- Sum of Net PnL for this position's closed lots within the current session (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Logic Definitions).- Monetary value display: Ref: CR-11.
6Total PNLLabelDisplaying rule:- = Unrealized PNL + Realized PNL.- Monetary value display: Ref: CR-11.
7Est SwapLabelDisplaying rule:- Forex-only, conditional visibility window (60 min before / 1 min after Forex rollover, 5:00 PM Eastern Time — DST-aware, shifts between 21:00/22:00 UTC). Ref: BR_4.2.1.1.

UC_4.2.2 — The Pulse

1. Overview

FieldContent
IDUC_4.2.2
Use CaseThe Pulse
DescriptionA 0–100 discipline score displayed on the Overview screen, tracking trading behavior (not P&L) within the current trading session — deducting for averaging-down/increasing-risk/erratic-sizing and rewarding pyramiding/risk-reduction. Resets to 100 at the start of every trading session. Same UC for both SIM and LIVE account types.
Zapier Flow
Zapier Table
3rd Party

Dashboard.png Overview screen — "The Pulse" panel, populated state (score + trend chart). Dashboard - Day 0.png Overview screen — "The Pulse" panel, session-start state (score = 100, empty chart).

Motion reference: UC_4.2.2 motion clips

2. Trigger

The Overview screen (Ref: UC_4.1.1) has rendered.

3. Pre-conditions

4. Post-conditions

  • The widget displays the current Pulse score for the active session, updating in real time as scoring events occur.

5. Basic Flow

  1. At the start of every trading session (Exchange Reset: 18:00 EST for Futures, 17:00 EST for Forex), the Pulse score resets to 100 (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Logic Definitions "Pulse Score").
  2. As the trader places/modifies orders during the session, the backend evaluates each action against the deduction/reward rules and recalculates current_pulse_score (Ref: BR_4.2.2.1).
  3. The backend pushes the updated current_pulse_score in real time via WebSocket (Ref: BR_4.2.2.2).
  4. The widget renders the current score, updating live as new values arrive.

6. Exceptional Flow

  • WebSocket connection drops, market is closed, or page reload (F5): the widget continues displaying the latest successfully captured score/snapshot rather than becoming empty (Ref: CR-14).

7. Business Rules

BR_4.2.2.1: Pulse Score — Reset, Deductions, Rewards

The Pulse Score is an integer, 0100, reset to 100 at the start of every trading session (Exchange Reset: 18:00 EST for Futures, 17:00 EST for Forex).

Deductions:

  • −25 — Averaging Down: submitting an order in the same direction on the same symbol while the current Unrealized P&L on that symbol is negative.
  • −20 — Increasing Risk: modifying an existing Hard Stop order to move the price further away from the current market price.
  • −15 — Erratic Sizing: submitting an order where the quantity exceeds 2× the average quantity of the last 10 fully filled or closed orders (partial fills ignored).

Rewards:

  • +5 — Pyramiding: adding to a winning position in the same direction on the same symbol, while Unrealized P&L on that symbol is positive.
  • +10 — Reducing Risk: modifying a Hard Stop to move it closer to the current market price, or locking in profit.

The score is clamped to the 0100 range — deductions cannot push it below 0, rewards cannot push it above 100. (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Logic Definitions "Pulse Score".)

BR_4.2.2.2: Real-Time Update via current_pulse_score

The Pulse widget updates in real time over WebSocket. The payload includes a current_pulse_score (integer) field (Source: BA confirmation, 2026-08-08, QnA_init_docs.md A-06 — supersedes the original architecture finding that no WebSocket event in the Customer supplies payload table carried a Pulse-related field).

BR_4.2.2.3: Widget Display — Score and Trend Chart

  • The panel title shows the current score inline, e.g. "The Pulse (42)".
  • Below the title, a trend-line/area chart plots the score's history within the session. At session start (no history yet) the chart area renders empty.
  • Chart data source: Get Pulse History endpoint (GET, user_id + limit, returns Array[[timestamp_utc, integer_score]]) (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Endpoints), refreshed live as current_pulse_score updates arrive (Ref: BR_4.2.2.2).

8. Screen Description

No.Field NameField TypeDisplaying rule / Behaviour rule
1Pulse ScoreLabelDisplaying rule:- Integer 0–100, shown inline in the panel title, e.g. "The Pulse (42)". Ref: BR_4.2.2.1, BR_4.2.2.3.Behaviour rule:- Read-only. Updates live via current_pulse_score (Ref: BR_4.2.2.2).
2Trend chartLabelDisplaying rule:- Session trend-line/area chart of the score's history. Empty at session start. Ref: BR_4.2.2.3.Behaviour rule:- Read-only, appends new points as the score updates.

UC_4.2.3 — Equity Curve

1. Overview

FieldContent
IDUC_4.2.3
Use CaseEquity Curve
Description[CR] A time-series chart of the trader's Net Equity (absolute notional value — Initial Starting Capital + Realized PnL + Unrealized PnL — not a relative PnL delta) on the Overview screen, filterable by 1D/1W/1M timeframe. Same UC for both SIM and LIVE account types. (Source: CR-20260831-001 — see References/CR/2026-08-31_equity-curve-net-equity-formula/CR_summary.md)
Zapier Flow
Zapier Table
3rd Party

Dashboard.png Overview screen — "Equity Curve" panel, populated state. Dashboard - Day 0.png Overview screen — "Equity Curve" panel, empty state (mockup shows a flat line at $0; [CR] per CR-20260831-001 this is now a flat line at the account's Initial Starting Capital baseline, not $0 — Ref: BR_4.2.3.1).

Motion reference: UC_4.2.3 motion clips

2. Trigger

The Overview screen (Ref: UC_4.1.1) has rendered, or the user changes the 1D/1W/1M filter.

3. Pre-conditions

4. Post-conditions

  • The chart displays the account balance time series for the selected timeframe.

5. Basic Flow

  1. On Overview screen load, frontend calls GET /equity-curve?timeframe=1D (default filter).
  2. [CR] Backend returns Array[[timestamp_utc, float_value]] where float_value is the absolute Net Equity notional value at that timestamp (e.g. 25500.00) — not a relative PnL delta (e.g. 500.00). Computed per the formula and baseline in BR_4.2.3.1 (Source: CR-20260831-001).
  3. [CR] Frontend renders the time series as a chart, plotting the exact array of absolute values returned by the backend — no client-side math (no re-basing, no delta calculation, no re-scaling of the underlying values) is performed on the data before charting (Ref: BR_4.2.3.2; Source: CR-20260831-001).
  4. User clicks the 1D/1W/1M filter → frontend re-calls GET /equity-curve?timeframe= with the new value (Ref: BR_4.2.3.1 for re-fetch behavior, BR_4.2.3.4 for the snapshot cadence/aggregation applied per timeframe).

6. Exceptional Flow

  • No balance snapshot yet (new account, Day 0): chart displays a flat line at the baseline — the account's Initial Starting Capital (Ref: §8 Screen Description row 2, BR_4.2.3.1).
  • WebSocket/API connection drops, market is closed, or page reload (F5): the chart continues displaying the latest successfully loaded series rather than becoming empty (Ref: CR-14).
  • [CR] Page reload (F5) after a snapshot has been captured but not yet pushed over WebSocket: if the backend has already captured a new 30-minute intraday snapshot (BR_4.2.3.4) but the corresponding WebSocket push to the chart has not fired yet, and the user reloads the page in that window, the reload must render the latest already-captured snapshot immediately (the page-load GET /equity-curve call always reads the backend's current persisted state, so it is not blocked on the socket push) — the chart must never show the older, pre-snapshot data merely because the socket event hasn't arrived (Ref: BR_4.2.3.5; Source: CR-20260831-001).

7. Business Rules

BR_4.2.3.1: 1D/1W/1M Filter — Re-fetch on Change; Net Equity Formula & Baseline

[CR] The chart calls GET /equity-curve?timeframe= on page load and every time the user changes the 1D/1W/1M filter — it does not pre-fetch or cache all 3 timeframes at once (Source: BA confirmation, 2026-08-08, QnA_init_docs.md A-09; re-fetch trigger unchanged by CR-20260831-001).

Baseline data source (Table A/B lookup): the chart's Initial Starting Capital baseline is not stored per-account — it is looked up live from the Zapier configuration matrix each time it's needed: the backend takes the account's asset class (Forex vs Futures) and its current level, finds the matching row in Table A (Forex Matrix) or Table B (Futures Matrix), and reads that row's Max_Forex_Notional / Max_Futures_Notional field as the baseline value. This is the same lookup used to derive the formula's Initial Starting Capital term below (Source: CR-20260831-001; BA confirmation 2026-09-03).

Formula (Source: CR-20260831-001 — see References/CR/2026-08-31_equity-curve-net-equity-formula/CR_summary.md):

Net Equity = Initial Starting Capital + (Realized PnL + Unrealized PnL) = Account Balance + Unrealized PnL

Note: all terms on the right-hand side — Account Balance (which already embeds Initial Starting Capital + Realized PnL), and Unrealized PnL — are read from the trader's own trading account (the live account/position data feed), not from a separate ledger or estimate. Only the Initial Starting Capital baseline itself comes from the Table A/B lookup above; everything else is the account's actual current balance and open-position PnL (Source: BA confirmation, 2026-09-03).

  • Initial Starting Capital (the baseline): looked up once per account from the Zapier configuration table matching the account's asset class:

    • Forex accounts: Max_Forex_Notional (Table A). This column is already documented (Source: Zapier Integration V7.pdf, Appendix A).
    • Futures accounts: Max_Futures_Notional (Table B). ✅ Confirmed by client, 2026-08-31 (CR-20260831-001): this is a new column, distinct from the existing Futures_Capital column — the two represent different things.
  • Each [timestamp_utc, float_value] point in the returned array is one snapshot's Net Equity computed by this formula, at the cadence defined in BR_4.2.3.4. No additional transformation, smoothing, or interpolation is applied on top of this formula.

Previously (superseded by CR-20260831-001): the series was built directly from the account's Daily Balance snapshots only — float_value was the raw account balance, which excludes Unrealized PnL entirely. This under-represented a trader's true net worth while holding open positions. See Changelog.

BR_4.2.3.2: Frontend Renders Absolute Values As-Is — No Client-Side Math

[CR] The frontend plots the exact [timestamp_utc, float_value] array returned by GET /equity-curve with no local/client-side computation on the float_value series — no subtracting a baseline to derive a delta, no adding a locally-held Unrealized PnL figure, no re-scaling, no smoothing/interpolation. Every value already fully embeds the BR_4.2.3.1 formula on the backend, so the chart is a pure renderer of whatever the backend sends. This guarantees a single source of truth for the Net Equity calculation — if the formula ever changes, only the backend needs updating, not the frontend chart logic. (Source: CR-20260831-001.)

BR_4.2.3.3: Y-Axis Dynamic Scaling & Target/Stop Overlay

The Y-axis does not start at $0 and is not a fixed range — it auto-scales dynamically to the trader's actual data:

  • Scale bounds: the Y-axis min/max are computed from the actual high and low Net Equity values (float_value) among the data points in the currently selected window, not from $0 and not from the baseline alone (a profitable trader's whole chart may sit well above $0; a drawdown trader's chart may sit below the baseline without ever approaching $0).
  • Padding for Target/Stop visibility: the backend also fetches the trader's Profit_Target and Market_Loss_When_Stopped for their current level via GET /current-level-detail (Ref: UC_4.8.1 BR_4.8.1.2), and derives the two static overlay levels:
    • Target level = Initial Starting Capital + Profit_Target.
    • Stop level = Initial Starting Capital − Market_Loss_When_Stopped.
    • The Y-axis top/bottom bounds must extend far enough beyond the min/max Net Equity data points that both the Target level and the Stop level remain visible within the chart frame at all times — i.e. axis_max ≥ max(high Net Equity, Target level) plus a visual padding margin, and axis_min ≤ min(low Net Equity, Stop level) minus a visual padding margin. If the trader's actual Net Equity range already exceeds the Target/Stop levels, the axis still auto-scales to the data (the Target/Stop lines simply sit inside the frame rather than at its edges).
  • Overlay rendering: Target and Stop are drawn as static horizontal reference lines across the chart (distinct styling from the Net Equity line itself), not as additional data points in the series.

Axis & color semantics:

ElementMeaning
X-axisTime. Tick granularity depends on the active filter —1D → hourly ticks; 1W/1M → daily ticks (see §8 row 2 for full tick rules, unchanged by this CR).
Y-axisNet Equity in USD (absolute notional value perBR_4.2.3.1not starting at $0), auto-scaled per this BR, monetary formatting per CR-11.
BaselineA horizontal reference line at the Initial Starting Capital value (Ref:BR_4.2.3.1Max_Forex_Notional or Max_Futures_Notional). This is the account's Day-0 equity, not $0.
Green segment/fill (above baseline)Net Equity is currentlyabove the Initial Starting Capital — the trader is net profitable.
Red segment/fill (below baseline)Net Equity is currentlybelow the Initial Starting Capital — the trader is net in a loss.
Line-color transitionColor is evaluated per-point against the baseline, so the line/fill switches between green and red at the exact point(s) where the Net Equity series crosses the baseline within the visible window.

(Y-axis scaling/Target-Stop overlay is display/rendering behavior, not the CR itself — see BR_4.2.3.1 for the CR-tagged formula change. Target/Stop field names — Source: RFQ_ Stack Trading Prop Tech V7.pdf, per UC_4.8.1 BR_4.8.1.2.)

BR_4.2.3.4: Snapshot Cadence & 1W/1M Aggregation

1D timeframe — 30-minute intraday snapshots: a background cron captures a Net Equity snapshot every 30 minutes throughout the trading session, populating the array that powers the 1D chart. A single daily balance snapshot cannot render a 1-day time-series chart, so intraday snapshotting at this cadence is the implied technical mechanism required to satisfy the V7 spec's mandate that GET /equity-curve support a 1D timeframe (Source: CR-20260831-001 — "capturing a snapshot every 30 minutes is the correct technical approach to power the 1D chart... intraday snapshotting is an implied technical necessity"; cross-ref: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Endpoints, Get Equity Curve 1D timeframe support).

  • 1W timeframe — aggregated by day: given the underlying data is stored at 30-minute granularity, GET /equity-curve?timeframe=1W does not return all ~48 points/day — it returns one aggregated point per calendar day within the 7-day window. The aggregated point's float_value is the last (most recent, i.e. end-of-day) snapshot's Net Equity for that day — consistent with the existing "daily ticks" display rule in §8 row 2.
  • 1M timeframe — aggregated by week: analogously, GET /equity-curve?timeframe=1M returns one aggregated point per calendar week within the window, using the last snapshot of that week.
  • Current (in-progress) day/week stays live: the aggregation above applies to closed days/weeks only. The data point representing the current, still-in-progress day (for 1W) or current, still-in-progress week (for 1M) continues to update in place with every new 30-minute snapshot — it is not frozen at the last aggregation boundary — so the chart accurately reflects "today" at all times, matching the existing real-time-update behavior already defined in §8 row 2.

(Source: CR-20260831-001.)

BR_4.2.3.5: F5/Reload Reflects the Latest Captured Snapshot Immediately

This rule is a chart-specific application of the shared CR-14 snapshot-persistence pattern, made explicit for the 30-minute snapshot cadence in BR_4.2.3.4: if a new 30-minute snapshot has already been captured and persisted on the backend, but the corresponding WebSocket push to update the live chart has not fired yet, and the user reloads the page (F5) during that window, the page-load GET /equity-curve call reads directly from the backend's already-persisted data — so the reloaded chart reflects the latest captured snapshot immediately, never the older pre-snapshot state. (Ref: §6 Exceptional Flow; Source: CR-20260831-001.)

8. Screen Description

No.Field NameField TypeDisplaying rule / Behaviour rule
1Timeframe filterTabDisplaying rule:- Options: 1D, 1W, 1M. Default: 1D.Behaviour rule:- On selection: re-fetches the chart data for the selected timeframe. Ref: BR_4.2.3.1.
2Equity chartLabel[CR] Displaying rule (Source: CR-20260831-001):- X-axis: time. Tick granularity depends on the active filter — 1D → hourly ticks (e.g. 09:00, 10:00, …, covering the current trading session); 1W/1M → daily ticks (one tick per calendar day in the window). Tick spacing is evenly distributed across the axis regardless of how many data points fall between ticks.- Y-axis: Net Equity in USD (absolute notional value, does not start at $0), auto-scaled to the trader's actual high/low Net Equity data points within the current window, with extra top/bottom padding so the static Target and Stop levels stay visible in-frame, monetary formatting per CR-11. Full scaling/padding rule and axis semantics: Ref: BR_4.2.3.3.- Baseline: horizontal reference line at the Initial Starting Capital (Max_Forex_Notional/Max_Futures_Notional). Green above baseline (profit), red below baseline (loss). Ref: BR_4.2.3.3.- Target/Stop overlay: two static horizontal reference lines — Target = Initial Starting Capital + Profit_Target; Stop = Initial Starting Capital − Market_Loss_When_Stopped (from GET /current-level-detail). Ref: BR_4.2.3.3.- Line: one point per snapshot returned by GET /equity-curve — each point is the absolute Net Equity value computed per BR_4.2.3.1; frontend performs no local math on these values (Ref: BR_4.2.3.2). Points connected in chronological order by a straight-line (linear) segment — no curve smoothing/interpolation. Snapshot cadence and 1W/1M aggregation: Ref: BR_4.2.3.4.- Empty state (Day 0, no snapshot yet): chart displays a flat line at the account's Initial Starting Capital (the baseline) across the full X-axis range, rather than an empty canvas.- Real-time behavior: as new snapshots arrive (Ref: CR-14 for the shared WebSocket resiliency pattern; Ref: BR_4.2.3.5 for the F5/reload edge case), the chart appends the new point and redraws the line — for the 1D filter this extends the line rightward within the current session; for 1W/1M the current (in-progress) day/week's point updates live in place per BR_4.2.3.4.Behaviour rule:- Read-only.

UC_4.2.4 — Profit factor

1. Overview

FieldContent
IDUC_4.2.4
Use CaseProfit factor
DescriptionThe ratio of gross profit to gross loss across the trader's closed trades at their current level, shown on the Overview screen alongside the underlying Gross Profit / Gross Loss values and a proportional profit-vs-loss bar. Same UC for both SIM and LIVE account types.
Zapier Flow
Zapier Table
3rd Party

Dashboard.png Overview screen — "Profit Factor" panel, populated state. Dashboard - Day 0.png Overview screen — "Profit Factor" panel, no-trades state (Profit Factor (0)).

Motion reference: UC_4.2.4 motion clips

2. Trigger

The Overview screen (Ref: UC_4.1.1) has rendered.

3. Pre-conditions

4. Post-conditions

  • The widget displays the trader's current-level Profit Factor, Gross Profit, and Gross Loss.

5. Basic Flow

  1. On Overview screen load, frontend calls GET /core-performance for the trader's current level (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Endpoints).
  2. Backend returns profit_factor, alongside gross_profit/gross_loss inputs used to compute it (Ref: BR_4.2.4.1).
  3. Frontend renders the score, the Gross Profit / Gross Loss values, and the proportional profit-vs-loss bar.
  4. On trade close, the PERFORMANCE_UPDATE WebSocket event pushes an updated profit_factor, and the widget updates live.

6. Exceptional Flow

  • WebSocket/API connection drops, market is closed, or page reload (F5): the widget continues displaying the latest successfully loaded values rather than becoming empty (Ref: CR-14).

7. Business Rules

BR_4.2.4.1: Profit Factor Formula, Scope, and Zero-Trade Clamp

Formula: Profit Factor = Gross Profit ÷ Gross Loss, where:

  • Gross Profit = sum of the absolute PnL of all winning closed trades at the trader's current level.
  • Gross Loss = sum of the absolute PnL of all losing closed trades at the trader's current level.
  • If Gross Loss = 0 (no losing trades yet), the result is Gross Profit itself, to avoid a divide-by-zero error.

(Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Logic Definitions "Profit Factor".)

Scope: the widget uses the current level scope (all closed trades since the trader reached their current level) via GET /core-performance / PERFORMANCE_UPDATE — there is no lookback-window selector on this widget (Source: BA confirmation, 2026-08-08, QnA_init_docs.md A-12). This differs from the period-scoped profit_factor shown inside the Win Rate widget's stats row (Ref: BR_4.2.5.1), which uses a selectable lookback window — the two are separate values by design, not duplicates.

Zero-trade clamp: when the trader has not closed any trade yet at their current level (Gross Profit = Gross Loss = 0), the widget displays 0 rather than (Source: BA confirmation, 2026-08-08, QnA_init_docs.md A-13; confirmed visually by wireframe Dashboard - Day 0.png, which shows "Profit Factor (0)").

8. Screen Description

No.Field NameField TypeDisplaying rule / Behaviour rule
1Profit FactorLabelDisplaying rule:- Shown inline in the panel title, e.g. "Profit Factor (1.85)". 0 when no trade has closed yet at the current level. Ref: BR_4.2.4.1.Behaviour rule:- Read-only. Updates live on trade close via PERFORMANCE_UPDATE.
2Gross ProfitLabelDisplaying rule:- Sum of absolute PnL of all winning closed trades at the current level. Monetary value display: Ref: CR-11.
3Gross LossLabelDisplaying rule:- Sum of absolute PnL of all losing closed trades at the current level. Monetary value display: Ref: CR-11.
4Profit / Loss barLabelDisplaying rule:- A single horizontal bar split into two proportional sections — PROFIT (green, left) and LOSS (red, right) — representing Gross Profit and Gross Loss (Ref: BR_4.2.4.1), with a needle/pointer marking the current split point between the two sections (Source: BA confirmation, 2026-09-03).- Split calculation: Profit section width % = Gross Profit ÷ (Gross Profit + Gross Loss) × 100; Loss section width % = Gross Loss ÷ (Gross Profit + Gross Loss) × 100. The two sections always sum to 100% of the bar's width; the needle sits at the boundary between them (i.e. at Profit section width % measured from the left edge).- First day / no trades yet (Gross Profit = Gross Loss = 0): the bar still renders as two sections — green (left) and red (right) — split evenly at the midpoint, with the needle centered at 50%, and both PROFIT/LOSS labeled $0, consistent with the "Profit Factor (0)" zero-trade clamp (Ref: BR_4.2.4.1). Behaviour rule:- Read-only. Section widths and needle position update live whenever gross_profit/gross_loss change via PERFORMANCE_UPDATE.

UC_4.2.5 — Win Rate

1. Overview

FieldContent
IDUC_4.2.5
Use CaseWin Rate
DescriptionWin-rate statistics for a selectable lookback window (10/30/50/100 trades) on the Overview screen — total trades, win rate %, period-scoped profit factor, average win/loss — plus a per-trade win/loss dot grid. Same UC for both SIM and LIVE account types.
Zapier Flow
Zapier Table
3rd Party

Dashboard.png Overview screen — "Win Rate" panel, populated state. Dashboard - Day 0.png Overview screen — "Win Rate" panel, no-trades state (empty dot grid).

Motion reference: UC_4.2.5 motion clips

2. Trigger

The Overview screen (Ref: UC_4.1.1) has rendered, or the user changes the lookback filter.

3. Pre-conditions

4. Post-conditions

  • The widget displays win-rate statistics and the win/loss dot grid for the selected lookback window.

5. Basic Flow

  1. On Overview screen load, frontend calls GET /win-rate-grid-data?lookback_count=100 (default 100, per wireframe default "Last 100 trades").
  2. Backend returns {period_total_trades, period_win_rate, period_profit_factor, period_avg_win, period_avg_loss, trade_results: [{ticker, timestamp_utc, pnl, holding_time_seconds, is_winner}...]}trade_results is an array of per-trade objects for the lookback window, not a flat array of booleans (Ref: BR_4.2.5.1).
  3. Frontend renders the stats row (Total trades, Win rate, Profit factor, Avg win/loss) and the dot grid from trade_results (Ref: BR_4.2.5.1).
  4. User changes the lookback dropdown (10/30/50/100) → frontend re-calls the endpoint with the new lookback_count.
  5. User hovers a dot in the grid → frontend renders a tooltip built from that trade's object (Ref: BR_4.2.5.1).
  6. On trade close, the PERFORMANCE_UPDATE WebSocket event pushes an updated win_rate_percent — alongside the other performance fields in that same event payload (profit_factor, avg_win, avg_loss, latest_trade, holding_time, etc.) — and the widget's Win rate stat updates live, without waiting for the next GET /win-rate-grid-data re-fetch (Source: RFQ_ Stack Trading Prop Tech V7.pdf §12 WebSocket Events, PERFORMANCE_UPDATE payload; Ref: BR_4.2.5.2).

6. Exceptional Flow

  • No closed trades yet: stats show 0/empty values and the dot grid renders with no colored dots (Ref: wireframe Dashboard - Day 0.png).
  • WebSocket/API connection drops, market is closed, or page reload (F5): the widget continues displaying the latest successfully loaded values rather than becoming empty (Ref: CR-14).

7. Business Rules

BR_4.2.5.1: Win/Loss Dot Grid — Per-Trade Data, Dot Coloring, and Hover Tooltip

Data source: trade_results in the Get Win Rate Grid Data response (GET /win-rate-grid-data?lookback_count=) is a chronologically ordered array of per-trade objects — one object per closed trade within the selected lookback window — not a flat array of booleans:

{
  "ticker": "ESZ5",
  "timestamp_utc": "2026-03-09 09:45 AM",
  "pnl": 450.00,
  "holding_time_seconds": 870,
  "is_winner": true
}

(Source: BA-supplied backend spec update, chat, 2026-08-10 — supersedes the earlier trade_results: [boolean...] shape; the backend now delivers individual trade metrics per dot instead of a flat win/loss flag.)

Dot coloring — one dot per trade in the grid, colored per trade object, checked in this order:

  • Greypnl = 0 (breakeven trade, no gain or loss), regardless of is_winner.
  • Greenis_winner = true (winning trade, pnl not 0).
  • Redis_winner = false (losing trade, pnl not 0).

Hover tooltip — hovering a dot renders a tooltip built directly from that trade's object, no separate lookup:

  • Ticker: ticker.
  • Trade time: timestamp_utc.
  • PnL: pnl, monetary value display per CR-11.
  • Holding time: frontend formats holding_time_seconds into a Xm Ys string (minutes = floor(seconds ÷ 60), remaining seconds = seconds mod 60) — e.g. 870 seconds displays as "14m 30s".
  • Tooltip trigger/dismiss behavior follows CR-10 Tooltip Interaction.

Grid layout: [ASSUMPTION] rows/columns, reading order follow the wireframe's column-major fill pattern (not confirmed by a data field in the response).

BR_4.2.5.2: Win Rate — Live Update via PERFORMANCE_UPDATE WebSocket Event

Per the client-supplied WebSocket events specification (Source: RFQ_ Stack Trading Prop Tech V7.pdf §12 WebSocket Events), the PERFORMANCE_UPDATE event fires on the closure of a trade and carries a JSON payload that includes win_rate_percent (alongside sharpe_ratio, sortino_ratio, profit_factor, avg_win, avg_loss, latest_trade, holding_time, etc.).

  • On receiving this event, the frontend updates the Win rate label (§8 row 3) in place, using the event's win_rate_percent value directly — no re-call of GET /win-rate-grid-data is needed for this field to update.
  • Same event also drives the live update of BR_4.2.4.1's profit_factor and appends the latest_trade object as a new dot in the win/loss dot grid (Ref: BR_4.2.5.1) — win_rate_percent updates in the same push, keeping the stats row and the dot grid in sync on every trade close.
  • This live-push update applies on top of the lookback-window fetch/re-fetch flow in §5 — it does not replace the GET /win-rate-grid-data?lookback_count= call on page load or filter change, since only the WebSocket event carries the incremental per-close update (Source: BA confirmation, 2026-09-03).

8. Screen Description

No.Field NameField TypeDisplaying rule / Behaviour rule
1Lookback filterDropdown (Single-selection)Displaying rule:- Options: 10, 30, 50, 100. Default: 100.Behaviour rule:- On selection: re-fetches GET /win-rate-grid-data?lookback_count=.
2Total tradesLabelDisplaying rule:- period_total_trades for the selected lookback window.
3Win rateLabelDisplaying rule:- period_win_rate, shown as a percentage. Formula: (count of winning trades ÷ total trade count) × 100, over the selected lookback window (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Risk Metrics Logic Definitions "Win Rate & RR").Behaviour rule:- Read-only. Updates live on trade close via the PERFORMANCE_UPDATE WebSocket event's win_rate_percent field, without waiting for a lookback-window re-fetch (Ref: BR_4.2.5.2).
4Profit factorLabelDisplaying rule:- period_profit_factor for the selected lookback window — distinct from the current-level Profit factor widget. Ref: BR_4.2.4.1.
5Avg win/lossLabelDisplaying rule:- period_avg_win / period_avg_loss. Monetary value display: Ref: CR-11.
6Win/loss dot gridLabelDisplaying rule:- One dot per trade in trade_results, ordered chronologically. Dot coloring, hover tooltip content, and data source: Ref: BR_4.2.5.1.

Changelog

DateVersionUpdated itemBeforeAfterNotes
2026-08-08v1Initial creationUC_4.2.1 → UC_4.2.5 full SRS (Overview, Trigger, Pre/Post-conditions, Basic/Exceptional Flow, Business Rules, Screen Description)Init Flow Step 3, Architect — seeQnA_init_docs.md for confirmed A-00→A-15 inputs
2026-08-31v2UC_4.2.1 §5 Basic Flow, §6 Exceptional Flow, new BR_4.2.1.3 (Snapshot Persistence, Delta Update by Position Identifier, Row Removal on Close), §8 row 1 (Symbol)POSITION_METRICS described as streaming the full Array<{symbol, ...}> of open positions on every event; no backend snapshot-persistence rule; no row-removal-on-close rule; Exceptional Flow only covered WebSocket disconnectBackend now holds the latest snapshot so the table restores on load/reload (F5) instead of appearing empty; subsequentPOSITION_METRICS events carry only the affected position's delta, keyed by symbol (position identifier) — Frontend maps the delta into the matching row; a closed-position flag on the delta triggers row removal; Exceptional Flow extended to cover market-closed and F5 alongside disconnectUser instruction (BA session), 2026-08-31
2026-08-31v2UC_4.2.2 §6, UC_4.2.3 §6, UC_4.2.4 §6, UC_4.2.5 §6 (Exceptional Flow — WebSocket/API connection drop wording)Only covered "WebSocket connection drops" / "WebSocket/API connection drops" (client reconnect case)Extended to also cover "market is closed" and "page reload (F5)" — widget/chart continues showing the latest successfully loaded snapshot/values rather than resetting to empty in either case, per the shared rule now defined atCR-14User instruction (BA session), 2026-08-31 — aligned withcommon_rules.md v1.7 CR-14 expansion
2026-08-31v3UC_4.2.1 §5 Basic Flow (steps 2-4), §7 BR_4.2.1.3, §8 row 1 (Symbol) — keying field for delta update / row removalDelta update and row removal keyed bysymbolCorrected: keyed byposition_id (the actual position identifier), not symbol — a trader can hold multiple open positions on the same symbol, so symbol cannot uniquely identify a row; symbol remains a display-only fieldUser instruction (BA session), 2026-08-31
2026-08-31v4UC Index (UC_4.2.3 row), UC_4.2.3 §1 Overview, §5 Basic Flow (steps 2-4), §6 Exceptional Flow, §7 BR_4.2.3.1 (rewritten), new BR_4.2.3.2/BR_4.2.3.3/BR_4.2.3.4/BR_4.2.3.5, §8 row 2 (Equity chart)Chart plotted raw Daily Balance snapshots only (excludes Unrealized PnL);GET /equity-curve float_value = raw account balance; Y-axis started near/at $0 and auto-scaled to balance min/max only; no Target/Stop overlay; no documented intraday snapshot cadence; 1W/1M returned undefined granularity; no F5-vs-socket-push edge case[CR] Reformulated as Net Equity = Initial Starting Capital + (Realized PnL + Unrealized PnL) (new BR_4.2.3.1 formula); backend float_value now the absolute Net Equity notional value, not a relative delta; baseline sourced from Max_Forex_Notional (Table A, existing) or Max_Futures_Notional (Table B, ⚠️ flagged as unconfirmed/not yet in documented Table B schema — see BR_4.2.3.1 action item); new BR_4.2.3.2 (frontend performs no client-side math, plots backend values as-is); new BR_4.2.3.3 (Y-axis dynamic auto-scale to actual high/low with padding to keep Target=Profit_Target/Stop=Market_Loss_When_Stopped from GET /current-level-detail visible; full X/Y-axis and baseline color semantics — green above baseline = profit, red below = loss); new BR_4.2.3.4 (30-min intraday snapshot cadence for 1D; 1W aggregates by day, 1M aggregates by week, both using the last snapshot of the closed period; current in-progress day/week stays live); new BR_4.2.3.5 (F5/reload during the gap between snapshot capture and WebSocket push must render the latest already-captured snapshot immediately, per CR-14 pattern)User instruction (BA session), 2026-08-31 — formalized asCR-20260831-001 (see References/CR/2026-08-31_equity-curve-net-equity-formula/), since this changes the previously RFQ-V7-sourced Daily-Balance-only formula
2026-08-31v5BR_4.2.3.1 (Max_Futures_Notional baseline sourcing); BR_4.2.3.3 (removed [CR] tag)Max_Futures_Notional flagged ⚠️ as unconfirmed/not-yet-in-documented-Table-B-schema, with open action item to confirm with client whether new column or alias of Futures_Capital; BR_4.2.3.3 tagged [CR]Client-confirmed:Max_Futures_Notional is a genuinely new Table B column, distinct from Futures_CapitalFutures_Capital = actual margin cash deposited at the FCM (e.g. $1,250), Max_Futures_Notional = face value/buying power (e.g. $25,000); baseline must use the notional field because prop traders track accounts by notional size, not margin cash. Flag/action item resolved — Table B schema migration (add column) still required before backend implementation. Removed [CR] tag from BR_4.2.3.3: Y-axis auto-scale/Target-Stop overlay is display/rendering behavior, not itself the CR — the CR is the Net Equity formula + baseline field change (BR_4.2.3.1)Client decision, relayed by user (BA session), 2026-08-31 — resolves the flagged discrepancy from CR-20260831-001 v4
2026-09-03v6UC_4.2.4 §8 row 4 (Profit / Loss bar) — section color/position layoutBar renderedLOSS (red) on the left and PROFIT (green) on the right; needle position measured from the left edge as Loss section width %; first-day/no-trade state showed red (left) / green (right)Swapped layout:PROFIT (green) now on the left, LOSS (red) on the right; needle position now measured from the left edge as Profit section width %; first-day/no-trade state now shows green (left) / red (right). Formulas and zero-trade clamp behavior (BR_4.2.4.1) unchangedSource: BA confirmation, 2026-09-03
2026-09-03v7UC_4.2.3 §7 BR_4.2.3.1 — Initial Starting Capital baseline sourcing for evaluation (SIM) accounts not yet promoted to LIVEBR_4.2.3.1 only stated the Table A/Max_Forex_Notional vs. Table B/Max_Futures_Notional baseline split by asset class, without addressing evaluation (SIM) accounts specifically — left ambiguous whether an account still in evaluation used the same lookupClarified: evaluation (SIM) accounts use the identical Table A/B lookup — no separate baseline source. The account's current level while in evaluation is Level 1/2/5 per the purchased track (Associate/Accelerate/Advanced, Ref:UC_4.8.2 BR_4.8.2.2), and the baseline is Max_Forex_Notional/Max_Futures_Notional from the Table A/B row for that levelSource: BA confirmation, 2026-09-03
2026-09-03v8UC_4.2.3 §7 BR_4.2.3.1 — added explicit "Baseline data source (Table A/B lookup)" explanation; note under the formula on term provenance; formula expandedThe Table A/B lookup mechanism for the baseline was only described inline inside the bulleted list below the formula, with no standalone statement ofhow the chart fetches the baseline; formula had no note on where its other terms come from; formula showed only the 2-term expanded formAdded a lead-in paragraph stating the baseline is looked up live from Table A (Forex Matrix)/Table B (Futures Matrix) by asset class + current level, readingMax_Forex_Notional/Max_Futures_Notional. Added a note directly under the formula clarifying Account Balance and Unrealized PnL are read from the trader's own trading account (live account/position feed) — only Initial Starting Capital comes from the Table A/B lookup. Extended the formula to Net Equity = Initial Starting Capital + (Realized PnL + Unrealized PnL) = Account Balance + Unrealized PnL, with a bullet noting the two forms are equivalent since Account Balance already embeds Initial Starting Capital + Realized PnLSource: BA confirmation, 2026-09-03
2026-09-03v9UC_4.2.5 §5 Basic Flow step 6 (new); new BR_4.2.5.2 (Win Rate — Live Update via PERFORMANCE_UPDATE); §8 row 3 (Win rate) Behaviour ruleWin rate stat (period_win_rate) was only ever fetched via GET /win-rate-grid-data on page load / lookback filter change — no rule stated it also updates live on trade close, even though the client-supplied PERFORMANCE_UPDATE WebSocket payload (RFQ Stack Trading Prop Tech V7.pdf) already carries a win_rate_percent fieldAdded Basic Flow step 6 and new BR_4.2.5.2 documenting that PERFORMANCE_UPDATE (fired on trade close) pushes win_rate_percent and the frontend updates the Win rate label in place from that field, in addition to the lookback-window fetch flow — same event that already drives BR_4.2.4.1 profit factor and the dot-grid append (BR_4.2.5.1), now confirmed to also carry win_rate_percent in sync. §8 row 3 Behaviour rule added, referencing BR_4.2.5.2Source: RFQ_ Stack Trading Prop Tech V7.pdf §12 WebSocket Events (PERFORMANCE_UPDATE payload); BA confirmation 2026-09-03

On this page

UC IndexNote on UC_4.3 relationshipOverview — Performance WidgetsUC_4.2.1 — Position Monitor Table1. Overview2. Trigger3. Pre-conditions4. Post-conditions5. Basic Flow6. Exceptional Flow7. Business RulesBR_4.2.1.1: Est. Swap — Forex-Only Visibility Window, Asynchronous StreamingBR_4.2.1.2: Empty StateBR_4.2.1.3: Snapshot Persistence, Delta Update by Position Identifier, and Row Removal on Close8. Screen DescriptionUC_4.2.2 — The Pulse1. Overview2. Trigger3. Pre-conditions4. Post-conditions5. Basic Flow6. Exceptional Flow7. Business RulesBR_4.2.2.1: Pulse Score — Reset, Deductions, RewardsBR_4.2.2.2: Real-Time Update via current_pulse_scoreBR_4.2.2.3: Widget Display — Score and Trend Chart8. Screen DescriptionUC_4.2.3 — Equity Curve1. Overview2. Trigger3. Pre-conditions4. Post-conditions5. Basic Flow6. Exceptional Flow7. Business RulesBR_4.2.3.1: 1D/1W/1M Filter — Re-fetch on Change; Net Equity Formula & BaselineBR_4.2.3.2: Frontend Renders Absolute Values As-Is — No Client-Side MathBR_4.2.3.3: Y-Axis Dynamic Scaling & Target/Stop OverlayBR_4.2.3.4: Snapshot Cadence & 1W/1M AggregationBR_4.2.3.5: F5/Reload Reflects the Latest Captured Snapshot Immediately8. Screen DescriptionUC_4.2.4 — Profit factor1. Overview2. Trigger3. Pre-conditions4. Post-conditions5. Basic Flow6. Exceptional Flow7. Business RulesBR_4.2.4.1: Profit Factor Formula, Scope, and Zero-Trade Clamp8. Screen DescriptionUC_4.2.5 — Win Rate1. Overview2. Trigger3. Pre-conditions4. Post-conditions5. Basic Flow6. Exceptional Flow7. Business RulesBR_4.2.5.1: Win/Loss Dot Grid — Per-Trade Data, Dot Coloring, and Hover TooltipBR_4.2.5.2: Win Rate — Live Update via PERFORMANCE_UPDATE WebSocket Event8. Screen DescriptionChangelog