Прогнозирование временных рядов криптовалют для чайников

Прогнозирование временных рядов криптовалют для чайников

В обанкротившейся криптофирме FTX отсутствует, по меньшей мере, 1 миллиард долларов клиентских средств, а их токен FTX потерял большую часть своей стоимости в ноябре 2022 года. Как бы вы уберегли свой портфель от огромных потерь в случае краха?

Это руководство поможет вам понять метод очистки данных временных рядов и то, как крупные финансовые компании создают популярные индексы, такие как S &P 500 или Nasdaq. Самое главное, как создать индекс вашего портфеля, содержащий различные криптовалюты, чтобы отслеживать ваши показатели и использовать машинное обучение для прогнозирования движения индекса в ближайшем будущем.

Цель этого руководства - помочь новичку, который немного разбирается во временных рядах, но испытывает трудности с обработкой реальных наборов данных. Вы сможете быстро восполнить пробел с помощью этого руководства. Я надеюсь, что каждый сможет найти что-то полезное в нём.

Загрузка наборов данных

Во-первых, давайте получим цену закрытия каждой криптовалюты, включая Bitcoin, Binance Coin, Dogecoin, Ethereum, USD Coin, Tether, XRP и токен FTX с 2010 года от Coincodex.

Примечание: Все цены, используемые в данных, основаны на обменном курсе между целевой валютой и долларом США.

import pandas as pd coins = pd.read_csv("/cryptocurrency/coins.csv", sep=",", header=0) coins.set_index("Date", inplace=True) # make the date become the index coins = coins.sort_index() coins
Прогнозирование временных рядов криптовалют для чайников

Затем нам нужно выяснить некоторые внешние факторы, которые могут повлиять на цену криптовалют. Давайте возьмём некоторые командные индексы с рынка, такие как S & P 500, Nasdaq, gold и silver, которые стартовали в 2018 году. Мы также можем добавить некоторые популярные экономические показатели, такие как ежедневные ставки номинальной доходности казначейских облигаций Министерства финансов США или CPI и PSR.

factors = pd.read_csv("/cryptocurrency/predictor_variables.csv", sep=",", header=0) factors.set_index("Date", inplace=True) # make the date become the index factors = factors.sort_index() factors
Прогнозирование временных рядов криптовалют для чайников

чистка данных

Когда мы получаем данные временных рядов, они лишь иногда бывают в требуемом формате. Большая часть необработанных данных либо должна быть более упорядочена, либо содержит множество отсутствующих значений или дат, что делает невозможным обучение моделей. Таким образом, понимание того, как правильно очищать и подготавливать данные, является одним из важных навыков для специалиста по обработке данных.

Очистка пропущенных значений

Во-первых, давайте проясним, что нулевые значения находятся в криптографических данных.

coins = coins.dropna() coins
Прогнозирование временных рядов криптовалют для чайников

Заполнение недостающих значений

Мы не можем использовать один и тот же метод для внешних факторов, поскольку данные основаны на разной временной последовательности. Таким образом, нам нужно найти и установить первые даты данных, которые будут совпадать со всеми криптовалютами. Из предыдущего результата мы знаем, что можем установить нашу дату как 2019/08/01. Чтобы преобразовать эти данные в полезную информацию, мы сначала предположим, что в течение отсутствующих дней большинство из них приходится либо на выходные, либо на праздничные дни, и значения остаются теми же, что и накануне. Основываясь на этом предположении, мы можем заполнить недостающее время даты значениями предыдущего дня.

factors = factors["2019-08-01":] factors = factors.reindex(pd.date_range("2019-08-01", "2022-11-15")).reset_index().rename(columns={"index": "Date"}) factors = factors.groupby(factors["Date"].dt.time).ffill() # fill the missing date values factors.set_index("Date", inplace=True) factors

Создание настраиваемого индекса

Мы хотим спрогнозировать индекс в этом проекте, и в какой-то момент времени t мы будем использовать простой метод индексации, называемый “Равновзвешенный индекс”. Это среднее значение по криптовалюте.

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

Прогнозирование временных рядов криптовалют для чайников
  • Значение индекса (V): относится к равновзвешенному индексу.
  • Цена(P): относится к цене криптовалюты.
  • Вес (W): относится к присвоенному весу, но в равновзвешенном индексе каждый вес равен 1 / N, где N - количество крипты в индексе.
result = [] # calculate the index value for i in range(len(coins.columns)): coin = coins[coins.columns[i]] / len(coins.columns) result.append(coin) # assign index value with date ew_index = pd.DataFrame(1 + pd.DataFrame(pd.concat(result, axis=1)).sum(axis=1)) ew_index.set_axis([*ew_index.columns[:-1], "Index"], axis=1, inplace=True) ew_index.tail(5)
Прогнозирование временных рядов криптовалют для чайников

Здесь мы можем использовать пакет seaborn для просмотра межквартильного диапазона индекса за каждый месяц.

import seaborn as sns import matplotlib.pyplot as plt ts_fig, ts_ax = plt.subplots(figsize=(36, 9)) sns.boxplot(x=ew_index.index.strftime("%Y-%b"), y=ew_index.Index, ax=ts_ax) ts_ax.set_xlabel("Month", labelpad=9, fontsize=15) ts_ax.set_ylabel("Total Rides", labelpad=9, fontsize=15) ts_ax.set_xticklabels(ts_ax.get_xticklabels(), rotation=90) ts_ax.set_title("Monthly Index", fontsize=21) plt.show()
Прогнозирование временных рядов криптовалют для чайников

Предварительная обработка данных

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

data = factors.merge(ew_index, how="left", left_on="Date", right_on="Date")

Нормализация переменных

Теперь у нас есть чистые данные, готовые к использованию. Прежде чем мы начнём обучать модель с этими данными, одним из важных шагов является обеспечение нормализации всех данных. Поскольку и наши целевые переменные, и переменные-предикторы измеряются в разных шкалах, мы должны привести значения в соответствие с условно стандартной шкалой в этом разделе. Есть много способов достичь этого, но в этом проекте будет использоваться один из самых простых методов, нормализация Min-Max, которая заключается в масштабировании диапазона объектов для масштабирования диапазона в [0, 1].

from sklearn.preprocessing import MinMaxScaler data_nor = pd.DataFrame(MinMaxScaler().fit_transform(data)).assign(label=data.index) # normalized the data with min-max scaling data_nor.columns = data.columns.to_list() + ["Date"] data_nor.set_index("Date", inplace=True) data_nor.tail(5)
Прогнозирование временных рядов криптовалют для чайников

Нахождение корреляции между переменными

Ещё одним необходимым шагом, прежде чем мы начнём обучать модель с использованием этих данных, является проверка корреляции между нашими целевыми переменными и переменными-предикторами. Мы будем использовать коэффициент корреляции Пирсона для анализа корреляции и, основываясь на следующем рисунке, удалим переменные слабой корреляции (коэффициент корреляции от -0,2 до 0,2).

Прогнозирование временных рядов криптовалют для чайников
data_nor.corr(method="pearson").style.background_gradient(cmap="coolwarm", axis=None).set_precision(2)
Прогнозирование временных рядов криптовалют для чайников
cor = data_nor.corr(method="pearson") data_nor.drop(data_nor.columns[(cor.Index >= -0.2) & (cor.Index <= 0.2)], axis=1, inplace=True) # remove the weak corellation (% between -0.2 to 0.2) data_nor.tail(5)
Прогнозирование временных рядов криптовалют для чайников

Прогнозирование временных рядов

Наборы для обучения и тестирования

В машинном обучении случайное разделение потока данных / теста является нормальным, потому что нет зависимости от одного наблюдения к другому. Тем не менее, это не относится к данным временных рядов. Как мы упоминали ранее, наши модели прогнозирования основаны на авторегрессионном анализе, что означает, что данные временного ряда 𝑌(𝑡+ℎ)Y(t+h) коррелируют с его историческим значением 𝑌(𝑡)Y(t). Здесь мы захотим использовать значения в конце набора данных для тестирования, а всё остальное - для обучения.

Исходя из этого предположения, у нас было 1203 записи с ежедневными интервалами (почти 4 года); хорошим подходом было бы сохранить первые 1143 записи (3,1 года) для обучения и последние 60 записей (2 месяца) для тестирования.

train_size = int(len(df) * 0.9505) X_train, y_train = pd.DataFrame(df.iloc[:train_size, :-1]), pd.DataFrame(df.iloc[:train_size, -1]) X_test, y_test = pd.DataFrame(df.iloc[train_size:, :-1]), pd.DataFrame(df.iloc[train_size:, -1])

Как Определить Параметры d? Стационарное обнаружение

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

ori_df = y_train # original time series fir_df = y_train.diff().dropna() # first difference time series sec_df = y_train.diff().diff().dropna() # second difference time series stationary_test = None for i in range(3): if i == 0: print("Original Time Series") stationary_test = adfuller(ori_df) elif i == 1: print("First Order Differencing") stationary_test = adfuller(fir_df) elif i == 2: print("Second Order Differencing") stationary_test = adfuller(sec_df) print("ADF Statistic: %f" %stationary_test[0]) print("p-value: %f\n" %stationary_test[1])
Прогнозирование временных рядов криптовалют для чайников

Реализация модели SARIMAX

Функция модели SARIMAX аналогична модели ARIMA, но добавляет два других факторы: сезонность и внешние факторы.

Ключевым выводом является то, что SARIMAX требует не только аргументов p, d и q, которые требуются ARIMA, но также требует другой набор аргументов P, D и Q для аспекта сезонности, а также аргумента, называемого “m”. Это периодичность сезонного цикла данных; другими словами, это количество периодов в каждом сезоне.

При выборе значения m попытайтесь получить представление о том, когда сезонные данные изменяются. Если ваши точки данных разделяются на ежемесячной основе, а сезонный цикл составляет год, то установите m равным 12. Или, если точки данных разделяются на ежедневной основе, а сезонный цикл составляет неделю, то сделайте s равным 7. Вот таблица, на которую вы можете сослаться, чтобы настроить параметры m.

Прогнозирование временных рядов криптовалют для чайников

Дальше необходимо определить наилучшие параметры, которые соответствуют нашей модели. На этом шаге мы будем использовать один из самых мощных инструментов под названием auto_arima, который поможет нам найти p, q, P и Q. Нам не нужно находить d с помощью этого инструмента, потому что мы уже выполнили стационарный тест в предыдущем разделе, что означает, что d и D можно установить равными 1. Не забудьте установить X_train в exogenous и seasonal в True.

from pmdarima import auto_arima sarimax_param = auto_arima(y_train, exogenous=X_train, m=7, start_p=0, d=1, start_q=0, start_P=0, D=1, start_Q=0, max_p=3, max_q=1, max_P=3, max_Q=1, trace=True, seasonal=True)
Прогнозирование временных рядов криптовалют для чайников

Основываясь на результате, мы обнаружили, что наилучшие параметры для моделей SARIMAX - это когда p равно 1, q равно 0, P равно 3, Q равно 0. Затем мы можем поместить эти параметры в модель и начать обучать её. На этом этапе мы поместим обучающий набор данных в SARIMAX, а параметры, полученные из auto_arima, - в order, сезонные параметры - в seasonal_order.

from statsmodels.tsa.statespace.sarimax import SARIMAX algorithm = SARIMAX(endog=y_train, exog=X_train, order=sarimax_param.get_params()["order"], seasonal_order=sarimax_param.get_params()["seasonal_order"]) model = algorithm.fit(disp=False)

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

from sklearn.metrics import mean_absolute_error, mean_squared_error # forecast the data forecast = model.get_prediction(start=len(y_train), end=len(y_train)+len(y_test)-1, exog=X_test, dynamic=True) prediction = forecast.predicted_mean ci = forecast.conf_int() # check error rate mse = mean_squared_error(y_test, prediction, squared=False) rmse = mean_squared_error(y_test, prediction, squared=True) print("The error rates of the SARIMAX forecasting are: \nMSE = %f \nRMSE = %f" %(mse, rmse))
Прогнозирование временных рядов криптовалют для чайников

Давайте сравним результаты прогнозирования с реальностью на графике:

plt.figure(figsize=(24, 9)) plt.plot(y_test.index, y_test, label="observation") plt.plot(prediction.index, prediction, label="prediction") plt.fill_between(ci.index, ci.iloc[:, 0], ci.iloc[:, 1], color="k", alpha=0.2) plt.ylim([0.18, 0.3]) plt.title("SARIMAX Model Prediction", fontsize=21) plt.legend() plt.show()
Прогнозирование временных рядов криптовалют для чайников

Когда мы смотрим на график, мы можем сказать, что прогноз очень близок к фактическим движениям рынка, а также уловить случайность в прогнозировании, за исключением 11 ноября, когда FTX внезапно подала заявление о защите от банкротства.

Вот и все!

ПРЕДУПРЕЖДЕНИЕ: ЭТО РУКОВОДСТВО НЕ ЯВЛЯЕТСЯ ФИНАНСОВЫМ СОВЕТОМИнформация, содержащаяся на этом веб-сайте, и ресурсы, доступные для загрузки через этот веб-сайт, не предназначены и не должны пониматься или истолковываться как финансовые рекомендации. Информация, содержащаяся на этом веб-сайте, не является заменой финансовой консультации от профессионала, который осведомлен о фактах и обстоятельствах вашей индивидуальной ситуации.

Статья взята из следующего источника:

1
Начать дискуссию