Подключение нейросетей от NeuroSolutions
Введение
Наверняка, все трейдеры при знакомстве с нейронными сетями думают о том, как было бы здорово применить нейросети для анализа рынка. Есть много программ, позволяющих в удобной визуальной форме создавать свои сети любой конфигурации, обучать и тестировать их. Можно выгрузить из терминала нужные данные, загрузить их в нейросетевую программу и там проанализировать.
Но как быть, если хочется построенную нейросеть использовать для автоматической торговли? Возможно ли сделать так, чтобы советник в терминале сам обращался к нейросети и торговал в реальном времени?
Да, это возможно. Некоторые нейросетевые программы имеют необходимые программные интерфейсы. Одна из таких программ называется NeuroSolutions. Последняя ее версия - 6-я, но она еще есть не у всех, а вот версией 5 пользуются многие. Поэтому в статье будет рассмотрено взаимодействие именно с 5-й версией. Нужен полный дистрибутив программы, туда входит Custom Solution Wizard, он нам понадобится.
Придумываем стратегию
Стратегия для нашего тестового примера будет простой. Назовем ее WeekPattern. На таймфрейме D1 с помощью нейросети она будет в начале текущего бара прогнозировать цену его закрытия. И в зависимости от этого будет открывать BUY или SELL и держать эту сделку весь день. Прогноз цены будет основываться на OHLC-значениях предыдущих 5-ти баров. Для повышения точности работы нейросети мы будем подавать в нее не сами цены, а лишь их изменения относительно цены открытия текущего (нулевого) бара.
Готовим обучающие данные
Прежде чем приступить к созданию сети, напишем MQL5-скрипт, который выгрузит из терминала котировки в нужном нам виде. Эти данные понадобятся чтобы обучить нейросеть. Выгрузка будет проводиться в текстовый файл. В первой его строке через запятую перечислим названия полей. А в следующих строках пойдут данные, разделенные запятой. Каждая строка - это одна комбинация входов и выходов нейросети. В нашем случае скрипт на каждой строке будет сдвигаться по ценовой истории в прошлое на один бар и записывать в строку OHLC-значения 6-ти баров (5 баров из прошлого - это входы, и один бар текущий - это выход).
Этот скрипт WeekPattern-Export.mq5 нужно запускать на нужном таймфрейме нужной валютной пары (в нашем примере это D1 EURUSD). В настройках указывается имя файла и сколько строк нужно (для D1 260 строк - это история примерно за 1 год). Полный код скрипта:
#property script_show_inputs //+------------------------------------------------------------------+ input string Export_FileName = "NeuroSolutions\\data.csv"; // Файл для экспорта (в папке "MQL5\Files") input int Export_Bars = 260; // Кол-во строк данных для экспорта //+------------------------------------------------------------------+ void OnStart() { // Создадим файл int file = FileOpen(Export_FileName, FILE_WRITE|FILE_CSV|FILE_ANSI, ','); if (file != INVALID_HANDLE) { // Запишем заголовок данных string row=""; for (int i=0; i<=5; i++) { if (StringLen(row)) row += ","; row += "Open"+i+",High"+i+",Low"+i+",Close"+i; } FileWrite(file, row); // Скопируем все нужные данные из истории MqlRates rates[], rate; int count = Export_Bars + 5; if (CopyRates(Symbol(), Period(), 1, count, rates) < count) { Print("Ошибка! Недостаточный размер истории для экспорта нужных данных."); return; } ArraySetAsSeries(rates, true); // Запишем данные for (int bar=0; bar<Export_Bars; bar++) { row=""; double zlevel=0; for (int i=0; i<=5; i++) { if (StringLen(row)) row += ","; rate = rates[bar+i]; if (i==0) zlevel = rate.open; // уровень отсчета цен row += NormalizeDouble(rate.open -zlevel, Digits()) + "," + NormalizeDouble(rate.high -zlevel, Digits()) + "," + NormalizeDouble(rate.low -zlevel, Digits()) + "," + NormalizeDouble(rate.close-zlevel, Digits()); } FileWrite(file, row); } FileClose(file); Print("Экспорт данных завершен успешно."); } else Print("Ошибка! Не удалось создать файл для экспорта данных. ", GetLastError()); } //+------------------------------------------------------------------+
После выгрузки данных получим файл data.csv, первые строки (для примера) выглядят примерно так:
Open0,High0,Low0,Close0,Open1,High1,Low1,Close1,Open2,High2,Low2,Close2,Open3,High3,Low3,Close3,Open4,High4,Low4,Close4,Open5,High5,Low5,Close5 0,0.00463,-0.0041,0.00274,-0.00518,0.00182,-0.00721,-6e-005,0.00561,0.00749,-0.00413,-0.00402,0.02038,0.02242,0.00377,0.00565,0.03642,0.0379,0.01798,0.02028,0.0405,0.04873,0.03462,0.03647 0,0.007,-0.00203,0.00512,0.01079,0.01267,0.00105,0.00116,0.02556,0.0276,0.00895,0.01083,0.0416,0.04308,0.02316,0.02546,0.04568,0.05391,0.0398,0.04165,0.04504,0.05006,0.03562,0.0456 0,0.00188,-0.00974,-0.00963,0.01477,0.01681,-0.00184,4e-005,0.03081,0.03229,0.01237,0.01467,0.03489,0.04312,0.02901,0.03086,0.03425,0.03927,0.02483,0.03481,0.02883,0.04205,0.02845,0.03809
Это формат, который NeuroSolutions понимает. Теперь мы можем приступить к построению и обучению сети.
Создаем нейросеть
В NeuroSolutions можно быстро создать нейросеть, даже видя эту программу в первый раз и мало разбираясь в нейросетях. Для этого при старте программы выбираем визард для новичков - NeuralExpert (Beginner):
Укажем ему тип задачи, который должна решать наша сеть:
Дадим ему файл с обучающими данными, который мы создали в прошлой главе:
В качестве входов сети пометим все поля файла, кроме полей 0-го бара:
Текстовых полей у нас нет - ничего не отмечаем:
Снова даем наш файл с данными:
Помечаем один-единственный выход нашей сети:
По умолчанию визард предлагает построить наиболее простую сеть. Так и сделаем:
Визард завершил свою работу, создав нам сеть (еще не обученную, просто структуру):
Теперь мы с ней можем работать. Обучать, тестировать, использовать для анализа данных.
Если кликнуть на кнопку Test, то можно посмотреть, как необученная сеть справится с нашей задачей. Отвечаем на вопросы визарда тестирования:
Тестируем на данных всё из того же файла:
Тестирование завершилось. В окошке "Output vs. Desired Plot" появились графики, показывающие, какие значения выдает на нашей истории сеть (красный цвет), и какие там были значения на самом деле (синий цвет). Видно, что они сильно различаются:
Теперь сеть обучим. Для этого нужно кликнуть зеленую кнопку Start на панели под меню. Обучение завершится за несколько секунд и красный график изменится:
Теперь по графикам видно, что сеть выдает "что-то, похожее на правду". Можно теперь использовать ее для торговли. Сохраним сеть под именем WeekPattern.
Экспортируем нейросеть в DLL
Не выходя из NeuroSolutions, кликнем вверху кнопку CSW, которая запустит Custom Solution Wizard. Он нужен, чтобы сгенерировать из текущей нейросети DLL.
Визард может генерировать DLL для разных программ. Как я понял, для компиляции DLL ему в любом случае понадобится Visual C++ одной из версий: 5.0/6.0/7.0 (.NET 2002)/7.1
(.NET 2003)/8.0 (.NET 2005). Версии Express он почему-то не использует (я это проверял).
MetaTrader в списке целевых программ нет. Поэтому выберем Visual C++.
Куда сохранить результат:
Если всё прошло успешно, визард об этом сообщит:
И в папке, указанной при работе визарда, появится много файлов. Самые нужные нам: WeekPattern.dll, в нем находится наша нейросеть с программным интерфейсом к ней; и файл WeekPattern.nsw с настройками весов сети после обучения. Среди остальных файлов есть пример работы с этой DLL-нейросетью. В данном случае это проект на Visual C++ 6.
Подключаем DLL-нейросеть к MetaTrader
Созданная в предыдущей главе DLL-нейросеть предназначена для использования в проектах Visual C++. Она оперирует объектами сложной структуры, которые было бы тяжело или даже невозможно описать на MQL5. Поэтому подключать эту DLL напрямую к MetaTrader мы не будем. Вместо этого создадим небольшой DLL-переходник. В этом переходнике будет содержаться одна-единственная простая функция работы с нейросетью. Она будет создавать сеть, передавать ей данные на вход и возвращать данные с выходов.
К этому переходнику легко можно будет обращаться из MetaTrader 5. А переходник уже будет обращаться к DLL-нейросети от NeuroSolutions. Так как переходник будет написан на Visual C++, у него не будет проблем с объектами этой DLL.
Ну а если вы имеете опыт программирования на C++ и вам интересно, как создать такой переходник, читайте главу до конца. Возможно, в будущем вы захотите его усовершенствовать - ведь из DLL-нейросети можно экспортировать еще какие-нибудь функции. Например, функцию обучения (чтобы советник мог сам адаптироваться к меняющемуся рынку, автоматически переобучая сеть). Полный перечень функций вы можете узнать, изучив пример, который в предыдущей главе сгенерировал Custom Solution Wizard.
Нам пригодятся от этого примера некоторые файлы.
В Visual C++ (той же версии, которую использовал Custom Solution Wizard) создадим пустой проект DLL с именем NeuroSolutionsAdapter и скопируем в него из примера файлы NSNetwork.h, NSNetwork.cpp, StdAfx.h. Также создадим пустой файл main.cpp:
В main.cpp напишем следующий код:
#include "stdafx.h" #include "NSNetwork.h" extern "C" __declspec(dllexport) int __stdcall CalcNeuralNet( LPCWSTR dllPath_u, LPCWSTR weightsPath_u, double* inputs, double* outputs) { // Преобразуем строки из Unicode в обычные CString dllPath (dllPath_u); CString weightsPath (weightsPath_u); // Создание сети NSRecallNetwork nn(dllPath); if (!nn.IsLoaded()) return (1); // Загрузка весов if (nn.LoadWeights(weightsPath) != 0) return (2); // Подача входных данных и расчет выходов if (nn.GetResponse(1, inputs, outputs) != 0) return (3); return 0; }
Build. DLL-переходник готова!
Используем нейросеть в советнике
Итак, у нас уже имеется несколько созданных нами файлов. Перечислю, какие именно нужны для работы советника, и в какие папки их надо положить. Все эти файлы есть в приложении к статье.
Файл | Описание | Куда положить (внутри папки терминала) |
---|---|---|
WeekPattern.dll | наша DLL-нейросеть от NeuroSolutions | MQL5\Files\NeuroSolutions\ |
WeekPattern.nsw | настройки весов нашей нейросети | MQL5\Files\NeuroSolutions\ |
NeuroSolutionsAdapter.dll | универсальный DLL-переходник для любой DLL-нейросети | MQL5\Libraries\ |
Привожу полный код советника WeekPattern.mq5. Для удобства поиска и последующей модификации, я организовал в отдельный класс CNeuroSolutionsNeuralNet всё, что относится к нейросети.
input double Lots = 0.1; //+------------------------------------------------------------------+ // Подключаем DLL-переходник, через которую будем использовать DLL-нейросеть от NeuroSolutions #import "NeuroSolutionsAdapter.dll" int CalcNeuralNet(string dllPath, string weightsPath, double& inputs[], double& outputs[]); #import //+------------------------------------------------------------------+ class CNeuroSolutionsNeuralNet { private: string dllPath; // Путь к DLL-нейрости, созданной в NeuroSolutions string weightsPath; // Путь к файлу весов сети public: double in[20]; // Входы сети - OHLC 5 баров double out[1]; // Выход сети - Close текущего бара CNeuroSolutionsNeuralNet(); bool Calc(); }; //+------------------------------------------------------------------+ void CNeuroSolutionsNeuralNet::CNeuroSolutionsNeuralNet() { string terminal = TerminalInfoString(TERMINAL_PATH); dllPath = terminal + "\\MQL5\\Files\\NeuroSolutions\\WeekPattern.dll"; weightsPath = terminal + "\\MQL5\\Files\\NeuroSolutions\\WeekPattern.nsw"; } //+------------------------------------------------------------------+ bool CNeuroSolutionsNeuralNet::Calc() { // Получим текущие котировки для нейросети MqlRates rates[], rate; CopyRates(Symbol(), Period(), 0, 6, rates); ArraySetAsSeries(rates, true); // Заполним массив входных данных нейросети double zlevel=0; for (int bar=0; bar<=5; bar++) { rate = rates[bar]; // 0-й бар на вход сети не идет if (bar==0) zlevel=rate.open; // уровень отсчета цен // 1-5 бары идут на вход сети else { int i=(bar-1)*4; // номер входа in[i ] = rate.open -zlevel; in[i+1] = rate.high -zlevel; in[i+2] = rate.low -zlevel; in[i+3] = rate.close-zlevel; } } // Проведем расчет сети в DLL NeuroSolutions (через DLL-переходник) int res = CalcNeuralNet(dllPath, weightsPath, in, out); switch (res) { case 1: Print("Ошибка создания нейросети из DLL \"", dllPath, "\""); return (false); case 2: Print("Ошибка загрузки весов в нейросеть из файла \"", weightsPath, "\""); return (false); case 3: Print("Ошибка расчетов в нейросети"); return (false); } // Выход нейрости появился в массиве out, с ним ничего делать не надо return (true); } //+------------------------------------------------------------------+ CNeuroSolutionsNeuralNet NN; double Prognoze; //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> //+------------------------------------------------------------------+ void OnTick() { // Получим ценовой прогноз от нейросети if (NN.Calc()) Prognoze = NN.out[0]; else Prognoze = 0; // Осуществим необходимые торговые действия Trade(); } //+------------------------------------------------------------------+ void Trade() { // Закроем открытую позицию, если она против прогноза if(PositionSelect(_Symbol)) { long type=PositionGetInteger(POSITION_TYPE); bool close=false; if((type == POSITION_TYPE_BUY) && (Prognoze <= 0)) close = true; if((type == POSITION_TYPE_SELL) && (Prognoze >= 0)) close = true; if(close) { CTrade trade; trade.PositionClose(_Symbol); } } // Если позиций нет, то откроем по прогнозу if((Prognoze!=0) && (!PositionSelect(_Symbol))) { CTrade trade; if(Prognoze > 0) trade.Buy (Lots); if(Prognoze < 0) trade.Sell(Lots); } } //+------------------------------------------------------------------+
Хороший способ проверить, правильно ли мы подключили нейросеть, это прогнать советник в тестере на том же участке истории, где сеть обучалась.
Ведь сеть, как говорят опытные автотрейдеры, "подогнана" под этот участок. Т.е. она обучена распознавать и выдавать прибыльный сигнал именно на те паттерны данных, которые доминируют на данном конкретном
участке. График доходности советника на таком
участке как правило должен получаться растущим.
Проверим это. В нашем случае получился вот такой красивый график:
Значит, мы всё подключили правильно.
Ну и для статистики другие отчеты о тестировании советника:
На всякий случай поясню начинающим разработчикам торговых стратегий и нейросетей в частности.
Прибыльность советника на участке истории, который использовался для его оптимизации (обучения его нейросети), не говорит о том, что советник в целом прибыльный. То есть, не гарантирует его прибыльность на других участках. Там могут оказаться другие доминирующие паттерны.
По этим причинам я не стал приводить здесь результат форвард-тестирования полученного советника. Создание прибыльной торговой стратегии не являлось целью данной статьи. Цель статьи - рассказать, как нейросеть подключить к советнику.
Заключение
Теперь в арсенале трейдеров появился еще один мощный и легкодоступный инструмент автоматического анализа и торговли. Его использование, подкрепленное глубоким пониманием принципов и возможностей нейросетей, а также правил их обучения, позволит вам встать на путь создания прибыльных торговых советников.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Надеюсь кто-то еще просматривает этот раздел форума...
Подскажите в чем может быть проблемка...
2015.02.09 23:39:15 Core 1 2015.02.01 00:00:00 Cannot load 'D:\Program Files\Alpari Limited MT5\Tester\Agent-127.0.0.1-3000\MQL5\Libraries\NeuroSolutionsAdapter.dll'
но по указанному адресу есть эта библиотека, так же я ее размножил и по некоторым другим директориям указанным в руководстве по MQL5
:( непомогло, кто сталкивался с таким поведением тестера?
как я это делал без dll переходника:
ns-unit.mqh
где,
my-net.dll - библиотека, которую создаёт по вашей сети NeuroSolutions
Globals.h - файл, который прилагается к вашей библиотеке после создания (перед компиляцией MQL скрипта его положить в подпапку "my-net")
а это добавить в основную программу:
Далее, можно успешно пользоваться процедурами getResponse для чтения отклика сети по заданному входу и train для дообучения сети в реальном режиме.
Первым параметром для этих процедур будет всегда параметр pNeuralNetwork, в который записан адрес структуры сети.
Для процедуры train последние три параметра можно передавать нулевыми, если не требуется кросс-проверка.
Вот и всё. Проверено - работает :)
Надеюсь кто-то еще просматривает этот раздел форума...
С MQL5 всё понятно, огромное спасибо автору.
А вот кто поможет подключить dll-сеть к NinjaTrader (C#) ?
Сам разбираюсь, но осилить не могу. Помогите, плизз.
Может у кого на компе завалялась, скиньте, пожалуйста.