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

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

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

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

@data_analysis_ml – инструменты анализа данных.

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

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

Во-первых, давайте получим цену закрытия каждой криптовалюты, включая 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
Прогнозирование временных рядов криптовалют с Python

Затем нам нужно выяснить некоторые внешние факторы, которые могут повлиять на цену криптовалют. Давайте возьмём некоторые командные индексы с рынка, такие как 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
Прогнозирование временных рядов криптовалют с Python

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

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

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

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

coins = coins.dropna()

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

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

Мы не можем использовать один и тот же метод для внешних факторов, поскольку данные основаны на разной временной последовательности. Таким образом, нам нужно найти и установить первые даты данных, которые будут совпадать со всеми криптовалютами. Из предыдущего результата мы знаем, что можем установить нашу дату как 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 мы будем использовать простой метод индексации, называемый “Равновзвешенный индекс”. Это среднее значение по криптовалюте.

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

Прогнозирование временных рядов криптовалют с Python
  • Значение индекса (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)
Прогнозирование временных рядов криптовалют с Python

Здесь мы можем использовать пакет 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()
Прогнозирование временных рядов криптовалют с Python

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

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

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

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)
Прогнозирование временных рядов криптовалют с Python

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

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

Прогнозирование временных рядов криптовалют с Python
data_nor.corr(method="pearson").style.background_gradient(cmap="coolwarm", axis=None).set_precision(2)
Прогнозирование временных рядов криптовалют с Python
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)
Прогнозирование временных рядов криптовалют с Python

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

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

В машинном обучении случайное разделение потока данных / теста является нормальным, потому что нет зависимости от одного наблюдения к другому. Тем не менее, это не относится к данным временных рядов. Как мы упоминали ранее, наши модели прогнозирования основаны на авторегрессионном анализе, что означает, что данные временного ряда 𝑌(𝑡+ℎ)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])
Прогнозирование временных рядов криптовалют с Python

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

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

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

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

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

Дальше необходимо определить наилучшие параметры, которые соответствуют нашей модели. На этом шаге мы будем использовать один из самых мощных инструментов под названием 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)
Прогнозирование временных рядов криптовалют с Python

Основываясь на результате, мы обнаружили, что наилучшие параметры для моделей 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))
Прогнозирование временных рядов криптовалют с Python

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

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()
Прогнозирование временных рядов криптовалют с Python

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

Вот и все!

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

+1
1
+1
1
+1
0
+1
1
+1
1

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *