Strategies
Penny-Jump 'Elephant' Restated for Bars: Trade Alongside a Freshly Posted Resting-Depth Elephant (Binance Vision bookDepth OBI Surge) on SOLUSDT.BINANCE 15m, Exit When the Elephant Is Pulled, 4h Clock, ATR Stop, Long-Short
Outcome: Abandoned
SolBookDepthElephantSurge15m
Outcome Summary
SolBookDepthElephantSurge15m was the fourth iteration of a hypothesis that trades alongside large newly posted resting orders on SOL. An earlier version never fired, so this one triggered on the elephant appearing rather than being pulled. The fix worked mechanically: there were about 160 trades a year, longs and shorts were balanced, and sizing followed the 1% ATR-risk rule. But the strategy lost money net of costs: -13.2% on the development period and -33.96% over the full backtest, with both sides losing and drawdown above the 20% limit. The analyst abandoned it at backtest review before optimization, so the analyst, risk and promotion stages were not reached; the verdict covers only this bar-level version, not the literal one-tick penny jump.
Hypothesis
Retry of a seed whose previous contract never fired (0 entries / 19,700 SOL 15m bars). Same instrument, timeframe and data source as requested by the retry instruction; the trigger is changed from 'pulled wall while price flat' to 'elephant appears' (measured firing rate ~1/day at |z|>=2.5-3.0), and the pull becomes the exit. Long-short and short-horizon buckets are both under target; the venue is over-represented but bookDepth exists only for Binance USD-M.
negative_expectancy: On the development period (Jan 2023 to Jul 2025, when bookDepth exists), the strategy loses money net of costs across 394 trades. Average trade return is 0.077% of notional against the 0.15% Binance USD-M floor. Profit factor is 0.876, total return -13.2%, Sharpe -0.40, and max drawdown 23.8% against the pre-registered 20%. Long and short trades both lose (about -$7.4k and -$5.8k), and most trades end early when the elephant is pulled, before the 4-hour clock. A freshly posted depth surge on SOL carries no directional information that survives costs at this horizon. Tuning the z threshold, base window or hold length cannot raise a sub-floor, PF<1 edge above costs. QA's concern is borne out. This verdict covers the Research Lead's bar-level operationalization of the penny-jump 'elephant' idea (15m bookDepth OBI surge, trade alongside it, exit on pull). It does not test the article's literal one-tick penny jump, which depends on queue priority and cannot be tested on this platform.
Implementation
SOLUSDT.BINANCE 15m long-short. Each bar: obi15 = mean of the valid (|obi|<=0.9) minute bookDepth OBI values inside the bar, read point-in-time via supp_arrays. It is undefined if fewer than 5 minutes are valid or the newest value is more than 30 minutes old. delta = obi15 - mean(obi15 over the previous base_bars bars); z = (delta - mean)/std of delta over the last z_window bars, with at least half of them valid. Long when z crosses up through +z_entry (bid elephant), short when z crosses down through -z_entry (ask elephant). Exit when the elephant is pulled (long: z <= pull_z; short: z >= -pull_z), after hold_bars (4h clock, from position.ts_opened), or at a reduce-only intrabar stop-market stop_atr x ATR(14) from the fill. Size so the loss at the stop is 1% of equity, with notional capped at min(1.3, leverage) x equity. 4-bar cooldown after a close. Market orders fill at the signal bar's close, which is the 24/7 equivalent of the next bar's open.
Iteration 4: previous_code still implemented the OLD contract (fade a pulled wall, only when price stayed flat), which is why it never entered. This version implements the current hypothesis: the entry is the elephant APPEARING (a one-sided OBI surge z-crossing), and the exit is the article's decoy warning (the elephant is pulled). The config changed to match the hypothesis optimization_plan: new parameter names, and leverage 2.0 wired into sizing via self.config.leverage. Offline check on the SOL bookDepth loader output with this exact formula (base 16, z_window 672): 22 up and 29 down crossings at z_entry 3.0 between 2026-03-15 and the end of the feed on 2026-06-26, so the sandbox window has entries. The base keeps only 500 bars and _max_bars may not be rebound, so the per-bar obi15/delta history lives in bounded deques filled incrementally; bars that calculate_signal missed are caught up in order. After a restart these deques rebuild from live data, which takes about 7 days of warm-up before z is valid again. Entry ATR, held side and exit time are scalar attributes.
Verification Results
No code change is required. If the full backtest does not trade, investigate how book_depth is injected in the subprocess, not the signal formula.
The Layer-3 sandbox reported 0 trades over 19,280 bars starting 2026-03-23. I rebuilt this exact signal offline from load_book_depth('SOLUSDT') on a 15m close grid (base_bars 16, z_window 672, needing half the window valid, glitch filter 0.9, minimum 5 valid minutes, 30-minute staleness). The window from 2026-03-23 contains 8,874 valid-z bars with 19 up-crossings and 27 down-crossings of |z|=3. Over the 20,000 bars from 2025-01-01 there are 72 up and 57 down. The entry logic is therefore reachable. The zero-trade sandbox probably comes from how the sandbox supplied book_depth, not from the code. If the full-history backtest also shows 0 entries, check the entry diagnostics (entry_signaled vs bars_seen) and whether book_depth was actually injected.
Limit the backtest/optimisation window to the bookDepth coverage (2023-01 to latest), or let the supp_tail freshness hold resolve it. This is not a code defect.
Data coverage: the SOLUSDT bookDepth series on disk runs from 2023-01-01 to 2026-06-26, with no files written after 2026-07-17. SOL 15m bars run from 2020-09 to today. The strategy correctly stays flat when obi is missing or stale. However, about 2.3 years of pre-2023 bars and about 4 months after June 2026 will produce no trades. The walk-forward and holdout windows (holdout is the last 20%, roughly mid-2025 to Oct 2026) will include long dead stretches unless the pipeline limits the window to bookDepth coverage, or the supp-tail freshness gate holds the run for data review.
Use int(event.ts_event) (or round it up to the next bar close) for last_exit_ts.
When the intrabar stop fills, on_position_closed stamps last_exit_ts with the PREVIOUS bar's ts_init (self._bars[-1]), because the stop is matched inside the bar that has not closed yet. The 4-bar cooldown is therefore effectively about 3 bars after a stop-out. Signal and time exits fill at the bar close, so their cooldown is exact.
Make sure the paper warm-up replays at least z_window/2 + base_bars bars.
Paper/live restart: obi_hist and delta_hist are in-memory deques. After a restart, z needs about 336 bars (about 3.5 days) of valid deltas before it becomes valid again, unless the warm-up replay covers that span (calculate_signal does run during warm-up, so a long enough replay rebuilds it). This does not affect the backtest.
None required. Document it in the description if desired.
The baseline accepts a mean over at least base_bars//2 valid prior obi15 values. The hypothesis says 'mean of obi15 over the previous base_bars bars' and does not state a validity rule. This is a reasonable gap-tolerance choice, not a mismatch. Note that z is computed over a window that includes the current delta, which is the usual reading of 'the last z_window bars'.
A 4h hold on a 15m depth-imbalance surge has to clear a ~0.10% taker round trip plus impact. The source edge (a one-tick penny jump) earns about 0.01% and depends on queue position, so the move this operationalization needs is the Research Lead's own assumption. Elephants are often decoys, which the article itself says, so the effect may be noise. On the full backtest, check that avg_trade_return_pct is above 0.15% and that the stop/time-exit mix is not dominated by stop-outs.
Backtest Review
- Sharpe
- -0.85
- Total return
- -33.96%
- Max drawdown
- 37.38%
- Trades
- 591
- Win rate
- 49.6%
- Profit factor
- 0.79
Retry fix worked: the signal fires. There are 394 closed trades from Jan 2023 to Jul 2025, when the bookDepth history is available, which is about 160 a year and in line with the predicted firing rate.
The trades match the mechanism. Longs and shorts are balanced (192/202), and entries come on z crossings with exits mostly when the elephant is pulled. Sizing follows the 1% ATR-risk rule, with notional capped (first trade at 0.36x).
The sample is reliable (metrics_reliable true, 293 effective daily observations).
Average trade return is 0.077% of notional, against the BINANCE USD-M floor of 0.15%.
Profit factor is 0.876, with net PnL -$13.2k on the 100k account (-13.2%), Sharpe -0.40 and expectancy -$33.5 per trade. The positive unweighted percentage average hides a losing notional-weighted ledger: the average loss is $568 against an average win of $449.
Both sides lose (long -$7.4k, short -$5.8k), so this is not one bad direction.
Max drawdown is 23.8%, above the pre-registered 20%, and the drawdown lasted 901 days. 2023 lost 17.6%; 2024 (+4.5%) and 2025 to date (+0.8%) did not recover it.
Exits: 372 of 394 trades end before the 4-hour clock, mostly through the pull exit or the stop (win rate 54% on those). Only 22 reach the time exit, and 16 of those lose. Commissions total $17.5k.
Iteration History
Verification failed (Layer 3 — sandbox backtest): No trades produced Bar type used: SOLUSDT.BINANCE-15-MINUTE-LAST-EXTERNAL, Bars processed: 19969 Diagnostics: should_enter() returned a side 0 times over 19969 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds. Ensure your strategy produces trades with the given data and parameters.
Verification failed (Layer 1.5 — hypothesis/config consistency) [class=hypothesis_mismatch]: - optimization_plan fixes leverage at 1.0
With the existing loader, search only minute keys whose entire minute has ended: use bisect_right(timestamps, ts - 60_000_000_000) - 1 and evaluate staleness against the aggregate's availability time, timestamps[index] + 60_000_000_000. Alternatively, correct the loader to stamp minute aggregates at minute end and retain the current one-sided lookup. Verify that a snapshot after a decision timestamp cannot change that decision's signal.
The book_depth lookup admits future observations despite using bisect_right. src/backtesting/supp_loaders.py::load_book_depth aggregates all snapshots within each minute and timestamps the aggregate at that minute's START. At a bar close of 12:00:00, this lookup accepts the 12:00 minute aggregate, which can include snapshots from 12:00:30 or later. The current and historical OBI samples therefore use information unavailable at their respective bar closes.
Require adequate valid OBI-change coverage within the fixed rolling window, and skip signals when gaps prevent that coverage rather than silently estimating sigma from a handful of observations.
The rolling OBI standard deviation can be estimated from only two valid changes when book coverage is sparse, although the experiment specifies a 288-observation window. Fresh endpoints alone do not establish adequate historical coverage for the threshold.
Verification failed (Layer 3 — sandbox backtest): No trades produced Bar type used: SOLUSDT.BINANCE-15-MINUTE-LAST-EXTERNAL, Bars processed: 19700 Diagnostics: should_enter() returned a side 0 times over 19700 evaluated bars -> your ENTRY CONDITION never triggered. Loosen the entry logic / thresholds. Ensure your strategy produces trades with the given data and parameters.
Outcome Summary
A fresh resting-depth surge in SOL bookDepth carried no directional information that survives costs at a 15m–4h horizon (signal IC 0.003, t=0.4), so future depth-based ideas need evidence that the signal predicts returns before more retries on how it triggers.
At the backtest-review gate the analyst chose abandon for negative_expectancy. The average trade return was below the 0.15% Binance USD-M floor, both long and short trades lost money, and drawdown went past the pre-registered 20%, so tuning was judged unable to rescue the edge.
A bar-level version of the FMZ 'penny jump' elephant idea: on SOLUSDT.BINANCE 15m, trade long or short in the direction of a sudden one-sided surge in Binance Vision bookDepth resting depth (OBI z-score crossing ±3.0), and exit when the elephant is pulled, after a 4h clock, or at an ATR stop.
The full-history backtest lost 33.96% over 591 trades (Sharpe -0.85, profit factor 0.79, avg trade return -0.010% of notional, max drawdown 37.4%), with about $28.1k in commissions and $25.5k in impact. On the bookDepth development period the review used (Jan 2023–Jul 2025), it lost 13.2% over 394 trades (avg 0.077% of notional, PF 0.876, Sharpe -0.40, max drawdown 23.8%).
Analysis
高频交易策略之Penny Jump
Backtest and paper results are hypothetical. Trading involves risk of loss.