Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions examples/backtest_adapter.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,43 @@
"""Use the installed backtest-harness package through its public API.

This example intentionally has no sibling-path or ``sys.path`` fallback. Install
the dependency first, then run the example from this repository.
the dependency first, then run the example from this repository::

uv pip install -e ../verdict-backtest
uv run python examples/backtest_adapter.py
"""

from __future__ import annotations

from backtest_harness import MonteCarloSimulator, load_kalshi_sample_trades, tearsheet
from backtest_harness import run_counterfactual

# Small illustrative per-trade return series (fractions). Synthetic, not market data.
SAMPLE_RETURNS = (0.04, -0.02, 0.03, -0.05, 0.06, 0.01, -0.03, 0.05, -0.01, 0.02, 0.03, -0.04)


def main() -> None:
"""Print a small deterministic report from the installed backtest package."""
returns, provenance = load_kalshi_sample_trades()
stats = MonteCarloSimulator.simulate_equity_paths(
trade_returns_pct=returns,
evidence = run_counterfactual(
run_id="strategy-adapter-example",
trade_returns=SAMPLE_RETURNS,
starting_equity=1_000.0,
num_simulations=1_000,
trades_per_sim=returns.size,
seed=20_260_713,
dataset_ref="synthetic:strategy-example-v1",
num_simulations=1_000,
trades_per_sim=len(SAMPLE_RETURNS),
walk_forward_splits=3,
)
summary = tearsheet(returns)
assert summary is not None
results = evidence["results"]
monte_carlo = results["monte_carlo"]

print("Installed backtest-harness adapter")
print(f" Fixture: {provenance['name']}")
print(f" P50 final equity: ${stats['p50_equity']:.2f}")
print(f" Risk of ruin: {stats['prob_ruin']:.2%}")
print(f" Max drawdown: {summary['max_drawdown']:.2%}")
print(
f" Provider: {evidence['receipt']['provider']} {evidence['receipt']['provider_version']}"
)
print(f" P50 final equity: ${monte_carlo['p50_equity']:.2f}")
print(f" Risk of ruin: {monte_carlo['prob_ruin']:.2%}")
print(f" Max drawdown: {results['tearsheet']['max_drawdown']:.2%}")
print(f" Results hash: {evidence['results_hash']}")


if __name__ == "__main__":
Expand Down
37 changes: 27 additions & 10 deletions tests/integration/test_backtest_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,36 @@

import pytest

SAMPLE_RETURNS = (0.04, -0.02, 0.03, -0.05, 0.06, 0.01, -0.03, 0.05, -0.01, 0.02, 0.03, -0.04)

@pytest.mark.integration
def test_backtest_harness_public_adapter() -> None:
"""Use only the installed package surface when the sibling package is present."""

def _run(seed: int) -> dict:
backtest_harness = pytest.importorskip("backtest_harness")
returns, provenance = backtest_harness.load_kalshi_sample_trades()
stats = backtest_harness.MonteCarloSimulator.simulate_equity_paths(
trade_returns_pct=returns,
return backtest_harness.run_counterfactual(
run_id="strategy-adapter",
trade_returns=SAMPLE_RETURNS,
starting_equity=1_000.0,
seed=seed,
dataset_ref="synthetic:strategy-adapter-v1",
num_simulations=100,
trades_per_sim=returns.size,
seed=20_260_713,
trades_per_sim=len(SAMPLE_RETURNS),
walk_forward_splits=3,
)

assert provenance["source"] == "synthetic"
assert stats["used_numba"] is True

@pytest.mark.integration
def test_backtest_harness_public_adapter() -> None:
"""Use only the installed package surface when the sibling package is present."""
evidence = _run(seed=20_260_713)

assert evidence["receipt"]["provider"] == "verdict-backtest"
assert evidence["receipt"]["outcome"] == "success"
monte_carlo = evidence["results"]["monte_carlo"]
assert monte_carlo["p05_equity"] <= monte_carlo["p50_equity"] <= monte_carlo["p95_equity"]
assert 0.0 <= monte_carlo["prob_ruin"] <= 1.0


@pytest.mark.integration
def test_backtest_harness_adapter_is_reproducible() -> None:
"""The same seed must give the same evidence hash across the package boundary."""
assert _run(seed=7)["results_hash"] == _run(seed=7)["results_hash"]
Loading