analysis: apply execution-adjusted cost model in v2 backtest pipeline (#368)
Some checks failed
Gitea CI / test (push) Successful in 32s
Gitea CI / test (pull_request) Failing after 6s

This commit is contained in:
agentson
2026-03-02 03:37:24 +09:00
parent c967ae6715
commit 200bc82a27
6 changed files with 216 additions and 1 deletions

View File

@@ -35,6 +35,7 @@ def _cost_model() -> BacktestCostModel:
commission_bps=3.0,
slippage_bps_by_session={"KRX_REG": 10.0, "US_PRE": 50.0},
failure_rate_by_session={"KRX_REG": 0.01, "US_PRE": 0.08},
partial_fill_rate_by_session={"KRX_REG": 0.1, "US_PRE": 0.2},
unfavorable_fill_required=True,
)
@@ -71,6 +72,9 @@ def test_pipeline_happy_path_returns_fold_and_artifact_contract() -> None:
assert names == {"B0", "B1", "M1"}
for score in fold.baseline_scores:
assert 0.0 <= score.accuracy <= 1.0
assert fold.execution_adjusted_trade_count >= 0
assert fold.execution_rejected_count >= 0
assert fold.execution_partial_count >= 0
def test_pipeline_cost_guard_fail_fast() -> None:
@@ -78,6 +82,7 @@ def test_pipeline_cost_guard_fail_fast() -> None:
commission_bps=3.0,
slippage_bps_by_session={"KRX_REG": 10.0},
failure_rate_by_session={"KRX_REG": 0.01},
partial_fill_rate_by_session={"KRX_REG": 0.1},
unfavorable_fill_required=True,
)
try:
@@ -166,3 +171,56 @@ def test_pipeline_rejects_minutes_spec_when_timestamp_missing() -> None:
assert "BacktestBar.timestamp is required" in str(exc)
else:
raise AssertionError("expected timestamp validation error")
def test_pipeline_execution_adjusted_returns_reflect_cost_and_fill_assumptions() -> None:
base_cfg = dict(
bars=_bars(),
entry_indices=[0, 1, 2, 3, 4, 5, 6, 7],
side=1,
triple_barrier_spec=TripleBarrierSpec(
take_profit_pct=0.02,
stop_loss_pct=0.01,
max_holding_minutes=3,
),
walk_forward=WalkForwardConfig(
train_size=4,
test_size=2,
step_size=2,
purge_size=1,
embargo_size=1,
min_train_size=3,
),
)
optimistic = BacktestCostModel(
commission_bps=0.0,
slippage_bps_by_session={"KRX_REG": 0.0, "US_PRE": 0.0},
failure_rate_by_session={"KRX_REG": 0.0, "US_PRE": 0.0},
partial_fill_rate_by_session={"KRX_REG": 0.0, "US_PRE": 0.0},
unfavorable_fill_required=True,
)
conservative = BacktestCostModel(
commission_bps=10.0,
slippage_bps_by_session={"KRX_REG": 20.0, "US_PRE": 60.0},
failure_rate_by_session={"KRX_REG": 0.2, "US_PRE": 0.4},
partial_fill_rate_by_session={"KRX_REG": 0.5, "US_PRE": 0.7},
unfavorable_fill_required=True,
)
opt_out = run_v2_backtest_pipeline(cost_model=optimistic, **base_cfg)
cons_out = run_v2_backtest_pipeline(cost_model=conservative, **base_cfg)
opt_avg = sum(
f.execution_adjusted_avg_return_bps for f in opt_out.folds
) / len(opt_out.folds)
cons_avg = sum(
f.execution_adjusted_avg_return_bps for f in cons_out.folds
) / len(cons_out.folds)
assert cons_avg < opt_avg
opt_trades = sum(f.execution_adjusted_trade_count for f in opt_out.folds)
cons_trades = sum(f.execution_adjusted_trade_count for f in cons_out.folds)
cons_rejected = sum(f.execution_rejected_count for f in cons_out.folds)
assert cons_trades <= opt_trades
assert cons_rejected >= 0