Skip to content
All strategies

Strategies

DOGE Deleveraging-Flush Reversal: 7-Day Sell-Off on Rising Volume and Falling Open Interest, Long-Only 3-Day Hold (DOGEUSDT.BINANCE USD-M, Daily Bars, Single Instrument)

Outcome: Abandoned

DogeDeleveragingFlushReversalLong

Outcome Summary

The strategy took the volume-up / open-interest-down conditioning from a futures short-term-reversal paper and traded only its long side on one Binance DOGE perp, holding each trade for 3 days. Its supporting evidence was a pre-study cell picked from a small grid (+1.84% mean over 54 trades, t≈2.3), which QA noted makes selection, not fees, the main risk; the hypothesis itself asked for an XRP cross-check before any promotion. The code never passed verification: after 3 iterations, QA still found an off-by-one in the time stop that held trades for 4 bars instead of 3. The run was abandoned as a verification-loop code defect before any backtest, optimization or analyst review.

Hypothesis

Adapted from QuantConnect / Quantpedia 'Short Term Reversal with Futures'. The source runs a weekly cross-sectional book over 24 CME/ICE futures. It keeps only contracts whose weekly volume change is in the top half and whose open-interest change is in the bottom half, then goes long the worst weekly loser and short the best weekly winner. The part worth keeping is the conditioning. A price move that comes with MORE volume but LESS open interest is driven by positions being closed (forced deleveraging and……Show moreShow less

Adapted from QuantConnect / Quantpedia 'Short Term Reversal with Futures'. The source runs a weekly cross-sectional book over 24 CME/ICE futures. It keeps only contracts whose weekly volume change is in the top half and whose open-interest change is in the bottom half, then goes long the worst weekly loser and short the best weekly winner. The part worth keeping is the conditioning. A price move that comes with MORE volume but LESS open interest is driven by positions being closed (forced deleveraging and stop-outs), not by new directional capital, so it should partly revert. The 24-future cross-section and the dollar-neutral two-leg book are dropped: our venues have no such universe, and lessons L137/L173 show multi-leg neutral books and ranked baskets die here. The mechanism is instead measured and traded on ONE Binance USD-M perp, where the open-interest feed (supplementary key `open_interest`, Binance metrics, 5-minute, history from 2021-12-01) lives on the same contract that is traded (L160, L143). Pre-study, point-in-time, daily close-stamped bars, OI = last 5-minute value of each day, non-overlapping trades. (1) The UNGATED weekly reversal is negative on all 14 names tested (for example SOL -1.4%, XRP -1.3%, TRX, AVAX), so plain short-term reversal is dead in crypto; momentum dominates. (2) With the vol-up/OI-down gate at |z| > 1, SHORT signals (rallies with falling OI) lose on most names, so the short leg is dropped. (3) LONG signals (sell-offs with rising volume and falling OI) are positive on 9 of 10 alts at a 3-day hold. DOGE: 54 longs, +1.84% mean over 3 days, t≈2.3. Pooled 7-day across 10 names: +0.62%, t=1.2. DOGE is the strongest cell of a small grid (10 names x 2 holds x 3 thresholds), so this is NOT an independent test. The pre-registered numbers below are therefore deliberately modest, and the analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged before any promotion. The strategy is flat about 90% of the time.

verification_loop: Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] The pre-study admits DOGE is the best cell of a 10x2x3 grid (t~2.3 on 54 longs), so the selection is not an independent test. Round trip on Binance USD-M is ~0.10% against a claimed +1.84% mean, so fees are not the risk; selection is. The analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged, as the hypothesis itself asks. - [critical] Off-by-one in the time stop: hold_bars=3 holds 4 daily……Show moreShow less

verification_loop: Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] The pre-study admits DOGE is the best cell of a 10x2x3 grid (t~2.3 on 54 longs), so the selection is not an independent test. Round trip on Binance USD-M is ~0.10% against a claimed +1.84% mean, so fees are not the risk; selection is. The analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged, as the hypothesis itself asks. - [critical] Off-by-one in the time stop: hold_bars=3 holds 4 daily bars, not 3. The entry market order fills inside bar N's event, at its close. On bar N+1, calculate_signal sees the position for the first time, sets _in_position=True and _bars_held=0. The counter then reads 1 on N+2, 2 on N+3 and 3 on N+4, and should_exit fires on N+4. So the position runs from close(N) to close(N+4): a 4-day hold. The hypothesis specifies a 3-day hold and its pre-registered +1.84% is a 3-day mean. The measured horizon would be 33% longer than the stated one, and every hold_bars value the optimizer tries would be mislabelled by +1 bar. (line 124) — fix: Count bars since the entry fill so the exit fires on bar N+hold_bars. Either set _bars_held = 1 the first time the position is seen, or compute the count from the position's open time: bars_held = (bar.ts_init - position.ts_opened) // NS_PER_DAY, exiting when it reaches hold_bars. Anchoring on position.ts_opened also removes the restart-state issue below. - [warning] _bars_held and _in_position live only in process memory. After a paper restart with an open position, the counter restarts at 0 and the hold is extended. The backtest does not restart, so this does not affect measurement. (line 56) — fix: Derive the hold from position.ts_opened (see the critical fix). - [warning] The sandbox took 688 s for 2,305 daily bars and was flagged runtime_review_required. supp_arrays is O(log n) per call. _oi_at calls it for two keys, twice per bar, and walks back up to 12 rows each time. That should be cheap, so the cost may come from the size of the metrics series or the first cache build. Runtime is a resource concern, not a correctness one. — fix: If open_interest is present, read only that key, and drop the metrics fallback when it is not needed.

Implementation

Long-only strategy on DOGEUSDT.BINANCE USD-M with daily bars. It waits for a 7-day sell-off during which weekly volume rose sharply and weekly open interest fell sharply: the flush score min(vol_z, -oi_z) must be above z_thresh, where vol_z and oi_z are z-scores of the weekly volume change and open-interest change. It then buys at the daily close, which on a 24/7 venue is the next bar's open, and sells after 3 daily bars. Each position uses 50% of equity at 1x.

Iteration 3 fix for the Layer-3 frozen supplementary snapshot failure. The old _build() step parsed metrics and open_interest once into cached arrays; it is removed. Open interest is now read on every bar with self.supp_arrays(key) and np.searchsorted on the point-in-time view, using only rows at or before the bar and within oi_tolerance_hours. Signal, entry, exit, sizing and config are unchanged. Risk control route (b): a time-stop exit with sizing capped at 50% of equity, 1x.

Verification Results

Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] The pre-study admits DOGE is the best cell of a 10x2x3 grid (t~2.3 on 54 longs), so the selection is not an independent test. Round trip on Binance USD-M is ~0.10% against a claimed +1.84% mean, so fees are not the risk; selection is. The analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged, as the hypothesis itself asks. - [critical] Off-by-one in the time stop: hold_bars=3 holds 4 daily bars, not 3. The……Show moreShow less

Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] The pre-study admits DOGE is the best cell of a 10x2x3 grid (t~2.3 on 54 longs), so the selection is not an independent test. Round trip on Binance USD-M is ~0.10% against a claimed +1.84% mean, so fees are not the risk; selection is. The analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged, as the hypothesis itself asks. - [critical] Off-by-one in the time stop: hold_bars=3 holds 4 daily bars, not 3. The entry market order fills inside bar N's event, at its close. On bar N+1, calculate_signal sees the position for the first time, sets _in_position=True and _bars_held=0. The counter then reads 1 on N+2, 2 on N+3 and 3 on N+4, and should_exit fires on N+4. So the position runs from close(N) to close(N+4): a 4-day hold. The hypothesis specifies a 3-day hold and its pre-registered +1.84% is a 3-day mean. The measured horizon would be 33% longer than the stated one, and every hold_bars value the optimizer tries would be mislabelled by +1 bar. (line 124) — fix: Count bars since the entry fill so the exit fires on bar N+hold_bars. Either set _bars_held = 1 the first time the position is seen, or compute the count from the position's open time: bars_held = (bar.ts_init - position.ts_opened) // NS_PER_DAY, exiting when it reaches hold_bars. Anchoring on position.ts_opened also removes the restart-state issue below. - [warning] _bars_held and _in_position live only in process memory. After a paper restart with an open position, the counter restarts at 0 and the hold is extended. The backtest does not restart, so this does not affect measurement. (line 56) — fix: Derive the hold from position.ts_opened (see the critical fix). - [warning] The sandbox took 688 s for 2,305 daily bars and was flagged runtime_review_required. supp_arrays is O(log n) per call. _oi_at calls it for two keys, twice per bar, and walks back up to 12 rows each time. That should be cheap, so the cost may come from the size of the metrics series or the first cache build. Runtime is a resource concern, not a correctness one. — fix: If open_interest is present, read only that key, and drop the metrics fallback when it is not needed.

Count bars since the entry fill so the exit fires on bar N+hold_bars. Either set _bars_held = 1 the first time the position is seen, or compute the count from the position's open time: bars_held = (bar.ts_init - position.ts_opened) // NS_PER_DAY, exiting when it reaches hold_bars. Anchoring on position.ts_opened also removes the restart-state issue below.

Off-by-one in the time stop: hold_bars=3 holds 4 daily bars, not 3. The entry market order fills inside bar N's event, at its close. On bar N+1, calculate_signal sees the position for the first time, sets _in_position=True and _bars_held=0. The counter then reads 1 on N+2, 2 on N+3 and 3 on N+4, and should_exit fires on N+4. So the position runs from close(N) to close(N+4): a 4-day hold. The hypothesis specifies a 3-day hold and its pre-registered +1.84% is a 3-day mean. The measured horizon would be 33% longer than the stated one, and every hold_bars value the optimizer tries would be mislabelled by +1 bar.

Derive the hold from position.ts_opened (see the critical fix).

_bars_held and _in_position live only in process memory. After a paper restart with an open position, the counter restarts at 0 and the hold is extended. The backtest does not restart, so this does not affect measurement.

If open_interest is present, read only that key, and drop the metrics fallback when it is not needed.

The sandbox took 688 s for 2,305 daily bars and was flagged runtime_review_required. supp_arrays is O(log n) per call. _oi_at calls it for two keys, twice per bar, and walks back up to 12 rows each time. That should be cheap, so the cost may come from the size of the metrics series or the first cache build. Runtime is a resource concern, not a correctness one.

Iteration History

Verification failed (Layer 1 — static analysis): - Syntax error: invalid decimal literal (<unknown>, line 1) (line 1)

Verification failed (Layer 3 — frozen supplementary snapshot): metrics, open_interest were read once and never again while new observations arrived. parameters['supplementary_data'] is a point-in-time view: anything built from it once holds only what was known at that bar. Read the series on every bar with self.supp_arrays(key) / self.supp_as_of(key) / self.supp_window(key, n).

Outcome Summary

Count the holding period from the position's open time (position.ts_opened), not from an in-memory counter that starts at 0 on the first bar after the fill, so the hold length matches the hypothesis and survives restarts.

After 3 iterations it was abandoned in the verification loop, at Layer 4 QA review. The review flagged a critical code defect: an off-by-one in the time stop meant hold_bars=3 actually held for 4 daily bars, which does not match the pre-registered 3-day horizon. It also warned that the hold counter lived only in memory and would reset on a restart, and that the sandbox run was slow (688 s for 2,305 bars).

A long-only, 3-day-hold reversal on DOGEUSDT.BINANCE daily bars, entering after a 7-day sell-off that came with rising volume and falling open interest, on the idea that forced deleveraging rather than new directional capital drove the move and that it should partly revert.

No pipeline backtest or optimization results exist. The only figures are from the hypothesis's own pre-study: 54 DOGE longs averaging +1.84% over 3 days (t≈2.3), picked as the best cell of a 10-name x 2-hold x 3-threshold grid, with a pooled 7-day result across 10 names of +0.62% (t=1.2).

Abandon Reason

verification_loop: Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] The pre-study admits DOGE is the best cell of a 10x2x3 grid (t~2.3 on 54 longs), so the selection is not an independent test. Round trip on Binance USD-M is ~0.10% against a claimed +1.84% mean, so fees are not the risk; selection is. The analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged, as the hypothesis itself asks. - [critical] Off-by-one in the time stop: hold_bars=3 holds 4 daily……Show moreShow less

verification_loop: Verification failed (Layer 4 — QA review) [class=code_defect]: - [edge_concern] The pre-study admits DOGE is the best cell of a 10x2x3 grid (t~2.3 on 54 longs), so the selection is not an independent test. Round trip on Binance USD-M is ~0.10% against a claimed +1.84% mean, so fees are not the risk; selection is. The analyst should require the XRPUSDT.BINANCE cross-check with the rule unchanged, as the hypothesis itself asks. - [critical] Off-by-one in the time stop: hold_bars=3 holds 4 daily bars, not 3. The entry market order fills inside bar N's event, at its close. On bar N+1, calculate_signal sees the position for the first time, sets _in_position=True and _bars_held=0. The counter then reads 1 on N+2, 2 on N+3 and 3 on N+4, and should_exit fires on N+4. So the position runs from close(N) to close(N+4): a 4-day hold. The hypothesis specifies a 3-day hold and its pre-registered +1.84% is a 3-day mean. The measured horizon would be 33% longer than the stated one, and every hold_bars value the optimizer tries would be mislabelled by +1 bar. (line 124) — fix: Count bars since the entry fill so the exit fires on bar N+hold_bars. Either set _bars_held = 1 the first time the position is seen, or compute the count from the position's open time: bars_held = (bar.ts_init - position.ts_opened) // NS_PER_DAY, exiting when it reaches hold_bars. Anchoring on position.ts_opened also removes the restart-state issue below. - [warning] _bars_held and _in_position live only in process memory. After a paper restart with an open position, the counter restarts at 0 and the hold is extended. The backtest does not restart, so this does not affect measurement. (line 56) — fix: Derive the hold from position.ts_opened (see the critical fix). - [warning] The sandbox took 688 s for 2,305 daily bars and was flagged runtime_review_required. supp_arrays is O(log n) per call. _oi_at calls it for two keys, twice per bar, and walks back up to 12 rows each time. That should be cheap, so the cost may come from the size of the metrics series or the first cache build. Runtime is a resource concern, not a correctness one. — fix: If open_interest is present, read only that key, and drop the metrics fallback when it is not needed.

Analysis

Short Term Reversal with Futures

Backtest and paper results are hypothetical. Trading involves risk of loss.