Skip to content

Add backtest metrics module (Sharpe, max drawdown, inventory-time-weighted PnL)#52

Open
Pattermesh wants to merge 1 commit into
mainfrom
pattermesh/meridian-backtest-metrics
Open

Add backtest metrics module (Sharpe, max drawdown, inventory-time-weighted PnL)#52
Pattermesh wants to merge 1 commit into
mainfrom
pattermesh/meridian-backtest-metrics

Conversation

@Pattermesh

Copy link
Copy Markdown
Contributor

What

Adds a reusable backtest-metrics module to the backtest engine with unit tests against known numeric vectors.

New: src/backtest/metrics.py

Pure, side-effect-free functions (numpy only):

  • sharpe_ratio(returns, risk_free_rate=0.0, periods_per_year=1.0) — mean(excess)/std(excess) with optional annualisation; returns 0.0 for <2 points or zero volatility.
  • max_drawdown(equity_curve) — largest running-peak-to-trough drop, in curve units; 0.0 for monotonic or trivial curves.
  • inventory_time_weighted_pnl(pnl_curve, inventory_curve) — sum of abs(inventory_carried) * pnl_increment per step, surfacing whether PnL is compensation for inventory risk.

Tests: tests/unit/backtest/test_metrics.py

17 tests with hand-computed expected values, e.g. drawdown of [100,120,90,110,80,130] == 40, ITW-PnL of pnl=[0,10,5,20], inv=[2,-3,4,1] == 65. Covers risk-free subtraction, sqrt-periods annualisation, short-inventory magnitude, length-mismatch ValueError, and edge/empty cases.

Refactor: src/backtest/engine.py

BacktestEngine.run now consumes the shared sharpe_ratio / max_drawdown instead of inline duplicates. Behaviour preserved (same mean/std Sharpe, same running-peak drawdown).

Test output

$ PYTHONPATH=. python3 -m pytest tests/unit/backtest/test_metrics.py -q
17 passed in 0.56s

$ PYTHONPATH=. python3 -m pytest -q
144 passed, 2 skipped, 703 warnings

CI (.github/workflows/ci.yml) already exists and runs python -m pytest tests/ -v, which auto-discovers the new tests/unit/backtest/ directory — no workflow change needed.

🤖 Generated with Claude Code

…ghted PnL)

Extract reusable, side-effect-free metric functions into
src/backtest/metrics.py and cover them with unit tests against known
numeric vectors. Wire BacktestEngine.run to consume the shared
functions instead of inline duplicates (behaviour preserved).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@abhicris

Copy link
Copy Markdown
Contributor

Welcome to kcolbchain, @Pattermesh — glad you're here. 🌱

Here's what happens from this PR:

  1. Our automated review looks for obvious issues (tests, secrets, size) within a couple of hours.
  2. If it's clean and CI passes, we merge without back-and-forth.
  3. If we need changes, we'll leave a specific comment — not a generic nit. Push another commit and we re-review.

While you wait:

  • Run the repo's tests locally (see the repo README.md).
  • Keep the PR scoped to one concern — bigger PRs land slower.
  • Don't commit tokens or .env contents.

What happens after your first merge

Thanks for writing the code. We're building this to last.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants