After my research certified that price action on 5-minute BTC has no tradable edge, the right question wasn't "what better signal can I find?", but: "is there an edge that doesn't require predicting price at all?".
The answer was in the structure of my setup: I could see two prices for the same asset. The reference exchange feed (Binance futures, via websocket) and my CFD broker's quote on the same underlying. The broker's price follows the exchange's — it must, by construction — but with variable delay and noise. When the fast feed moves sharply, for a fraction of time the slow price is "wrong": not a prediction — a fact, with an expiry.
This is latency arbitrage in its retail form: buy/sell the slow price in the direction the fast one has already gone, and exit at convergence. The edge source is structural: it's paid by the friction of the broker's quoting mechanism.
v4, v5: chronicle of an instructive failure
v4 worked "by log feel": it fired on divergences, closed on time. v5 added ambitious take profits (0.55–0.85%) with a 600-second max horizon. Result: 50 live trades, market −$8.54, commissions −$118.48, net −$127.02. 93% of the loss was costs. The autopsy goes further, and every detail is a general lesson:
- Zero take profits hit out of fifty. The 0.55–0.85% TPs were physically unreachable within the divergence's lifespan (seconds, not minutes). The parameter wasn't badly tuned: it was conceptually foreign to the traded phenomenon. If the phenomenon is a convergence, the exit must be the convergence — not a hoped-for price level.
- The guardian anchored to the wrong number. The drawdown limit was computed on a balance read at runtime instead of the prop account's true baseline. The guardian was protecting an imaginary account. On a prop account the baseline is a contractual constant, and must be written as such, not inferred from current state.
- The saturated score. The signal's adaptive threshold was pinned at its maximum: it filtered everything equally, i.e. filtered nothing. Every adaptive threshold needs testing at its extremes: a saturated filter is a dead filter that no ordinary log will flag.
Three different bugs with the same root: components written before precisely understanding the phenomenon. v6 was born by inverting the order: first the physics of the phenomenon, then the code.
v6: the cost-gated architecture
- Cost-gate: enter only if the measured divergence exceeds 2× the total live-estimated cost (commissions + current spread + EWMA slippage). It's the filter that sends the system silent for hours, and that's correct: here, selectivity is the strategy.
- Exit at convergence, not at a target: gap closed, trade closed. Max holding time 120 seconds — beyond that, the hypothesis that justified the trade has expired, and a position whose hypothesis has expired must be closed regardless of its P&L.
- Explicit prop baseline, hard-coded as a contractual constant; anti-martingale sizing anchored to the remaining margin above the floor.
- EV kill-switch: the system keeps books on its own realized expectancy over a rolling window; if measured EV turns negative net of costs, it shuts itself down. The question "is it broken or is it variance?" answered with a written threshold instead of anxiety.
- Shadow mode: the system does everything — detects, decides, sizes, records — except sending orders. It produces the dataset of virtual trades with timestamps and estimated costs, at zero risk.
The promotion criterion from shadow mode to real money is written in the code, not in my mood: at least 30 shadow trades with positive average EV. The system stays there until the criterion is met. If it never is, v6 will die without having lost a euro — the second-best possible outcome for a system, and infinitely better than the third.
The portable lessons (even if you never do HFT)
- The best edge doesn't predict — it exploits a structural constraint. Look for mechanism asymmetries — calendar, microstructure, forced flows — before looking for signals.
- Every parameter must belong to the physics of the phenomenon. A price TP on a temporal-convergence phenomenon is a category error, not a tuning error — and no optimizer will tell you.
- Shadow mode before money, with a written promotion criterion. True for an HFT bot as for your new discretionary setup.
- On latency, rank matters, not absolute value: you don't need to be fast in absolute terms — you need to be faster than the others milking the same signal on the same venue. The right question isn't "how low is my ping?" but "who else is milking this cow, and do they get there before me?". When the answer becomes "too many", the edge is over — and the EV kill-switch is there to notice before you do.
The Binance feed and data pipeline behind this project: Quant research with Python and the Binance API. The AI development method that wrote v6: here, with the prompts.