Strategies
SPY Bull-Market Pullback Countertrend (faithful port of pinkfish 'ac-countertrend' by Farrell Aultman) — Long-Only All-In, DAILY bars, SPY.USEQ
Outcome: Abandoned
SpyAcCountertrendPullback
Outcome Summary
SpyAcCountertrendPullback ported the pinkfish 'ac-countertrend' bull-market dip-buying strategy to daily SPY.USEQ, keeping the source's rules, defaults and pullback quirk unchanged. It went through 3 iterations and hit repeated Layer 3 sandbox timeouts (over the 300s limit). The last version already used O(1) per-bar updates, and the developer noted the time appeared to go outside strategy code. The run was abandoned in the verification loop before any backtest metrics were produced, so the hypothesis itself was never tested.
Hypothesis
Iteration 3 fixes the second Layer-3 sandbox_timeout. It changes nothing in the rules, indicators or parameters, and the signal output is numerically identical to v2 (max relative diff ~3e-15 over 3,000 test bars). Lesson 155(c) diagnosis: v2 was already O(1) per bar. The window holds only ~1,650 daily bars, which is under 1 s of strategy time even at host load ~50. The wall-clock is therefore most likely spent in catalog/engine work outside the strategy (the same finding as the Eth/Bnb v3 timeout diagnoses). Even so, per-bar work is now cheaper still: the rolling std of returns and the exit SMA use running sums instead of per-bar list copies and re-summing. The rolling 20-close max scans a fixed 20-slot deque, and the EMAs are seeded once and then updated recursively. If this times out again, the cause is sandbox plumbing or host load, not the strategy code.
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 SPY.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
Faithful Stratmill port of pinkfish 'ac-countertrend' (Farrell Aultman, MIT) on SPY.USEQ daily bars. In a bull regime (TA-Lib-style SMA-seeded EMA40 > EMA80), buy all-in (whole shares, leverage 1) when pullback = (20-day highest close incl. current - close) / 40-bar sample std of pct_change >= 3.0 (source's dollar/unitless quirk kept). Exit on bear flip, close > SMA20, close < entry*(1-0.15), or 20 bars held.
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 SPY.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
The developer had already reduced per-bar work to O(1) with running sums and fixed-size deques, and its notes say the time was spent outside strategy code (catalog/engine under host load), so repeated sandbox timeouts on USEQ daily bars should be checked as an infrastructure issue rather than answered with more code rewrites.
It was abandoned in a verification loop after 3 iterations. The deciding failure was the Layer 3 sandbox backtest going over the 300s wall-clock limit on a ~20,000-bar (2,400-day) SPY.USEQ daily window. Backtest review, optimization, analyst review and risk review were never reached.
A faithful port of Farrell Aultman's pinkfish 'ac-countertrend' strategy on daily SPY.USEQ: long-only, all-in, it buys dips below the 20-day highest close while EMA(40) > EMA(80) and exits on a close above SMA(20), a 15% stop, a regime flip or after 20 bars. The source's dollar-over-return-std 'pullback' quirk was kept on purpose.
No performance data exists: the backtest report is empty, there is no optimization report, and no return, Sharpe or trade count was ever produced.
Analysis
ac-countertrend
Backtest and paper results are hypothetical. Trading involves risk of loss.