BTC Regime-Gated Maker Grid Range-Harvest, Market-Neutral (Single-Instrument BTCUSDT.BINANCE Perp, Layered MAKER Limit Orders Around a Mean, Active ONLY in Confirmed Ranging Regimes, Hard Flatten on Breakout, Wide Fee-Clearing Spacing, 3-Parameter)
Outcome: Abandoned
BtcRegimeGatedMakerGridRangeHarvest
Backtest gate: - metrics unreliable: Incoherent: Sharpe 0.20 disagrees in sign with total_return -64.92% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on…
A MARKET-NEUTRAL, single-instrument, range-harvest GRID strategy on BTCUSDT.BINANCE USD-M perpetual — a mechanically DIFFERENT FAMILY from everything proposed this session (all of which were directional momentum, relative-value, supplementary-confirm, or reversion, and all of which died). It places a ladder of MAKER limit orders (buys below, sells above a rolling mean) and harvests the bid/ask oscillation as price ranges, netting the grid spacing minus fees on each captured round-trip. It is engineered against……Show moreShow less
A MARKET-NEUTRAL, single-instrument, range-harvest GRID strategy on BTCUSDT.BINANCE USD-M perpetual — a mechanically DIFFERENT FAMILY from everything proposed this session (all of which were directional momentum, relative-value, supplementary-confirm, or reversion, and all of which died). It places a ladder of MAKER limit orders (buys below, sells above a rolling mean) and harvests the bid/ask oscillation as price ranges, netting the grid spacing minus fees on each captured round-trip. It is engineered against the grid family's two known killers. (1) TRENDS destroy grids (unbounded loss on the losing side): so it is STRICTLY REGIME-GATED — it only arms the grid when a ranging regime is confirmed (flat MA slope + price contained in a Bollinger/Keltner channel + low ADX), and it HARD-FLATTENS all inventory and disarms the moment a breakout/trend regime is detected. (2) FEES kill tight grids: so it uses WIDE spacing (each level ≥ grid_spacing apart, default 0.6%) and MAKER limit orders (0.02% maker vs 0.05% taker on Binance USD-M), making each round-trip's ~0.04% maker cost far smaller than the ≥0.6% harvested per oscillation. It is pure OHLCV-driven for the regime gate (reliably measurable, no supplementary coverage issue), single-instrument, developer-safe, and generates a large measurable sample (grids fill many times per ranging episode → hundreds of round-trips over multi-year history). It fills the under-target market-neutral and LONG-SHORT buckets (13.6% vs 86.4% long-only) and adds genuine mechanism diversity (grid range-harvest) absent from the entire momentum-dominated pending book. 3 parameters.
The gate's finding was that Sharpe +0.20 disagrees in sign with total_return -64.92%. Both are now computed from the same mark-to-market equity curve (runner.py builds the daily series from mtm_equity_curve), so this is not a marked-vs-realized accounting split any more -- it is the payoff SHAPE: a positive arithmetic daily mean with a deeply negative compounded return is a fat left tail, where volatility drag (sigma^2/2) exceeds the mean. For a grid, those outlier loss days are the ones where a leaned book is……Show moreShow less
The gate's finding was that Sharpe +0.20 disagrees in sign with total_return -64.92%. Both are now computed from the same mark-to-market equity curve (runner.py builds the daily series from mtm_equity_curve), so this is not a marked-vs-realized accounting split any more -- it is the payoff SHAPE: a positive arithmetic daily mean with a deeply negative compounded return is a fat left tail, where volatility drag (sigma^2/2) exceeds the mean. For a grid, those outlier loss days are the ones where a leaned book is carried through a breakout. So the change attacks the tail, not the bookkeeping: (1) the inventory stop is evaluated at the bar's adverse extreme, so a bar that pierces the cap intra-bar and closes back inside no longer carries the excursion forward; (2) the tail is scaled down where it is generated -- peak gross exposure drops from 30% to 10% of equity and a carried book can now cost at most ~0.5% of equity. Everything that passed Layers 1-3 and QA (regime gate, continuous signal, profitable-side reduce clamp, reduce-only disarm, frozen unit reference, 3-parameter surface) is untouched. HONEST NOTE: this makes the numbers coherent and caps the tail, it does not create edge. Three measurements of this mechanism have now come back at -73.19%, -58.80% and -64.92%, and even the best-case arithmetic mean is only ~0.2 Sharpe -- scaling exposure down far enough for the drag not to swallow it leaves roughly a 2%/yr book, far below every promotion floor. Regime-gated grids on BTC 1H pay the trend-resolution cost every time a range ends and no gate is fast enough to dodge it without also killing the ranging fills that pay for it, which is why I recommend abandon; this submission exists only so the reviewer can take one clean, coherent, tail-capped measurement first if they want it.
Negative expectancy on a reliable, decisive 4641-trade / 6.7-year sample: profit_factor 0.817, total_return -31.06%, avg_trade_return_pct 0.0305% (far below the 0.15% Binance USD-M fee floor and below net-zero), expectancy -$6.67/trade, Sharpe -0.31, Sortino -0.30. The trades correctly implement the hypothesis (market-neutral maker grid, balanced 2299 long / 2342 short, ~50% exposure), so this is a fair test of the range-harvest premise — and the premise is falsified: the book loses in EVERY calendar year……Show moreShow less
Negative expectancy on a reliable, decisive 4641-trade / 6.7-year sample: profit_factor 0.817, total_return -31.06%, avg_trade_return_pct 0.0305% (far below the 0.15% Binance USD-M fee floor and below net-zero), expectancy -$6.67/trade, Sharpe -0.31, Sortino -0.30. The trades correctly implement the hypothesis (market-neutral maker grid, balanced 2299 long / 2342 short, ~50% exposure), so this is a fair test of the range-harvest premise — and the premise is falsified: the book loses in EVERY calendar year (2020-2026) and in ALL three vol regimes (calm -9.6%, normal -24.4%, stressed -12.6%). Commission is only 13.6% of gross, so this is not fee-fragility; the grid's payoff is the known fat-left-tail killer (win_rate 0.69 but avg_loss 118.5 >> avg_win 42.9, return_kurtosis 82.5) where leaned inventory carried through breakouts erases the maker round-trip wins. This is the FOURTH negative measurement of the same regime-gated grid mechanism (prior -73%, -59%, -65%) and the developer's own honest analysis recommends abandon; the 3 tunable knobs only trade ranging fills against trend-exit cost and cannot invert a PF-0.82, below-fee signal. QA's edge/payoff-shape concern is borne out on full history. Not worth 2 hours of optimization. abandon_class=negative_expectancy.
Implementation
Market-neutral maker grid on BTCUSDT.BINANCE 1H perp. A rolling 96-bar mean is the anchor; resting post-only limit orders one grid level below and above the current price lean the netted inventory against displacement from that mean (target inventory = -k units at grid level k, capped at max_levels). Each captured oscillation banks one 0.6% grid spacing against a ~0.04% maker round trip. The grid is armed only while a ranging regime is confirmed (normalized slope of the mean <= trend_max in random-walk sigma units AND price contained within 3 ATR of the mean); it disarms to reduce-only in the hysteresis band, and it flattens the whole book at market on a hard trend/containment break, on the inventory loss cap, or when a disarmed book outlives disarm_grace bars. This iteration measures the inventory stop at the bar's adverse extreme (low while long, high while short) instead of only at the close, and halves the exposure that generates the tail (unit_frac 0.10 -> 0.05, default max_levels 3 -> 2, inv_stop_frac 0.010 -> 0.005).
Verification Results
Analyst should confirm on full-history backtest whether any (grid_spacing, trend_max, max_levels) region produces per-trade return above the fee floor; developer already recommends abandon.
Realized sandbox avg_trade_return_pct is 0.0258% of notional, far below the ~0.15% USD-M fee floor, even though the structural grid_spacing (0.6% gross vs ~0.04% maker round-trip) clears fees on paper. The gap between the designed 0.6% capture and the realized 0.026% is the tell that flattens/trend-exits erode most captured spacing. Advisory only — this is realized edge, judged by the analyst on full history, not a code defect.
Sandbox is decisively negative (total_return -12.3%, Sharpe -1.13, PF 0.74) and this is the FOURTH negative end-to-end measurement of the same regime-gated grid mechanism (prior -73.19%, -58.80%, -64.92%). The payoff shape is the known grid killer: a slightly positive arithmetic daily mean (~0.2 Sharpe best case) with heavy left-tail loss days (return_skew -0.78, kurtosis 26.4, avg_loss 95.6 >> avg_win 39.2) from books carried through breakouts, so volatility drag swallows the mean. Regime performance is negative in all three vol terciles (calm -0.68%, normal -5.39%, stressed -9.31%). Even with the tail-cap changes the developer's own honest math leaves ~2%/yr at Sharpe ~0.2, below every promotion floor, and the 3 tunable knobs only trade ranging fills against trend-exit cost. The developer recommends abandon on these grounds. This is an edge/payoff-shape concern for the analyst to decide with full-history numbers, NOT a correctness defect.
Backtest Review
Sharpe
-0.31
Total return
-31.06%
Max drawdown
31.07%
Trades
4641
Win rate
69.3%
Profit factor
0.82
Large, reliable sample (4641 trades / 2440 days, metrics_reliable=true) so the result is decisive, not noise.
Mechanism is genuinely novel (market-neutral maker grid) and correctly implements the hypothesis: balanced 2299 long / 2342 short, exposure ~50%, maker execution, regime gate present.
Negative expectancy on a decisive sample: profit_factor 0.817, total_return -31.1%, expectancy -$6.67/trade, Sharpe -0.31 (CI [-1.04, 0.50]), Sortino -0.30.
avg_trade_return_pct 0.0305% is far below the 0.15% Binance USD-M fee floor and below zero net edge — commissions are only 13.6% of gross, so this is gross-marginal/negative, not merely fee-fragility.
Adverse payoff geometry: win_rate 0.69 but avg_loss 118.5 >> avg_win 42.9 (return_kurtosis 82.5) — the classic grid fat-left-tail where books carried through breakouts erase many small maker wins.
Loses in EVERY calendar year 2020-2026 and in ALL three vol regimes (calm -9.6%, normal -24.4%, stressed -12.6%) — the premise is falsified across regimes.
This is the FOURTH negative end-to-end measurement of the same regime-gated grid mechanism (prior -73%, -59%, -65%); the developer's own honest note recommends abandon.
Analysis
Backtest gate:
- metrics unreliable: Incoherent: Sharpe 0.20 disagrees in sign with total_return -64.92% — the Sharpe is computed from the mtm_equity_curve series while the return comes from the equity curve. Judge on the equity curve.
Iteration History
Verification failed (Layer 3 — sandbox backtest): 'nautilus_trader.model.orders.limit.LimitOrder' object has no attribute 'instrument'
Bar type used: BTCUSDT.BINANCE-1-HOUR-LAST-EXTERNAL, Bars processed: 0
Ensure your strategy produces trades with the given data and parameters.
Verification failed (Layer 4 — QA review): - DECISIVELY NEGATIVE EDGE -- the regime gate does NOT save the grid, which is the entire thesis. Over a measurable 612-trade sample the strategy loses: total_return -12.92%, Sharpe -2.32 (CI [-3.65, -0.84], entirely below zero), profit_factor 0.665, probabilistic_sharpe 0.0009, expectancy -$21/trade. The payoff geometry is the classic grid death and is diagnostic: win_rate 0.49 with INVERTED reward:risk (avg_win $85 < avg_loss $124), largest_loss -$1,593 vs largest_win……Show moreShow less
Verification failed (Layer 4 — QA review):
- DECISIVELY NEGATIVE EDGE -- the regime gate does NOT save the grid, which is the entire thesis. Over a measurable 612-trade sample the strategy loses: total_return -12.92%, Sharpe -2.32 (CI [-3.65, -0.84], entirely below zero), profit_factor 0.665, probabilistic_sharpe 0.0009, expectancy -$21/trade. The payoff geometry is the classic grid death and is diagnostic: win_rate 0.49 with INVERTED reward:risk (avg_win $85 < avg_loss $124), largest_loss -$1,593 vs largest_win $678, return_skew -1.95, return_kurtosis 17.1 -- many small range-harvest wins overwhelmed by occasional large losses when a range breaks into a trend and the hard-flatten realizes a loss bigger than the accumulated spacing capture. The regime gate reduces but cannot prevent this: by the time slope_sigma exceeds trend_max x 1.5, the inventory is already underwater, so the flatten books the loss rather than avoiding it. This is a genuine mechanism/economic failure, not a code defect -- the grid logic is correct (fade displacement, unwind wrong-side one unit at a time, inventory cap, hard-flatten).
Verification failed (Layer 4 — QA review): - CONFIRMED NET-LOSER TAKER GRID -- unchanged from iter2, and the iteration-3 inventory-stop fix had ZERO effect. The sandbox metrics are byte-identical to iteration 2: total_return -12.924%, Sharpe -2.32 (CI [-3.65, -0.84]), profit_factor 0.665, win_rate 0.49, 612 trades, largest_loss -$1,592.998, skew -1.95 -- identical to the cent. A 1%-of-equity inventory P&L stop that flattens the whole book would change which bars hold inventory and cascade through the entire……Show moreShow less
Verification failed (Layer 4 — QA review):
- CONFIRMED NET-LOSER TAKER GRID -- unchanged from iter2, and the iteration-3 inventory-stop fix had ZERO effect. The sandbox metrics are byte-identical to iteration 2: total_return -12.924%, Sharpe -2.32 (CI [-3.65, -0.84]), profit_factor 0.665, win_rate 0.49, 612 trades, largest_loss -$1,592.998, skew -1.95 -- identical to the cent. A 1%-of-equity inventory P&L stop that flattens the whole book would change which bars hold inventory and cascade through the entire 612-trade sequence, so identical results mean the inventory stop NEVER materially fired in this window (or the run did not pick up the change). Check the _n_inv_stop diagnostic to disambiguate, but either way the iteration-3 mechanism fix is inert/unverified and does not repair the inverted reward:risk (avg_win $85 < avg_loss $124) or the fat left tail. The underlying result stands: a taker-executed mean-reversion grid pays the spread on hundreds of fills (turnover 106.7, avg_trade_return_pct 0.088% below the 0.15% floor) and its breakout/flatten losses exceed the harvested spacing -- a decisive net loser.
- PLATFORM BLOCKER worth escalating beyond this strategy: resting limit orders crash the backtest on the submission path with "'LimitOrder' object has no attribute 'instrument'" (iteration 1 booked zero bars). A LimitOrder in this NautilusTrader version exposes instrument_id, not instrument, so pipeline-side code reading .instrument on order submission fails for EVERY resting limit order. This blocks an entire capability class -- maker / market-making / passive-execution / limit-entry strategies -- not just this grid, and it is why the whole maker-grid hypothesis had to be downgraded to a taker proxy that inverts its core fee economics.
Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]: - [edge_concern] Even setting the maker/taker issue aside, the sandbox smoke test shows realized avg_trade_return_pct 0.059% over 1220 trades — below the ~0.15% USD-M round-trip fee floor and an order of magnitude below the >=0.6% grid_spacing the mechanism is supposed to harvest per oscillation (commission_pct_of_gross 27.52%, total_return -16.5%). The gap between spacing and realized capture suggests the grid is churning across level……Show moreShow less
Verification failed (Layer 4 — QA review) [class=hypothesis_mismatch]:
- [edge_concern] Even setting the maker/taker issue aside, the sandbox smoke test shows realized avg_trade_return_pct 0.059% over 1220 trades — below the ~0.15% USD-M round-trip fee floor and an order of magnitude below the >=0.6% grid_spacing the mechanism is supposed to harvest per oscillation (commission_pct_of_gross 27.52%, total_return -16.5%). The gap between spacing and realized capture suggests the grid is churning across level boundaries far more often than it completes full 0.6% round-trips. The analyst should confirm on full history whether the mechanism realizes anything near the spacing per round-trip once the maker-vs-taker construction is resolved.
- [critical] The hypothesis is explicitly a MAKER grid ('Layered MAKER Limit Orders' in the title). Its entire fee-viability argument — the SECOND of the two engineered defenses against grid death — is that maker execution costs ~0.04% round-trip vs the >=0.6% harvested, so hundreds of fills stay net-positive. The code implements NONE of this: every grid unit is submitted via self._submit_entry_instrument(..., side, qty, bar), which is a MARKET (taker) order, and the flatten path is a base market exit. This pays the spread (0.10% taker round-trip) on every one of the hundreds of fills the mechanism requires instead of earning it. The developer concedes this directly in the module docstring and config rationale ('this grid still executes TAKER … the taker construction is not the hypothesis'). The specific fee-clearing mechanic the hypothesis names is therefore absent — the code tests a materially different construction than the one hypothesized. (line 385) — fix: Implement the grid legs as resting post_only limit orders via self.order_factory.limit() so execution is genuinely maker, as the hypothesis specifies. The iteration-1 sandbox crash on the order-submission path must be diagnosed and fixed (correct price precision, tick alignment, and post_only handling on BTCUSDT) rather than worked around by switching to taker market orders. Only a maker construction actually tests this hypothesis; a taker grid is a different strategy whose economics the hypothesis does not describe.
- [warning] min_bars_required(self) overrides a framework method (static-analysis base_shadow warning). If the base template does not honor the override for warm-up gating, the ATR/anchor warm-up may not be enforced before the first signal evaluation. (line 211) — fix: Confirm FactoryStrategy calls this override; the code already gates entries internally on anchor/ATR readiness in calculate_signal, so residual risk is low, but verify the override is actually consumed.