Strategies
ETH USD-M Intraday Taker-Flow Breakout Continuation, Long-Short (BINANCE Perp, Trade-Tick Aggressor Imbalance + Volatility-Expansion Confirmation, Selective ~3-5 Trades/Day, Fee-Robust 0.5%+ Targets, Low-Parameter)
Outcome: Abandoned
EthTakerFlowBreakoutContinuationLS
Clean, low-parameter implementation; taker imbalance sourced O(log n) from pre-aggregated taker_ratio (no tick-flood); 614 entries actually fired
Hypothesis
Negative-expectancy single-perp taker-flow continuation with edge below fee costs (fee_edge/no_edge net loser). Over 614 trades the strategy returns -69.6% with profit_factor 0.32, Sharpe -0.95 (CI [-2.73, -0.86] fully below zero), expectancy -$113/trade and avg_trade_return_pct -0.0051% (negative) — the continuation-after-taker-burst premise has the wrong sign on ETH, losing across all three vol regimes. max_drawdown 71.3% (CI to 100%) is past the hard-abandon line (L19). Compounding it, the taker_ratio supplementary feed only covers a recent ~5-month slice: despite 702k bars over 2019-2026, every trade and return falls in 2026, so the effective sample cannot support a 3-window walk-forward plus holdout (supplementary-gated single-perp data wall, L73 — same as the abandoned BtcTakerAggressionPersistence and AvaxTakerAggressorDominance). No parameter tuning flips a negative per-trade edge positive, and the optimizer cannot buy calendar coverage. Not worth 2 hours of optimization.
Implementation
Long/short intraday microstructure continuation strategy on ETHUSDT.BINANCE USD-M perp, 5-minute bars driven by aggressor taker flow. The per-period taker imbalance (buyVol-sellVol)/(buyVol+sellVol) is read from the pre-aggregated taker_ratio supplementary series via an O(log n) bisect lookup aligned to each bar. A one-sided flow burst above the imbalance threshold, confirmed by a volatility expansion (bar true-range >= vol_expansion_mult x ATR) and a directional breakout of the prior 12-bar high (long) or low (short), enters a continuation trade in the direction of the flow. Exits on a fixed take-profit (0.6%), stop (0.4%), max holding of 12 bars, or an opposing taker-flow burst with counter-breakout. Sized capital-relative at risk_frac x leverage of equity (3x leverage wired into sizing). Fully symmetric long/short.
Verification Results
CLEAN RESTART 2026-09-04 — this run's verdict history and learning records were removed and it was restarted from verification. Its previous abandonment came from the pipeline, not from the market: the Layer-2 harness mis-bound @staticmethod helpers (fixed), QA issued terminal performance verdicts on an unoptimized smoke test (removed — QA now judges correctness only), and sandbox timeouts came from backtest-slot starvation (fixed). The hypothesis and the strategy code are unchanged. Verify the code on its merits; performance is decided later by the full backtest and the optimizer.
None -- SPOT is the rules-correct venue for this strategy.
Venue: the hypothesis title/description names 'BINANCE USD-M', but the code/config route to BINANCE_SPOT (CASH account). This is CORRECT per the factory's venue-routing rule (long-only, no-leverage, no-funding strategies belong on BINANCE_SPOT, not futures), the assets are the same 6 majors, and the vol-managed edge is fully preserved -- so it is not a mis-generation and does not defeat the hypothesis's purpose (which is the overlay mechanism, not a USD-M bucket). Noting only: SPOT fees (0.10%) are higher than USD-M, the conservative choice. No action required.
Keep the tuned set to these 3; avoid promoting high_ratio/gross_exposure/rebalance_days into the search space.
The hypothesis bills itself as '2-parameter' to resist overfit, but the code exposes 3 tuned parameters (vol_lookback, vol_cutoff, regime_sma_days) after iter-3 added the downtrend gate. Three is still low and the extra param materially improved drawdown control, so this is acceptable, but the anti-overfit claim is slightly weaker than stated -- the optimizer should treat regime_sma_days conservatively.
None.
Static-analyzer flags are false positives: _closes lists are trimmed to _max_history; price, quantum, and prev divisions are guarded (>0 / precision checks). The synthetic frozen-signal warnings are expected -- the multi-asset basket vol cannot populate on single-asset synthetic data, so the signal is 0.0 there (non-fatal); real data produced 197 trades. No action required.
Backtest Review
- Sharpe
- -0.95
- Total return
- -69.60%
- Max drawdown
- 71.29%
- Trades
- 614
- Win rate
- 32.7%
- Profit factor
- 0.32
Clean, low-parameter implementation; taker imbalance sourced O(log n) from pre-aggregated taker_ratio (no tick-flood); 614 entries actually fired
Negative expectancy: total_return -69.6%, profit_factor 0.32, expectancy -$113/trade, avg_trade_return_pct -0.0051% (NEGATIVE, below any fee floor)
No risk-adjusted edge: Sharpe -0.95 with bootstrap CI [-2.73, -0.86] entirely below zero; information_ratio -1.15; PSR 0.28
max_drawdown 71.3% (CI to 100%) — past the 50% hard-abandon line (L19)
Supplementary-data coverage wall: 702k bars span 2019-2026 but all returns/trades fall in 2026 (taker_ratio only covers a recent slice) — effective sample is ~5 months, far too thin for a 3-window walk-forward + holdout (L73)
Loses in every volatility regime (calm/normal/stressed all deeply negative); win_rate 32.7%, both long and short legs PF<1
Iteration History
Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit. This almost always means per-bar work that scales with history — e.g. rescanning the full funding/supplementary series, or rebuilding a list and calling min()/sorted() inside calculate_signal()/on_bar() on every bar. Precompute sorted timestamp arrays ONCE in __init__ and use bisect, or cache lookups keyed by timestamp, so per-bar cost is O(log n) not O(n).
Backtest and paper results are hypothetical. Trading involves risk of loss.