Strategy research: find a Stage-1 positive-E[R] edge (honest OOS) #137
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Provenance
Goal
Find a Stage-1 positive-
E[R]strategy that survives honestout-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):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)
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.
selects the best cell on noise; OOS + MC + cross-symbol consistency
is what controls it.
quality; Stage-2 (broker/costs, the existing #116… milestone) is the
gate a survivor then passes (ledger:
E[R] > 0before 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:
aura walkforwardis locked to the SMA sample blueprint + fixed90/30/30-day windows — cannot run stage1-r or a new candidate, no R.
aura mcis synthetic-only, 3 hardcoded seeds — useless on realcandidates.
(only in
aura-engine/tests/ger40_breakout.rs+ ingest examples).instrument_spec()entry(NAS100, USDJPY, USDCHF, NZDUSD) —
--realrefuses them.Plan (phased; each phase a truthful verdict, cheap to kill)
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.drives
walk_forward+monte_carloover a chosen candidateblueprint 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).
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.
E[R] > 0OOS, robust under MC and across symbols, proceeds to costs/broker
realism (the existing Stage-2 broker milestone).
Out of scope (for now)
pure price strategies don't need them).
E[R] > 0survivor exists).first).
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:
Verdict: a clean, honest null. A fast (2/4-bar) SMA cross on M1 has
E[R] ≈ 0(GER40) to slightly negative (FX), frictionless — aguaranteed 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.
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:
Shipped this session
e94b79eRED,54a5d68GREEN):aura sweep --strategy stage1-rgains--fast/--slow/--stop-length/--stop-kCSV gridflags;
aura-compositesgotrisk_executor_vol_open(open vol-stop knobsas 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:
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 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 andthe 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.
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):
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.
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.
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.
(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.
RollingMax/RollingMinover N bars; breakoutcomposed from them +
Delay(1)+ comparison + a latch register; new--strategy stage1-breakoutvariant. 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/Delayring-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 — 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= rawsqn= the one-samplet-statistic for E[R]=0.)
GER40 — E[R] (t):
FRA40 — E[R] (t):
Same three failures as momentum:
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.
−0.276 OOS (t=−1.9): the in-sample-best long channel is the OOS-worst, the textbook
overfit signature.
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; thecandidate is killed.
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_stopEWMA-σ pattern and needszero new nodes.
Fork: σ construction →
Sqrt(Ema((price − Ema(price))²))— deviationsquared first, then smoothed (the exact
vol_stopshape). Derived: squaringthe 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_stopalready builds σ this way.Fork: causality (C2) → no
Delay(1)on the band path. Derived: thecurrent 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
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 theoverextension (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_stopdeviation-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= rawsqn= the one-sample t-statistic forE[R]=0.) 90 cells total.
Headline cells, E[R] (t):
The full GER40/FRA40 IS/OOS/full tables are in the cycle transcript.
The failure modes:
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).
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.
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) ispermanent 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
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).