trader.reporting.equity_curve module¶
Equity curve over time from account_snapshots (requirements §12.3, issue #20).
Split deliberately into two halves:
Data preparation (equity_curve_points, summarize) turns AccountSnapshot rows into plain, sorted EquityPoints and a summary — pure functions, no rendering, fully unit-testable without a terminal.
Rendering (render_sparkline, format_report) turns those points into text. This stayed an ASCII sparkline even after trader web (§12.3) added a second, interactive renderer over the SAME two functions below — this one is still useful with no browser (e.g. over SSH into the host running the daemon), and needed no new dependency when it was built. It is not being replaced; trader.reporting.web.charts.equity_curve_figure is the sibling that calls equity_curve_points/summarize for a browser instead.
The ROI-vs-benchmark overlay from the issue’s stretch goal is built in trader web’s equity-curve page, not here — this module stays exactly the narrow ASCII report it was.
- class trader.reporting.equity_curve.EquityCurveSummary(start, end, high, low, change, change_pct, count)[source]¶
Bases:
objectHeadline numbers over a series of EquityPoints.
- Parameters:
start (EquityPoint)
end (EquityPoint)
high (EquityPoint)
low (EquityPoint)
change (Decimal)
change_pct (Decimal | None)
count (int)
- start: EquityPoint¶
- end: EquityPoint¶
- high: EquityPoint¶
- low: EquityPoint¶
- change: Decimal¶
- change_pct: Decimal | None¶
None when start.equity is zero — a percentage change from zero is undefined, not zero, so this is None rather than a misleading 0% or a ZeroDivisionError reaching the CLI.
- count: int¶
- class trader.reporting.equity_curve.EquityPoint(captured_at, equity)[source]¶
Bases:
objectOne plotted point: an account’s equity at a point in time.
- Parameters:
captured_at (datetime)
equity (Decimal)
- captured_at: datetime¶
- equity: Decimal¶
- trader.reporting.equity_curve.equity_curve_points(snapshots)[source]¶
Convert snapshot rows into chronological EquityPoints.
Sorts defensively by (captured_at, id) rather than trusting the caller’s query order, so this function is correct standalone and testable with an out-of-order fixture — the same tiebreak SnapshotRepository uses.
- Parameters:
snapshots (Sequence[AccountSnapshot])
- Return type:
list[EquityPoint]
- trader.reporting.equity_curve.format_report(points, width=60)[source]¶
Render the full CLI report: sparkline plus a start/end/high/low summary.
- Parameters:
points (Sequence[EquityPoint])
width (int)
- Return type:
str
- trader.reporting.equity_curve.render_sparkline(points, width=60)[source]¶
Render points as a one-line block-character sparkline.
Downsamples via _resample when there are more points than width; otherwise renders one glyph per point (a narrower series than width prints shorter than width, rather than being stretched).
- Parameters:
points (Sequence[EquityPoint])
width (int)
- Return type:
str
- trader.reporting.equity_curve.summarize(points)[source]¶
Start/end/high/low/change over a chronological series, or None if empty.
points is assumed already chronological (as equity_curve_points returns it); this does not re-sort.
- Parameters:
points (Sequence[EquityPoint])
- Return type:
EquityCurveSummary | None