Mean reversion z-score
ma_20[t] = mean of close[t-19 … t]
std_20[t] = sample std of close[t-19 … t] (ddof = 1)
zscore[t] = (close[t] − ma_20[t]) / std_20[t]
signal[t] = +1 if zscore < −1.25
−1 if zscore > +1.25
0 otherwiseQuery
WITH
'2024-01-01' AS start_date,
'2024-12-31' AS end_date,
20 AS window_size,
1.25 AS n_std,
candles AS (
SELECT toDate(start) AS day, toFloat64(close) AS close
FROM api.ohlcv(candle_duration_in_minutes = 1440)
WHERE exchange = 'binance'
AND market = 'BTC-USDT'
AND start BETWEEN start_date AND end_date
),
z AS (
SELECT day, close,
avg(close) OVER w AS ma_20,
stddevSamp(close) OVER w AS std_20,
(close - avg(close) OVER w) / nullIf(stddevSamp(close) OVER w, 0) AS zscore,
count(*) OVER w AS valid_rows
FROM candles
WINDOW w AS (ORDER BY day ROWS BETWEEN 19 PRECEDING AND CURRENT ROW)
)
SELECT day, close, ma_20, std_20, zscore,
if(zscore < -n_std, 1, if(zscore > n_std, -1, 0)) AS signal
FROM z
WHERE valid_rows = window_size
ORDER BY dayOutput (2024)
day
close
ma_20
std_20
zscore
signal
Extending it
Last updated