Strategies
Avellaneda-Lee Single-Pair Sector-ETF Residual s-Score Reversion: XOM vs XLE, Beta-Hedged, Canonical Fixed Thresholds, Flat ~55% of the Time (USEQ DAILY, zero-commission, long-short)
Outcome: Abandoned
XomXleAvellanedaLeeSScorePair
Outcome Summary
The strategy attempted daily XOM/XLE statistical arbitrage by trading ETF-factor residual s-score extremes while maintaining beta hedging. It did not reach a recorded backtest result because the Layer 3 sandbox smoke test exceeded the 300-second limit on approximately 20,000 bars. After three iterations, the verification timeout ended the run and no later stages were reached.
Hypothesis
Iteration 3 performance fix: removed the per-bar primary and hedge position/order reconciliation lookups from calculate_signal. Hedge management remains tied to entry and signal exits, while the rolling fit stays bounded at 60 observations per bar. This preserves the previously passing static and synthetic layers and removes the expensive cache work that caused the Layer-3 timeout.
verification_loop: sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of XOM.USEQ-1-DAY-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
Trades the Avellaneda-Lee residual s-score between XOM and XLE using a rolling 60-session return regression, cumulative residual OU fit, beta-neutral long/short pair construction, and canonical entry, exit, and half-life thresholds.
Verification Results
sandbox_timeout: Verification failed (Layer 3 — sandbox backtest): smoke test exceeded the 300s wall-clock limit on a ~20000-bar window (2400 days of XOM.USEQ-1-DAY-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
Per-bar calculations should avoid rescanning full supplementary series or repeatedly rebuilding and sorting data; lookups should be precomputed or cached.
The strategy was abandoned after three iterations when verification failed with a sandbox timeout. Later pipeline stages were not reached.
It tried to trade mean-reverting, beta-hedged residuals between XOM and XLE using Avellaneda-Lee ETF-factor s-score thresholds on daily USEQ data.
No backtest metrics were recorded because verification stopped during the sandbox backtest. The smoke test exceeded the 300-second limit on approximately 20,000 bars.
Analysis
statistical arbitrage vs factor trading
Backtest and paper results are hypothetical. Trading involves risk of loss.