6.0 KiB
Effective initial-risk floor A/B - frozen specification
Date frozen: 2026-08-05 Branch: research/portfolio-capacity-rebalancing Runner: scripts/run_portfolio_construction_matrix.py Study ID: risk-floor-ab
Question
Does rejecting an otherwise qualified cap-10 entry when its actual initial stop-risk after cash and notional sizing is below 0.5% of marked equity improve trade selection?
The completed capacity bracket cannot answer this. Its cash_unbounded arm removed the count cap and applied the 0.5% floor simultaneously. In the 70 paths where the control cap never bound, that arm still raised mean EV from 0.328 to 0.399 R and profit factor from 1.60 to 1.75 while trades fell about 8% and exposure stayed nearly flat. Capacity was a no-op in those paths, so the floor is the plausible cause, but the prior arm remains confounded.
This A/B changes only the floor. It has no formal promotion gate and does not automatically change production.
Frozen arms
- cap10_incumbent: current production-style cap-10 control, with no minimum effective-risk floor.
- cap10_min_risk_005: the same cap-10 strategy, rejecting an entry only when actual initial stop-risk after cash/notional sizing is below 0.5% of marked equity.
Both arms have max_positions=10, weekly replacement disabled, 1% target risk per trade, and identical admission ordering. The only differing simulator argument is min_initial_risk_fraction: None versus 0.005.
All other settings remain the frozen daily Phase A control: current production construction universe, full-universe residual-momentum/low-volatility 80/20 rank, threshold 80, normal gate-reset re-entry, close fills, 3x ATR trail, 30-session maximum hold, 20% per-position notional ceiling, no leverage, and costs of 0.10% and 0.20% per fill.
Every priced symbol contributes to the daily cross-sectional rank. Rank-only symbols cannot submit trades. Validation retains the 450-600-symbol production construction guardrail and the legacy-snapshot column-scoped loader.
Frozen cohorts
Reuse the completed bracket's point-in-time daily candidate/rank cache and cohort manifest:
- Empty book: first eligible session of each month in 2019-2025, with 504 prior scoring sessions and 252 measurement sessions. This is the primary start-date evidence.
- Warm book: weekly seeds 63-126 sessions before each 2019-2025 annual anchor, with state carried into the same 252-session measurement window. This is a state-carrying replication, not independent evidence.
The expected realization is 78 empty-book paths, 97 warm paths, seven annual clusters in each protocol, two costs, two arms, and 700 cells.
Do not use warm-seed IQR as evidence. Six of seven completed-bracket anchors were structurally degenerate because fractional sizing is scale invariant and the 30-session maximum hold washed out books before anchors. The 2023 exception shows that state carrying itself works.
Reporting and interpretation
For every protocol and cost, pair identical paths. Report:
- mean, median, P25, and P75 paired net-EV changes in R;
- positive-path and bit-identical-path fractions;
- the median paired delta within each year and the median across seven years;
- simple 90% cluster-bootstrap context for EV and Calmar, with no CI gate;
- mean paired PF, Gain-to-Pain, Sortino, Calmar/MAR, CAGR, maximum drawdown, total return, and Sharpe changes;
- trades, floor rejections, holding time, cash, gross exposure, average/peak positions, turnover, and costs.
Means and identical-path fractions must appear beside medians so inert cohorts cannot turn a left- or right-skewed treatment into a misleading zero headline. For these 252-session windows, the implementation's full-window Calmar is CAGR divided by maximum drawdown, the same numeric definition commonly called MAR; do not present the duplicate label as a second independent metric.
Today's production membership is projected backward. Use paired differences for the treatment conclusion; absolute profitability remains descriptive and survivorship-biased. Empty and warm protocols cover the same seven market years and must not be interpreted as independent replications.
Interpretation is deliberately simple:
- a positive result means the isolated floor improves the paired EV distribution without an economically important loss of total-return or drawdown quality;
- a negative result closes the floor;
- mixed EV/portfolio-quality results are reported as a trade-off, not forced through a composite score.
Reproducibility and macOS execution
The authoritative run refuses a dirty worktree. Its fingerprint includes the implementation commit, this specification hash, snapshot hash, candidate-cache key, construction view, cohort manifest, arm definitions, costs, and study version. Cells checkpoint atomically and --resume verifies the fingerprint.
From the repository root on macOS:
python3 -m venv .venv
./.venv/bin/python -m pip install -e '.[dev]'
Preflight, reusing the completed bracket's candidate/rank cache:
./.venv/bin/python scripts/run_portfolio_construction_matrix.py + backtest_snapshots/research.sqlite + --study risk-floor-ab + --run-id prod505-effective-risk-floor-ab-daily-v1 + --candidate-cache reports/.cache/prod505-capacity-bracket-daily-v1-candidates.pkl + --workers 8 + --resume + --validate-only
Authoritative run:
./.venv/bin/python scripts/run_portfolio_construction_matrix.py + backtest_snapshots/research.sqlite + --study risk-floor-ab + --run-id prod505-effective-risk-floor-ab-daily-v1 + --candidate-cache reports/.cache/prod505-capacity-bracket-daily-v1-candidates.pkl + --workers 8 + --resume
On an M2 Pro, eight workers is the explicit high-utilization setting. Use six instead on a memory-constrained machine; auto intentionally caps itself at six. Changing worker count does not change the fingerprint or results.
Commit only the compact final JSON and Markdown reports. Candidate caches, checkpoints, raw curves, and trade ledgers remain ignored.