Skip to content

Add multi asset backtest support with full single-asset backward compatibility#1351

Open
TheNoobiCat wants to merge 4 commits intokernc:masterfrom
TheNoobiCat:master
Open

Add multi asset backtest support with full single-asset backward compatibility#1351
TheNoobiCat wants to merge 4 commits intokernc:masterfrom
TheNoobiCat:master

Conversation

@TheNoobiCat
Copy link

Why

The change makes multi-asset portfolio simulation a first-class capability in backtesting.py while preserving existing single-asset behavior and API.

The goal is to let users run one backtest across multiple symbols with minimal friction (ideally only changing data from a DataFrame to a dict[symbol -> DataFrame]), and keep strategy ergonomics close to current single-asset usage.

What I changed

1) Backtest input now supports multi-asset data

  • Backtest(...) now accepts:
    • pd.DataFrame (legacy, unchanged)
    • Mapping[str, pd.DataFrame] (preferred multi-asset API)
    • Sequence[pd.DataFrame] (fallback; auto-symbols)
  • In multi-asset mode, all input DataFrames must have identical aligned indexes.
    • Clear validation error is raised if indexes differ.

2) Strategy trading API extended with optional symbol=

  • Strategy.buy(...) and Strategy.sell(...) now accept optional symbol.
  • Single-asset behavior is unchanged: symbol is optional and legacy code still works.

3) Data access expanded for per-symbol use

  • self.data supports per-symbol access in multi-asset strategies:
    • self.data['AAPL'].Close[-1]
    • self.data.get('BTC-USD')
  • Existing single-asset access patterns remain valid:
    • self.data.Close[-1]

4) Position / order / trade internals are symbol-aware

  • Orders and trades now carry symbol metadata.
  • Broker execution logic is symbol-scoped for order matching and position management.
  • self.position['AAPL'] provides per-symbol position view.
  • self.position.size remains portfolio aggregate (legacy semantics preserved).

5) Stats remain portfolio-level; trade table adds symbol attribution

  • Existing top-level stats format remains unchanged (Return, Sharpe, Max Drawdown, etc.).
  • Multi-asset runs aggregate performance at portfolio level.
  • stats._trades now includes Symbol in multi-asset mode for attribution.

6) Plotting supports multi-asset runs

  • bt.plot() signature remains compatible.
  • Multi-asset plotting now includes:
    • Total equity curve
    • Per-asset normalized price section
    • Symbol-attributed trade markers
  • Single-asset plots remain visually and behaviorally consistent.

7) Compatibility fix for FractionalBacktest

  • FractionalBacktest.run() now patches both internal _data and _asset_data paths so fractional scaling continues to work correctly after multi-asset integration.

Backward compatibility

  • Existing single-asset calls and strategies continue to work unchanged.
  • Existing .run(), .plot(), and stats consumption patterns remain valid.
  • Legacy single-asset strategy code does not need modification.

Tests

Added focused coverage for:

  • Multi-asset run correctness and Symbol propagation in _trades
  • Per-symbol position[...] access + aggregate portfolio position behavior
  • Misaligned multi-asset index validation

Also verified key existing single-asset tests continue to pass.

Notes

  • Multi-asset optimize path currently prioritizes correctness/backward safety over multiprocessing complexity in this iteration.
  • Portfolio settings (cash, commission, margin, etc.) remain shared across assets

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.

1 participant