Тест Дики-Фуллера

Знакомимся со стандартным статистическим тестом, который формально отвечает на вопрос «ряд стационарен?».

Тест Дики-Фуллера (ADF) проверяет наличие единичного корня: нулевая гипотеза — ряд нестационарен; маленький p-value позволяет её отвергнуть и считать ряд стационарным.

Зачем нужен формальный тест

Глаз обманывает: короткий нестационарный ряд может выглядеть «ровным», а шумный стационарный — «дрейфующим». Формальный тест даёт воспроизводимый критерий. ADF — самый распространённый: он встроен в statsmodels и почти всегда используется как первый шаг проверки.

Воспроизводимость здесь — ключевое слово. В прогнозной системе решение «дифференцировать ряд или нет» нельзя принимать каждый раз заново на глазок: если завтра трафик пересчитает другой аналитик, он должен прийти к тому же выводу. Формальный тест превращает субъективное «мне кажется, тут тренд» в число, которое можно записать, сравнить с порогом и автоматизировать. Когда вы строите прогноз спроса по сотням товаров или нагрузку по десяткам сервисов, разглядывать каждый график вручную невозможно — тест становится частью конвейера, который сам решает, какие ряды требуют обработки.

Как читать результат

ADF возвращает статистику и p-value. Логика обратная привычной: нулевая гипотеза говорит, что ряд нестационарен. Если p-value мал (обычно < 0.05), нулевую гипотезу отвергаем — ряд можно считать стационарным. Если p-value велик — оснований считать ряд стационарным нет, нужно дифференцировать.

p-valueВывод
< 0.05отвергаем H0 → ряд стационарен
≥ 0.05не отвергаем H0 → ряд нестационарен

Обратная логика — главный источник путаницы у новичков, поэтому стоит её прочувствовать. Тест по умолчанию «подозревает» ряд в нестационарности и требует доказательств обратного. Маленькое p-value — это и есть улика против нестационарности: вероятность увидеть настолько «возвращающийся к среднему» ряд, будь он на самом деле нестационарным, мала. А большое p-value — это не оправдательный приговор, а отсутствие улик: тест просто не набрал доказательств, и ряд остаётся под подозрением. Запомните формулу: ADF доказывает стационарность, а не нестационарность.

Как это выглядит в коде

На проде ADF берут из библиотеки. Этот блок только для чтения — он использует сторонний statsmodels, поэтому помечен как нерабочий пример.

from statsmodels.tsa.stattools import adfuller

stat, pvalue, *_ = adfuller(series)
print("ADF statistic:", stat)
print("p-value:", pvalue)
if pvalue < 0.05:
    print("Ряд стационарен")
else:
    print("Ряд нестационарен, нужно дифференцировать")

Помимо статистики и p-value функция возвращает ещё критические значения для уровней 1%, 5% и 10%: статистику можно сравнивать прямо с ними. Правило простое — чем отрицательнее ADF-статистика, тем сильнее свидетельство в пользу стационарности; если она ниже критического значения, нулевую гипотезу отвергают. На практике обычно достаточно смотреть на p-value и порог 0.05, а критические значения держать про запас для более строгих выводов.

Логика теста на чистом Python

Сама идея ADF — регрессия приращения на уровень: если коэффициент при уровне значимо отрицателен, ряд возвращается к среднему (стационарен). Оценим этот коэффициент простым МНК для двух рядов.

def gamma(x):
    dx = [x[i]-x[i-1] for i in range(1, len(x))]   # приращения
    lx = x[:-1]                                     # уровень с лагом 1
    mx = sum(lx)/len(lx); md = sum(dx)/len(dx)
    num = sum((lx[i]-mx)*(dx[i]-md) for i in range(len(lx)))
    den = sum((v-mx)**2 for v in lx)
    return round(num/den, 3)

stat_series  = [10,9,11,10,12,9,10,11,9,10]
trend_series = [10,13,17,22,28,35,43,52,62,73]
print("Стационарный gamma:", gamma(stat_series))
print("С трендом    gamma:", gamma(trend_series))

Вывод:

Стационарный gamma: -1.462
С трендом    gamma: 0.149

У стационарного ряда коэффициент сильно отрицателен (-1.46): ряд тянет назад к среднему. У ряда с трендом он положителен (0.15): отклонения не гасятся, а нарастают. Именно знак и величину этого коэффициента ADF и проверяет на значимость.

Интуиция за знаком простая. Коэффициент γ отвечает на вопрос: «если сегодня значение оказалось высоким, что произойдёт завтра — оно вернётся вниз или поедет ещё выше?». Отрицательный γ означает «вернётся»: высокое значение влечёт отрицательное приращение, ряд гасит собственные отклонения и колеблется вокруг устойчивого уровня — это и есть стационарность. Нулевой или положительный γ означает, что приращение не зависит от текущего уровня (случайное блуждание) или даже усиливается вместе с ним (взрывной рост) — отклонения накапливаются, и уровень уплывает. Настоящий ADF не довольствуется знаком: он проверяет, достаточно ли γ отрицателен, чтобы это нельзя было списать на случайность выборки.

Как работает под капотом

ADF строит регрессию Δx_t = γ·x_{t-1} + (лаги) + шум и тестирует гипотезу γ = 0 против γ < 0. Расширенная версия добавляет лаги приращений, чтобы убрать автокорреляцию остатков. Критические значения нестандартны (распределение Дики-Фуллера), поэтому сравнивают не с обычными квантилями t, а со специальными таблицами — об этом заботится библиотека.

Почему вообще понадобились особые таблицы? Под нулевой гипотезой (единичный корень) ряд — это случайное блуждание, а его уровень x_{t-1} сам растёт неограниченно. Обычная теория t-критерия предполагает «хорошо ведущие себя» регрессоры, и здесь это предположение ломается: распределение статистики оказывается смещённым в сторону отрицательных значений. Поэтому Дики и Фуллер заранее посчитали правильные критические значения методом Монте-Карло. Слово «расширенный» (Augmented) в названии как раз про добавленные лаги Δx: без них автокорреляция в остатках исказила бы оценку, а с ними тест применим и к рядам с более богатой динамикой. Число лагов выбирают автоматически по информационному критерию — ещё одна деталь, которую берёт на себя библиотека.

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

  • Трактовать большое p-value как «доказательство стационарности» — это лишь отсутствие доказательств обратного.
  • Забыть, что нулевая гипотеза ADF — нестационарность (логика перевёрнута).
  • Применять ADF к ряду с сильной сезонностью без сезонного дифференцирования.
  • Делать выводы по слишком короткому ряду: на десятке точек у теста почти нет мощности, и он «не замечает» даже явную нестационарность.
  • Полагаться на единственный тест — на пограничных случаях полезно сверяться с KPSS, у которого нулевая гипотеза противоположна.

Итоги

  • ADF проверяет единичный корень; H0 — ряд нестационарен.
  • p-value < 0.05 → отвергаем H0 → ряд считаем стационарным.
  • Суть теста — значимо отрицательный коэффициент возврата к среднему.
  • Тест доказывает стационарность, а не нестационарность: большое p-value — лишь отсутствие улик.
  • На коротких или сезонных рядах результату нельзя доверять без оговорок; полезна перепроверка KPSS.
Проверьте себя
1. Что означает p-value < 0.05 в тесте Дики-Фуллера?
AРяд точно нестационарен
BОтвергаем нулевую гипотезу — ряд можно считать стационарным
CТест не сработал
DНужно больше данных
2. Какова нулевая гипотеза теста Дики-Фуллера?
AРяд стационарен
BРяд имеет единичный корень (нестационарен)
CУ ряда нет тренда
DДисперсия равна нулю