
Применение Conditional LSTM и индикатора VAM в автоматической торговле
Введение
В динамичном мире финансовых рынков трейдеры и аналитики всегда ищут новые и креативные способы получить преимущество перед своими конкурентами. В настоящей статье рассматривается новый метод автоматической торговли, сочетающий в себе навыки прогнозирования с помощью глубокого обучения и возможности обычного технического анализа. Мы стремимся разработать стабильную и гибкую торговую технику, способную справиться со сложностями современных рынков, объединив сложную модель нейронной сети условной долгой кратковременной памяти (LSTM) с собственным техническим индикатором Импульс с поправкой на волатильность (Volatility Adjusted Momentum, VAM).
Технические индикаторы уже давно используются финансовой индустрией для определения тенденций и потенциальных торговых возможностей. Несмотря на свою важность, эти индикаторы часто не в полной мере отражают сложность рыночной динамики, особенно в периоды крайней волатильности или резких изменений. Однако архитектуры глубокого обучения, такие, в частности, как LSTM, продемонстрировали удивительный потенциал в моделях машинного обучения для распознавания паттернов и прогнозирования в сложных, зависящих от времени данных. Однако эти модели не всегда обладают такой интерпретируемостью и знаниями о конкретной предметной области, как обычный технический анализ.
Целью нашей стратегии является ликвидировать этот пробел, объединив преимущества обоих подходов. В настоящей статье представлен инструмент-новинка под названием индикатор Импульс с поправкой на волатильность (Volatility Adjusted Momentum, VAM), позволяющий измерить динамику рынка, принимая во внимание лежащую в его основе волатильность. По сравнению с обычными индикаторами импульсов, он даёт более подробную картину динамики рынка. VAM направлен на предоставление более надежных сигналов в различных рыночных сценариях, от спокойных до штормовых, путем учета волатильности.
Для улучшения индикатора VAM мы используем условную модель LSTM, которая представляет собой тип рекуррентной нейронной сети, специально предназначенной для обработки последовательных данных с дополнительными контекстуальными данными. Поскольку эта модель обучена на основе исторических ценовых данных и технических индикаторов, она может выявлять сложные нелинейные рыночные связи, которые могут быть упущены обычными методами анализа. Из-за "условной" характеристики LSTM модель может учитывать больше рыночных переменных, что может привести к более точным прогнозам, учитывающим контекст.
Советник (EA), специально разработанная автоматическая торговая система, сочетающая в себе индикатор VAM и прогнозы от условной модели LSTM, является «мозгом», стоящим за нашей стратегией. Используя сигналы от обоих компонентов, этот советник интегрирован в известную платформу MetaTrader 5, чтобы трейдеры могли принимать достаточно обоснованные решения. Кроме того, он обладает возможностями динамического управления рисками, которые изменяют уровни тейк-профита и стоп-лосса в ответ на колебания рынка.
В настоящей публикации мы рассмотрим теоретические основы моделей индикаторов: условной LSTM и VAM; дадим представление об их соответствующих преимуществах и способах их наилучшего взаимодействия. Мы рассмотрим каждый этап создания и внедрения советника на практике, включая настройку данных, обучение модели и ее интеграцию в среду MetaTrader 5. Кроме того, продемонстрируем результаты комплексной оптимизации и бэк-тестирования, сравнивая эффективность метода, использующего только VAM, с комбинированным методом, использующим VAM и условную LSTM.
Поговорим о трудностях и факторах, связанных с сочетанием передовых методов машинного обучения с традиционным техническим анализом, по мере исследования этой торговой стратегии-новинки. Мы стремимся предложить подробный обзор практических элементов внедрения такой системы, включая все, начиная от качества данных и интерпретируемости моделей и заканчивая вычислительными требованиями, необходимыми для запуска сложных моделей в торговых ситуациях в режиме реального времени.
К концу данной публикации читатели получат полное представление о том, как передовые методы машинного обучения могут быть использованы для дополнения традиционного технического анализа и потенциального улучшения результатов сделок. Настоящее исследование VAM и условной LSTM в автоматизированной торговле предлагает ценную информацию о будущем алгоритмической торговли, независимо от того, являетесь ли вы трейдером, специалистом по обработке данных или исследователем, изучающим границы финансовой математики.
Импульс с поправкой на волатильность (Volatility Adjusted Momentum, VAM)
Основная концепция, лежащая в основе VAM, заключается в учете волатильности рынка при оценке динамики. Он вычисляет разницу между текущей ценой и прошлой ценой (импульс, динамика), а затем делит ее на произведение волатильности и квадратного корня из периода импульса. Это значение, умноженное на коэффициент, указывает на силу импульса, скорректированного с учетом недавней волатильности рынка.
Модель глубокого обучения
В статье используется условная модель LSTM, тип рекуррентной нейронной сети (RNN), подходящей для обработки финансовых данных временных рядов. Эта модель использует исторические ценовые данные и технические индикаторы (например, используемый здесь MACD) в качестве входных данных и прогнозирует будущие движения цен. Преимущество условных LSTM заключается в их способности улавливать сложные взаимосвязи между различными рыночными факторами.
Советник (EA)
В статье описано создание советника, сочетающего в себе прогнозы модели глубокого обучения с VAM. Ниже приведено краткое описание основных функций:
- Инициализация: Советник загружает и настраивает входные и выходные параметры для предварительно обученной модели глубокого обучения ONNX.
- Сбор и нормализация данных: Советник собирает показания MACD и предыдущие ценовые данные. Прежде чем включить эти переменные в модель глубокого обучения, он нормализует их.
- Расчет VAM: Используя исторические и текущие ценовые данные, советник рассчитывает индикатор VAM.
- Торговая логика и прогнозирование: Советник извлекает ценовой прогноз из модели глубокого обучения.
- Советник начинает сделку на покупку, если VAM высок и прогноз указывает на повышение цены.
- И напротив, советник открывает сделку на продажу, если VAM низкий, а прогноз показывает падение цены.
Советник управляет рисками, динамически определяя уровни стоп-лосса и тейк-профита на основе среднего истинного диапазона (ATR).
Результаты:
В статье упоминаются результаты тестирования на исторических данных для советника с использованием VAM со стратегией условной LSTM и без нее.
Создадим новый индикатор (VAM)
Что, если мы создадим новый индикатор, например, этот:
// Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000;
Для создания нового индикатора мы будем использовать Импульс и Волатильность. Этот индикатор будет называться VAM.
Импульс делится на произведение квадратного корня периода импульса и волатильности.
Для масштабирования полученный результат затем умножается на 10 000.
Учитывая волатильность, индикатор VAM стремится количественно оценить динамику. Он пытается выровнять динамику в различных рыночных условиях путем деления динамики на волатильность. Квадратный корень из знаменателя периода импульса помогает стандартизировать индикатор на протяжении различных периодов времени.
Положительное значение VAM указывает на восходящий импульс, в то время как отрицательное значение указывает на нисходящий импульс. Величина VAM отражает силу импульса, скорректированного с учетом недавней волатильности рынка.
Этот индикатор может быть использован для выявления потенциальных разворотов тренда или для оценки силы текущих рыночных тенденций при учете волатильности рынка.
Используя только этот индикатор, мы можем создать советник и проверить является ли он прибыльным.
Стратегия будет выглядеть следующим образом:
void OnTick() { int bars = iBars(NULL, 0); if(bars < MathMax(momentum_period, MathMax(volatility_period, (vam_period))))//, MathMax(ma_long_period, rsi_period))))) return; double close_price = iClose(NULL, 0, 0); // Calcular Momentum double momentum = close_price - iClose(NULL, 0, momentum_period); // Calcular Volatilidad double volatility = iMA(NULL, 0, volatility_period, 0, MODE_SMA, PRICE_CLOSE); // Calcular VAM double vam =( momentum / (volatility * MathSqrt(momentum_period)))*10000; double atr = iATR(_Symbol,PERIOD_CURRENT,14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul*atr,_Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul*atr,_Digits); double slPriceSell = NormalizeDouble(Ask + slmul*atr,_Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul*atr,_Digits); // Señales if(vam > VAMTHRESH)// && ma_short > ma_long)// && rsi < 70 && ma_short > ma_long ) { // Comprar trade.Buy(lot_size,_Symbol, Ask, slPriceBuy, tpPriceBuy, " BUY EA "); } else if(vam < -VAMTHRESH)// && ma_short < ma_long)// rsi > 30 && ma_short < ma_long ) { // Vender trade.Sell(lot_size,_Symbol, Bid, slPriceSell, tpPriceSell, " SELL EA "); } }
Функция iBars(NULL, 0) выдает общее количество баров, доступных для данного инструмента и таймфрейма.
bars int: Общее количество баров или возвращаемое значение сохраняется в переменной bars.
MathMax: Данная функция возвращает максимальное значение из введенных чисел. В этом случае nested используется для определения максимального значения за множество периодов времени.
Установленные ранее переменные momentum_period, volatility_period, vam_period, ma_long_period и rsi_period указывают интервалы между различными индикаторами или вычислениями.
Если: Это условие определяет, будет ли общее количество баров меньше суммы назначенных периодов времени.
Если условие "if" является истинным (т.е. баров недостаточно), функция немедленно останавливается и остальной код не выполняется.
Результаты VAM
Результаты таковы (после быстрой оптимизации я его не закончил):
Это решение кажется приемлемым для простой стратегии и простого индикатора.
Давайте посмотрим, чего мы могли бы достичь, если бы использовали для этого модель глубокого обучения (но сегодня мы будем использовать кое-что другое). Мы создадим модель глубокого обучения с некоторыми индикаторами, чтобы понять, что подходит лучше.
Модели глубокого обучения
Мы экспортируем эту модель в ONNX, но сначала сравним, какая из них лучше.
Чтобы сделать все это, мы будем использовать Google Colab (чтобы не расходовать ресурсы наших ПК) с его прилагаемым Python-скриптом.
Поскольку это веб-сайт на mql5, я не буду объяснять код на python.
Существует два py-скрипта: первый - это py-скрипт, в котором используются все индикаторы, а второй - тот же скрипт, но только с индикатором MACD (поскольку в первом скрипте мы предположили, что MACD имеет хороший уровень попадания и R2, с низким уровнем ошибок.
Графические результаты работы первого скрипта таковы:
Решив использовать MACD, мы подготовили скрипт и установили даты на первое января 2024 года (чтобы можно было протестировать на исторических данных результаты на mql5 с 01/01/2024 и далее).
Результаты второго скрипта были такими (очень похожими).
и т.д. (вы можете выполнить его самостоятельно и проверить результаты с помощью colab).
Скрипт на python предназначен для Colab, вы должны сначала запустить первую ячейку, а когда все библиотеки будут установлены, запустить вторую ячейку, принять ее, чтобы сохранить модели и графики на вашем диске, и просто дождаться завершения.
Данные получены из mql5, поскольку MetaTrader не установлен в Colab (значения должны быть аналогичными).
Как можно увидеть на второй группе изображений, модель MACD имеет действительно хороший уровень попадания, именно поэтому мы выбрали ее.
Условная LSTM
Усовершенствованная версия обычной нейронной сети с долгой кратковременной памятью называется условная LSTM. Добавляя больше контекстуальных данных или ситуаций в процесс прогнозирования архитектуры LSTM, мы улучшаем его. Поскольку на изменение цен на финансовых рынках может влиять множество факторов, это особенно интересно для прогнозирования финансовых рынков.Эффективным инструментом в области прогнозирования на фондовом рынке или рынке Форекс является условная логистическая регрессионная машина. Она позволяет модели учитывать различные рыночные индикаторы и внешние переменные в дополнение к прошлым ценовым данным. Она может включать в себя данные о настроениях, более общие экономические показатели и технические индикаторы, такие как RSI или скользящие средние. Цель модели - обеспечить более полную картину динамики рынка за счет интеграции этих многочисленных вводных данных.
Контекстуальная осведомленность является одним из основных преимуществ использования условной LSTM для финансового прогнозирования. Финансовые рынки - это сложные системы, на которые воздействует широкий спектр переменных. Поскольку условная LSTM может комбинировать несколько индикаторов, она может быть способна выявить сложные взаимосвязи между многочисленными динамиками рынка. Её способность управлять как статическими характеристиками, так и данными временных рядов делает её подходящей для финансовых рынков, где прошлые тенденции и текущие обстоятельства одинаково важны.
Кроме того, условные LSTM, как и обычные LSTM, превосходно фиксируют долгосрочные зависимости в данных временных рядов. Это особенно удобно на финансовых рынках, где могут проявляться долгосрочные паттерны. Данная модель может обнаруживать паттерны, которые могут быть пропущены более простыми моделями, благодаря своей способности сохранять соответствующую информацию в расширенных последовательностях.
Тем не менее, использование условной LSTM для финансового прогнозирования сопряжено с определенными трудностями. Несмотря на то, что бОльшая сложность модели может иметь свои преимущества, она также представляет сложности. Переобучение становится все более вероятным по мере усложнения обучения, в частности, при работе с небольшими наборами данных. Из-за такой сложности возникают более высокие вычислительные затраты, что может быть основным фактором в приложениях для торговли в режиме реального времени.
Качество и актуальность данных становятся еще более важными при использовании условных LSTM. Модель требует не только данных о ценах, но и высококачественных, актуальных данных индикаторов. Обеспечение согласованности и точности данных по всем этим аспектам может быть сложной задачей в быстро меняющемся и порой непрозрачном мире финансовых рынков.
При оценке потенциала условных LSTM также важно учитывать фундаментальную природу финансовых рынков. На рынки влияют непредсказуемые события и поведение людей, что может ограничить эффективность любой прогностической модели, какой бы сложной она ни была. Модель может превосходно выявлять паттерны в исторических данных, но испытывать трудности при столкновении с беспрецедентными рыночными условиями или серьезными экономическими потрясениями.
Другой проблемой, связанной с условными LSTM, как и со многими моделями глубокого обучения, является интерпретируемость. Даже несмотря на то, что эти модели могут давать точные прогнозы, бывает трудно понять причины, стоящие за ними. Такой аспект, как "черный ящик", может вызвать проблемы в финансовых приложениях, где часто важна объяснимость и открытость.
И, наконец, несмотря на то, что условные LSTM обладают интересными возможностями для прогнозирования фондовых и валютных курсов на основе индикаторов, важно подходить к ним вдумчиво. Их способность включать сложные, многогранные данные может привести к более точным и детализированным прогнозам. Однако их следует использовать как компонент более комплексного, тщательно продуманного аналитического подхода из-за трудностей, связанных с растущей сложностью, требованиями к данным, а также внутренней непредсказуемостью финансовых рынков, глубоким пониманием ограничений модели в практических ситуациях и тщательным бэк-тестированием. Применение таких передовых методов в сфере финансовой торговли с высокими ставками требует тщательного бэк-тестирования и знания ограничений модели в практических условиях.
Модель (выполненная в py-скрипте) выглядит следующим образом:
а её входящие и исходящие данные должны выглядеть следующим образом:
Код советника
Основная цель данного советника (EA) - автоматизировать принятие торговых решений на основе сочетания технических индикаторов и прогнозов, основанных на модели глубокого обучения (ONNX). В советнике используется индикатор Импульс с поправкой на волатильность (Volatility Adjusted Momentum, VAM) и MACD (Moving Average Convergence Divergence, Индикатор схождения-расхождения скользящих средних), а также прогнозы цен, сделанные с помощью модели машинного обучения. Он совершает сделки в зависимости от комбинации этих элементов.
Советник начинает с определения нескольких свойств и библиотек. Класс "CTrade" включен для совершения сделок, а другие заголовки - для статистических функций и управления массивами. Для расчета VAM и исполнения сделки определяются входные параметры, такие как `momentum_period`, `volatility_period` и `vam_period`, которые используются для управления логикой расчета импульса и волатильности. Здесь также определяются торговые параметры, такие как `lot_size`и множители для стоп-лосса (`slmul`) и тейк-профита (`tpmul`), что обеспечивает гибкость в работе советника. Кроме того, константы, определяющие параметры модели ONNX, такие как `BATCH_SIZE`, `SEQUENCE_LENGTH` и другие, включены для управления тем, как данные передаются в модель глубокого обучения.
//+------------------------------------------------------------------+ //| VAM + DL(MACD) EA | //| Copyright 2024, Javier Santiago Gaston de Iriarte Cabrera | //| https://www.mql5.com/en/users/jsgaston/news | //+------------------------------------------------------------------+ #property copyright "Javier Santiago Gaston de Iriarte Cabrera" #property link "https://www.mql5.com/en/users/jsgaston/news" #property version "1.01" #include <Trade\Trade.mqh> #include <Math\Stat\Math.mqh> #include <Arrays\ArrayFloat.mqh> CTrade trade; // Inputs input int momentum_period = 13; input int volatility_period = 7; input int vam_period = 9; input double lot_size = 0.01; input int slippage = 3; input double VAMTHRESH = 9.0; input int slmul = 2; input int tpmul = 4; // ONNX model parameters #define BATCH_SIZE 1 #define SEQUENCE_LENGTH 30 #define INPUT_FEATURES 3 #define CONDITION_FEATURES 2 #define HIDDEN_DIM 128 #define NUM_LAYERS 2 float input_x[][SEQUENCE_LENGTH][INPUT_FEATURES]; float input_condition[][CONDITION_FEATURES]; float h0[][BATCH_SIZE][HIDDEN_DIM]; float c0[][BATCH_SIZE][HIDDEN_DIM]; #define PRICE_UP 0 #define PRICE_SAME 1 #define PRICE_DOWN 2 long ExtHandle = INVALID_HANDLE; int ExtPredictedClass = -1; datetime ExtNextBar = 0; datetime ExtNextDay = 0; float ExtMin = 0.0; float ExtMax = 1.0; // Initialize to 1.0 to prevent division by zero float predicted_last; #resource "/Files/stock_prediction_model_MACD.onnx" as uchar ExtModel[]
Функция инициализации `OnInit()` является критически важной, поскольку загружает модель ONNX из двоичного ресурса (`stock_prediction_model_MACD.onnx`), настраивая входную и выходную формы модели. Входные данные для модели ONNX состоят из исторических ценовых данных, значений MACD и инициализированных скрытых состояний и состояний ячеек (`h0`, `c0`) для повторяющихся уровней модели. Если модель загружена успешно, функция также инициализирует минимальное и максимальное значения цены (`ExtMin` и `ExtMax`), которые будут использоваться для приведения входных данных в соответствие с моделью ONNX. Если во время загрузки модели возникает какая-либо ошибка, она возвращает `INIT_FAILED`, действенно останавливая работу советника.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("BATCH_SIZE: ", BATCH_SIZE, ", CONDITION_FEATURES: ", CONDITION_FEATURES); ExtHandle = OnnxCreateFromBuffer(ExtModel,ONNX_DEFAULT); if(ExtHandle == INVALID_HANDLE) { Print("OnnxCreateFromBuffer error ", GetLastError()); return(INIT_FAILED); } // Set input shapes long input_shape[] = {BATCH_SIZE, SEQUENCE_LENGTH, INPUT_FEATURES}; if(!OnnxSetInputShape(ExtHandle, ONNX_DEFAULT, input_shape)) { Print("OnnxSetInputShape for input_x error ", GetLastError()); return(INIT_FAILED); } long condition_shape[] = {BATCH_SIZE,CONDITION_FEATURES}; if(!OnnxSetInputShape(ExtHandle, 1, condition_shape)) { Print("OnnxSetInputShape for input_condition error ", GetLastError()); return(INIT_FAILED); } long h0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 2, h0_shape)) { Print("OnnxSetInputShape for h0 error ", GetLastError()); return(INIT_FAILED); } long c0_shape[] = {NUM_LAYERS, BATCH_SIZE, HIDDEN_DIM}; if(!OnnxSetInputShape(ExtHandle, 3, c0_shape)) { Print("OnnxSetInputShape for c0 error ", GetLastError()); return(INIT_FAILED); } const long output_shape[] = {1,1}; if(!OnnxSetOutputShape(ExtHandle,0,output_shape)) { Print("OnnxSetOutputShape error ",GetLastError()); return(INIT_FAILED); } // Initialize ExtMin and ExtMax GetMinMax(); Print("Initializing EA with VAM and ONNX integration"); return(INIT_SUCCEEDED); }
Функция `OnTick()` - это основная логика, которая запускается при каждом ценовом тике. Она начинается с проверки того, что сегодня новый день, и используя `GetMinMax()` обновляет минимальные и максимальные цены соответственно. Следующий блок гарантирует, что функция будет работать только при появлении нового ценового бара. Затем советник обновляет переменные `ExtMin` и `ExtMax` до самых последних значений цены. В основе данной функции лежит комбинация расчета VAM и прогнозирования ONNX. VAM рассчитывается путем взятия разницы в цене (импульсе) и деления ее на произведение волатильности и квадратного корня из `momentum_period`, умноженного на 10 000. Если VAM превышает пороговое значение (`VAMTHRESH`), это указывает на сильную тенденцию на рынке, сигнализируя о потенциальной сделке.
Затем советник объединяет прогноз и результаты VAM. Если VAM высокий (больше, чем `VAMTHRESH`) а модель ONNX прогнозирует рост цены, советник открывает сделку на покупку с рассчитанными стоп-лоссом и тейк-профитом на основе среднего истинного диапазона (ATR). Аналогично, если VAM низкий (ниже отрицательного значения `VAMTHRESH`), а модель ONNX предсказывает снижение цены, советник открывает сделку на продажу. Эти сделки совершаются с использованием класса `CTrade`, взаимодействующего с торговыми функциями платформы MetaTrader 5.
С точки зрения управления рисками, уровни стоп-лосса и тейк-профита рассчитываются динамически на основе ATR актива. Это гарантирует, что стратегия адаптируется к волатильности рынка, обеспечивая более гибкие торговые выходы в зависимости от текущих рыночных условий.void OnTick() { // Check for new day and update ExtMin and ExtMax if(TimeCurrent() >= ExtNextDay) { GetMinMax(); ExtNextDay = TimeCurrent() - TimeCurrent() % PeriodSeconds(PERIOD_D1) + PeriodSeconds(PERIOD_D1); } // Check for new bar if(TimeCurrent() < ExtNextBar) return; ExtNextBar = TimeCurrent() - TimeCurrent() % PeriodSeconds() + PeriodSeconds(); // Update ExtMin and ExtMax double close = iClose(_Symbol, _Period, 0); if(ExtMin > close) ExtMin = (float)close; if(ExtMax < close) ExtMax = (float)close; int bars = iBars(_Symbol, PERIOD_CURRENT); if(bars < MathMax(momentum_period, MathMax(volatility_period, MathMax(vam_period, SEQUENCE_LENGTH)))) return; // Calculate VAM double momentum = close - iClose(_Symbol, PERIOD_CURRENT, momentum_period); double volatility = iStdDev(_Symbol, PERIOD_CURRENT, volatility_period, 0, MODE_SMA, PRICE_CLOSE); double vam = (momentum / (volatility * MathSqrt(momentum_period))) * 10000; Print("VAM ", vam); // Get ONNX prediction int result=GetPrediction(); // Trading logic combining VAM and ONNX prediction double atr = iATR(_Symbol, PERIOD_CURRENT, 14)*_Point; double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); double slPriceBuy = NormalizeDouble(Bid - slmul * atr, _Digits); double tpPriceBuy = NormalizeDouble(Ask + tpmul * atr, _Digits); double slPriceSell = NormalizeDouble(Ask + slmul * atr, _Digits); double tpPriceSell = NormalizeDouble(Bid - tpmul * atr, _Digits); //Print(result); if(vam > VAMTHRESH && result == 0) { trade.Buy(lot_size, _Symbol, Ask, slPriceBuy, tpPriceBuy, "BUY VAM+ONNX"); } else if(vam < -VAMTHRESH && result == 2) { trade.Sell(lot_size, _Symbol, Bid, slPriceSell, tpPriceSell, "SELL VAM+ONNX"); } }
Прогноз модели ONNX извлекается путем вызова функции `GetPrediction()`. Входные данные для модели подготавливаются функцией `PrepareInputs()`, которая собирает исторические цены закрытия и данные MACD, нормализует их, используя диапазон цен (`ExtMin` и `ExtMax`), и заполняет входные массивы, ожидаемые моделью. Она устанавливает данные для входной последовательности цен (`input_x`) и основанных на MACD условий (`input_condition`), одновременно сбрасывая скрытые состояния (`h0`, `c0`). Как только входные данные готовы, модель запускается функцией `OnnxRun()`, которая вычисляет прогнозируемую цену. Разница между прогнозируемой ценой и последней прогнозируемой ценой используется для определения того, ожидает ли модель, что цена будет двигаться вверх, вниз или останется прежней. Если изменение в прогнозе слишком незначительно, модель предполагает отсутствие изменений (цена остается прежней).
void PrepareInputs() { ArrayResize(input_x, BATCH_SIZE); ArrayResize(input_condition, BATCH_SIZE); ArrayResize(h0, NUM_LAYERS); ArrayResize(c0, NUM_LAYERS); for(int i = 0; i < SEQUENCE_LENGTH; i++) { input_x[0][i][0] = (float)((iClose(_Symbol, PERIOD_CURRENT, i) - ExtMin) / (ExtMax - ExtMin)); double macd_main[], macd_signal[]; int macd_handle = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle, 0, i, 1, macd_main); CopyBuffer(macd_handle, 1, i, 1, macd_signal); input_x[0][i][1] = (float)((macd_main[0] - ExtMin) / (ExtMax - ExtMin)); input_x[0][i][2] = (float)((macd_signal[0] - ExtMin) / (ExtMax - ExtMin)); } double macd_main2[], macd_signal2[]; int macd_handle2 = iMACD(_Symbol, PERIOD_CURRENT, 12, 26, 9, PRICE_CLOSE); CopyBuffer(macd_handle2, 0, 0, 1, macd_main2); CopyBuffer(macd_handle2, 1, 0, 1, macd_signal2); input_condition[0][0] = (float)macd_main2[0]; input_condition[0][1] = (float)macd_signal2[0]; ArrayInitialize(h0, 0.0f); ArrayInitialize(c0, 0.0f); } //+------------------------------------------------------------------+ //| Get prediction from ONNX model | //+------------------------------------------------------------------+ int GetPrediction() { PrepareInputs(); float output_data[]; ArrayResize(output_data, 1); // Run the ONNX model if(!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, input_x, input_condition, h0, c0, output_data)) { Print("OnnxRun error: ", GetLastError()); return ExtPredictedClass = -1; } float predicted=output_data[0]*(ExtMax-ExtMin)+ExtMin; Print("Predicted last ", predicted_last); Print("Predicted ",predicted); float last_close = (float)iClose(_Symbol, PERIOD_CURRENT, 0); Print("last close ",last_close); float delta = predicted_last - predicted; predicted_last=predicted; Print("Delta ",delta); if(MathAbs(delta) <= 0.00001) ExtPredictedClass = PRICE_SAME; else if(delta < 0) ExtPredictedClass = PRICE_UP; else ExtPredictedClass = PRICE_DOWN; Print(ExtPredictedClass); return ExtPredictedClass; }
Функция `GetMinMax()` отвечает за установку минимального (`ExtMin`) и максимального (`ExtMax`) значений цены за последний день хранения данных. Эти значения используются для нормализации входных данных перед передачей их в модель ONNX, гарантируя, что модель получает входные данные в согласованном диапазоне. Если советнику не удается получить необходимые ценовые данные, он по умолчанию устанавливает безопасный диапазон, чтобы избежать деления на ноль.
void GetMinMax() { double close[]; int copied = CopyClose(_Symbol, PERIOD_D1, 0, SEQUENCE_LENGTH, close); if(copied > 0) { ExtMin = (float)MathMin(close); ExtMax = (float)MathMax(close); } else { Print("Failed to copy price data. Error: ", GetLastError()); ExtMin = 0; ExtMax = 1; // Prevent division by zero } }
Наконец, советник включает функцию деинициализации `OnDeinit()`, освобождающую хэндл модели ONNX при удалении советника, обеспечивая правильное управление памятью и предотвращая утечку ресурсов.
void OnDeinit(const int reason) { if(ExtHandle != INVALID_HANDLE) { OnnxRelease(ExtHandle); ExtHandle = INVALID_HANDLE; } }
Таким образом, этот советник сочетает технический анализ (с помощью VAM и MACD) с прогнозами машинного обучения на основе модели ONNX для принятия обоснованных автоматических торговых решений. Технический анализ помогает определить тенденции, в то время как модель машинного обучения прогнозирует движение цены, что приводит к созданию гибридной стратегии.
Результаты
После оптимизации
Заключение
В этой статье рассматривается интеграция глубокого обучения, в частности условных LSTM моделей, с индикатором Импульс с поправкой на волатильность (Volatility Adjusted Momentum, VAM) для улучшения автоматизированных торговых систем. Данная стратегия, объединяя прогностические возможности LSTM и чувствительный к волатильности динамический анализ VAM, нацелена на учет сложной динамики рынка. Данная система, реализованная в MetaTrader 5, генерирует торговые сигналы и динамически адаптирует управление рисками.
При сочетании LSTM с VAM бэктестирование демонстрирует улучшенные результаты. Несмотря на такие проблемы, как переобучение и вычислительные требования, исследование показывает, что интеграция глубокого обучения с техническим анализом может значительно улучшить алгоритмические торговые стратегии.
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/15956
Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.
Данная статья написана пользователем сайта и отражает его личную точку зрения. Компания MetaQuotes Ltd не несет ответственности за достоверность представленной информации, а также за возможные последствия использования описанных решений, стратегий или рекомендаций.





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Привет, Хавьер
Спасибо за ответ.
Я нашел проблему. Вы назвали "stock_prediction_model_MACD.onnx" в советнике, но в zip-файлах он назван как stock_prediction_model_MACD_Signal.onnx
Также я заметил в коде неуместное использование хэндла индикатора (ошибка!!!). Вы использовали
В MQL5 значения индикаторов выводятся с помощью CopyBuffer и индикаторного хэндла, который вы использовали в
Не могли бы вы пояснить, почему для получения значений в первом случае использовался другой хэндл, а не двойная переменная?С уважением и хороших выходных.
Вы полностью правы!
Я допустил ошибку, спасибо, что указали на это.
Вы должны использовать copybuffer и handle.
Здравствуйте Хавьер
Спасибо за эту замечательную статью, ваш бот использует соотношение риска и вознаграждения 135:20, что делает его рискованным. Когда я пробую подходящее соотношение, например 1:2 или 1:3, его бот проигрывает. Любые предложения о том, как я могу сделать его лучше с правильным соотношением риска и вознаграждения.
Здравствуйте, Хавьер
Спасибо за эту замечательную статью, ваш бот использует соотношение риска и вознаграждения 135:20, что делает его рискованным. Когда я пробую подходящее соотношение, например 1:2 или 1:3, его бот проигрывает. Любые предложения о том, как я могу сделать его лучше с правильным соотношением риска и вознаграждения.
Привет, думаю, я не слишком ясно выразил, что этот пример служит только для того, чтобы показать, что вы можете использовать LSTM не только с OHLC. Просто не используйте этот пример для торговли.
Привет, Хавьер
как убедиться, что этот параметр VAMTHRESH имеет значение?
.
Исправление: Измените значение index + window_size - 1 для условий, чтобы использовать только последние доступные данные.
Влияние: Реальные результаты будут составлять ~48-52%, а не 80-90%. Эти результаты не пригодны для торговли на реальных рынках.