Модель ETS для прогнозирования временных рядов

Экспоненциальное сглаживание остается одним из надежных методов прогнозирования временных рядов в количественном анализе. Модель ETS (Error, Trend, Seasonality) представляет формализованную версию этого подхода через представление в пространстве состояний. Метод обеспечивает баланс между простотой реализации и качеством прогнозов для данных с выраженной трендовой и сезонной структурой.

ETS работает через рекурсивное обновление компонентов модели: уровня, тренда и сезонности. Каждое новое наблюдение корректирует оценки компонентов с весами, которые определяют скорость адаптации модели к изменениям. В отличие от методологий Box-Jenkins, ETS не требует ручной настройки порядка дифференцирования и сложной идентификации структуры.

Математическая основа ETS

ETS разделяет временной ряд на три базовых компонента:

  • Уровень (level) отражает текущее значение ряда без учета тренда и сезонности;
  • Тренд (trend) показывает направление изменения уровня во времени;
  • Сезонность (seasonality) описывает повторяющиеся паттерны фиксированной длины.

Модель обновляет компоненты на каждом шаге через сглаживающие параметры α, β, γ (значения от 0 до 1). Параметр α контролирует скорость адаптации уровня, β — тренда, γ — сезонных коэффициентов. Высокие значения означают быструю реакцию на новые данные, низкие — сохранение исторических паттернов.

Типы комбинирования

ETS поддерживает аддитивный и мультипликативный способы комбинирования компонентов:

  • В аддитивном варианте компоненты суммируются: наблюдаемое значение = уровень + тренд + сезонность;
  • Мультипликативный вариант использует произведение: наблюдаемое значение = уровень × тренд × сезонность.

Выбор типа комбинирования зависит от характера данных. Аддитивная сезонность подходит для рядов с постоянной амплитудой колебаний. Мультипликативная — когда амплитуда сезонных колебаний растет пропорционально уровню ряда. Для финансовых данных с изменяющейся волатильностью предпочтительнее мультипликативный вариант.

Пространство состояний

ETS формализует экспоненциальное сглаживание через модель пространства состояний. Состояние системы включает текущие значения уровня, тренда и сезонных коэффициентов. Уравнение наблюдений связывает наблюдаемые значения с компонентами состояния. Уравнение перехода описывает эволюцию состояния во времени.

Представление в пространстве состояний дает несколько преимуществ:

  1. Возможность применения фильтра Калмана для оценки компонентов;
  2. Естественный способ построения доверительных интервалов прогноза;
  3. Единый математический аппарат для всех вариантов модели.

Ошибка прогноза в ETS может входить в модель аддитивно или мультипликативно. Аддитивная ошибка означает, что случайные отклонения не зависят от уровня ряда. Мультипликативная ошибка предполагает гетероскедастичность — дисперсия растет с уровнем. Эта особенность делает ETS гибче классического экспоненциального сглаживания.

👉🏻  Новейшие модели прогнозирования временных рядов

Классификация моделей ETS

Номенклатура ETS использует трехбуквенный код для обозначения типа каждого компонента:

  • Первая буква — тип ошибки (A для аддитивной, M для мультипликативной);
  • Вторая буква — тип тренда (N отсутствует, A аддитивный, Ad затухающий аддитивный, M мультипликативный, Md затухающий мультипликативный);
  • Третья буква — тип сезонности (N отсутствует, A аддитивная, M мультипликативная).

Полное пространство ETS включает 30 теоретически возможных комбинаций. Из них 15 моделей имеют практический смысл и стабильные свойства. Нестабильные варианты исключены из стандартных имплементаций: мультипликативная ошибка с аддитивным трендом или сезонностью приводит к проблемам с отрицательными значениями.

Наиболее распространенные спецификации:

  • ETS(A,N,N) — простое экспоненциальное сглаживание без тренда и сезонности;
  • ETS(A,A,N) — метод Хольта с линейным трендом;
  • ETS(A,Ad,N) — затухающий тренд для стабилизации долгосрочных прогнозов;
  • ETS(A,A,A) — метод Хольта-Винтерса с аддитивной сезонностью;
  • ETS(A,A,M) — мультипликативная сезонность для растущих амплитуд;
  • ETS(M,N,M) — мультипликативная модель для волатильных рядов.

Выбор типа модели

Решение между аддитивной и мультипликативной сезонностью принимается на основе визуального анализа данных. График временного ряда показывает характер изменения амплитуды сезонных колебаний. Постоянная амплитуда указывает на аддитивную сезонность. Растущая амплитуда — на мультипликативную.

Затухающий тренд (damped trend) стабилизирует долгосрочные прогнозы. Параметр затухания φ (значение от 0 до 1) контролирует скорость выхода тренда на плато. Значения близкие к 1 дают медленное затухание, близкие к 0 — быстрое. Затухающий тренд предотвращает неограниченный рост или падение прогноза, что критично для горизонтов более 10-15 периодов.

Для финансовых рядов с высокой волатильностью мультипликативная ошибка часто показывает лучшие результаты. Доверительные интервалы прогноза автоматически расширяются с ростом уровня ряда, что соответствует реальному поведению рисков. Аддитивная ошибка дает симметричные интервалы независимо от уровня.

Автоматический подбор модели

Информационные критерии

Выбор оптимальной спецификации ETS происходит через перебор допустимых моделей и сравнение информационных критериев.

AIC (Akaike Information Criterion) балансирует качество подгонки и сложность модели:

👉🏻  Нейросети для прогнозирования последовательных данных

AIC = -2×log(L) + 2×k

где:

  • L — функция правдоподобия,
  • k — число параметров.

Меньшее значение AIC указывает на лучшую модель.

AICc (corrected AIC) вводит дополнительную штраф за параметры для малых выборок:

AICc = AIC + 2×k×(k+1)/(n-k-1), где n — размер выборки.

Для временных рядов длиной менее 100 наблюдений AICc предпочтительнее стандартного AIC. Коррекция предотвращает переобучение на коротких историях.

BIC (Bayesian Information Criterion) применяет более жесткий штраф за сложность:

BIC = -2×log(L) + k×log(n)

BIC склонен выбирать более простые модели по сравнению с AIC. Для прогнозирования AIC и AICc обычно дают лучшие результаты данные отложенных выборок, BIC больше подходит для задач интерпретации структуры.

Процедура оптимизации

Автоматический подбор модели включает две стадии:

  1. Выбор структуры модели (наличие тренда, тип сезонности). Алгоритм перебирает все 15 допустимых комбинаций компонентов, для каждой оценивает параметры сглаживания и вычисляет информационный критерий. Модель с минимальным критерием становится финалистом.
  2. Оптимизация параметров сглаживания α, β, γ и начальных состояний. Процедура использует максимизацию правдоподобия через численную оптимизацию. Функция правдоподобия зависит от типа ошибки: гауссовское правдоподобие для аддитивной ошибки, преобразованное правдоподобие для мультипликативной.

Начальные значения компонентов оценивают из первых наблюдений:

  • Для уровня — среднее первых нескольких точек;
  • Для тренда — наклон между первыми сезонными циклами;
  • Для сезонных коэффициентов — отношение наблюдений к среднему внутри каждого сезона.

Качественная инициализация ускоряет сходимость оптимизации.

Практическая реализация на Python

Пакет statsmodels содержит имплементацию ETS в модуле statsmodels.tsa.exponential_smoothing.ets. Класс ETSModel поддерживает все 15 допустимых спецификаций и автоматический выбор модели. Метод fit() оценивает параметры через максимизацию правдоподобия.

import pandas as pd
import numpy as np
import yfinance as yf
from statsmodels.tsa.exponential_smoothing.ets import ETSModel
import matplotlib.pyplot as plt

# Загрузка дневных данных
ticker = yf.Ticker("TSM")
data = ticker.history(start="2022-09-15", end="2025-09-15")

# Проверка на MultiIndex и извлечение цен закрытия
if isinstance(data.columns, pd.MultiIndex):
    prices = data['Close'].iloc[:, 0]
else:
    prices = data['Close']

# Преобразование в Series с DatetimeIndex
prices = pd.Series(prices.values, index=pd.DatetimeIndex(data.index))
prices = prices.asfreq('D')

# Агрегация до недельных данных для выявления паттернов
weekly_prices = prices.resample('W-FRI').last().dropna()

print(f"Размер выборки: {len(weekly_prices)} недель")
print(f"Период: {weekly_prices.index[0]} - {weekly_prices.index[-1]}")
print(weekly_prices.tail())
Размер выборки: 157 недель
Период: 2022-09-16 00:00:00-04:00 - 2025-09-12 00:00:00-04:00

Date
2025-08-15 00:00:00-04:00    238.128754
2025-08-22 00:00:00-04:00    232.257278
2025-08-29 00:00:00-04:00    230.143936
2025-09-05 00:00:00-04:00    242.644516
2025-09-12 00:00:00-04:00    258.514435

Код загружает котировки акций TSMC через yfinance и агрегирует данные до недельной частоты. Агрегация снижает шум дневных колебаний и делает структурные паттерны более заметными. Метод resample() с якорем ‘W-FRI’ группирует данные по неделям с окончанием в пятницу. Функция last() берет последнее значение в каждой неделе — цену закрытия пятницы.

👉🏻  Теория вероятностей и биржевая торговля

Следующий этап — построение прогноза.

# Разделение на обучающую и тестовую выборку
train_size = int(len(weekly_prices) * 0.85)
train = weekly_prices[:train_size]
test = weekly_prices[train_size:]

# Автоматический подбор модели
model_auto = ETSModel(
    train,
    error='add',
    trend='add',
    seasonal=None,
    damped_trend=True
)

fitted_auto = model_auto.fit()

# Прогноз на горизонте тестовой выборки
forecast_steps = len(test)
forecast = fitted_auto.forecast(steps=forecast_steps)
forecast_index = test.index

# Расчет метрик точности
mae = np.mean(np.abs(test.values - forecast.values))
rmse = np.sqrt(np.mean((test.values - forecast.values)**2))
mape = np.mean(np.abs((test.values - forecast.values) / test.values)) * 100

# Формируем словарь параметров с именами
params_dict = dict(zip(fitted_auto.model.param_names, fitted_auto.params))

print(f"\nСпецификация модели: {fitted_auto.model.error}/{fitted_auto.model.trend}/{fitted_auto.model.seasonal}")
print(f"AIC: {fitted_auto.aic:.2f}")
print(f"BIC: {fitted_auto.bic:.2f}")

print("\nПараметры сглаживания:")
print(f"α (уровень): {params_dict.get('smoothing_level', np.nan):.6f}")
print(f"β (тренд): {params_dict.get('smoothing_trend', np.nan):.6f}")
print(f"φ (затухание): {params_dict.get('damping_trend', np.nan):.6f}")
print(f"Начальный уровень: {params_dict.get('initial_level', np.nan):.6f}")
print(f"Начальный тренд: {params_dict.get('initial_trend', np.nan):.6f}")

print("\nТочность прогноза:")
print(f"MAE: ${mae:.2f}")
print(f"RMSE: ${rmse:.2f}")
print(f"MAPE: {mape:.2f}%")
Спецификация модели: add/add/None
AIC: 893.35
BIC: 910.69

Параметры сглаживания:
α (уровень): 0.903461
β (тренд): 0.000090
φ (затухание): 0.980000
Начальный уровень: 72.444994
Начальный тренд: 1.160603

Точность прогноза:
MAE: $46.95
RMSE: $54.04
MAPE: 20.95%

Разделение данных на обучающую (85%) и тестовую (15%) выборки позволяет оценить качество прогноза отложенной выборке. Спецификация модели задает аддитивную ошибку, аддитивный затухающий тренд и отсутствие сезонности. Для недельных финансовых данных без выраженных календарных эффектов сезонный компонент избыточен.

Параметр damped_trend=True активирует затухание тренда через коэффициент φ. Это предотвращает линейную экстраполяцию, которая быстро расходится на длинных горизонтах.

Метод fit() оптимизирует все параметры включая α, β, φ и начальные состояния. Доступ к оцененным параметрам через атрибут params позволяет анализировать скорость адаптации модели.

Метрики MAE и RMSE измеряют абсолютные отклонения прогноза в долларах. MAPE дает относительную ошибку в процентах, что удобно для сравнения точности на разных инструментах. MAPE чувствителен к значениям близким к нулю — для финансовых данных это обычно не проблема.

Давайте теперь посмотрим на визуализацию компонентов.

# Создание фигуры с подграфиками
fig, axes = plt.subplots(3, 1, figsize=(12, 10))
fig.suptitle('ETS: декомпозиция и прогноз', fontsize=14, fontweight='bold')

# График 1: Исходный ряд и прогноз
axes[0].plot(train.index, train.values, label='Обучающая выборка', 
             color='#2C3E50', linewidth=1.5)
axes[0].plot(test.index, test.values, label='Тестовая выборка', 
             color='#27AE60', linewidth=1.5)
axes[0].plot(forecast_index, forecast.values, label='Прогноз ETS', 
             color='#E74C3C', linewidth=2, linestyle='--')
axes[0].set_ylabel('Цена ($)', fontsize=11)
axes[0].legend(loc='upper left', fontsize=10)
axes[0].grid(True, alpha=0.3)
axes[0].set_title('Временной ряд и прогноз', fontsize=11, loc='left')

# График 2: Компонент уровня
level = fitted_auto.level
axes[1].plot(train.index, level, color='#34495E', linewidth=1.5)
axes[1].set_ylabel('Уровень ($)', fontsize=11)
axes[1].grid(True, alpha=0.3)
axes[1].set_title('Эволюция уровня', fontsize=11, loc='left')

# График 3: Компонент тренда
trend = fitted_auto.slope
axes[2].plot(train.index, trend, color='#8E44AD', linewidth=1.5)
axes[2].axhline(y=0, color='gray', linestyle='--', linewidth=1, alpha=0.5)
axes[2].set_ylabel('Тренд ($/период)', fontsize=11)
axes[2].set_xlabel('Дата', fontsize=11)
axes[2].grid(True, alpha=0.3)
axes[2].set_title('Динамика тренда', fontsize=11, loc='left')

plt.tight_layout()
plt.savefig('ets_decomposition.png', dpi=300, bbox_inches='tight')
plt.show()

# Анализ остатков
residuals = fitted_auto.resid

fig, axes = plt.subplots(2, 2, figsize=(12, 8))
fig.suptitle('Диагностика остатков', fontsize=14, fontweight='bold')

# График остатков
axes[0, 0].plot(train.index, residuals, color='#2C3E50', linewidth=1)
axes[0, 0].axhline(y=0, color='red', linestyle='--', linewidth=1, alpha=0.5)
axes[0, 0].set_ylabel('Остатки ($)', fontsize=10)
axes[0, 0].set_title('Временной график остатков', fontsize=10, loc='left')
axes[0, 0].grid(True, alpha=0.3)

# Гистограмма остатков
axes[0, 1].hist(residuals, bins=30, color='#34495E', alpha=0.7, edgecolor='black')
axes[0, 1].set_xlabel('Остатки ($)', fontsize=10)
axes[0, 1].set_ylabel('Частота', fontsize=10)
axes[0, 1].set_title('Распределение остатков', fontsize=10, loc='left')
axes[0, 1].grid(True, alpha=0.3, axis='y')

# ACF остатков
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(residuals, lags=20, ax=axes[1, 0], color='#2C3E50')
axes[1, 0].set_title('Автокорреляция остатков', fontsize=10, loc='left')
axes[1, 0].grid(True, alpha=0.3)

# Q-Q plot
from scipy import stats
stats.probplot(residuals, dist="norm", plot=axes[1, 1])
axes[1, 1].set_title('Q-Q график', fontsize=10, loc='left')
axes[1, 1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('ets_residuals.png', dpi=300, bbox_inches='tight')
plt.show()

print("\nСтатистика остатков:")
print(f"Среднее: {np.mean(residuals):.4f}")
print(f"Ст. отклонение: {np.std(residuals):.4f}")
print(f"Skewness: {stats.skew(residuals):.4f}")
print(f"Kurtosis: {stats.kurtosis(residuals):.4f}")

Декомпозиция временного ряда на компоненты ETS. Верхняя панель показывает исходные данные, разделение на обучающую/тестовую выборку и прогноз. Средняя панель отображает эволюцию компонента уровня — сглаженную версию ряда без краткосрочных колебаний. Нижняя панель демонстрирует динамику тренда — скорость изменения уровня во времени. Затухание тренда проявляется в постепенном движении к нулевой линии

Рис. 1: Декомпозиция временного ряда на компоненты ETS. Верхняя панель показывает исходные данные, разделение на обучающую/тестовую выборку и прогноз. Средняя панель отображает эволюцию компонента уровня — сглаженную версию ряда без краткосрочных колебаний. Нижняя панель демонстрирует динамику тренда — скорость изменения уровня во времени. Затухание тренда проявляется в постепенном движении к нулевой линии

Диагностика остатков модели ETS. Верхний левый график показывает остатки во времени — отклонения фактических значений от модельных. Отсутствие систематических паттернов указывает на адекватную спецификацию. Верхний правый график — гистограмма распределения остатков для проверки нормальности. Нижний левый — автокорреляционная функция остатков: значения внутри доверительных границ подтверждают отсутствие неучтенной автокорреляции. Нижний правый — Q-Q график для визуальной оценки соответствия нормальному распределению

Рис. 2: Диагностика остатков модели ETS. Верхний левый график показывает остатки во времени — отклонения фактических значений от модельных. Отсутствие систематических паттернов указывает на адекватную спецификацию. Верхний правый график — гистограмма распределения остатков для проверки нормальности. Нижний левый — автокорреляционная функция остатков: значения внутри доверительных границ подтверждают отсутствие неучтенной автокорреляции. Нижний правый — Q-Q график для визуальной оценки соответствия нормальному распределению

Статистика остатков:
Среднее: 0.3296
Ст. отклонение: 6.6404
Skewness: -0.1481
Kurtosis: 0.8448

Атрибуты level и slope объекта fitted_auto содержат временные ряды компонентов уровня и тренда. Визуализация компонентов помогает понять как модель интерпретирует структуру данных. Резкие изменения уровня соответствуют периодам высокой волатильности. Отрицательный тренд указывает на нисходящую динамику, положительный — на восходящую.

👉🏻  Поиск аномалий в данных с Python

Диагностика остатков проверяет предположения модели. Остатки должны быть случайными, независимыми и нормально распределенными. Автокорреляция остатков сигнализирует о неучтенных паттернах — возможно требуется другая спецификация или дополнительные компоненты. Гетероскедастичность (изменяющаяся дисперсия) указывает на необходимость мультипликативной ошибки.

Сравнение с альтернативными методами

ETS занимает промежуточную позицию между простыми эвристиками и сложными моделями машинного обучения. По сравнению со скользящими средними ETS адаптируется к изменениям через оцениваемые параметры сглаживания. В отличие от наивных методов ETS явно моделирует тренд и сезонность.

Относительно LSTM и других рекуррентных сетей ETS требует меньше данных для обучения и быстрее обучается. Модель интерпретируема — компоненты имеют понятный смысл. Однако модель ETS не улавливает сложные нелинейные зависимости и ограничена фиксированной структурой компонентов.

Модель Prophet использует похожую декомпозицию на тренд, сезонность и праздники. Prophet лучше работает с данными содержащими пропуски и выбросы, предоставляет гибкость в задании праздничных эффектов. ETS дает более точные краткосрочные прогнозы для регулярных рядов без специфических календарных эффектов.

Модель TBATS (Trigonometric, Box-Cox, ARMA, Trend, Seasonal) расширяет подход ETS для рядов с множественной сезонностью и высокочастотными данными. Метод применяет Box-Cox преобразование для стабилизации дисперсии и тригонометрические функции для гибкого моделирования сезонности. Однако модель TBATS сложнее настраивать и она требует больше вычислительных ресурсов.

Практические рекомендации

Когда применять ETS

ETS эффективен для временных рядов с выраженной трендовой и сезонной структурой. Метод подходит для краткосрочных и среднесрочных прогнозов — горизонты от 1 до 20-30 периодов вперед. Для финансовых данных это соответствует прогнозам на несколько недель или месяцев.

👉🏻  Прогнозирование вероятности дефолта через логистическую регрессию

Для корректной работы алгоритма важна регулярная частота наблюдений и отсутствие аномалий. Пропуски данных требуют предварительной обработки через интерполяцию или заполнение последним известным значением. Выбросы влияют на оценку компонентов — желательна предварительная очистка данных.

ETS работает для рядов с одной сезонной частотой. Данные с множественной сезонностью (часовые данные с дневной и недельной цикличностью) требуют альтернативных методов (можно рассмотреть Prophet). Длина сезона должна быть известна заранее и оставаться постоянной на всей истории.

Ограничения метода

ETS плохо прогнозирует временные ряды с частыми сменами тренда. Резкое изменение режима рынка (например переход от роста к падению после кризиса) не улавливается алгоритмом автоматически. Модель продолжает экстраполировать старые паттерны даже когда рыночные условия изменились.

ETS предполагает что будущее продолжает прошлое с постепенной адаптацией. Метод не учитывает экзогенные факторы — макроэкономические индикаторы, корпоративные события, регуляторные изменения. Для задач где важны внешние драйверы требуются регрессионные расширения.

Долгосрочные прогнозы (более 30 периодов) теряют точность из-за накопления ошибок. Доверительные интервалы быстро расширяются делая прогноз малоинформативным. Затухающий тренд частично решает проблему, однако не устраняет фундаментальную неопределенность.

Настройка параметров

В большинстве случаев автоматический подбор модели через информационные критерии работает хорошо. Ручная настройка требуется при специфических знаниях о данных. Принудительное задание типа сезонности ускоряет обучение если структура известна заранее.

Параметр seasonal_periods определяет длину сезонного цикла. Для месячных данных с годовой сезонностью надо выбирать значение 12. Для недельных данных с квартальными паттернами значение примерно 13. Неправильная длина сезона приводит к смещенным прогнозам.

👉🏻  Кто такие квант-аналитики (Quantitative Analysts) и чем они занимаются?

Ограничения на параметры сглаживания стабилизируют оптимизацию. Значения α, β, γ близкие к 0 или 1 указывают на проблемы с данными или спецификацией. Параметр затухания φ обычно лежит в диапазоне 0.8-0.98 — более низкие значения дают агрессивное затухание.

Горизонт прогноза влияет на выбор между аддитивным и затухающим трендом. Для горизонтов до 5-10 периодов лучше выбирать линейный тренд. Для более длинных горизонтов затухание предотвращает неправдоподобные экстраполяции. Сравнение прогнозов на отложенной выборке определяет оптимальную спецификацию.

Заключение

ETS представляет зрелый инструмент для прогнозирования временных рядов с балансом между простотой и функциональностью. Метод формализует интуитивное экспоненциальное сглаживание через математически строгую модель пространства состояний. Автоматический подбор спецификации снижает барьер входа — не требуется глубокая экспертиза в анализе временных рядов.

Практическая ценность ETS проявляется в задачах краткосрочного и среднесрочного прогнозирования с регулярными данными. Интерпретируемость компонентов помогает понять структуру ряда и выявить аномалии. Быстрая работа позволяет использовать метод для массового прогнозирования множества инструментов. В портфеле аналитика ETS занимает место надежного бейзлайн решения, которое работает из коробки и дает предсказуемые результаты.