trading/tests/backtester/test_metrics_kevin_extensions.py
Viktor Barzin cd75c4ab7e
Some checks failed
ci/woodpecker/push/woodpecker Pipeline was canceled
feat(backtester): extend compute_metrics with alpha/beta/winners/best
In-place extension (no fork). Existing tests still pass; new fields are
optional and None when no benchmark is supplied.
2026-05-24 00:57:42 +00:00

99 lines
2.9 KiB
Python

"""Kevin-extension tests for compute_metrics (alpha/beta/winners/losers/best/worst)."""
from datetime import datetime, timedelta, timezone
from decimal import Decimal
import pandas as pd
from backtester.metrics import compute_metrics
def _ts(day):
return datetime(2026, 5, 15, tzinfo=timezone.utc) + timedelta(days=day)
def test_compute_metrics_returns_alpha_and_beta_with_benchmark():
spy = pd.DataFrame(
{
"open": [500, 500, 510, 510, 520],
"high": [500] * 5,
"low": [500] * 5,
"close": [500, 500, 510, 510, 520],
"volume": [0] * 5,
},
index=pd.date_range("2026-05-15", periods=5, freq="D", tz="UTC"),
)
trades = [
{
"symbol": "NVDA",
"source_mention_id": 1,
"entry_at": _ts(0),
"entry_price": Decimal("100"),
"exit_at": _ts(4),
"exit_price": Decimal("110"),
"qty": Decimal("10"),
"pnl_usd": Decimal("100"),
"pnl_pct": Decimal("10"),
"holding_days_actual": 4,
}
]
curve = [(_ts(i), Decimal(str(100000 + 25 * i))) for i in range(5)]
result = compute_metrics(
trade_log=trades,
equity_curve=curve,
initial_capital=Decimal("100000"),
benchmark_bars=spy,
)
assert result.alpha_vs_spy_pct is not None
assert result.beta_vs_spy is not None
def test_compute_metrics_returns_winners_losers_best_worst():
trades = [
{
"symbol": "NVDA",
"source_mention_id": 1,
"entry_at": _ts(0),
"entry_price": Decimal("100"),
"exit_at": _ts(5),
"exit_price": Decimal("110"),
"qty": Decimal("10"),
"pnl_usd": Decimal("100"),
"pnl_pct": Decimal("10"),
"holding_days_actual": 5,
},
{
"symbol": "INTC",
"source_mention_id": 2,
"entry_at": _ts(0),
"entry_price": Decimal("50"),
"exit_at": _ts(5),
"exit_price": Decimal("45"),
"qty": Decimal("20"),
"pnl_usd": Decimal("-100"),
"pnl_pct": Decimal("-10"),
"holding_days_actual": 5,
},
]
result = compute_metrics(
trade_log=trades,
equity_curve=[(_ts(0), Decimal("100000"))],
initial_capital=Decimal("100000"),
)
assert result.avg_winner_pct == Decimal("10")
assert result.avg_loser_pct == Decimal("-10")
assert result.best_trade == {"symbol": "NVDA", "pnl_pct": Decimal("10")}
assert result.worst_trade == {"symbol": "INTC", "pnl_pct": Decimal("-10")}
def test_compute_metrics_no_benchmark_omits_alpha_beta():
result = compute_metrics(
trade_log=[],
equity_curve=[(_ts(0), Decimal("100000"))],
initial_capital=Decimal("100000"),
)
assert result.alpha_vs_spy_pct is None
assert result.beta_vs_spy is None