Strategy research: find a Stage-1 positive-E[R] edge (honest OOS) #137

Closed
opened 2026-06-24 23:57:09 +02:00 by Brummel · 8 comments
Owner

Provenance

Seeded by an in-session decision (no prior tracker issue). The user
redirected aura from infrastructure-building to its raison d'être:
find a genuinely profitable algorithmic strategy and prove an edge.
Verbatim: "Ich will endlich mal eine Algo-Strategie sehen, die
wirklich profitabel ist. Genau dafür erfinden wir Aura."
;
"wäre nett, wenn wir eine Edge beweisen könnten, dafür existiert das
Projekt"
; "DU sollst die Strategie schreiben". This issue is the
decision log for the /boss research run.

Goal

Find a Stage-1 positive-E[R] strategy that survives honest
out-of-sample validation — measured in R (flat-1R, feed-forward,
frictionless), per ledger C10. Success is not a guaranteed profit; it is
a truthful verdict per candidate. aura's value here is that it makes
look-ahead structurally impossible (C2) and forces OOS/MC honesty — a
lie-detector for backtests, the ingredient missing from 5 years of
overfit/leaked live failures.

Tradeable universe (user-set: low transaction cost only)

DAX = GER40, Nasdaq = NAS100, FX majors = EURUSD, GBPUSD,
USDJPY, USDCHF, USDCAD, NZDUSD
(AUDUSD absent from the data server).
All other symbols may be read as signal inputs but never traded.

Data on the server (M1, ZIP-packed .bin, read via --real):

  • GER40, NAS100: 2014-08 … 2026-06 (~12y)
  • the six FX majors: 2011-03 … 2026-06 (~15y)

This is ample material for generous IS/OOS splits and rolling
walk-forward — no single-year overfitting.

Methodology (the discipline that breaks the 5-year pattern)

  • Out-of-sample from the start — never tune on the test set.
  • Walk-forward + Monte-Carlo as default, not the exception.
  • Few parameters, large data — every knob is an overfit dimension.
  • Cross-symbol generalization is the killer test — a real
    structural effect appears (directionally) across several instruments
    and periods; an edge that only pops in one symbol/one window/one
    param cell is noise. This is the strongest anti-overfit weapon.
  • Multiple-comparisons control — a sweep over K params × M symbols
    selects the best cell on noise; OOS + MC + cross-symbol consistency
    is what controls it.
  • R first, currency/costs later — Stage-1 frictionless R signal
    quality; Stage-2 (broker/costs, the existing #116… milestone) is the
    gate a survivor then passes (ledger: E[R] > 0 before Stage 2).

Current runnable surface (grounded 2026-06-24) — and its gaps

Runnable today: aura run --harness {sma,macd,stage1-r} --real SYM,
aura sweep --strategy {sma,momentum,stage1-r} --real SYM,
aura runs family <id> rank <metric>. Library API is clean:
sweep(), walk_forward(WindowRoller, space, run_window),
monte_carlo(base, seeds, run_one), summarize_r(record, cost).

Gaps that block honest candidate validation:

  1. aura walkforward is locked to the SMA sample blueprint + fixed
    90/30/30-day windows — cannot run stage1-r or a new candidate, no R.
  2. aura mc is synthetic-only, 3 hardcoded seeds — useless on real
    candidates.
  3. The GER40 session-breakout composite exists but is not CLI-wired
    (only in aura-engine/tests/ger40_breakout.rs + ingest examples).
  4. 4 of the 8 tradeable symbols lack an instrument_spec() entry
    (NAS100, USDJPY, USDCHF, NZDUSD) — --real refuses them.

Plan (phased; each phase a truthful verdict, cheap to kill)

  • Phase 0 — calibrate the null (no new code). Run the existing
    stage1-r SMA-cross on real data across the wired instruments, full
    history; confirm the apparatus produces R-metrics end-to-end and that
    the toy is E[R] ≈ 0/negative (honest null). Calibrates everything.
  • Phase 1 — research harness (the spike). A repo-side harness that
    drives walk_forward + monte_carlo over a chosen candidate
    blueprint
    on real data and reports OOS R-metrics (per symbol +
    pooled). Authorized as an in-engine spike (defer the C9 project-crate
    split #109 until the loop proves valuable).
  • Phase 2 — candidate search. Author candidates grounded in
    structural effects (lead candidate: time-series momentum / Donchian
    breakout on a higher timeframe + vol/ATR trailing stop — strongest
    cross-asset prior, low-param, cost-friendly), each OOS-validated from
    the start; kill anything that fails OOS or fails to generalize.
  • Phase 3 — survivor → Stage 2. Only a candidate with E[R] > 0
    OOS, robust under MC and across symbols, proceeds to costs/broker
    realism (the existing Stage-2 broker milestone).

Out of scope (for now)

  • IONOS/news-bias signals (need per-session consent + the record edge;
    pure price strategies don't need them).
  • Stage-2 currency P&L, real frictions, equity feedback (only after an
    E[R] > 0 survivor exists).
  • The full #109 project-as-crate authoring workflow (spike in-repo
    first).
## Provenance > Seeded by an in-session decision (no prior tracker issue). The user > redirected aura from infrastructure-building to its raison d'être: > find a genuinely profitable algorithmic strategy and prove an edge. > Verbatim: *"Ich will endlich mal eine Algo-Strategie sehen, die > wirklich profitabel ist. Genau dafür erfinden wir Aura."*; > *"wäre nett, wenn wir eine Edge beweisen könnten, dafür existiert das > Projekt"*; *"DU sollst die Strategie schreiben"*. This issue is the > decision log for the `/boss` research run. ## Goal Find a **Stage-1 positive-`E[R]` strategy** that survives honest out-of-sample validation — measured in R (flat-1R, feed-forward, frictionless), per ledger C10. Success is not a guaranteed profit; it is a **truthful verdict** per candidate. aura's value here is that it makes look-ahead structurally impossible (C2) and forces OOS/MC honesty — a lie-detector for backtests, the ingredient missing from 5 years of overfit/leaked live failures. ## Tradeable universe (user-set: low transaction cost only) DAX = **GER40**, Nasdaq = **NAS100**, FX majors = **EURUSD, GBPUSD, USDJPY, USDCHF, USDCAD, NZDUSD** (AUDUSD absent from the data server). All other symbols may be *read as signal inputs* but **never traded**. Data on the server (M1, ZIP-packed `.bin`, read via `--real`): - GER40, NAS100: 2014-08 … 2026-06 (~12y) - the six FX majors: 2011-03 … 2026-06 (~15y) This is ample material for generous IS/OOS splits and rolling walk-forward — no single-year overfitting. ## Methodology (the discipline that breaks the 5-year pattern) - **Out-of-sample from the start** — never tune on the test set. - **Walk-forward + Monte-Carlo as default**, not the exception. - **Few parameters, large data** — every knob is an overfit dimension. - **Cross-symbol generalization is the killer test** — a real structural effect appears (directionally) across several instruments and periods; an edge that only pops in one symbol/one window/one param cell is noise. This is the strongest anti-overfit weapon. - **Multiple-comparisons control** — a sweep over K params × M symbols selects the best cell on noise; OOS + MC + cross-symbol consistency is what controls it. - **R first, currency/costs later** — Stage-1 frictionless R signal quality; Stage-2 (broker/costs, the existing #116… milestone) is the gate a *survivor* then passes (ledger: `E[R] > 0` before Stage 2). ## Current runnable surface (grounded 2026-06-24) — and its gaps Runnable today: `aura run --harness {sma,macd,stage1-r} --real SYM`, `aura sweep --strategy {sma,momentum,stage1-r} --real SYM`, `aura runs family <id> rank <metric>`. Library API is clean: `sweep()`, `walk_forward(WindowRoller, space, run_window)`, `monte_carlo(base, seeds, run_one)`, `summarize_r(record, cost)`. Gaps that block honest candidate validation: 1. **`aura walkforward` is locked** to the SMA sample blueprint + fixed 90/30/30-day windows — cannot run stage1-r or a new candidate, no R. 2. **`aura mc` is synthetic-only**, 3 hardcoded seeds — useless on real candidates. 3. The **GER40 session-breakout composite exists but is not CLI-wired** (only in `aura-engine/tests/ger40_breakout.rs` + ingest examples). 4. **4 of the 8 tradeable symbols lack an `instrument_spec()`** entry (NAS100, USDJPY, USDCHF, NZDUSD) — `--real` refuses them. ## Plan (phased; each phase a truthful verdict, cheap to kill) - **Phase 0 — calibrate the null (no new code).** Run the existing stage1-r SMA-cross on real data across the wired instruments, full history; confirm the apparatus produces R-metrics end-to-end and that the toy is `E[R] ≈ 0`/negative (honest null). Calibrates everything. - **Phase 1 — research harness (the spike).** A repo-side harness that drives `walk_forward` + `monte_carlo` over a *chosen candidate blueprint* on real data and reports OOS R-metrics (per symbol + pooled). Authorized as an in-engine spike (defer the C9 project-crate split #109 until the loop proves valuable). - **Phase 2 — candidate search.** Author candidates grounded in *structural* effects (lead candidate: time-series momentum / Donchian breakout on a higher timeframe + vol/ATR trailing stop — strongest cross-asset prior, low-param, cost-friendly), each OOS-validated from the start; kill anything that fails OOS or fails to generalize. - **Phase 3 — survivor → Stage 2.** Only a candidate with `E[R] > 0` OOS, robust under MC and across symbols, proceeds to costs/broker realism (the existing Stage-2 broker milestone). ## Out of scope (for now) - IONOS/news-bias signals (need per-session consent + the record edge; pure price strategies don't need them). - Stage-2 currency P&L, real frictions, equity feedback (only after an `E[R] > 0` survivor exists). - The full #109 project-as-crate authoring workflow (spike in-repo first).
Brummel added the feature label 2026-06-24 23:57:09 +02:00
Author
Owner

Phase 0 — null baseline (no new code)

Ran the existing stage1-r SMA-2/4-cross (frictionless Stage-1 R) on the
full real history of the 4 already-wired symbols:

symbol window E[R] n_trades win PF sqn
GER40 2014-08…2026-06 −0.0000079 967,464 0.355 0.99998 −0.005
EURUSD 2011-03…2026-06 −0.010966 1,515,384 0.354 0.975 −8.17
GBPUSD 2011-03…2026-06 −0.013855 1,520,800 0.354 0.969 −8.96
USDCAD 2011-03…2026-06 −0.006148 1,497,777 0.350 0.987 −4.14

Verdict: a clean, honest null. A fast (2/4-bar) SMA cross on M1 has
E[R] ≈ 0 (GER40) to slightly negative (FX), frictionless — a
guaranteed loser once costs are added. The cross-symbol consistency of
the null (all three FX ≈ −0.01 R, win ≈ 0.35, PF < 1) both validates the
cross-symbol logic and shows fast signals are mean-reverting /
chop-dominated at the M1 scale. The apparatus produces sane R-metrics
end-to-end on real data (~4 s/symbol for 12–15 y in the release build).

Implication for the candidate search: a momentum edge, if any, lives
at slower timescales — which strengthens the lead candidate (slow
time-series momentum) and means the stop timescale must match the signal
timescale (the pinned 3-bar = 3-minute vol-stop is far too fast for a
slow signal).

Next: an enabling change to grid the stage1-r signal and stop
timescales via CLI, plus register the 4 missing tradeable instruments
(NAS100, USDJPY [pip 0.01], USDCHF, NZDUSD), so the momentum timeframe
screen can run across the full allowed universe.

## Phase 0 — null baseline (no new code) Ran the existing stage1-r SMA-2/4-cross (frictionless Stage-1 R) on the full real history of the 4 already-wired symbols: | symbol | window | E[R] | n_trades | win | PF | sqn | |---|---|---|---|---|---|---| | GER40 | 2014-08…2026-06 | −0.0000079 | 967,464 | 0.355 | 0.99998 | −0.005 | | EURUSD | 2011-03…2026-06 | −0.010966 | 1,515,384 | 0.354 | 0.975 | −8.17 | | GBPUSD | 2011-03…2026-06 | −0.013855 | 1,520,800 | 0.354 | 0.969 | −8.96 | | USDCAD | 2011-03…2026-06 | −0.006148 | 1,497,777 | 0.350 | 0.987 | −4.14 | **Verdict: a clean, honest null.** A fast (2/4-bar) SMA cross on M1 has `E[R] ≈ 0` (GER40) to slightly negative (FX), frictionless — a guaranteed loser once costs are added. The cross-symbol consistency of the null (all three FX ≈ −0.01 R, win ≈ 0.35, PF < 1) both validates the cross-symbol logic and shows fast signals are mean-reverting / chop-dominated at the M1 scale. The apparatus produces sane R-metrics end-to-end on real data (~4 s/symbol for 12–15 y in the release build). **Implication for the candidate search:** a momentum edge, if any, lives at slower timescales — which strengthens the lead candidate (slow time-series momentum) and means the stop timescale must match the signal timescale (the pinned 3-bar = 3-minute vol-stop is far too fast for a slow signal). **Next:** an enabling change to grid the stage1-r signal *and* stop timescales via CLI, plus register the 4 missing tradeable instruments (NAS100, USDJPY [pip 0.01], USDCHF, NZDUSD), so the momentum timeframe screen can run across the full allowed universe.
Brummel added this to the Edge research: prove a real tradeable edge milestone 2026-06-25 09:15:52 +02:00
Author
Owner

Run status — folded into a milestone

This research run is now organised under the milestone "Edge research:
prove a real tradeable edge"
(motivation + full phased plan there). This
issue stays the run log / what-has-run-so-far record. Forward work lives
in the milestone's issues; the next item is the memory BLOCKER.

Milestone issue map:

  • #138 — BLOCKER: sweep memory ~2 GiB/member (next, gates everything below)
  • #139 — walk-forward + MC OOS validation for R candidates (depends on #138)
  • #140 — register NAS100 / USDJPY / USDCHF / NZDUSD
  • #141 — research lead: the index-trend hypothesis (depends on #139, #140)

Shipped this session

  • Enabling change (commits e94b79e RED, 54a5d68 GREEN): aura sweep --strategy stage1-r gains --fast/--slow/--stop-length/--stop-k CSV grid
    flags; aura-composites got risk_executor_vol_open (open vol-stop knobs
    as sweep axes) via a shared topology body, byte-identical defaults. 541
    tests green, clippy clean.

Phase 0 — null baseline (logged above): clean honest null.

First momentum screen (in-sample, full history, frictionless R)

GER40 showed the first positive E[R] (4h–8h / 32h slow SMA-cross, +0.069 /
+0.072) — but the cross-symbol test failed for a universal edge:

 fast/slow    EURUSD    GBPUSD     GER40    USDCAD   #pos
 240/1920   -0.0262   -0.0142   +0.0687   -0.0468     1
 240/7680   -0.0431   -0.0325   +0.0088   +0.0060     2
 480/1920   -0.0170   +0.0104   +0.0722   -0.0509     2
 480/7680   -0.0144   -0.0060   -0.0129   +0.0339     1
1920/7680   +0.0736   -0.0127   -0.1061   -0.0163     1

GER40-positive, FX-negative — consistent with "indices trend, FX
mean-reverts". Reframed as the index-trend hypothesis (own issue),
to be tested forward on FRA40 / NAS100 + temporal OOS. The cross-symbol
discipline caught what would have been a GER40-only overfit.

Blocker hit

Full-history multi-member sweeps use ~2 GiB/member and nearly exhaust
RAM+swap (own BLOCKER issue) — the reason work pauses here.

## Run status — folded into a milestone This research run is now organised under the milestone **"Edge research: prove a real tradeable edge"** (motivation + full phased plan there). This issue stays the **run log / what-has-run-so-far** record. Forward work lives in the milestone's issues; the next item is the memory BLOCKER. Milestone issue map: - **#138** — BLOCKER: sweep memory ~2 GiB/member (next, gates everything below) - **#139** — walk-forward + MC OOS validation for R candidates (depends on #138) - **#140** — register NAS100 / USDJPY / USDCHF / NZDUSD - **#141** — research lead: the index-trend hypothesis (depends on #139, #140) ### Shipped this session - **Enabling change** (commits `e94b79e` RED, `54a5d68` GREEN): `aura sweep --strategy stage1-r` gains `--fast/--slow/--stop-length/--stop-k` CSV grid flags; `aura-composites` got `risk_executor_vol_open` (open vol-stop knobs as sweep axes) via a shared topology body, byte-identical defaults. 541 tests green, clippy clean. ### Phase 0 — null baseline (logged above): clean honest null. ### First momentum screen (in-sample, full history, frictionless R) GER40 showed the first positive `E[R]` (4h–8h / 32h slow SMA-cross, +0.069 / +0.072) — but the **cross-symbol test failed for a universal edge**: ``` fast/slow EURUSD GBPUSD GER40 USDCAD #pos 240/1920 -0.0262 -0.0142 +0.0687 -0.0468 1 240/7680 -0.0431 -0.0325 +0.0088 +0.0060 2 480/1920 -0.0170 +0.0104 +0.0722 -0.0509 2 480/7680 -0.0144 -0.0060 -0.0129 +0.0339 1 1920/7680 +0.0736 -0.0127 -0.1061 -0.0163 1 ``` GER40-positive, FX-negative — consistent with "indices trend, FX mean-reverts". Reframed as the **index-trend hypothesis** (own issue), to be tested forward on FRA40 / NAS100 + temporal OOS. The cross-symbol discipline caught what would have been a GER40-only overfit. ### Blocker hit Full-history multi-member sweeps use ~2 GiB/member and nearly exhaust RAM+swap (own BLOCKER issue) — the reason work pauses here.
Author
Owner

Run log — momentum family exhausted; next thrust = breakout

The slow-SMA-cross momentum lead is closed as refuted (full analysis on
#141): tested forward on FRA40 plus a temporal IS/OOS split on both GER40 and
FRA40. No (fast/slow) cell is positive across both indices and both temporal
halves, and no positive cell is statistically significant (raw sqn = t-stat
≤ ~1.2 full-history, report.rs:171). Together with Phase 0's fast-MA null and
the FX-negative screen, simple moving-average momentum has no Stage-1 edge on
the tradeable universe
.

Next thrust (decided autonomously per the milestone research mandate): a
structurally different trend entry — breakout / channel-extreme
(Donchian-style:
signal on a new N-bar high/low, not a smoothed MA cross), the untested flavour of
this issue's named lead candidate ("time-series momentum / Donchian breakout … on
a higher timeframe + vol/ATR trailing stop — strongest cross-asset prior").

Rationale: MA-cross (persistence of a smoothed drift) and breakout
(range-expansion impulse at an extreme) are structurally distinct trend
mechanics that empirically diverge — a market can fail one while paying the
other. Breakout is the canonical trend-following entry (Turtle/Donchian) and
remains untested here. Same discipline: cross-symbol + temporal-OOS from the
start, frictionless Stage-1 R.

Deferred: #139 (candidate-aware WFO + MC harness) and #140 (register the
4 remaining symbols) — until a candidate shows cross-symbol signal worth the
added rigor/breadth. Manual single-split + SQN-as-t-stat verdicts are sufficient
at the screening stage; building the elaborate test rig before any candidate has
signal is premature.

Apparatus note: the #138 finalize/folding-sink fix makes these full-history
sweeps RAM-safe and fast (~1.5–3 s/sweep, release build), so the screening loop
is now cheap to iterate.

## Run log — momentum family exhausted; next thrust = breakout The slow-SMA-cross momentum lead is **closed as refuted** (full analysis on #141): tested forward on FRA40 plus a temporal IS/OOS split on both GER40 and FRA40. No (fast/slow) cell is positive across both indices and both temporal halves, and no positive cell is statistically significant (raw `sqn` = t-stat ≤ ~1.2 full-history, `report.rs:171`). Together with Phase 0's fast-MA null and the FX-negative screen, **simple moving-average momentum has no Stage-1 edge on the tradeable universe**. **Next thrust (decided autonomously per the milestone research mandate): a structurally different trend entry — breakout / channel-extreme** (Donchian-style: signal on a new N-bar high/low, not a smoothed MA cross), the untested flavour of this issue's named lead candidate ("time-series momentum / Donchian breakout … on a higher timeframe + vol/ATR trailing stop — strongest cross-asset prior"). Rationale: MA-cross (persistence of a *smoothed drift*) and breakout (range-expansion *impulse at an extreme*) are structurally distinct trend mechanics that empirically diverge — a market can fail one while paying the other. Breakout is the canonical trend-following entry (Turtle/Donchian) and remains untested here. Same discipline: cross-symbol + temporal-OOS from the start, frictionless Stage-1 R. Deferred: **#139** (candidate-aware WFO + MC harness) and **#140** (register the 4 remaining symbols) — until a candidate shows cross-symbol signal worth the added rigor/breadth. Manual single-split + SQN-as-t-stat verdicts are sufficient at the screening stage; building the elaborate test rig before any candidate has signal is premature. Apparatus note: the #138 finalize/folding-sink fix makes these full-history sweeps RAM-safe and fast (~1.5–3 s/sweep, release build), so the screening loop is now cheap to iterate.
Author
Owner

Breakout candidate — node-design decisions (settled before specify)

Driving the breakout thrust autonomously (milestone research mandate). The
load-bearing node-level forks, derived and locked (adversarial self-check applied
to F2 and the causality shift):

  • F1 — close-only channel, not high/low. Build the channel over prior-N
    closes, not the OHLC high/low range, so the breakout uses the same
    information set
    as the refuted SMA candidate (a single close stream) and the
    A/B isolates the signal mechanic (extremum vs smoothed mean) from the data
    (close vs high/low). High/low is a later refinement only if close-breakout
    shows signal.
  • F2 — stateful latched ±1 (canonical Donchian/Turtle direction). Bias flips
    to +1 on an up-break (close > prior-N channel max), to −1 on a down-break
    (close < prior-N channel min), and is held between breaks via a latch
    register — the discrete regime-flip-at-the-extreme that is breakout, vs a
    stateless instantaneous signal (never holds a position) or a continuous
    channel-position reading (an oscillator, not a breakout). Self-check: re-entry
    in the same direction after a vol-stop exit is desirable trend-following
    behaviour and is the same executor composition the SMA path already validated.
  • F3 — vol-stop defines R, identical to stage1-r. Direction comes from the
    breakout signal, exit/R from the existing vol-stop + risk-executor, so the only
    thing differing from the momentum candidate is the signal leg → a clean A/B.
  • F4 — one swept param: channel length N (symmetric up/down). A single knob
    (vs momentum's fast+slow), fewer overfit dimensions per the milestone's "few
    parameters, large data"; the vol-stop is the exit, so no separate exit-channel
    is needed.
  • F5 — new primitives RollingMax / RollingMin over N bars; breakout
    composed from them + Delay(1) + comparison + a latch register; new
    --strategy stage1-breakout variant.
    No rolling-extremum node exists today
    (only a special-purpose session-breakout). The channel must exclude the current
    bar (Delay(1) over the rolling extremum → close[t] vs max/min(close[t-N..t-1]))
    — a load-bearing causality (C2) test. New nodes mirror the Sma/Delay ring-
    buffer pattern with warm-up skip-emit.

Same screening discipline as momentum: cross-symbol (GER40 + FRA40) + temporal
IS/OOS split, frictionless Stage-1 R. refs #137

## Breakout candidate — node-design decisions (settled before specify) Driving the breakout thrust autonomously (milestone research mandate). The load-bearing node-level forks, derived and locked (adversarial self-check applied to F2 and the causality shift): - **F1 — close-only channel, not high/low.** Build the channel over prior-N *closes*, not the OHLC high/low range, so the breakout uses the *same information set* as the refuted SMA candidate (a single close stream) and the A/B isolates the signal *mechanic* (extremum vs smoothed mean) from the *data* (close vs high/low). High/low is a later refinement only if close-breakout shows signal. - **F2 — stateful latched ±1 (canonical Donchian/Turtle direction).** Bias flips to +1 on an up-break (close > prior-N channel max), to −1 on a down-break (close < prior-N channel min), and is *held* between breaks via a latch register — the discrete regime-flip-at-the-extreme that *is* breakout, vs a stateless instantaneous signal (never holds a position) or a continuous channel-position reading (an oscillator, not a breakout). Self-check: re-entry in the same direction after a vol-stop exit is desirable trend-following behaviour and is the same executor composition the SMA path already validated. - **F3 — vol-stop defines R, identical to stage1-r.** Direction comes from the breakout signal, exit/R from the existing vol-stop + risk-executor, so the only thing differing from the momentum candidate is the signal leg → a clean A/B. - **F4 — one swept param: channel length N (symmetric up/down).** A single knob (vs momentum's fast+slow), fewer overfit dimensions per the milestone's "few parameters, large data"; the vol-stop is the exit, so no separate exit-channel is needed. - **F5 — new primitives `RollingMax` / `RollingMin` over N bars; breakout composed from them + `Delay(1)` + comparison + a latch register; new `--strategy stage1-breakout` variant.** No rolling-extremum node exists today (only a special-purpose session-breakout). The channel must exclude the current bar (`Delay(1)` over the rolling extremum → close[t] vs max/min(close[t-N..t-1])) — a load-bearing causality (C2) test. New nodes mirror the `Sma`/`Delay` ring- buffer pattern with warm-up skip-emit. Same screening discipline as momentum: cross-symbol (GER40 + FRA40) + temporal IS/OOS split, frictionless Stage-1 R. refs #137
Author
Owner

Breakout candidate — refuted (same failure mode as momentum)

Built and screened the Donchian channel-breakout candidate (cycle 0071,
--strategy stage1-breakout): close-channel breakout, latched ±1 direction,
vol-stop R — the same yardstick as the momentum screen, only the signal leg differs.
Cross-symbol (GER40 + FRA40) + temporal IS/OOS split (2021-01-01), channel grid
{480, 960, 1920, 3840, 7680} bars, stop 1920/2.0. (t = raw sqn = the one-sample
t-statistic for E[R]=0.)

GER40 — E[R] (t):

channel IS OOS full
ch480 +0.005 (0.1) +0.074 (1.3) +0.040 (0.9)
ch960 +0.036 (0.4) +0.083 (1.0) +0.058 (0.9)
ch1920 +0.020 (0.2) −0.104 (−0.9) −0.046 (−0.5)
ch3840 +0.205 (0.9) −0.276 (−1.9) −0.064 (−0.5)
ch7680 +0.011 (0.0) −0.093 (−0.4) −0.057 (−0.3)

FRA40 — E[R] (t):

channel IS OOS full
ch480 −0.042 (−0.7) +0.073 (1.0) +0.007 (0.1)
ch960 −0.117 (−1.3) −0.144 (−1.5) −0.132 (−2.0)
ch1920 −0.028 (−0.2) −0.146 (−1.1) −0.088 (−0.9)
ch3840 −0.013 (−0.1) −0.162 (−0.9) −0.088 (−0.6)
ch7680 −0.181 (−0.7) −0.327 (−1.5) −0.254 (−1.5)

Same three failures as momentum:

  1. No cross-index generalization. GER40's positive channels (480/960) are
    negative-or-flipping on FRA40; ch960 is GER40-positive / FRA40-negative (FRA40 full
    t=−2.0, significantly negative). No channel is positive across both indices and both
    temporal halves.
  2. Violent IS→OOS sign flips at the longer channels — GER40 ch3840 +0.205 IS →
    −0.276 OOS (t=−1.9): the in-sample-best long channel is the OOS-worst, the textbook
    overfit signature.
  3. No statistically significant positive cell (max positive t≈1.3); the only
    significant cells are negative.

Verdict: breakout refuted. Two structurally distinct price-only trend mechanics —
smoothed MA-cross momentum (#141) and channel breakout — both fail the cross-index +
OOS + significance bar on the European indices. The #137 lead candidate (time-series
momentum / Donchian breakout, "strongest cross-asset prior") is now exhausted in both
flavours: trend-following at these M1-derived timescales, frictionless Stage-1 R,
shows no demonstrable edge on this universe.
The breakout machinery (RollingMax/
RollingMin nodes, --strategy stage1-breakout) is permanent and reusable; the
candidate is killed.

refs #137

## Breakout candidate — refuted (same failure mode as momentum) Built and screened the Donchian channel-breakout candidate (cycle 0071, `--strategy stage1-breakout`): close-channel breakout, latched ±1 direction, vol-stop R — the same yardstick as the momentum screen, only the signal leg differs. Cross-symbol (GER40 + FRA40) + temporal IS/OOS split (2021-01-01), channel grid {480, 960, 1920, 3840, 7680} bars, stop 1920/2.0. (`t` = raw `sqn` = the one-sample t-statistic for E[R]=0.) **GER40** — E[R] (t): | channel | IS | OOS | full | |---|---|---|---| | ch480 | +0.005 (0.1) | +0.074 (1.3) | +0.040 (0.9) | | ch960 | +0.036 (0.4) | +0.083 (1.0) | +0.058 (0.9) | | ch1920 | +0.020 (0.2) | −0.104 (−0.9) | −0.046 (−0.5) | | ch3840 | +0.205 (0.9) | −0.276 (−1.9) | −0.064 (−0.5) | | ch7680 | +0.011 (0.0) | −0.093 (−0.4) | −0.057 (−0.3) | **FRA40** — E[R] (t): | channel | IS | OOS | full | |---|---|---|---| | ch480 | −0.042 (−0.7) | +0.073 (1.0) | +0.007 (0.1) | | ch960 | −0.117 (−1.3) | −0.144 (−1.5) | −0.132 (−2.0) | | ch1920 | −0.028 (−0.2) | −0.146 (−1.1) | −0.088 (−0.9) | | ch3840 | −0.013 (−0.1) | −0.162 (−0.9) | −0.088 (−0.6) | | ch7680 | −0.181 (−0.7) | −0.327 (−1.5) | −0.254 (−1.5) | Same three failures as momentum: 1. **No cross-index generalization.** GER40's positive channels (480/960) are negative-or-flipping on FRA40; ch960 is GER40-positive / FRA40-negative (FRA40 full t=−2.0, significantly negative). No channel is positive across both indices and both temporal halves. 2. **Violent IS→OOS sign flips at the longer channels** — GER40 ch3840 +0.205 IS → −0.276 OOS (t=−1.9): the in-sample-best long channel is the OOS-worst, the textbook overfit signature. 3. **No statistically significant positive cell** (max positive t≈1.3); the only significant cells are negative. **Verdict: breakout refuted.** Two structurally distinct price-only trend mechanics — smoothed MA-cross momentum (#141) and channel breakout — both fail the cross-index + OOS + significance bar on the European indices. The #137 lead candidate (time-series momentum / Donchian breakout, "strongest cross-asset prior") is now exhausted in both flavours: **trend-following at these M1-derived timescales, frictionless Stage-1 R, shows no demonstrable edge on this universe.** The breakout *machinery* (RollingMax/ RollingMin nodes, `--strategy stage1-breakout`) is permanent and reusable; the candidate is killed. refs #137
Author
Owner

Next candidate: mean-reversion (cycle 0072) — derived design forks

Trend-following is exhausted in both flavours (MA-cross momentum #141, channel
breakout above). The user green-lit mean-reversion as the next direction.
The mechanic was left to me; the load-bearing forks below are derived
orchestrator decisions (rationale, not user provenance), recorded for audit/veto.

  • Fork: which mean-reversion mechanicEWMA Bollinger-band fade (price
    vs a rolling mean ± k·σ). Derived: this directly tests the hypothesis the
    user named — reversion to a mean — whereas a Donchian-channel fade (the
    literal inverse of the just-refuted breakout) is about channel extremes, not
    a mean, and fading a signal whose trend-direction was noise is itself noise.
    The band-fade also reuses the trusted vol_stop EWMA-σ pattern and needs
    zero new nodes.

  • Fork: σ constructionSqrt(Ema((price − Ema(price))²)) — deviation
    squared first, then smoothed (the exact vol_stop shape). Derived: squaring
    the small deviation (~tens of points), not the raw price (~10⁴), avoids
    catastrophic cancellation, so there is no NaN risk and no clamp / new
    RollingStdDev node
    — unlike the Sma(p²) − Sma(p)² form, which subtracts two
    ~3×10⁸ numbers. This is why vol_stop already builds σ this way.

  • Fork: causality (C2)no Delay(1) on the band path. Derived: the
    current bar legitimately belongs to its own Bollinger band (computing mean/σ
    over a window ending at t and comparing price[t] to it uses only information
    available at t — standard Bollinger, no look-ahead). This differs from
    breakout, whose "break of the prior channel" semantics required excluding
    the current bar.

  • Fork: direction → latch wiring inverted vs breakout: price above the
    upper band → short (−1), below the lower band → long (+1), latched ±1
    and held until the opposite break (0 before the first break). Derived: the
    mean-reversion sign; latched ±1 keeps it directly comparable to momentum /
    breakout.

  • Fork: swept signal knobs → window n (one Ema length, ganged across the
    mean Ema and the variance Ema by build-time bind) + band width k (in σ).
    Downstream vol-stop R knobs (stop_length, stop_k) unchanged. Same R Stage-1
    seam (bias → RiskExecutor → flat-1R), same cross-symbol + temporal-OOS +
    significance screen (split 2021-01-01).

Same lie-detector bar as momentum/breakout: a cell must generalize across
indices, survive IS→OOS, and clear |t| ≳ 2 to count as a real edge.

refs #137

## Next candidate: mean-reversion (cycle 0072) — derived design forks Trend-following is exhausted in both flavours (MA-cross momentum #141, channel breakout above). The user green-lit **mean-reversion** as the next direction. The mechanic was left to me; the load-bearing forks below are **derived** orchestrator decisions (rationale, not user provenance), recorded for audit/veto. - **Fork: which mean-reversion mechanic** → **EWMA Bollinger-band fade** (price vs a rolling mean ± k·σ). *Derived:* this directly tests the hypothesis the user named — reversion to a **mean** — whereas a Donchian-channel fade (the literal inverse of the just-refuted breakout) is about channel *extremes*, not a mean, and fading a signal whose trend-direction was noise is itself noise. The band-fade also reuses the trusted `vol_stop` EWMA-σ pattern and needs **zero new nodes**. - **Fork: σ construction** → **`Sqrt(Ema((price − Ema(price))²))`** — deviation squared first, then smoothed (the exact `vol_stop` shape). *Derived:* squaring the small deviation (~tens of points), not the raw price (~10⁴), avoids catastrophic cancellation, so there is **no NaN risk and no clamp / new RollingStdDev node** — unlike the `Sma(p²) − Sma(p)²` form, which subtracts two ~3×10⁸ numbers. This is why `vol_stop` already builds σ this way. - **Fork: causality (C2)** → **no `Delay(1)` on the band path.** *Derived:* the current bar legitimately belongs to its own Bollinger band (computing mean/σ over a window ending at t and comparing price[t] to it uses only information available at t — standard Bollinger, no look-ahead). This differs from breakout, whose "break of the *prior* channel" semantics *required* excluding the current bar. - **Fork: direction** → latch wiring **inverted vs breakout**: price above the upper band → **short** (−1), below the lower band → **long** (+1), latched ±1 and held until the opposite break (0 before the first break). *Derived:* the mean-reversion sign; latched ±1 keeps it directly comparable to momentum / breakout. - **Fork: swept signal knobs** → window **n** (one Ema length, ganged across the mean Ema and the variance Ema by build-time bind) + band width **k** (in σ). Downstream vol-stop R knobs (stop_length, stop_k) unchanged. Same R Stage-1 seam (bias → RiskExecutor → flat-1R), same cross-symbol + temporal-OOS + significance screen (split 2021-01-01). Same lie-detector bar as momentum/breakout: a cell must generalize across indices, survive IS→OOS, and clear |t| ≳ 2 to count as a real edge. refs #137
Author
Owner

Mean-reversion candidate — refuted (richer failure than the trend pair, but still no edge)

Built and screened the EWMA Bollinger-band fade (cycle 0072,
--strategy stage1-meanrev): price vs a rolling mean ± k·σ, latched ±1, fade the
overextension (above band → short, below → long), same vol-stop R yardstick as the
momentum/breakout screens — only the signal leg differs (zero new nodes; σ reuses
the vol_stop deviation-squared-then-smoothed shape). Cross-symbol (GER40 + FRA40),
temporal IS/OOS split 2021-01-01, grid window {120,240,480,960,1920} × band_k
{1.5,2.0,2.5}, stop 1920/2.0. (t = raw sqn = the one-sample t-statistic for
E[R]=0.) 90 cells total.

Headline cells, E[R] (t):

cell GER40 IS GER40 OOS FRA40 IS FRA40 OOS FRA40 full
w240/k2.5 −0.019 (−0.41) −0.017 (−0.36) +0.135 (+2.42) +0.066 (+0.99) +0.109 (+2.54)
w960/k2.5 −0.039 (−0.42) −0.043 (−0.48) +0.071 (+0.70) +0.204 (+1.45) +0.123 (+1.49)
w1920/k2.5 +0.072 (+0.49) −0.026 (−0.20) +0.103 (+0.70) +0.237 (+1.21) +0.164 (+1.38)

The full GER40/FRA40 IS/OOS/full tables are in the cycle transcript.

The failure modes:

  1. No cross-symbol generalization — and the sharpest possible kind. FRA40
    leans positive almost everywhere (IS: all 15 cells positive); GER40 leans
    negative/zero (no significant positive cell anywhere). The two indices are
    highly correlated European equity benchmarks, so a sign disagreement between
    them is stronger evidence of non-robustness than a disagreement between
    unrelated assets would be. The one IS-significant cell (w240/k2.5, FRA40 IS
    t=+2.42) is negative on GER40 (t=−0.41).

  2. No OOS-significant cell on either index. Every |t| > 2 cell lives on FRA40
    IS or full (full contains IS). In the true out-of-sample half
    (≥ 2021-01-01) the best |t| is 1.45 (FRA40 w960/k2.5) and 1.94 negative
    (GER40 w240/k1.5). The significance is IS-driven, not OOS-confirmed.

  3. Multiple-testing: the lone significant cell is noise-consistent. Across ~30
    independent IS/OOS tests at p≈0.05 one expects ~1.5 false positives by chance.
    We found one independent IS-significant cell (FRA40 w240/k2.5; its "full"
    restatement is not independent). One hit below the ~1.5 chance rate is exactly
    what pure noise produces.

Verdict: mean-reversion refuted. It is the most alive of the three
candidates — FRA40 shows a consistent positive tilt rather than breakout's violent
sign flips — but it fails the same bar: no cross-index generalization (the two
correlated indices disagree in sign), no OOS significance on either index, and its
single IS-significant cell is consistent with multiple-testing noise. The
machinery (--strategy stage1-meanrev, the composed EWMA Bollinger band) is
permanent and reusable; the candidate is killed.

Cumulative finding (three candidates down). Three structurally distinct
price-only, single-symbol Stage-1 signals — smoothed MA-cross momentum (#141),
Donchian channel breakout (0071), EWMA Bollinger mean-reversion (0072) — have now
each been refuted on the European-index universe at M1-derived timescales,
frictionless Stage-1 R, under cross-symbol + OOS + significance. A recurring
sub-pattern across all three: per-index idiosyncratic tilts that do not
generalize
(momentum favoured GER40, mean-reversion favoured FRA40), never a
cross-index-robust edge. This is a milestone-level signal about the price-only
single-symbol thesis itself, not just about any one signal.

refs #137

## Mean-reversion candidate — refuted (richer failure than the trend pair, but still no edge) Built and screened the EWMA Bollinger-band fade (cycle 0072, `--strategy stage1-meanrev`): price vs a rolling mean ± k·σ, latched ±1, fade the overextension (above band → short, below → long), same vol-stop R yardstick as the momentum/breakout screens — only the signal leg differs (zero new nodes; σ reuses the `vol_stop` deviation-squared-then-smoothed shape). Cross-symbol (GER40 + FRA40), temporal IS/OOS split 2021-01-01, grid window {120,240,480,960,1920} × band_k {1.5,2.0,2.5}, stop 1920/2.0. (`t` = raw `sqn` = the one-sample t-statistic for E[R]=0.) 90 cells total. **Headline cells, E[R] (t):** | cell | GER40 IS | GER40 OOS | FRA40 IS | FRA40 OOS | FRA40 full | |---|---|---|---|---|---| | w240/k2.5 | −0.019 (−0.41) | −0.017 (−0.36) | **+0.135 (+2.42)** | +0.066 (+0.99) | **+0.109 (+2.54)** | | w960/k2.5 | −0.039 (−0.42) | −0.043 (−0.48) | +0.071 (+0.70) | +0.204 (+1.45) | +0.123 (+1.49) | | w1920/k2.5 | +0.072 (+0.49) | −0.026 (−0.20) | +0.103 (+0.70) | +0.237 (+1.21) | +0.164 (+1.38) | The full GER40/FRA40 IS/OOS/full tables are in the cycle transcript. **The failure modes:** 1. **No cross-symbol generalization — and the sharpest possible kind.** FRA40 leans positive almost everywhere (IS: all 15 cells positive); GER40 leans negative/zero (no significant positive cell anywhere). The two indices are highly correlated European equity benchmarks, so a sign disagreement between them is *stronger* evidence of non-robustness than a disagreement between unrelated assets would be. The one IS-significant cell (w240/k2.5, FRA40 IS t=+2.42) is **negative** on GER40 (t=−0.41). 2. **No OOS-significant cell on either index.** Every |t| > 2 cell lives on FRA40 **IS** or **full** (full contains IS). In the true out-of-sample half (≥ 2021-01-01) the best |t| is 1.45 (FRA40 w960/k2.5) and 1.94 *negative* (GER40 w240/k1.5). The significance is IS-driven, not OOS-confirmed. 3. **Multiple-testing: the lone significant cell is noise-consistent.** Across ~30 independent IS/OOS tests at p≈0.05 one expects ~1.5 false positives by chance. We found one independent IS-significant cell (FRA40 w240/k2.5; its "full" restatement is not independent). One hit below the ~1.5 chance rate is exactly what pure noise produces. **Verdict: mean-reversion refuted.** It is the *most alive* of the three candidates — FRA40 shows a consistent positive tilt rather than breakout's violent sign flips — but it fails the same bar: no cross-index generalization (the two correlated indices disagree in sign), no OOS significance on either index, and its single IS-significant cell is consistent with multiple-testing noise. The machinery (`--strategy stage1-meanrev`, the composed EWMA Bollinger band) is permanent and reusable; the candidate is killed. **Cumulative finding (three candidates down).** Three structurally distinct price-only, single-symbol Stage-1 signals — smoothed MA-cross momentum (#141), Donchian channel breakout (0071), EWMA Bollinger mean-reversion (0072) — have now each been refuted on the European-index universe at M1-derived timescales, frictionless Stage-1 R, under cross-symbol + OOS + significance. A recurring sub-pattern across all three: **per-index idiosyncratic tilts that do not generalize** (momentum favoured GER40, mean-reversion favoured FRA40), never a cross-index-robust edge. This is a milestone-level signal about the price-only single-symbol thesis itself, not just about any one signal. refs #137
Author
Owner

Closing — milestone wound down (a means-end inversion, honestly disproved)

This milestone set out to find a Stage-1 positive-E[R] edge by hand. It is being
wound down, not completed — and that is the right outcome, for two reasons.

The empirical result. Three structurally distinct price-only, single-symbol
signals — smoothed MA-cross momentum (#141), Donchian channel breakout (cycle
0071), EWMA Bollinger mean-reversion (cycle 0072) — were each screened under the
full discipline (cross-symbol GER40+FRA40, temporal IS/OOS split 2021-01-01,
significance, multiple-testing). All three came back E[R] ≈ 0, frictionless.
The entry carries no edge. A recurring sub-pattern across all three: per-index
idiosyncratic tilts that never generalize (momentum→GER40, mean-reversion→FRA40).
The lie-detector worked exactly as designed — it honestly killed the simple stuff.

The framing error. The milestone existed to "quickly find an edge so the
broker implementation has something to test against." That is a means-end
inversion: if an edge were quick to find by hand, the engine would be pointless.
We are here to develop Aura, not to use it. The genuine prerequisite the broker
needs is any strategy to drive the bias→R→executor path — and a losing
strategy exercises a broker's friction model / position-event table / currency
curve exactly as well as a winning one. We now have three.

What is kept (permanent engine code, the broker's test material): the R
apparatus (stage1-r / --strategy {sma|momentum|stage1-r|stage1-breakout| stage1-meanrev}, summarize_r, the vol-stop RiskExecutor, flat-1R Sizer,
PositionManagement R-record), the streaming finalize + folding sinks
(GatedRecorder / SeriesReducer), and the RollingMax / RollingMin nodes.

Survivors detached to standalone backlog (genuine engine/data work,
independent of the abandoned edge hunt): #139 (generalize walk-forward + MC to any
harness + R) and #140 (register the remaining tradeable instruments — now MORE
relevant: the FX pairs are what the realistic-broker milestone needs for
currency-P&L). #142 (end-of-milestone report) is closed — its premise is gone.

Closing #137 and the milestone container. Next: develop Aura (recommended:
realistic broker, C10 A-side).

## Closing — milestone wound down (a means-end inversion, honestly disproved) This milestone set out to *find* a Stage-1 positive-E[R] edge by hand. It is being **wound down, not completed** — and that is the right outcome, for two reasons. **The empirical result.** Three structurally distinct price-only, single-symbol signals — smoothed MA-cross momentum (#141), Donchian channel breakout (cycle 0071), EWMA Bollinger mean-reversion (cycle 0072) — were each screened under the full discipline (cross-symbol GER40+FRA40, temporal IS/OOS split 2021-01-01, significance, multiple-testing). All three came back **E[R] ≈ 0, frictionless**. The entry carries no edge. A recurring sub-pattern across all three: per-index idiosyncratic tilts that never generalize (momentum→GER40, mean-reversion→FRA40). The lie-detector worked exactly as designed — it honestly killed the simple stuff. **The framing error.** The milestone existed to "quickly find an edge so the broker implementation has something to test against." That is a means-end inversion: if an edge were quick to find by hand, the engine would be pointless. We are here to **develop Aura**, not to use it. The genuine prerequisite the broker needs is *any* strategy to drive the bias→R→executor path — and a *losing* strategy exercises a broker's friction model / position-event table / currency curve exactly as well as a winning one. We now have three. **What is kept (permanent engine code, the broker's test material):** the R apparatus (`stage1-r` / `--strategy {sma|momentum|stage1-r|stage1-breakout| stage1-meanrev}`, `summarize_r`, the vol-stop RiskExecutor, flat-1R Sizer, PositionManagement R-record), the streaming `finalize` + folding sinks (GatedRecorder / SeriesReducer), and the RollingMax / RollingMin nodes. **Survivors detached to standalone backlog** (genuine engine/data work, independent of the abandoned edge hunt): #139 (generalize walk-forward + MC to any harness + R) and #140 (register the remaining tradeable instruments — now MORE relevant: the FX pairs are what the realistic-broker milestone needs for currency-P&L). #142 (end-of-milestone report) is closed — its premise is gone. Closing #137 and the milestone container. Next: develop Aura (recommended: realistic broker, C10 A-side).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Brummel/Aura#137