Quant for Free
Home / Learn / Online FDR
Learn · Deep dive · Method explainer

Your Live Signal Stream Has No N — Online FDR Control After the Deflated Sharpe Ratio

The Deflated Sharpe Ratio answers a finished-batch question: you counted your trials, you have all N results, now correct the winner. A live scanner never gives you that batch. Signals arrive one at a time, each is acted on before the next exists, and the stream has no N. Muhammad Minhas Qamar's Online False Discovery Rate Control: Putting an Error Budget on a Live Signal Stream (MQL5 24577, 16 Oct 2026) ports the online answer — LORD3, LORD++ and SAFFRON — into pure MQL5, builds the causal p-value source they need, and then spends most of its effort trying to break them. This page is that method as the sequel the DSR page was missing. It is not a gate you bolt on to make a losing rule profitable; the author's own gated EA loses money, and says so.

The opening arithmetic is the motivation, and it is the author's: a 28-symbol × 7-timeframe scanner tested at 5% per cell expects roughly ten false lights per sweep on pure noise — about five hundred confident signals a year if run weekly. An EA firing forty times a month at 5% manufactures two false alarms a month by construction, and the strongest-looking are the ones that get deployed.

1 / What the object actually is

Alpha-wealth. Start with a budget w0 below the target α. Every hypothesis examined spends its test level α_t; every discovery refunds a payout (α − w0 for the first, α thereafter). Discoveries finance further testing; a long run of nulls starves the procedure — which, the author insists, is correct behaviour, not a defect. The guarantee, provided the p-values are valid: among the signals you acted on, the expected fraction that were noise stays below α. That is FDR, not family-wise error: it tolerates a known share of mistakes among discoveries in exchange for still being able to find things. A false discovery is a statement about the hypothesis, not the trade — a true discovery can lose money and a false one can win.

The level comes from a gamma sequence (non-increasing, summing to at most one) — the only real tuning knob. Two shapes ship. ZETA (j^-1.6 / ζ(1.6), ζ(1.6) ≈ 2.2856) front-loads: γ₁ = 0.4375, 88% of its allowance in the first 20 terms. LORD (the Javanmard–Montanari default) holds reserve: γ₁ = 0.0500, and after 2,000 hypotheses it has paid out only 0.305 of its total — a large part of LORD++'s later gap to target is the sequence, the author notes, not the procedure. Every number in the article uses the LORD sequence.

Where the p-values come from is the part a port can get wrong. The stream is firings, not bars (a bar-by-bar stream would submit near-duplicate questions). Five heterogeneous close-only rules ship (MA cross, z-score reversion, breakout, momentum, volatility squeeze), each firing on a transition, not a state. For a firing at bar i, the p-value is computed from the rule's own past firings inside an evidence window that ends h bars before i, so every forward return in it is already observed; the outcome window i..i+h is strictly later. The null is a stationary (block) bootstrap over the same window, same firing count, same direction multiset, mean block 20 against horizon h = 10 throughout. Two silent failures live here:

  1. The resolution floor. A rank-based bootstrap p-value cannot be smaller than 1/(B+1). At B = 200 the floor is 0.005, while LORD++ hands out 0.0025 on the first hypothesis and reaches 1e-4 by the twentieth quiet one. The smallest producible p-value is larger than the threshold it must clear: zero rejections are arithmetically certain, and from outside that looks exactly like a well-behaved quiet gate. B = 2000 only moves the floor to 5.00e-04. The fix shipped is BOOT_NORMAL: keep the block-bootstrap null, read the tail off a normal fitted to the draws (centre estimated, not assumed zero). No floor — at the cost of an explicit modelling assumption in the far tail where there are no draws to check.
  2. Anti-conservative tails. Validity requires super-uniformity — P(p ≤ x) ≤ x — which is one-sided. The author's first attempt used a two-sided KS test and condemned the correct bootstrap alongside the broken comparator; the shipped check is D+ = sup(F_n(x) − x).

Calibration before the market (α 0.10, w0 0.05, λ 0.50, LORD gamma, seed 20260826, as reported). On null series: 6,148 null hypotheses from four 6,000-bar Gaussian random walks at B = 2000. Both bootstrap modes pass D+ (0.0101 and 0.0118 vs 5% critical 0.0156); the naive t-test fails (0.0828), returning 10.74% of p-values below 0.05 where 5% are promised. The uncomfortable column the author keeps: below 0.01, the rank bootstrap returns 1.63% and boot-normal 1.84% — neither is conservative that deep, and the online levels live deeper still. D+ passing means "no gross failure", not "valid at the levels the procedures use". Then, procedures alone (exact p-values, 2,000 hypotheses, 5% non-null at effect size 3 SD, target FDR 10%, 200 replications): uncorrected realises FDR 0.6691 at power 0.9567; Bonferroni 0.0013 at power 0.0841; LORD3 0.0786 / 0.4021; LORD++ 0.0266 / 0.3123; SAFFRON 0.0242 / 0.3125. All three real procedures sit under the 10% target; LORD3 is closest and most powerful — in the independent case.

2 / What it does not claim — and where it fails

3 / How a reader could tear it down next

Not a signal. A next attempt on a stream you already run:

  1. Validate the p-value source first, one-sided, and then past D+. Super-uniformity on a known-null series, then the sub-0.01 tail specifically, because that is where online levels live. A marginal check does not establish conditional validity; treat a pass as a licence to continue, not as the guarantee.
  2. Check resolution against the smallest level before you check anything else. If your p-value floor sits above the level the procedure will assign after a quiet stretch, zero rejections are guaranteed by arithmetic. Change the estimator (a fitted tail, with its assumption stated), not just the replication count.
  3. Default to LORD++ when dependence is unknown — on this evidence it is the only one of the three that held in every block and burst cell. If you ship LORD3 or SAFFRON on a multi-symbol, multi-timeframe scanner (the block-dependence case), the burden of proof is yours.
  4. Throttle correlated groups. One submission per group per gap, gap pre-declared. Expect to buy the guarantee back with most of the questions under block dependence; under pure repetition it can be nearly free.
  5. Report the starved share with every quiet result. A gate that found nothing while spending a third (or 94%) of its stream below 1e-4 has told you about its budget, not about the market. Throttle the stream rather than lowering α until something passes.
  6. Keep the arms honest. If you A/B a gate, the control must be "every tested firing" with the same position constraints, plus the control this article did not run: a random gate passing the same fraction. Otherwise fewer trades will flatter any gate.

4 / Verdict

The DSR corrects a batch you have finished; online FDR control is the error budget for a stream that never finishes. The portable findings are narrower than the port: validate p-values one-sided and in the far tail, never let a resolution floor masquerade as conservatism, prefer LORD++ under unknown dependence, and read starved share before you read silence. None of that makes the underlying rules profitable — on the author's EURUSD stream there was nothing to find, and the gate correctly found approximately nothing, at 3% of the exposure. The small open edge is procedural: a live scanner that today reports "significant at 5%" per cell is running the uncorrected arm, whose measured false-discovery share in the bench was two-thirds. Replacing that one habit is a real improvement even before any rule behind the gate has an edge.

Source

Numbers

From the article, not from a Quant for Free run: scanner arithmetic ≈10 false lights per 196-cell sweep at 5%, ≈500/year weekly (author's illustration); gamma γ₁ LORD 0.0500 vs ZETA 0.4375, LORD sum 0.305 after 2,000 terms, ζ(1.6) ≈ 2.2856; calibration 6,148 null hypotheses, D+ bootstrap 0.0101 / boot-normal 0.0118 / t-test 0.0828 (critical 0.0156), P(p<0.05) 0.0395 / 0.0389 / 0.1074, P(p<0.01) 0.0163 / 0.0184 / 0.0423, smallest p 5.00e-04 vs 3.23e-13; procedure bench (target 0.10) FDR/power: uncorrected 0.6691/0.9567, Bonferroni 0.0013/0.0841, LORD3 0.0786/0.4021, LORD++ 0.0266/0.3123, SAFFRON 0.0242/0.3125; block ρ=0.9 FDR LORD3 0.2396, SAFFRON 0.1542, LORD++ 0.0760, throttled LORD3 0.0125 (2,000 → 100 hypotheses at gap 25); EURUSD stream 3,428 hypotheses, accepts ≈3%, starved shares 98.9% / 57.5% / 33.3% / 32.6% (Bonferroni/LORD3/LORD++/SAFFRON), 4,000-bar LORD++ starved 94%; gated EA (SAFFRON, α 0.10) OFF 938 trades −$1,773.90 DD 19.08% vs ON 89 trades −$132.86 DD 2.95%, passed 116, book-busy skips 1,232 (OFF) vs 22 (ON). Config throughout: h=10, B=2000 (StreamBench) / 500 (EA), mean block 20, evidence window 1,500 bars, ≥25 past firings, α 0.10, w0 0.05, λ 0.50, seed 20260826. No site numbers; no summary.json (no clean-room run).

Educational analysis, not investment advice. A methodology note of a publicly documented source — not a recommendation to trade or avoid any instrument, script, parameter set, or workflow. This page does not report a Quant for Free clean-room backtest and does not attach a summary.json. Figures in the text are the source’s, labeled as such. See the full disclaimer.