Прогнозирование с statsmodels
У меня есть .csv-файл, содержащий 5-летний временной ряд, с часовым разрешением (commoditiy price). Основываясь на исторических данных, я хочу создать прогноз цен на 6-й год.
Я прочитал пару статей на www об этих типах процедур, и я в основном основывал свой код на коде, опубликованном там, так как мои знания как в Python (особенно statsmodels), так и в статистике максимально ограничены.
Таковы звенья, для тех, кто интересует:
Http://www.seanabu.com/2016/03/22/time-series-seasonal-ARIMA-model-in-python/
Http://www.johnwittenauer.net/a-simple-time-series-analysis-of-the-sp-500-index/
Прежде всего, вот пример.CSV-файл. Данные отображаются с ежемесячным разрешением в этом случае, это не реальные данные, просто случайно выбранные числа, чтобы привести пример здесь (в этом случае я надеюсь, что одного года достаточно, чтобы иметь возможность разработать прогноз на 2-й год). год; если нет, доступен полный файл csv):
Price
2011-01-31 32.21
2011-02-28 28.32
2011-03-31 27.12
2011-04-30 29.56
2011-05-31 31.98
2011-06-30 26.25
2011-07-31 24.75
2011-08-31 25.56
2011-09-30 26.68
2011-10-31 29.12
2011-11-30 33.87
2011-12-31 35.45
Мой текущий прогресс выглядит следующим образом:
После чтения входного файла и установки столбца date в качестве индекса datetime, сценарий follwing был использован для разработки прогноза для доступных данных
model = sm.tsa.ARIMA(df['Price'].iloc[1:], order=(1, 0, 0))
results = model.fit(disp=-1)
df['Forecast'] = results.fittedvalues
df[['Price', 'Forecast']].plot(figsize=(16, 12))
, что дает следующий результат:
Теперь, как я уже сказал, У меня нет никаких статистических навыков, и я почти не знаю, как я добрался до этого вывода (в основном, изменение атрибута order внутри первой строки меняется вывод), но "фактический" прогноз выглядит довольно хорошо, и я хотел бы продлить его еще на один год (2016).
Для этого в фрейме данных создаются дополнительные строки:
start = datetime.datetime.strptime("2016-01-01", "%Y-%m-%d")
date_list = pd.date_range('2016-01-01', freq='1D', periods=366)
future = pd.DataFrame(index=date_list, columns= df.columns)
data = pd.concat([df, future])
Наконец, когда я использую .прогнозировать функция statsmodels:
data['Forecast'] = results.predict(start = 1825, end = 2192, dynamic= True)
data[['Price', 'Forecast']].plot(figsize=(12, 8))
То, что я получаю в качестве прогноза, - это прямая линия (см. ниже), которая совсем не похожа на прогноз. Более того, если я расширю диапазон, который сейчас составляет от 1825-го до 2192-го дня (2016 год), на весь 6-летний промежуток времени, линия прогноза является прямой линией на весь период (2011-2016).
Я также пытался использовать статсмодели.управление транспортной безопасности.пространство состояний.саримакс.САРИМАКС.метод predict', который учитывает сезонную вариацию (что имеет смысл в данном случае), но я получаю некоторую ошибку о том, что 'модуль' не имеет атрибута 'SARIMAX'. Но это уже второстепенная проблема, при необходимости разберемся подробнее.
Где-то я теряю хватку, и я ... понятия не имею где. Спасибо за чтение. Ура!
2 ответа:
Похоже, что вы используете старую версию statsmodels, которая не поддерживает SARIMAX. Вы захотите установить последнюю выпущенную версию 0.8.0 смотрите http://statsmodels.sourceforge.net/devel/install.html .
Я использую Anaconda и устанавливаю через pip.
Класс результатов модели SARIMAX имеет ряд полезных методов, включая прогнозирование.pip install -U statsmodels
data['Forecast'] = results.forecast(100)
Будет использовать вашу модель для прогнозирования 100 шагов в будущее.
ARIMA (1,0,0) - однопериодная авторегрессионная модель. Итак, это модель, которая следует этой формуле:
Это означает, что значение в периоде времени t равно некоторой константе (phi_0) плюс значение, определенное путем подгонки модели ARMA (phi_1), умноженное на значение в предыдущем периоде r_(t-1), плюс термин ошибки белого шума (a_t).
Ваша модель имеет память только на 1 период, поэтому текущее предсказание полностью определяется значением 1 периода. предыдущий период. Это не очень сложная модель; она не делает ничего необычного со всеми предыдущими значениями. Он просто берет вчерашнюю цену, умножая ее на некоторое значение и добавляя константу. Вы должны ожидать, что он быстро перейдет в равновесие, а затем останется там навсегда.
Причина, по которой прогноз на верхнем рисунке выглядит так хорошо, заключается в том, что он просто показывает вам сотни прогнозов на 1 Период, которые начинаются заново с каждым новым периодом. Он не показывает долгосрочный прогноз как ты, наверное, и думаешь.
Глядя на ссылку, которую вы послали:
Http://www.johnwittenauer.net/a-simple-time-series-analysis-of-the-sp-500-index/
Прочитайте раздел, где он обсуждает, почему эта модель не дает вам то, что вы хотите.
" Таким образом, на первый взгляд кажется, что эта модель работает довольно хорошо. Но хотя кажется, что прогнозы действительно близки (линии почти неразличимы в конце концов), помните, что мы использовали безразличные серии! Индекс колеблется лишь на небольшой процент изо дня в день относительно общего абсолютного значения. Чего мы действительно хотим, так это предсказать первое различие или ежедневные движения. Мы можем либо повторно запустить модель, используя дифференцированный ряд, либо добавить термин "I" к модели ARIMA (в результате чего получится модель (1, 1, 0)), которая должна выполнить то же самое. Давайте попробуем использовать дифференцированный ряд."
Чтобы сделать то, что вы пытаетесь сделать, вам нужно будет провести больше исследований в этих областях. модели и выяснить, как форматировать ваши данные, и какая модель будет подходящей. Самое важное-знать, какая информация, по вашему мнению, содержится в данных, которые вы вводите в модель. В настоящее время ваша модель пытается сказать: "сегодня цена составляет 45 долларов. Какова будет цена завтра?- Вот именно. Он не имеет никакой информации о импульсе, волатильности и т. д. Это не так уж много, чтобы уйти.