Skip to content
All strategies

Strategies

QuantRocket 'TrendDayStrategy' port: leveraged-ETF afternoon trend-day continuation (long if up >6% vs prior close at the afternoon checkpoint, short if down >6%, flat at session close) on TQQQ/SQQQ/UVXY USEQ 1-HOUR

Outcome: Abandoned

TrendDayLeveragedEtfUseq

Outcome Summary

TrendDayLeveragedEtfUseq ported QuantRocket's afternoon trend-day continuation rule to three leveraged/volatility ETFs on USEQ hourly bars. It was adapted to a 14:30 ET checkpoint because the Yahoo hourly grid has no 14:00 close. Both iterations failed the Layer 3 sandbox backtest by exceeding the 300s limit on an 833-day TQQQ window. The developer attributed the timeout to catalog file discovery under heavy host I/O load, not to strategy logic. The run was abandoned in a verification loop without reaching backtest, optimization, analyst or risk review, so its edge was never measured.

Hypothesis

Port of QuantRocket's open-source Moonshot strategy 'TrendDayStrategy' (code 'trend-day', https://github.com/quantrocket-codeload/trend-day, Apache-2.0, author QuantRocket LLC, who gets the credit). ORIGINAL RULES, exactly as written: universe 'leveraged-etf' on US-stock 1-minute data; DB_TIMES 14:00 and 15:59; MIN_PCT_CHANGE = 0.06. Each day: return = (OPEN of the 14:00 bar - CLOSE of the prior session's 15:59 bar) / prior session close. Signal +1 (long) if return > +0.06, -1 (short) if return < -0.06, otherwise……Show moreShow less

Port of QuantRocket's open-source Moonshot strategy 'TrendDayStrategy' (code 'trend-day', https://github.com/quantrocket-codeload/trend-day, Apache-2.0, author QuantRocket LLC, who gets the credit). ORIGINAL RULES, exactly as written: universe 'leveraged-etf' on US-stock 1-minute data; DB_TIMES 14:00 and 15:59; MIN_PCT_CHANGE = 0.06. Each day: return = (OPEN of the 14:00 bar - CLOSE of the prior session's 15:59 bar) / prior session close. Signal +1 (long) if return > +0.06, -1 (short) if return < -0.06, otherwise 0. Weights: allocate_fixed_weights_capped(signals, 0.20, cap=1.0), so each active position gets 20% of capital, and all weights are scaled down proportionally if gross exposure would exceed 100%. Positions are entered the same day as the signal with a MARKET order at 14:01 (the close of the 14:00 bar is the entry price) and exited with a market-on-close (MOC) order at the 16:00 session close. There are no stops, no take-profit and no overnight holding. The original's costs were $0.005/share commission and 3 bps slippage; ours use the USEQ model, which charges zero commission and models spread and impact. PLATFORM ADAPTATION, stated honestly: (1) The universe is the 3 leveraged/volatility ETFs that exist in our USEQ universe and catalog: TQQQ.USEQ, SQQQ.USEQ and UVXY.USEQ. Other leveraged ETFs such as SOXL, SPXL and TNA are not collected. (2) Timeframe is 1-HOUR, not 1-minute. USEQ 1-minute bars start 2026-08-06, about 38 sessions, which would give fewer than 10 signals at a 6% threshold. USEQ 1-HOUR bars cover 2024-08-14 to now, about 530 sessions. Yahoo hourly bars are close-stamped at 10:30, 11:30, 12:30, 13:30, 14:30, 15:30 and 16:00 ET, so no bar closes at 14:00. The checkpoint is therefore the CLOSE of the bar stamped 14:30 ET, 30 minutes later than the original's 14:00, and the hold is 14:30 to 16:00, not 14:01 to 16:00. On half-day sessions (13:00 close) there is no 14:30 bar, so no trade, which matches the original because its 14:00 bar is missing on half-days. (3) The prior session close is the close of the previous session's final bar (stamped 16:00 ET, or 13:00 on half-days), equivalent to the original's 15:59 bar close. Sizing: 20% of current equity notional per active instrument, as in the original. With 3 instruments, gross exposure is at most 60%, so the 1.0 cap never binds but is still implemented. Long and short are allowed; USEQ is a Reg-T margin account, run at leverage 1.0. Note that TQQQ and SQQQ are mirror images, so a strong Nasdaq day usually signals both, long one and short the other. That is effectively the same bet on two instruments, net about 40% of equity on the Nasdaq direction. The original does this too and it is kept faithfully. Pre-study on our 1h catalog (gross, close-to-close, no costs), 6% threshold, return from 14:30 to 16:00 in the signal direction: TQQQ n=45, mean +0.31%, hit rate 64%; SQQQ n=44, mean +0.41%, hit rate 66%; UVXY n=94, mean +0.98%, hit rate 70%. That totals about 183 position-days in about 2 years. Treat these numbers as unverified until our backtest runs.

Faithful port of the user's submitted QuantRocket strategy. The default parameters (MIN_PCT_CHANGE = 0.06, 20% fixed weight, 1.0 cap, same-day entry, MOC exit) are kept exactly. Only one threshold is tunable, within a narrow band around the original. The USEQ venue and long-short direction fill under-represented buckets (USEQ 5.7%, long-short 17%), and the 3 ETFs have almost no history in the corpus. The trigger is a market observation (a 6% intraday move), not a calendar date, so lesson L179 does not apply. The forced closing flows of leveraged-ETF rebalancing make this different from the dead crypto-perp momentum family. 1-HOUR replaces 1-minute only because USEQ 1-minute history is about 38 sessions.

verification_loop: sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (833 days of TQQQ.USEQ-1-HOUR-LAST-EXTERNAL). 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).

Implementation

Port of QuantRocket's TrendDayStrategy to TQQQ/SQQQ/UVXY on USEQ 1-HOUR bars. For each ETF, compare the close of the 14:30 ET bar with the prior session's close. Go long if it is up more than 6%, short if it is down more than 6%. Each position is 20% of equity (scaled down if gross would pass 1.0), entered with a market order at the 14:30 bar close and closed at the 16:00 bar. Positions are never held overnight; there are no stops.

Iteration 2 makes no change to the rules. The sandbox timeout came from the host, not from the strategy: per-bar work was already O(1), with scalar state only, no history buffers and no supplementary data. A local run of the iteration-1 code on the sandbox window ran at about 9% CPU for more than 10 minutes. Its backtest child was stuck in catalog file discovery under host I/O pressure of about 65% and a load average of about 87. Two small speed-ups were made: leg-index and InstrumentId lookups are now built once, and the ET UTC offset is cached per UTC day instead of rebuilding 4 datetimes every bar. The cached offset was checked against zoneinfo America/New_York on 20k session timestamps with 0 mismatches. Signal, entry and exit logic, sizing and parameters are unchanged. The platform adaptations from iteration 1 still apply: a 14:30 ET checkpoint on Yahoo's hourly grid, and a 3-ETF universe. If this times out again, the cause is catalog and host load, which needs an infrastructure re-run, not a code edit.

Verification Results

sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (833 days of TQQQ.USEQ-1-HOUR-LAST-EXTERNAL). 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).

Outcome Summary

If a strategy with O(1) per-bar work still times out in the sandbox, investigate the infrastructure (catalog discovery, host I/O pressure) instead of resubmitting code with no real change, since code-only iterations cannot fix a host-side cause.

After 2 iterations it was abandoned in a verification loop. Both times the Layer 3 sandbox smoke test hit the 300s wall-clock limit on a ~20,000-bar, 833-day TQQQ.USEQ 1-hour window (sandbox_timeout). Iteration 2 made only micro-optimizations because the developer judged the per-bar cost already O(1) and blamed catalog/host I/O load.

A port of QuantRocket's TrendDayStrategy to TQQQ/SQQQ/UVXY on USEQ 1-hour bars: at the 14:30 ET checkpoint it goes long if the ETF is up more than 6% from the prior session close, or short if down more than 6%, puts 20% of equity in each active leg and exits at the 16:00 close.

No backtest or optimization metrics exist because the strategy never passed verification. The only numbers are the hypothesis's unverified gross pre-study figures: TQQQ n=45, mean +0.31%; SQQQ n=44, mean +0.41%; UVXY n=94, mean +0.98%.

Analysis

TrendDayStrategy

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