Skip to content

Fix two critical bugs: avg entry price and equity curve VWAP benchmark#33

Merged
tommed merged 2 commits intomainfrom
claude/codebase-review-HBYM5
Apr 19, 2026
Merged

Fix two critical bugs: avg entry price and equity curve VWAP benchmark#33
tommed merged 2 commits intomainfrom
claude/codebase-review-HBYM5

Conversation

@tommed
Copy link
Copy Markdown
Contributor

@tommed tommed commented Apr 19, 2026

Summary

  • get_position() returned wrong avg_entry_price for mixed buy/sell fills, causing incorrect unrealised_pnl and corrupting Sharpe, drawdown, and total equity metrics downstream.
  • IDC equity curve snapshots benchmarked fills against zero price when no market trades had occurred yet for a product, wildly inflating or deflating cumulative_pnl in early MTUs.
  • Removed duplicate VWAP accumulation in _run_idc — the matching engine already tracks this internally since the previous fix; exposed get_vwap_accumulator() to avoid the dual-write.

Details

Critical: get_position() avg entry price (backtest.py:492)

The old formula blended buy and sell costs into a single total_cost divided by net_mw. After BUY 100@50 then SELL 50@60, the remaining 50 MW long reported avg_entry_price = 60 instead of 50. Root cause: abs(total_cost / net_mw) — the sell at 60 lifted the blended cost.

Fix: track buy and sell cost/volume separately. For net long positions use total_buy_cost / total_buy_vol; for net short use total_sell_cost / total_sell_vol. Three regression tests added covering pure long, partial-close long, and partial-buyback short.

Critical: Equity curve zero VWAP fallback (backtest.py:1174)

running_vwaps.get(product_id, Decimal("0")) fell back to 0 when no historical trades had been seen yet for a product. compute_fill_pnl with a zero benchmark makes every buy appear as a loss equal to fill_price × volume and every sell a gain of the same magnitude — corrupting cumulative_pnl and every metric built on it.

Fix: fall back to f.price (zero alpha — fill benchmarked against itself until real market VWAP data accumulates).

Cleanup: Duplicate VWAP accumulation

Removed the idc_vwap_accum local dict from _run_idc and exposed ContinuousMatchingEngine.get_vwap_accumulator() instead. Both accumulated identical data; the dual-write was a maintenance hazard. Removed now-unused HistoricalTrade import from backtest.py.

Test plan

  • tests/test_delivery_position.py — three new regression tests for mixed buy/sell avg price
  • make ci passes (727 tests, 0 failures)

https://claude.ai/code/session_01XqYtc2t1oCV8eTmXN8aaiY

claude added 2 commits April 19, 2026 08:41
Critical:
- get_position() was computing avg_entry_price by blending buy and sell
  costs into a single total_cost, then dividing by net_mw. After a partial
  close at a different price (e.g. BUY 100@50 then SELL 50@60) the formula
  returned 60 instead of 50 for the remaining long. Fix: track buy and sell
  cost/volume separately; use total_buy_cost/total_buy_vol for net long
  positions and total_sell_cost/total_sell_vol for net short. Three new
  regression tests added.

- IDC equity curve snapshots used Decimal("0") as the VWAP benchmark
  fallback when no market trades had occurred yet for a product, causing
  fill PnL to be benchmarked against zero price and corrupting cumulative_pnl
  (and therefore Sharpe, drawdown, and total_equity). Fix: fall back to
  f.price (zero alpha — neutral until real VWAP data accumulates).

Cleanup:
- Removed the duplicate idc_vwap_accum accumulator from _run_idc. The
  matching engine already accumulates the same data in _vwap_accum (added
  in the previous fix for get_vwap). Exposed get_vwap_accumulator() on
  ContinuousMatchingEngine so the engine loop can read it directly, removing
  the dual-write maintenance hazard. Removed now-unused HistoricalTrade
  import from backtest.py.

https://claude.ai/code/session_01XqYtc2t1oCV8eTmXN8aaiY
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@tommed tommed merged commit 1e58b4e into main Apr 19, 2026
2 checks passed
@tommed tommed deleted the claude/codebase-review-HBYM5 branch April 19, 2026 09:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants