feat(b3b): expose candidate-top-k/min-history on backtest-equity CLI (use bounded path by default)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
jgrusewski
2026-06-18 09:09:01 +02:00
parent 76e07ec3be
commit 9068f73b51
2 changed files with 29 additions and 0 deletions

View File

@@ -514,6 +514,8 @@ def backtest_equity(
cost_bps: float = typer.Option(15.0, "--cost-bps", help="Cost in bps per unit (two-way) turnover."),
borrow_annual: float = typer.Option(0.0, "--borrow-annual", help="Annual borrow cost on short notional."),
out: str = typer.Option("/backtest-data/equity_backtest_report.json", "--out", help="Report JSON path."),
candidate_top_k: int = typer.Option(2000, help="Bounded candidate universe: top-K most-liquid names (caps memory; the full universe OOMs)."),
candidate_min_history: int = typer.Option(300, help="Min daily bars (close+volume) a name needs to be a candidate."),
) -> None:
"""B3b: walk-forward backtest of the 3 price-only equity-factor constructions against the DEDICATED
survivorship-free backtest warehouse (settings.backtest_warehouse_path) -> gauntlet verdict + JSON report."""
@@ -527,6 +529,7 @@ def backtest_equity(
try:
result = EquityBacktestRunner(
store, n=n, cost_bps_per_turnover=cost_bps, borrow_annual=borrow_annual,
candidate_top_k=candidate_top_k, candidate_min_history=candidate_min_history,
).run()
report = evaluate_constructions(
result,

View File

@@ -57,3 +57,29 @@ def test_cli_backtest_equity_writes_report(tmp_path, monkeypatch) -> None:
for block in report["constructions"].values():
assert {"stats", "verdict"} <= set(block)
assert {"passed", "dsr", "is_sharpe", "oos_sharpe"} <= set(block["verdict"])
def test_cli_backtest_equity_bounded_candidate_flags(tmp_path, monkeypatch) -> None:
"""The bounded memory pre-filter flags (--candidate-top-k / --candidate-min-history) are exposed
and passed to the runner; with thresholds the 3 synthetic names qualify -> full report."""
import fxhnt.cli as cli
wh = str(tmp_path / "wh.duckdb")
_build_warehouse(wh).close()
out = tmp_path / "report.json"
monkeypatch.setenv("FXHNT_BACKTEST_WAREHOUSE_PATH", wh)
cli.get_settings.cache_clear() # settings are lru_cached — pick up the env override
res = CliRunner().invoke(
cli.app,
[
"backtest-equity", "--n", "10", "--out", str(out),
"--candidate-top-k", "100", "--candidate-min-history", "10",
],
)
cli.get_settings.cache_clear()
assert res.exit_code == 0, res.output
assert out.exists(), "backtest-equity must write the report JSON at --out"
report = json.loads(out.read_text())
assert set(report["constructions"]) == {"long", "ls", "tilt"}