Skip to main content
Pro Feature. Requires a Pro or Ultra subscription. Get started at api.mathematicalcompany.com

Horizon Backtesting

Horizon provides a full backtesting engine via hz.backtest(). It uses the same pipeline, risk engine, and paper exchange as live trading. Your strategy code runs identically in both modes.
By default, backtesting uses mid-price matching against the paper exchange. For simulation, enable L2 orderbook replay, probabilistic fill models, market impact, and latency simulation. All matching logic runs in Rust.

Quick Start


hz.backtest() Signature


Data Formats

Horizon accepts historical data in multiple formats.
The simplest format. Each dict represents one tick.
Required fields: timestamp, price. Optional: bid, ask, volume.

L2 Orderbook Simulation

For realistic prediction market backtesting, replay historical L2 orderbook snapshots. Orders are matched by walking the book at each tick, not at a single mid-price.

Book Data Format

Pass book_data as a dict mapping market IDs to lists of orderbook snapshots:
Each snapshot has timestamp (float), bids (list of (price, size) tuples, descending), and asks (list of (price, size) tuples, ascending). Book state carries forward between snapshots. When book_data is provided, the engine automatically switches to the BookSim exchange which walks the L2 book to fill orders. BookSim supports split maker/taker fees via paper_maker_fee_rate and paper_taker_fee_rate, computing mid from the best bid/ask to determine each fill’s maker/taker status.

Fill Models

Control how realistically orders are filled against the book.
Default behavior. Orders fill if the price crosses the book level. 100% fill rate at each level.

Market Impact

Simulate price impact from your own orders. Both temporary (during fill) and permanent (persists after fill) impact are supported.
How it works: When your buy order walks the ask side, each level’s effective price increases by filled_so_far * temporary_bps / 10000. After the fill, total_notional * permanent_fraction * temporary_bps / 10000 is added as a persistent book displacement.

Latency Simulation

Simulate the delay between order submission and arrival at the exchange:
Latency is converted to ticks based on the average tick interval in your data. Orders enter a pending queue and only become active after the specified delay. This models the real-world effect of network latency on fill rates.

Calibration Analytics

Evaluate prediction accuracy with Rust-powered analytics. Available when outcomes are provided.

Calibration Curve

Log Loss

Edge Decay

Measure how your edge decays as events approach resolution:

Walk-Forward Optimization

Avoid overfitting with rolling out-of-sample testing. The walk_forward() function splits your data into train/test windows, runs grid search on each training window, and evaluates the best parameters on the held-out test window.

walk_forward() Parameters

All additional **kwargs are passed through to each backtest() call (e.g., fill_model, impact_temporary_bps).

WalkForwardResult


BacktestResult

hz.backtest() returns a BacktestResult object with full analytics.

result.metrics

The metrics property returns a lazy-computed Metrics object with all performance statistics.

Full Metrics Reference

result.summary()

Returns a formatted string summary of all metrics, ready for printing.

result.pnl_by_market()

Returns a dict mapping each market ID to its realized PnL.

result.equity_curve

A list of (timestamp, equity) tuples showing the portfolio value over time.

result.trades

A list of Fill objects representing every trade executed during the backtest.

result.to_csv()

Export results to CSV files for further analysis.

Examples

Basic Backtest

Multi-Feed Backtest

DataFrame Input

Brier Score with Outcomes

For prediction markets, you can evaluate calibration by providing known outcomes.
A Brier score of 0.0 means perfect calibration; 0.25 is equivalent to always predicting 50%. Scores below 0.2 indicate meaningful predictive power.

With Risk Configuration

For more realistic results, enable L2 book simulation with probabilistic fills, market impact, and latency. This significantly reduces the gap between backtest and live performance. Use walk-forward optimization to validate that your strategy parameters are robust out-of-sample.

Tearsheet

Generate performance reports from backtest results.
Even with L2 simulation, backtests cannot perfectly replicate live trading. Your own orders would have changed the book in real time (market impact feedback), and fill probabilities are estimates. Always apply a conservative discount to backtest results.