QuantProp. Analyze a trade file ↗
stockback / Experiment design

EXP-011 design — Turtle + Bollinger squeeze, 30-symbol generalization

Preregistered basket rules, accounting fixes and 8 promotion gates fixed before testing the squeeze filter on 30 symbols.

Original record: not stated in the original · Migrated: 2026-10-27 · Translated from Korean: 2026-10-27
A historical record, not rerun in this migration.

The figures, hypotheses and verdicts of the time are preserved. A past positive result or candidate mention does not mean validated profitability today or a live-trading recommendation. Validation periods that were already used are not treated as new independent validation.

This is an English translation of a preserved Korean original. It describes conditions at the time of writing, not current provider specifications, costs or regulations.

EXP-011 design — Turtle + Bollinger squeeze, 30-symbol generalization

  • Designed and run: 2026-09-10
  • Execution model: claude-opus-5 / high
  • Week: work week 5 (2026-W37)
  • Status: pre-registered

The question this experiment answers

EXP-008 recorded that on 7 symbols the squeeze filter raised the locked OOS median CAGR from 2.05% → 9.33% and cut mean MDD from -30.54% → -16.30%. But with about 4 OOS trades per symbol, that table cannot tell edge from luck.

So this experiment searches no further parameters. With the contract fixed, it only increases the number of symbols to see whether the EXP-008 result reproduces. If it does not, the EXP-008 figures are an artefact of 7 symbols.

Hypotheses fixed in advance

  1. The squeeze filter's MDD improvement holds as symbols are added.
  2. The squeeze filter's CAGR improvement holds as symbols are added.
  3. If only one of the two effects holds, only the one that holds is accepted as a reusable component.
  4. If no contract beats buy-and-hold over the same period, none is promoted regardless of the sign of its return.

The case where hypothesis 2 breaks and only hypothesis 1 remains is defined in advance as a normal verdict outcome, not a failure.

Basket preregistration

Before seeing results, the basket was fixed with select_exp011_universe.py (original supporting file) and saved in EXP-011-universe.json (original supporting file).

GateRuleResult
Candidate poolAll symbols in data/raw/creon/bulk/all_research3,552
A · CoverageFirst bar ≤ 2009-06-30, last bar ≥ 2026-06-30Excluded: 1,221 with no train-period bars · 980 short of coverage
B · Quality0 duplicate dates, 0 OHLC violations, train trading days ≥ 2,100309 excluded
C · RankMedian daily trading value over the train period (2010–2018), descendingEligible 1,042
SelectedTop 3030

Leakage prevention: the rank calculation reads only train-period bars. Validation and locked OOS are not used for basket selection at all, so symbols cannot be picked to produce good OOS results.

Limit: all_research is a listing snapshot as of 2026-08-26, so symbols delisted before then are absent. Survivorship bias remains, so even if this basket's results pass the criteria, it is not final adoption. All 7 EXP-008 symbols are in the top 30. So the real subject of the generalization test is the 23 new symbols, and the existing 7 symbols are aggregated separately as the control.

Execution contract

The EXP-008 contract is inherited as is. Only the three items below are accounting fixes; no strategy rule changes.

ItemContract
DataCREON daily bars, 30 preregistered symbols
Indicator warm-upSignals generated from 2005-01-01 (250-day squeeze and 55-day breakout mature by 2010-01-01)
BandsSMA(20) ± 2σ, BandWidth=(upper-lower)/middle
squeezePrior bar's BandWidth in the bottom 20% of its distribution over the previous 60/125/250 days
EntryClose above the prior 55-day high → next trading day's open
ExitClose below the prior 20-day low → next trading day's open, or ATR stop
StopEntry price - ATR(14) × 1.0/1.5/2.0
AccountingInitial 3,000,000 KRW, 95% of cash just before entry, integer quantities, no leverage
Costs0bp / CREON 1.5bp one-way provisional proxy / 2x / proxy + 5bp one-way slippage
TaxPer product. A069500 and A102110 are ETFs, so no securities transaction tax
Riskresearch_unhalted and account_halt run separately

Fix 1 — per-period capital isolation

EXP-008 ran the full time series once and cut it by date. So drawdowns in the train period reduced order sizes in locked OOS. This time each period is an independent run, and at the start of each period capital is reset to 3,000,000 KRW. Signals are still generated from the full time series, so warm-up is preserved.

The engine contract is PortfolioConfig.trading_window; open positions at the end of a period are closed at the close as window_end. The regression test is in test_segment_trading_window.py (original supporting file).

Fix 2 — per-period buy-and-hold benchmark

Buy-and-hold is computed for the same period, same bars and same one-way commission and kept in a separate ledger. Excess CAGR, strategy CAGR minus benchmark CAGR, is used for the verdict. Since 2023 the domestic index has risen sharply, so a positive CAGR by itself is no evidence of an edge.

Fix 3 — flagging capital-starved cells

Entry signals discarded because cash could not buy even 1 share are counted as starved. Cells with starved > 0 are not strategy performance but cells contaminated by accounting starvation, so they are excluded from the verdict population and reported separately.

Matrix

  • 4 contracts: turtle_only (control), turtle_squeeze_60, turtle_squeeze_125, turtle_squeeze_250
  • In EXP-008, bulge exclusion did not actually remove signals and standalone bb_breakout_* provided no grounds. This is a generalization test, not an expanded search, so those two diagnostic groups are not carried over.
  • 4 contracts × 3 ATR × 4 costs × 2 risk × 30 symbols × 4 periods = 11,520 rows
  • Periods: train (2010–2018), validation (2019–2022), locked_oos (2023–2026-08-26), full (2010–2026-08-26)

1st verdict cell and criteria

A single verdict cell is fixed before checking results: locked_oos × normalized_actual_proxy × ATR 1.5 × research_unhalted.

To pass to advance, all of the following must be met.

  1. Median per-symbol CAGR on the 23 new symbols ≥ 15%
  2. Median per-symbol MDD ≥ -25%
  3. Median excess CAGR > 0 (did it beat buy-and-hold?)
  4. Total locked OOS trades ≥ 100
  5. Direction held at 2x costs and 5bp one-way slippage
  6. Direction held at neighbouring ATR 1.0 and 2.0
  7. Consistent direction across train, validation and locked_oos
  8. starved = 0 in the verdict cell

If any is unmet, record hold; if the effect disappears on the new symbols relative to the control, record rejected. The best parameters after the fact are not picked for promotion.

Reproduction command

cd [original local path withheld]
python -X utf8 scripts\build\select_exp011_universe.py
python -X utf8 scripts\backtest\run_turtle_squeeze_basket_exp011.py

Result paths

  • 0
  • 0
  • Ledgers: reports/ledgers/EXP-011-summary.csv, reports/ledgers/EXP-011-benchmark.csv

Source and migration evidence

Source: docs/test-plans/2026-W37-turtle-squeeze-basket-exp011.md

Original SHA-256: 819809bb8061074791feec690605fddd9d85dcd4327d1356baa920d9ade521c8

Raw data and account information are not part of the public package. The original results do not replace statistical or scientific revalidation. The English text is a translation; numbers, tables and charts are carried over unchanged.