Skip to content

View translation

ChinaAShareT1WashoutBounceBasketCneq

Hypotheses

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)

Hypotheses

A LONG-ONLY, multi-instrument, pure-OHLCV short-horizon washout-bounce strategy on Chinese A-shares (CNEQ, SSE+SZSE, XSHG session calendar). This is a deliberate move onto a venue with ZERO experiments in the entire 3065-run corpus: the catalog holds 311 CSI-300 A-shares with 8.6 years of split-adjusted daily bars (2018-01-02 -> 2026-09-10, 2108 sessions) that this factory has never touched once, while 70% of all research has re-mined Binance USD-M. The mechanism is NOT the generic rank-based cross-sectional reversal that died on crypto and USEQ (those were dollar-neutral, rank-ranked, fee-dead two-leg constructions on ~0.20% RT venues). It is an ABSOLUTE-THRESHOLD, single-leg, event-triggered bounce specific to A-share market microstructure, on a venue whose statutory round-trip is only ~0.15%. PRE-VALIDATED ON THE ACTUAL CATALOG BEFORE PROPOSING: on the 30-name mega-cap panel below, conditioning on trailing-5-session return <= -8% with no price-limit hit on the trigger day gives a mean forward 5-session return of +0.934% (median +0.702%, win rate 56.7%) over n=1796 events, versus an unconditional forward-5-session mean of +0.150% — an excess of +0.78% per event. The effect is monotone in the threshold (-6%: +0.705%, -8%: +0.934%, -10%: +1.124%, -12%: +1.249%) and FLAT in holding period (3d +0.710%, 5d +0.934%, 8d +0.896%, 10d +0.918%), i.e. neither tunable is a cliff parameter. It fires on 704 of 2108 sessions (33%) with ~2.6 qualifying names per signal day, so trade count is in the four figures, not the dozens that made every ETF regime-rotation sibling structurally un-validatable. Deliberately simple: one trigger, one fixed hold, no regime gate, no indicator stack, no second leg, no supplementary data.

Hypotheses

Iteration 4 fixes the ZERO-TRADE sandbox failure and changes NOTHING else. The diagnostic ('should_enter() returned a side 0 times over 19 evaluated bars' out of 1605 primary bars) was not an entry-threshold problem: the base template's cross-leg alignment barrier holds the primary until every same-timeframe extra leg has a bar at the primary's EXACT timestamp, and I verified against the catalog that 601888.CNEQ's entire daily history is stamped 07:01 UTC while all other CNEQ names are stamped 07:00 (601888 shares only 20 of the primary's 2114 session timestamps; every other leg shares 2113-2114). That single mis-stamped leg blocked ~99% of sessions -- exactly the 19 evaluated bars observed -- and it entered the basket only in iteration 2 (iteration 1, which produced 676 sandbox trades, held 300750 in that slot instead). The fix is therefore a ONE-LEG config swap: 601888.CNEQ -> 601088.CNEQ (China Shenhua, CSI-300 mega cap, full 2018-01-02 span, stamps identical to the panel). I re-scanned all 311 CNEQ daily symbols and confirmed every one of the 30 legs now shares >= 2113 of the primary's 2114 session timestamps, so the barrier passes on essentially every session. All five search-space items from the feedback stay exactly as shipped in iterations 2-3: _param_bounds holds only drop_threshold [0.08, 0.14] and hold_sessions [4, 7]; position_frac (0.15), drop_lookback (5), max_positions (8) and cash utilisation are underscore-prefixed structural constants the optimizer cannot search; gross <= 1.0x cash; no regime gate, indicator stack, stop-loss or new parameter was added. The strategy logic is byte-for-byte unchanged (only the docstring records the finding), since Layer 1/2 and the iteration-1 Layer 3 all passed on it. On the corrected panel the pre-registered event study still holds: 687 raw events at -10% (647 after the 8-slot cap), per-event mean forward 5-session return 1.29%, monotone in depth (1.14% / 1.46% / 2.03% / 3.01% at -8/-10/-12/-14%), which clears the ~0.10% CNEQ round trip by an order of magnitude. Honest caveat for the analyst, unchanged from iteration 3: per-event returns are positive in every year except 2023 (-1.62%) and the 2025/2026 samples are thin, so if the sweep confined to the >= 8% depth region still returns OOS < 0.5 the period-specific abandon verdict in the feedback should stand.

Hypotheses

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

Fix the SEARCH SPACE, not the logic. (1) Narrow _param_bounds['drop_threshold'] to [0.08, 0.14] — Optuna picked 0.0610 and that shallow trigger is what killed the walk-forward: it doubled trade count (447→912) and halved the per-trade edge (1.289%→0.667%), turning 2022 from +1.47%/trade into +0.16% and 2026 from +1.26% into +0.00%; the pre-registered event study is monotone in depth, so the sub-8% half is a priori the dilution zone. (2) REMOVE 'position_frac' from _param_bounds, hard-fix 0.15 — a sizing knob cannot change Sharpe except through noise. (3) REMOVE 'drop_lookback', fix at 5 — sensitivity 4/5/6 = 0.861/1.072/0.973, no cliff, no gradient. That leaves drop_threshold (optionally hold_sessions in [4,7]) as the only free params, which lowers n_trials_effective (39), raises DSR, and removes the degenerate ranking noise behind PBO 0.61. (4) Widen the basket from 19 legs to the ~30 CSI-300 mega caps the hypothesis declared (311 A-shares available on the same span) so the 8 slots fill with the DEEPEST drops and the thin 2023/2025 years get sample. (5) Keep max_positions=8, gross ≤1.0x cash. Do NOT add a regime gate, indicator stack, stop-loss or any new parameter. Bar for next round: OOS ≥ 0.5 with all three windows non-negative, is_overfitted=false, PBO ≤ 0.5, holdout still positive, per-trade ≥ ~1.0%. If a sweep confined to the ≥8% depth region still gives OOS < 0.5, the edge is period-specific and the next verdict must be abandon. Detail: workspace/discussions/87a3d165-fb50-437b-ab12-b19384f2ee7c/iteration_1_feedback.md

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.

Outcome Summary

ChinaAShareT1WashoutBounceBasketCneq-4e9bc8062d

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.

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.

Outcome Summary

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).

Outcome Summary

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.

Outcome Summary

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).

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.
Strategy report

Backtest and paper results are hypothetical. Trading involves risk of loss.