Bollinger Bands
middle_band[t] = mean of close[t-19 … t]
std_20[t] = population std of close[t-19 … t] (ddof = 0)
upper_band[t] = middle_band[t] + 2 · std_20[t]
lower_band[t] = middle_band[t] − 2 · std_20[t]
signal[t] = +1 if close < lower_band (oversold → potential long)
−1 if close > upper_band (overbought → potential short)
0 otherwiseQuery
WITH
'2024-01-01' AS start_date,
'2024-12-31' AS end_date,
20 AS window_size,
2.0 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
),
bands AS (
SELECT day, close,
avg(close) OVER w AS middle_band,
avg(close) OVER w + n_std * stddevPop(close) OVER w AS upper_band,
avg(close) OVER w - n_std * stddevPop(close) OVER w AS lower_band,
count(*) OVER w AS valid_rows
FROM candles
WINDOW w AS (ORDER BY day ROWS BETWEEN 19 PRECEDING AND CURRENT ROW)
)
SELECT day, close, middle_band, upper_band, lower_band,
if(close < lower_band, 1, if(close > upper_band, -1, 0)) AS signal
FROM bands
WHERE valid_rows = window_size
ORDER BY dayOutput (2024)
day
close
middle_band
upper_band
lower_band
signal
Extending it
Last updated