English Español Deutsch 日本語 Português
preview
Как опередить любой рынок?

Как опередить любой рынок?

MetaTrader 5Примеры | 8 августа 2024, 12:59
1 152 3
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana

Содержание

  1. Краткое содержание
  2. Введение
  3. Обзор стратегии: Альтернативные источники данных
  4. Методы машинного обучения
  5. Построение стратегии
  6. Заключение
  7. Рекомендации


Краткое содержание

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

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

Мы рассмотрим данные, предоставляемые Федеральным резервным банком Сент-Луиса (St. Louis Federal Reserve Bank), в частности, их комплексную базу данных эконометрических временных рядов, известную как FRED. FRED находится в открытом доступе и, несомненно, предоставляет данные, имеющие решающее значение для принятия обоснованных решений в торговле. Более того, данные, полученные от центральных банков, часто служат опережающими индикаторами, улучшая нашу способность эффективно рассчитывать время входа и выхода.

Более того, эти данные невосприимчивы к внешним манипуляциям, что делает их идеальным кандидатом для интеграции в нашу торговую стратегию.

Статья призвана служить практическим руководством, демонстрирующим простоту использования Python и MetaTrader 5 для создания современных торговых стратегий. Ясность и простота изложения гарантирует простоту освоения описанного здесь метода. Читатель сможет начать применять его уже сегодня!


Введение: Цель этой статьи – продемонстрировать, как можно легко применять альтернативные данные в торговых стратегиях. 

Читатели получат представление о следующих ключевых областях:

  1. Как альтернативные данные могут помочь в принятии решений в условиях шума и неопределенности.
  2. Методы проверки и выявления надежных источников альтернативных данных.
  3. Анализ и предварительная обработка альтернативных данных.
  4. Создание надежных торговых стратегий, которые интегрируют альтернативные источники данных для улучшения процесса принятия решений.

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

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


Обзор стратегии: Альтернативные источники данных

Наша торговая стратегия проста для понимания. Мы объединим традиционные рыночные данные из нашего терминала MetaTrader 5 с альтернативными данными Федерального резервного банка Сент-Луиса, уделяя особое внимание прогнозированию будущих движений цен пары GBPUSD.

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

Аналогичным образом, второй набор данных содержит информацию о USD и представляет собой временной ряд процентных ставок, взимаемых по межсуточным (овернайт, overnight) кредитам американским банкам, управляемым Федеральной резервной системой. Контроль Федеральной резервной системы над этими процентными ставками посредством корректировок денежно-кредитной политики предлагает альтернативное понимание экономических тенденций, которые могут повлиять на USD.

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

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

  1. Достоверность: как ваш источник альтернативных данных вообще получает данные? Изучите надежность информационных каналов. Как источник получает доступ к своей информации? Надежны ли его каналы информации? Эти вопросы имеют решающее значение для оценки достоверности. Любые сомнения относительно этих аспектов сигнализируют о необходимости более тщательной оценки.
  2. Частота обновлений: Мы уделяем особое внимание альтернативным источникам данных, которые обновляются ежедневно в соответствии с нашими торговыми временными рамками. Однако не все источники предлагают ежедневные обновления. Некоторые могут обновляться ежемесячно или ежегодно. Поэтому обязательно выбирайте источник, который соответствует желаемой частоте торговли.
  3. Репутация: Помимо доверия, отдавайте предпочтение источникам с хорошей репутацией и доказанной заинтересованностью в обеспечении точности. Авторитетный поставщик несет ответственность за достоверность своих данных.
  4. Прозрачность: выбирайте поставщиков, которые представляют данные прозрачно и удобно для пользователя. Ясность и простота представления данных имеют первостепенное значение для эффективного принятия решений, особенно с учетом когнитивной нагрузки, связанной со сложными данными.
  5. Структура ценообразования: оцените модели ценообразования альтернативных источников данных, соблюдая баланс между своими потребностями и бюджетом. Некоторые источники могут быть бесплатными, другие - нет. Наш выбор должен соответствовать ценности каждого источника.
  6. Условия: внимательно изучите условия предоставления данных, особенно если они предоставляются за деньги. Четкое понимание ограничений и запретов использования обеспечивает принятие обоснованных решений и предотвращает любые непреднамеренные проблемы с соблюдением требований.

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

Изучим некоторые альтернативные данные, полученные от Федерального резервного банка Сент-Луиса. Есть два способа получить данные банка:

  1. Программное использование библиотеки FRED Python
  2. Вручную на веб-сайте FRED. 

Если вы впервые используете эти наборы данных, я бы посоветовал вам сначала собрать данные вручную. Дело в том, что на сайте FRED есть полезные примечания и информация о каждом наборе данных, о том, как он был сформирован, что представляют собой данные, скорректированы ли они с учетом сезонных колебаний, о единицах и масштабах измерений и других деталях такого рода. Как только вы ознакомитесь с характером данных, вы можете перейти к их сбору программными методами. Итак, для нашей первой демонстрации наборы данных были загружены вручную с сайта Федерального резервного банка Сент-Луиса. При построении стратегии мы перейдем к программному подходу. 

Первое, что мы сделаем, это соберем рыночные данные из MetaTrader 5 с помощью скрипта MQL5. Я предпочитаю собирать данные таким образом, потому что мы можем выполнять любую необходимую предварительную обработку на стороне MQL5, где у нас есть неограниченный доступ к данным. Наш скрипт довольно прост.

  • Начнем с объявления обработчиков наших технических индикаторов. Мы будем использовать четыре скользящие средние.
  • Затем мы объявляем буферы для хранения показаний наших скользящих средних. Буферы в нашем случае представляют собой динамические массивы.
  • Далее нам нужно дать имя нашему файлу. В нашем случае это будет имя пары, которой мы торгуем, за которым следует строка "Market Data As Series" (серия рыночных данных). Файл будет иметь формат CSV.
  • Впоследствии мы заявляем, какой объем данных мы хотели бы собрать. 
  • Обратите внимание, что скрипт работает с текущим таймфреймом графика, к которому он применен.
  • Мы подошли к обработчику событий OnStart(), где находится сердце нашего скрипта.
  • Мы начинаем с инициализации всех четырех наших технических индикаторов.
  • Затем копируем значения индикатора в созданные ранее массивы.
  • Как только это будет сделано, мы создадим обработчик файла для создания, записи и закрытия нашего файла.
  • Затем мы используем простой цикл for для перебора массивов и записи их в наш CSV-файл. Обратите внимание, что на первой итерации нашего цикла мы записываем заголовки столбцов, а затем - фактические значения, которые нам нужны.
  • После завершения цикла мы закрываем наш файл, используя обработчик файла, и теперь мы готовы объединить данные из нашего терминала MetaTrader 5 с нашими альтернативными данными.

#property copyright "Gamuchirai Zororo Ndawana"
#property link      "https://www.mql5.com"
#property version   "1.00"

//---Our handlers for our indicators
int ma_handle_5;
int ma_handle_15;
int ma_handle_30;
int ma_handle_150;

//---Data structures to store the readings from our indicators
double ma_reading_5[];
double ma_reading_15[];
double ma_reading_30[];
double ma_reading_150[];

//---File name
string file_name = _Symbol + " " + " Market Data As Series.csv";

//---Amount of data requested
int size = 1000000;
int size_fetch = size + 100;

void OnStart()
  {
      //---Setup our technical indicators
      ma_handle_5 = iMA(_Symbol,PERIOD_CURRENT,5,0,MODE_EMA,PRICE_CLOSE);
      ma_handle_15 = iMA(_Symbol,PERIOD_CURRENT,15,0,MODE_EMA,PRICE_CLOSE);
      ma_handle_30 = iMA(_Symbol,PERIOD_CURRENT,30,0,MODE_EMA,PRICE_CLOSE);
      ma_handle_150 = iMA(_Symbol,PERIOD_CURRENT,150,0,MODE_EMA,PRICE_CLOSE);
      
      //---Copy indicator values
      CopyBuffer(ma_handle_5,0,0,size_fetch,ma_reading_5);
      ArraySetAsSeries(ma_reading_5,true);
      CopyBuffer(ma_handle_15,0,0,size_fetch,ma_reading_15);
      ArraySetAsSeries(ma_reading_15,true);
      CopyBuffer(ma_handle_30,0,0,size_fetch,ma_reading_30);
      ArraySetAsSeries(ma_reading_30,true);
      CopyBuffer(ma_handle_150,0,0,size_fetch,ma_reading_150);
      ArraySetAsSeries(ma_reading_150,true);

      //---Write to file
       int file_handle=FileOpen(file_name,FILE_WRITE|FILE_ANSI|FILE_CSV,",");
       
    for(int i=-1;i<=size;i++){
      if(i == -1){
            FileWrite(file_handle,"Time","Open","High","Low","Close","MA 5","MA 15","MA 30","MA 150");
      }
      
      else{
            FileWrite(file_handle,iTime(_Symbol,PERIOD_CURRENT,i),
                                 iOpen(_Symbol,PERIOD_CURRENT,i),
                                 iHigh(_Symbol,PERIOD_CURRENT,i),
                                 iLow(_Symbol,PERIOD_CURRENT,i),
                                 iClose(_Symbol,PERIOD_CURRENT,i),
                                 ma_reading_5[i],
                                 ma_reading_15[i],
                                 ma_reading_30[i],
                                 ma_reading_150[i]
                                 );
      } 
    }
  }
//+------------------------------------------------------------------+

Теперь мы готовы изучать альтернативные данные наряду с нашими рыночными данными.

Как всегда, мы начнем с импорта необходимых пакетов.

import pandas as pd
import numpy as np 
import matplotlib.pyplot as plt
import seaborn as sns

Теперь мы считываем данные, которые мы экспортировали из нашего скрипта MQL5.

GBPUSD = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\MetaQuotes\\Terminal\\NVUSDVJSNDU3483408FVKDL\\MQL5\\Files\\GBPUSD Market Data As Series.csv")

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

GBPUSD = GBPUSD[::-1]

Затем нам нужно сбросить индекс.

GBPUSD.reset_index(inplace=True)

Давайте определим, насколько далеко вперед мы хотели бы прогнозировать.

look_ahead = 30
splits = 30

Теперь нам нужно подготовить цель. 

GBPUSD["Target"] = GBPUSD["Close"].shift(-look_ahead)
GBPUSD.dropna(inplace=True)

Теперь нам нужно сделать дату индексом. Позже это поможет нам легко согласовать наши рыночные данные с альтернативными.

GBPUSD["Time"] = pd.to_datetime(GBPUSD["Time"])
GBPUSD.set_index("Time",inplace=True)

Первый альтернативный набор данных, который мы рассмотрим, — это средняя дневная ставка индекса стерлинга овернайт (Daily Sterling Overnight Index Average, SOIA). Это среднее значение процентных ставок, взимаемых с банков за займы в GBP в нерабочее время.

Если средние процентные ставки по GBP растут, а средние процентные ставки по USD падают, это может быть потенциальным сигналом о том, что GBP становится сильнее USD на институциональном уровне. 

SOIA = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\Downloads\\FED Data\\Daily Sterling Overnight Index Average\\IUDSOIA.csv")

Давайте очистим альтернативные данные. Сначала сделайте столбец даты объектом.

SOIA["DATE"] = pd.to_datetime(SOIA["DATE"])

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

SOIA["IUDSOIA"] = SOIA["IUDSOIA"].replace(".","0")
SOIA["IUDSOIA"] = pd.to_numeric(SOIA["IUDSOIA"])
non_zero_mean = SOIA.loc[SOIA['IUDSOIA'] != 0, 'IUDSOIA'].mean()
SOIA['IUDSOIA'] = SOIA['IUDSOIA'].replace(0, non_zero_mean)

Далее мы делаем дату индексом.

SOIA.set_index("DATE",inplace=True)

Следующим источником альтернативных данных, который мы рассмотрим, будет обеспеченная ставка финансирования овернайт (Secured Overnight Financing Rate, SOFR). Это стоимость обеспеченных кредитов овернайт. Она публикуется ежедневно Федеральным резервным банком Нью-Йорка (New York Federal Reserve Bank). 

SOFR = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\Downloads\\FED Data\\Secured Overnight Financing Rate\\SOFR.csv")

Этапы предварительной обработки, применяемые к набору данных SOFR, идентичны шагам, применяемым к набору данных SOIA, поэтому, чтобы статью было легко читать, мы опустим эти шаги. 

Давайте теперь объединим три имеющихся у нас фрейма данных. Установив для left_index и right_index значение true, мы гарантируем, что оба набора данных будут выровнены только в те дни, когда у нас есть полные наблюдения для каждого из них. Например, в наборе данных GBPUSD нет записей за выходные, поэтому все альтернативные точки данных, наблюдаемые за выходные, не включены в наш окончательный объединенный фрейм данных. 

merged_df = SOIA.merge(SOFR,left_index=True,right_index=True)
merged_df = merged_df.merge(GBPUSD,left_index=True,right_index=True)

Затем нам нужно сбросить наш индекс.

merged_df.reset_index(inplace=True)
merged_df.drop(columns=["index"],inplace=True)

Давайте определим наши предикторы.

normal_predictors = ['Open', 'High', 'Low', 'Close', 'MA 5', 'MA 15','MA 30', 'MA 150']
alternative_predictors = ['IUDSOIA', 'SOFR']
all_predictors = normal_predictors + alternative_predictors

Создадим фрейм данных для хранения уровней ошибок каждой комбинации предикторов.

accuracy = pd.DataFrame(columns=["Normal","Alternative","All"],index=np.arange(0,splits))

Вот как сейчас выглядит наш фрейм данных.

merged_df

Наш объединенный фрейм данных

Рис. 1. Наш набор данных, который содержит как наши обычные, так и альтернативные данные


В первом столбце указана средняя процентная ставка по GBP, во втором - по USD. Следующие столбцы должны быть вам уже знакомы. Помните, что целью является цена закрытия на 30 дней вперед.

Наконец, мы экспортируем наш объединенный фрейм данных в файл csv для дальнейшего использования.

merged_df.to_csv('Alternative Data Target Look Ahead 30.csv')

Давайте масштабируем наши данные.

from sklearn.preprocessing import StandardScaler
scaled_data = merged_df.loc[:,all_predictors]
scaler = StandardScaler()
scaler.fit(scaled_data)
scaled_data = pd.DataFrame(scaler.transform(scaled_data),index=merged_df.index,columns=all_predictors)

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

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error 
from sklearn.model_selection import TimeSeriesSplit

Давайте подготовим разделение данных на тренировочные и контрольные.

tscv = TimeSeriesSplit(gap=look_ahead+10,n_splits=splits)

for i,(train,test) in enumerate(tscv.split(merged_df)):
    model = LinearRegression()
    model.fit(scaled_data.loc[train[0]:train[-1],all_predictors],merged_df.loc[train[0]:train[-1],"Target"])
    accuracy["All"][i] = mean_squared_error(merged_df.loc[test[0]:test[-1],"Target"],model.predict(scaled_data.loc[test[0]:test[-1],all_predictors]))


Теперь мы отображаем результаты в виде блочных диаграмм.

fig,axs = plt.subplots(1,3,sharex=True,sharey=True,figsize=(16,4))

for i,ax in enumerate(axs.flat):
    ax.boxplot(merged_df.iloc[:,i])
    ax.set_title(accuracy.columns[i])

Комбинации предикторов

Рис. 2. Анализ значений ошибок, полученных при использовании обычных данных (слева), альтернативных данных (в центре) и всех доступных данных (справа)

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

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

sns.scatterplot(x=merged_df["IUDSOIA"],y=merged_df["Target"])

Эффекты взаимодействия GBP

Рис. 3. Анализ взаимосвязи между процентной ставкой, взимаемой по GBP, и будущей стоимостью пары GBPUSD

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


Методы машинного обучения 

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

  • Размер набора данных: Для небольших наборов данных, содержащих менее десяти тысяч строк или менее 30 столбцов, рекомендуется использовать более простые модели, чтобы снизить риск переобучения. Сложные модели, такие как глубокие нейронные сети, могут испытывать трудности с обучением на таких ограниченных данных.
  • Зашумленность данных: Зашумленные наборы данных (обычно это наборы данных с отсутствующими точками данных или случайными необъяснимыми колебаниями) лучше подходят для более простых моделей. Сложные модели, как правило, демонстрируют высокую дисперсию, что повышает вероятность их переобучения на зашумленных данных, а в особенно шумные рыночные дни, возможно, лучше вообще отказаться от их использования.
  • Размерность данных: В случаях, когда набор данных имеет большое количество столбцов, могут быть полезны методы предварительной обработки. Используйте модели, которые эффективны при обработке многомерных данных, и применяйте выбор функций и уменьшение размерности.
  • Размер данных и вычислительная мощность: Если у вас есть большие наборы данных с приемлемыми уровнями шума, а также доступ к достаточным вычислительным ресурсам, то вы можете применять сложные моделей, такие как глубокие нейронные сети. Эти модели могут эффективно фиксировать сложные закономерности и взаимосвязи в данных при наличии адекватных вычислительных возможностей и чистых данных.

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


Начнем с импорта необходимых нам библиотек.

import statistics as st

import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

from sklearn.linear_model import Lasso,Ridge,LinearRegression
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import TimeSeriesSplit
from sklearn.metrics import mean_squared_error
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler

from xgboost import XGBRegressor

Теперь мы прочитаем данные из экспортированного нами CSV-файла. В CSV были все наши объединенные данные.

csv = pd.read_csv("C:\\Enter\\Your\\Path\\Here\\Alternative Data.csv")

Давайте подготовимся к масштабированию данных.

predictors = ['IUDSOIA', 'SOFR', 'Open', 'High', 'Low', 'Close']
target = 'Target'
scaled_data = csv.loc[:,predictors]
scaler = StandardScaler()
scaler.fit(scaled_data)
scaled_data = scaler.transform(scaled_data)

Обучим наши модели.

splits = 10
gap = 30
models = ['Linear','Lasso','Ridge','Random Forest','Linear SVR','Sigmoid SVR','RBF SVR','2 Poly SVR','3 Poly SVR','XGB']

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

tscv = TimeSeriesSplit(n_splits=splits,gap=gap)
error_df = pd.DataFrame(index=np.arange(0,splits),columns=models)

Теперь мы можем наблюдать показатели ошибок нашей модели.

for i,(train,test) in enumerate(tscv.split(csv)):
    model=XGBRegressor()
    model.fit(scaled_data.loc[train[0]:train[-1],predictors],csv.loc[train[0]:train[-1],target])
    error_df.iloc[i,9] =mean_squared_error(csv.loc[test[0]:test[-1],target],model.predict(scaled_data.loc[test[0]:test[-1],predictors]))

error_df

Ошибка каждой модели

Рис. 4. Значения ошибок, полученные нами для каждой подобранной нами модели


Визуализируем некоторые данные в виде блочных диаграмм.

fig , axs = plt.subplots(2,5,figsize=(20,20),sharex=True)

for i,ax in enumerate(axs.flat):
    ax.boxplot(error_df.iloc[:,i])
    ax.set_title(error_df.columns[i])


Линейные модели

Рис. 5. Значения ошибок некоторых линейных моделей, которые мы использовали


Нелинейные модели

Рис. 6.Значения ошибок некоторых нелинейных моделей, которые мы использовали


Приведем некоторые полученные сводные статистические данные.

Дисперсия      Ошибка 
Линейная дисперсия: 1,3365981802501968e-06 Линейная среднеквадратическая ошибка: 0,0022242681292296462
Дисперсия лассо: 3,0466413126186177e-05 Среднеквадратическая ошибка лассо: 0,004995731270431843
Гребневая дисперсия: 2,5678314939547713e-06 Гребневая среднеквадратическая ошибка: 0,002467126140156681
Дисперсия случайного леса: 2,607918492340197e-06 Среднеквадратическая ошибка случайного леса: 0,002632579355696408
Дисперсия линейной SVR (регрессии опорных векторов): 3,825627012092798e-05 Среднеквадратическая ошибка линейной SVR: 0,004484702122899226
Дисперсия сигмовидной SVR: 27,654341711864102 Среднеквадратическая ошибка сигмовидной SVR: 1,6693947903605928
Дисперсия SVR RBF (радиальной базисной функции): 4,1654658535332505e-05 Среднеквадратическая ошибка SVR RBF: 0,004992333849448852
Дисперсия 2 Poly (полиномиальной) SVR: 6,739873404310582e-05 Среднеквадратическая ошибка 2 Poly SVR: 0,008163708245600027
Дисперсия 3 Poly SVR: 0,0005393054392191576 Среднеквадратическая ошибка 3 Poly SVR: 0,018431036676781344
Дисперсия XGB: 7,053078880392137e-06 Среднеквадратическая ошибка XGB: 0,003163819414983548


Обратите внимание, что ни одна из моделей не выделяется в плане качества работы. Все они более или менее находятся в одном диапазоне производительности. В таких обстоятельствах более простая модель может оказаться лучшим выбором, поскольку она менее подвержена переобучению. Поэтому в этом примере мы будем использовать линейную регрессию в качестве модели для нашей торговой стратегии. Мы выбираем ее, потому что ее уровень ошибок такой же, как и у любой другой модели, которую мы могли бы выбрать, и, кроме того, ее дисперсия невелика. Таким образом, линейная модель с меньшей вероятностью будет переобучаться и с большей вероятностью будет оставаться стабильной с течением времени. 


Построение стратегии 

Теперь мы готовы применить всё, что обсуждалось в предыдущих разделах, в надежную торговую стратегию, используя библиотеку MetaTrader 5 для Python. 

Пояснения будут даны на каждом этапе пути для простоты понимания всего кода.

Сначала импортируем нужные нам пакеты.

from fredapi import Fred
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import time
from datetime import datetime
import matplotlib.pyplot as plt

Пакет fredapi позволяет нам программно извлекать данные из базы данных FRED. Однако прежде чем мы сможем использовать библиотеку, мы должны создать ключ API. Ключи API можно создать бесплатно, но получить их можно только после создания бесплатной учетной записи пользователя на сайте Федерального резервного банка Сент-Луиса.

Теперь определим глобальные переменные.

LOGIN = ENTER_YOUR_LOGIN
PASSWORD = 'ENTER_YOUR_PASSWORD'
SERVER = 'ENTER_YOUR_SERVER'
SYMBOL = 'GBPUSD'
TIMEFRAME = mt5.TIMEFRAME_D1
DEVIATION = 1000
VOLUME = 0
LOT_MULTIPLE = 1
FRED = Fred(api_key='ENTER_YOUR_API_KEY')

Теперь войдем в наш торговый аккаунт.

if mt5.initialize(login=LOGIN,password=PASSWORD,server=SERVER):
    print('Logged in successfully')
else:
    print('Failed To Log in')

Авторизация выполнена успешно

Определим наш торговый объем.

for index,symbol in enumerate(mt5.symbols_get()):
    if symbol.name == SYMBOL:
        print(f"{symbol.name} has minimum volume: {symbol.volume_min}")
        VOLUME = symbol.volume_min * LOT_MULTIPLE

GBPUSD имеет минимальный объем: 0,01


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

Сначала нам нужна функция для получения текущей рыночной цены из нашего терминала MetaTrader 5.

def get_prices():
    start = datetime(2024,3,20)
    end   = datetime.now()
    data  = pd.DataFrame(mt5.copy_rates_range(SYMBOL,TIMEFRAME,start,end))
    data['time'] = pd.to_datetime(data['time'],unit='s')
    data.set_index('time',inplace=True)
    return(data.iloc[-1,:])

Далее нам нужна функция для запроса альтернативных данных у Федеральной резервной системы Сент-Луиса.

def get_alternative_data():
    SOFR = FRED.get_series_as_of_date('SOFR',datetime.now())
    SOFR = SOFR.iloc[-1,-1]
    SOIA = FRED.get_series_as_of_date('IUDSOIA',datetime.now())
    SOIA = SOIA.iloc[-1,-1]
    return(SOFR,SOIA)

Затем нам нужна функция для подготовки входных данных для нашей модели.

def get_model_inputs():
    LAST_OHLC = get_prices()
    SOFR , SOIA = get_alternative_data()
    MODEL_INPUT_DF = pd.DataFrame(index=np.arange(0,1),columns=predictors)
    MODEL_INPUT_DF['Open'] = LAST_OHLC['open']
    MODEL_INPUT_DF['High'] = LAST_OHLC['high']
    MODEL_INPUT_DF['Low'] =  LAST_OHLC['low']
    MODEL_INPUT_DF['Close'] = LAST_OHLC['close']
    MODEL_INPUT_DF['IUDSOIA'] = SOIA
    MODEL_INPUT_DF['SOFR'] = SOFR
    model_input_array = np.array([[MODEL_INPUT_DF.iloc[0,0],MODEL_INPUT_DF.iloc[0,1],MODEL_INPUT_DF.iloc[0,2],MODEL_INPUT_DF.iloc[0,3],MODEL_INPUT_DF.iloc[0,4],MODEL_INPUT_DF.iloc[0,5]]])
    return(model_input_array,MODEL_INPUT_DF.loc[0,'Close'])


Затем нам нужна функция, которая поможет нам сделать прогноз с использованием нашей модели.

def ai_forecast():
    model_inputs,current_price = get_model_inputs()
    prediction = model.predict(model_inputs)
    return(prediction[0],current_price)

Давайте обучим нашу модель.

training_data = pd.read_csv('C:\\Enter\\Your\\Path\\Here\\Alternative Data.csv')

Настроим модель.

from sklearn.linear_model import LinearRegression
model = LinearRegression()

Определяем наши предикторы и цель.

predictors = ['Open','High','Low','Close','IUDSOIA','SOFR']
target     = 'Target'

Устанавливаем нашу модель.

model.fit(training_data.loc[:,predictors],training_data.loc[:,target])

Теперь мы подошли к сути нашего торгового алгоритма:

  • Сначала мы определяем бесконечный цикл, чтобы наша стратегия работала постоянно.
  • Затем мы получаем текущие рыночные данные и используем их для прогноза.
  • После этого у нас будут логические флаги, отражающие ожидания нашей модели. Если наша модель ожидает роста цены, BUY_STATE имеет значение True, в противном случае, если наша модель ожидает падения цены, SELL_STATE имеет значение false.
  • Если у нас нет открытых позиций, мы будем следовать прогнозу нашей модели.
  • Если у нас есть открытые позиции, проверим, соответствует ли прогноз модели нашей открытой позиции. Если нет, закрываем позицию. Если соответствует, мы можем оставить позицию открытой.
  • Наконец, после выполнения всех вышеперечисленных шагов мы переведем алгоритм в режим ожидания на день и получим обновленные данные на следующий день.

while True:
    #Get data on the current state of our terminal and our portfolio
    positions = mt5.positions_total()
    forecast , current_price = ai_forecast()
    BUY_STATE , SELL_STATE = False , False

    #Interpret the model's forecast
    if(current_price > forecast):
        SELL_STATE = True
        BUY_STATE  = False 

    elif(current_price > forecast):
        SELL_STATE = False
        BUY_STATE  = True

    print(f"Current price is {current_price} , our forecast is {forecast}")

    #If we have no open positions let's open them
    if(positions == 0):
        print(f"We have {positions} open trade(s)")
        if(SELL_STATE):
            print("Opening a sell position")
            mt5.Sell(SYMBOL,VOLUME)
        elif(BUY_STATE):
            print("Opening a buy position")
            mt5.Buy(SYMBOL,VOLUME)

    #If we have open positions let's manage them
    if(positions > 0):
        print(f"We have {positions} open trade(s)")
        for pos in mt5.positions_get():
            if(pos.type == 1):
                if(BUY_STATE):
                    print("Closing all sell positions")
                    mt5.Close(SYMBOL)
            if(pos.type == 0):
                if(SELL_STATE):
                    print("Closing all buy positions")
                    mt5.Close(SYMBOL)
    #If we have finished all checks then we can wait for one day before checking our positions again
    time.sleep(24 * 60 * 60)


Конечный результат

Рис. 7. Наша сделка в первый день ее открытия



День 2

Рис. 8. Наша сделка на следующий день


Заключение 

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


Рекомендации

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

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/14441

Прикрепленные файлы |
Alternative_Data.zip (569.06 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (3)
linfo2
linfo2 | 3 апр. 2024 в 01:55
И снова отличный материал Ndawa, захватывающий материал, заставляющий меня захотеть проверить другие источники больших данных. Несмотря на то, что все хорошо написано и понятно, мне потребуется время, чтобы переварить это. Большое спасибо за то, что поделились, наличие файлов Jupiter - это фантастическая помощь. Не уверен, что это имеет значение, но может быть разумно дезинфицировать пути к файлам в jupterfiles, например, C:\\\\Users\\\\<Ваше имя пользователя>\\\\<Ваше местоположение>\\\\jupyter-notebooks\\\\AlternativeData\\\\Alternative Data.csv'
didei didei
didei didei | 9 авг. 2024 в 11:37
Какие - в теории - альтернативные данные могут быть по золоту, нефти и газу?
Gamuchirai Zororo Ndawana
Gamuchirai Zororo Ndawana | 11 авг. 2024 в 17:09
didei didei золота, нефти и газа?
Да, Дидей, именно в этом и заключается идея.
Нейросети в трейдинге: Модели пространства состояний Нейросети в трейдинге: Модели пространства состояний
В основе большого количества рассмотренных нами ранее моделей лежит архитектура Transformer. Однако они могут быть неэффективны при работе с длинными последовательностями. И в этой статье я предлагаю познакомиться с альтернативным направлением прогнозирования временных рядов на основе моделей пространства состояний.
Алгоритм искусственного пчелиного улья — Artificial Bee Hive Algorithm (ABHA): Тестирование и результаты Алгоритм искусственного пчелиного улья — Artificial Bee Hive Algorithm (ABHA): Тестирование и результаты
В этой статье мы продолжим изучение алгоритма искусственного пчелиного улья ABHA, углубляясь в написание кода и рассматривая оставшиеся методы. Напомним, что каждая пчела в модели представлена как индивидуальный агент, чье поведение зависит от внутренней и внешней информации, а также мотивационного состояния. Мы проведем тестирование алгоритма на различных функциях и подведем итоги, представив результаты в рейтинговой таблице.
Разбираем примеры торговых стратегий в клиентском терминале Разбираем примеры торговых стратегий в клиентском терминале
В статье рассмотрим наглядно по блок-схемам логику прилагаемых к терминалу учебных советников, расположенных в папке Experts\Free Robots, торгующих по свечным паттернам.
Алгоритм искусственного пчелиного улья — Artificial Bee Hive Algorithm (ABHA): Теория и методы Алгоритм искусственного пчелиного улья — Artificial Bee Hive Algorithm (ABHA): Теория и методы
В статье мы познакомимся с алгоритмом искусственного пчелиного улья (ABHA), разработанным в 2009 году. Алгоритм направлен на решение задач непрерывной оптимизации. Мы рассмотрим, как ABHA черпает вдохновение из поведения пчелиной колонии, где каждая пчела выполняет уникальную роль, что способствует более эффективному поиску ресурсов.