Как посчитать stationarity test в SQL

Закрепи формулу stationarity test в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать stationarity test в Telegram

Зачем stationarity

Stationary ряд — тот, у которого статистические свойства (mean, variance) не меняются во времени. Большинство time-series методов (ARIMA, ACF/PACF, regression) требуют stationarity. На non-stationary ряду ACF медленно затухает, регрессии дают spurious результаты.

Rolling mean и std

Глазами проверяют через скользящее среднее и std. Если оба «дрейфуют» — не stationary.

SELECT
    event_date,
    value,
    AVG(value) OVER (ORDER BY event_date ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AS rolling_mean,
    STDDEV_SAMP(value) OVER (ORDER BY event_date ROWS BETWEEN 30 PRECEDING AND CURRENT ROW) AS rolling_std
FROM daily_metrics
WHERE metric_name = 'dau'
ORDER BY event_date;

Постройте в дашборде: rolling_mean плавно растёт = тренд, не stationary.

Простой ADF-like чек

Augmented Dickey-Fuller — стандартный тест. В чистом SQL только приближение через регрессию Δy_t = α + ρ × y_{t-1}:

WITH base AS (
    SELECT
        event_date,
        value,
        LAG(value, 1) OVER (ORDER BY event_date) AS prev,
        value - LAG(value, 1) OVER (ORDER BY event_date) AS diff
    FROM daily_metrics
    WHERE metric_name = 'dau'
)
SELECT
    REGR_SLOPE(diff, prev) AS rho,
    REGR_R2(diff, prev) AS r2,
    -- Простой t-stat = rho / SE
    REGR_SLOPE(diff, prev) / (STDDEV_SAMP(diff) / SQRT(COUNT(*))) AS t_stat
FROM base
WHERE prev IS NOT NULL;

В строгом ADF критическое значение примерно −3 (для α=0.05). t_stat < −3 → отвергаем unit root, ряд stationary. В SQL это грубое приближение, точный ADF — в Python statsmodels.tsa.stattools.adfuller.

Что делать с non-stationary

Если тест провален или rolling stats дрейфуют:

  1. Differencing: y_t − y_{t-1} часто делает stationary.
  2. Log-transform: стабилизирует variance.
  3. Detrend: вычесть линейный тренд.
  4. Seasonal differencing: y_t − y_{t-7} для недельной сезонности.
Закрепи формулу stationarity test в Карьернике
Запомнить надолго — 5 коротких сессий с задачами на эту тему. Бесплатно
Тренировать stationarity test в Telegram

Differencing

SELECT
    event_date,
    value,
    value - LAG(value, 1) OVER (ORDER BY event_date) AS first_diff,
    value - LAG(value, 7) OVER (ORDER BY event_date) AS seasonal_diff_7
FROM daily_metrics
WHERE metric_name = 'dau'
ORDER BY event_date;

После differencing проверьте rolling mean — должна стать стабильной.

Частые ошибки

Ошибка 1. Прыгать в ARIMA без stationarity. ARIMA автоматически делает differencing (d параметр), но если изначально не проверили — выбор d ошибочный.

Ошибка 2. Differencing раз и навсегда. Сначала first diff. Если всё ещё non-stationary — second diff. Чаще 1-2 раза достаточно.

Ошибка 3. Сравнивать rolling-mean на разных окнах. Окно 7 и 30 могут давать разные впечатления. Standardize choice.

Ошибка 4. Игнорировать сезонность. Сезонные ряды формально non-stationary в первой разностности. Нужна seasonal differencing.

Ошибка 5. Stationarity ≠ predictability. Stationary ряд может быть pure noise. Stationarity — необходимо, не достаточно.

Связанные темы

FAQ

Strict vs wide-sense stationarity?

Wide-sense (covariance stationary) — стандарт. Mean и variance не меняются, autocovariance зависит только от lag.

Какие методы тестируют?

ADF (null: unit root), KPSS (null: stationary), Phillips-Perron. Часто запускают несколько.

Differencing меняет интерпретацию?

Да. Если работаете с Δy, прогноз тоже в Δ-единицах. Кумулировать обратно.

Можно ли без stationarity?

Современные методы (Prophet, neural nets) гибче. Но ARIMA-семейство требует.

Trend и stationarity?

Linear trend → not stationary in mean. Detrend или first-diff.