trader.reporting.web.charts module¶
Plotly figures for trader web — pure functions, no FastAPI coupling.
Mirrors equity_curve.py’s split between data and rendering: every function here takes rows the caller already fetched and returns a plotly.graph_objects.Figure, so each is testable without a running server. Decimal is used throughout Core; every value crosses to float only inside these functions, at the point it is handed to Plotly — the same presentation-only cast render_sparkline already performs internally.
- trader.reporting.web.charts.candlestick_figure(symbol, bars, trades=())[source]¶
OHLC candlesticks for one symbol, with a marker on every filled buy/sell against that symbol’s own price line.
The previously-deferred “per-symbol candlestick + entry/exit markers” item (docs/next-session.md, 2026-08-18 session) — unblocked by simply reading live bars through the same MarketDataProvider.get_history the benchmark lines on / already call, rather than the backtest-only local bars cache the earlier deferral was about.
- trader.reporting.web.charts.cumulative_pl_by_strategy_figure(trips)[source]¶
Running total of realized P/L over time, one line per strategy.
pnl_by_strategy_figure answers “which strategy is ahead right now”; this answers “is that lead a trend or one lucky trade” — the same “learn from wins and losses as they happen, not just a lagging total” framing issue #28 was raised for. Each strategy’s own trips are ordered by closed_at before the running sum, so two strategies’ lines are each internally chronological even though the account interleaves them.
- Parameters:
trips (Sequence[RoundTrip])
- Return type:
Figure
- trader.reporting.web.charts.equity_curve_figure(points, benchmarks, starting_value, trades=())[source]¶
Account equity over time, one line per benchmark ticker alongside it, with a marker for every filled buy/sell.
Each benchmark is plotted as what starting_value would be worth having bought and held that ticker instead, scaled from its own first close — the same “lump sum into a benchmark” framing trader performance already uses via buy_and_hold, just continuous instead of first/last only.
trades are placed on the equity line itself (via _value_at_or_before), not on a separate axis — hovering answers “what happened here” the same way the ../backtesting finplot scripts overlay buy/sell markers on a price line, just applied to account equity instead of one symbol’s price, since this chart has no single price series to mask against. Unfilled orders (filled_at is None) are excluded — this answers “when did a buy or sell actually happen”, not “when was one submitted.”
- Parameters:
points (Sequence[EquityPoint])
benchmarks (Mapping[str, Sequence[Bar]])
starting_value (Decimal)
trades (Sequence[Trade])
- Return type:
Figure
- trader.reporting.web.charts.pnl_by_strategy_figure(trips)[source]¶
Realized P/L summed per strategy, across every closed round trip.
strategy_id is nullable on RoundTrip (rows predating the column, or a non-strategy path like acceptance_forced_buy); those group under “(unknown)” rather than being silently dropped from the total.
- Parameters:
trips (Sequence[RoundTrip])
- Return type:
Figure
- trader.reporting.web.charts.pnl_by_symbol_figure(trips)[source]¶
Realized P/L summed per symbol, across every closed round trip.
- Parameters:
trips (Sequence[RoundTrip])
- Return type:
Figure
- trader.reporting.web.charts.pnl_heatmap_figure(trips)[source]¶
Realized P/L summed per (symbol, strategy) cell.
Sized to the real data rather than a fixed grid — a heatmap over mostly empty cells is worse than no heatmap, and this project’s live sample is currently ~10-20 total round trips (see issue #28’s own caution). Rows and columns are exactly the symbols/strategies that actually appear, never a padded universe.
- Parameters:
trips (Sequence[RoundTrip])
- Return type:
Figure
- trader.reporting.web.charts.trade_distribution_figure(trips)[source]¶
One point per closed round trip: return % vs. holding period.
Reveals a pattern a total-return number hides — e.g. “short holds lose, longer holds win” (or the reverse) — by plotting every trip rather than only its sum. return_pct returns None for a zero cost basis (a corporate-action share grant); those trips are dropped from this chart rather than plotted at a fabricated 0%, since they would otherwise land on the axis and read as a real, unremarkable outcome.
- Parameters:
trips (Sequence[RoundTrip])
- Return type:
Figure