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
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.