Strategies
China A-Share T+1 Forced-Holding Washout Bounce, Long-Only Basket (30 CSI-300 Mega Caps on CNEQ, DAILY Bars — Buy Names Down >=8% Over 5 Sessions With No Limit-Hit on the Trigger Day, Equal-Weight, Fixed 5-Session Hold, 3-Parameter)
Outcome: Abandoned
ChinaAShareT1WashoutBounceBasketCneq
Outcome Summary
This strategy took the factory onto an untouched venue, CNEQ A-shares, with a deliberately simple thesis: buy CSI-300 mega caps that fell >=8% over five sessions without hitting the price limit, hold a fixed five sessions, equal-weight, no regime gate or supplementary data. Optimization results existed and looked economically plausible — 60.19% total return, Sharpe 0.876 over 912 trades, 0.712% average per-trade return, 8.99% max drawdown, and a passing holdout at Sharpe 0.932 on 112 trades — but the robustness layer was much less kind, with walk-forward overfitting flagged (IS 1.600 vs OOS 0.250), PBO 0.606 and failure to survive the programme FDR screen. What actually ended the run was mechanical, not statistical: on iteration 4 the Layer 3 sandbox backtest blew through its 300-second wall-clock limit on the 2400-day smoke window, following iteration 3's zero-trade failure caused by one mis-stamped leg. The pipeline abandoned it before any analyst or risk verdict was recorded.
Hypothesis
verification_loop: sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of 600519.CNEQ-1-DAY-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Implementation
Long-only CNEQ (China A-share) washout-bounce basket over 30 CSI-300 mega caps on DAILY bars. Each session every leg's trailing 5-session return is computed; a name qualifies when that return is <= -drop_threshold (default 10%) and the trigger day itself did NOT close at the statutory daily price limit (10% main board, 20% ChiNext/STAR, 0.95 guard). Qualifying names are ranked DEEPEST-DROP-FIRST and fill up to 8 equal-weight slots at 15% of NAV each, hard-capped by free cash so gross never exceeds 1.0x cash (CASH venue, long-only, no leverage, whole shares). Every position is closed unconditionally after hold_sessions (default 5) exchange sessions, aged from the position's own open timestamp against the observed session calendar, so a T+1 same-day round trip is impossible. No regime gate, no indicator stack, no stop-loss, no supplementary data.
Verification Results
sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of 600519.CNEQ-1-DAY-LAST-EXTERNAL). This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Analysis
Benjamini-Hochberg at q=0.10 over 284 programme candidates keeps 4. A candidate that does not survive here is not distinguishable from the programme's own noise, however good its individual statistics look.
Iteration History
Verification failed (Layer 3 — sandbox backtest): No trades produced Bar type used: 600519.CNEQ-1-DAY-LAST-EXTERNAL, Bars processed: 1605 Diagnostics: should_enter() returned a side 0 times over 19 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds. Ensure your strategy produces trades with the given data and parameters.
Outcome Summary
A 19-leg multi-instrument daily basket must keep per-bar cost near O(log n) — precompute sorted arrays and cache timestamp lookups in __init__ — or Layer 3's 300s budget will kill it regardless of how good the economics look; iteration 3's zero-trade bar-stamp misalignment and iteration 4's timeout were both plumbing failures, not edge failures.
The run was abandoned in the verification loop at iteration 4: the Layer 3 sandbox backtest exceeded its 300s wall-clock limit on the ~20,000-bar (2400-day) smoke window, indicating per-bar work that scales with history. It therefore never reached backtest review, analyst or risk-officer verdicts (all are empty).
A long-only, event-triggered washout-bounce basket on 30 CSI-300 mega caps (CNEQ, daily bars): buy names down >=8% over 5 sessions that did not hit the daily price limit on the trigger day, equal-weight, and exit after a fixed ~5-session hold.
The optimized backtest over 2018-01-02 to 2026-09-10 produced 60.19% total return, Sharpe 0.876, 912 trades, avg trade return 0.712% of notional, win rate 55.2% and 8.99% max drawdown, with holdout Sharpe 0.932 on 112 trades passing the holdout gate. Robustness was weaker: walk-forward flagged overfitting (IS avg Sharpe 1.600 vs OOS avg 0.250, two of three OOS windows negative), PBO 0.606, deflated Sharpe 0.475, and the candidate did not survive the programme-level BH-FDR screen (p=0.5246, 4 of 284 kept).
Backtest Review
- Sharpe
- 1.07
- Total return
- 101.93%
- Max drawdown
- 9.39%
- Trades
- 447
- Win rate
- 58.6%
- Profit factor
- 1.65
Backtest and paper results are hypothetical. Trading involves risk of loss.