Skip to content
All strategies

Strategies

ETH OKX 4H Positive-Skew Trend Anomaly (Lemperiere et al. 2014): Vol-Normalised EMA-Distance Trend With a Flat Deadband, Long-Short, Scored on Skew as Well as Return (ETHUSDT.OKX 4H, pure OHLCV, single leg)

Outcome: Abandoned

EthOkxVolNormEmaDistanceTrendLS

Outcome Summary

This hypothesis pre-registered a volatility-normalised EMA-distance trend rule on ETHUSDT.OKX 4H, predicting positive return together with positive skew, a low win rate and a right tail of large winners. The code went through 3 iterations. The last one only changed performance: the EMA and rolling volatility became O(1) running updates, and the trading rules stayed the same. The Layer 3 sandbox backtest still ran past its 300s limit on the ~20k-bar window, and the run was abandoned in the verification loop. No backtest, optimization, analyst or risk review was ever reached, so the pre-registered skew claim remains untested in the pipeline.

Hypothesis

The abstract makes one testable claim for a tradeable rule. Most risk premia earn their Sharpe by carrying negative skew, which is crash risk. Trend following is the exception: it earns positive excess return WITH positive skew. We test the crypto version of that claim on ETHUSDT.OKX (OKX USDT perpetual swap, 4-hour bars, data from 2019-12-25, about 14.8k bars). OKX is 0.3% of the corpus and is a pure-OHLCV venue, as lesson L160 requires. Signal: s_t = (close_t - EMA_100(close)_t) / (close_t * sigma_100_t), where……Show moreShow less

The abstract makes one testable claim for a tradeable rule. Most risk premia earn their Sharpe by carrying negative skew, which is crash risk. Trend following is the exception: it earns positive excess return WITH positive skew. We test the crypto version of that claim on ETHUSDT.OKX (OKX USDT perpetual swap, 4-hour bars, data from 2019-12-25, about 14.8k bars). OKX is 0.3% of the corpus and is a pure-OHLCV venue, as lesson L160 requires. Signal: s_t = (close_t - EMA_100(close)_t) / (close_t * sigma_100_t), where sigma_100 is the rolling standard deviation of 100 four-hour log returns. So s is the distance from trend measured in per-bar volatility units. The strategy is FLAT whenever |s| has not exceeded 2 since the last exit. That deadband is the flat state required by L150, not an extra regime gate. It is long when s crosses above +2 and short when s crosses below -2, and it exits when s crosses zero. Beyond return, the hypothesis also predicts the SHAPE of the trade distribution: a low win rate (~30%), a right tail of large winners, and positive skew. That is the paper's diagnostic. If the backtest shows a profit but negative skew, the premise is falsified even if Sharpe is positive. Point-in-time pre-study (close-to-close, 0.10% round trip deducted, done before any code): 259 trades, +2.17% mean net per trade, t = 2.8, trade-return skew +2.9, win rate 32%, 7 of 7 calendar years positive. The result is robust across a 3x3 grid: EMA span 20/50/100 x threshold 1/2/3 gave t between 1.7 and 2.9 on every 4H cell, with skew positive in all of them. We pre-register the centre-right cell (100, 2) and will NOT optimise it away. Selection choices, stated per L122: ETH because it is the most liquid OKX swap with 2019+ history (BNB OKX starts 2022, others ~2 days of data); OKX to spend the under-used venue; 4H because 1D gives only 35-135 trades, below the sample floor.

Iteration 3 fixes only the Layer-3 sandbox_timeout, and the trading rules are unchanged. Per-bar work is now strictly O(1). The EMA is a recursive scalar. Sigma comes from running scalar sums of r and r^2 over the vol_window returns: each bar adds the newest return and drops the one leaving the window, both read by index from the bar buffer. That replaces the per-bar numpy rebuild of 101 closes. The state is re-seeded from the buffer only when the timestamp chain breaks, or every 2000 bars to guard against float drift. All state is plain scalars on self, so it survives restarts. Projected per-bar cost is about 10 float ops, independent of the span. Note that the previous code was already O(window) with a bounded buffer, so part of the timeout may have come from host load.

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 ETHUSDT.OKX-4-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

Lemperiere et al. (2014) vol-normalised EMA-distance trend on ETHUSDT.OKX 4H: s=(close-EMA100)/(close*sigma100 of 4H log returns). Long when s>+2, short when s<-2, flat otherwise; exit when s crosses zero. 50% equity notional at 1x.

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 ETHUSDT.OKX-4-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

A simple rule still has to fit the ~20k-bar sandbox budget, so per-bar cost should be designed to stay flat as history grows before the first submission. Iteration 3 rewrote the EMA/volatility state as O(1) running sums, but the rewrite was not confirmed to pass Layer 3 in time.

It was abandoned in a verification loop after 3 iterations. The Layer 3 sandbox smoke test went past the 300s wall-clock limit on a ~20,000-bar (2,400-day) ETHUSDT.OKX 4H window, so backtest review, analyst review and risk review never ran.

A long-short trend rule on ETHUSDT.OKX 4H bars (Lemperiere et al. 2014): it entered when the close's distance from EMA_100, measured in units of 100-bar return volatility, crossed ±2, and exited when that distance crossed zero, with a flat deadband in between. The test was whether the strategy earned positive return with positive trade-return skew.

No pipeline backtest or optimization metrics exist, because the strategy never passed verification. The only numbers are from the hypothesis's own pre-study, done before any code: 259 trades, +2.17% mean net per trade, t = 2.8, skew +2.9, 32% win rate and 7 of 7 years positive. The pipeline never confirmed them.

Analysis

Risk Premia: Asymmetric Tail Risks and Excess Returns

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