
Программируем режимы работы советника с помощью ООП
Введение
В данной статье речь пойдет о программировании режимов, в которых может работать MQL5-советник. Цель статьи - описать идею "каждому режиму – своя реализация". Такой подход, по мнению автора, позволяет выполнять задачи на разных этапах разработки торгового робота более эффективно.
Сначала рассмотрим, из каких этапов состоит разработка советника. Затем изучим режимы, в которых может работать советник в MetaTrader 5 и его вспомогательных приложениях. И в завершении предлагаю разработать иерархию классов для воплощения вышеуказанной идеи.
1. Этапы разработки
Разработка торгового робота (советника) – это многоаспектный процесс. Ключевыми здесь выступают 2 блока: алгоритмизация идеи и тестирование. Причем тестируется как торговая логика робота, так и сам код алгоритма.
Схематично этапы данного процесса можно представить так (рис.1).
Рис.1. Этапы разработки и внедрения торгового робота
Пятый этап "Алготрейдинг" венчает все усилия разработчика, программиста, аналитика и других специалистов, участвующих в этом деле. Чаще всего все эти роли выполняет один человек. Пусть это будет трейдер-программист.
Данную схему можно изменять и дополнять. На мой взгляд, она иллюстрирует самые важные моменты разработки робота. Циклический характер схемы указывает на то, что совершенствовать и видоизменять код робота можно на протяжении всей его жизни.
Отмечу, что на каждом этапе от разработчика требуются свои инструменты, знания и умения.
Мне представляется, что разработчик сталкивается с такой простой матрицей вариантов (рис.2).
Рис.2. Матрица вариантов
Ясно, что до пятого этапа "Алготрейдинг" должен дойти только тот робот, который реализует прибыльную торговую идею с качественным кодом.
2. Режимы в MQL5
MQL5-среда представляет возможности для работы с роботом в разных режимах. Всего их 7. Позже рассмотрим каждый.
С точки зрения типа файла программы можно выделить 2 группы:
- режимы, требующие файл исходного кода и исполняемый файл;
- режимы, требующие только исполняемый файл.
К первой группе относятся режимы отладки и профилирования.
Другой критерий для классификации режимов – это работа советника на потоке реальных котировок или исторических. С историческими котировками связаны все режимы тестирования.
Программным образом определяются 6 режимов. Исходя из результатов, можно сделать вывод о том, работает ли советник в обычном (релиз) режиме или нет. Готовая программа (файл с расширением *.ex5), которая и кодировалась с целью работы на финансовых рынках, будет работать именно в этом режиме. Готовая программа позволяет обратиться и к другим режимам в Тестере стратегий.
Создадим перечисление режимов работы MQL-программы под названием ENUM_MQL_MODE:
//+------------------------------------------------------------------+ //| MQL-режим | //+------------------------------------------------------------------+ enum ENUM_MQL_MODE { MQL_MODE_RELEASE=0, // Релиз MQL_MODE_DEBUG=1, // Отладка MQL_MODE_PROFILER=2, // Профилирование MQL_MODE_TESTER=3, // Тестирование MQL_MODE_OPTIMIZATION=4, // Оптимизация MQL_MODE_VISUAL=5, // Визуальное тестирование MQL_MODE_FRAME=6, // Сбор фреймов };
Позже оно понадобится для определения типа режима, в котором работает робот.
2.1. Функции определения и проверки режима
Напишем простую функцию, которая пройдется по всем режимам и выведет информацию в журнал.
//+------------------------------------------------------------------+ //| Проверка всех MQL-режимов | //+------------------------------------------------------------------+ void CheckMqlModes(void) { //--- если режим отладки if(MQLInfoInteger(MQL_DEBUG)) Print("Debug mode: yes"); else Print("Debug mode: no"); //--- если режим профилирования кода if(MQLInfoInteger(MQL_PROFILER)) Print("Profile mode: yes"); else Print("Profile mode: no"); //--- если режим тестирования if(MQLInfoInteger(MQL_TESTER)) Print("Tester mode: yes"); else Print("Tester mode: no"); //--- если режим оптимизации if(MQLInfoInteger(MQL_OPTIMIZATION)) Print("Optimization mode: yes"); else Print("Optimization mode: no"); //--- если режим визуального тестирования if(MQLInfoInteger(MQL_VISUAL_MODE)) Print("Visual mode: yes"); else Print("Visual mode: no"); //--- если режим сбора фреймов результатов оптимизации if(MQLInfoInteger(MQL_FRAME_MODE)) Print("Frame mode: yes"); else Print("Frame mode: no"); }
Давайте проверим для каждого режима работу этой функции. Можно вызывать эту функцию в обработчике OnInit.
Для целей тестирования создадим шаблон советника Test1_Modes_EA.mq5.
В input-параметрах сделаем возможность обозначения режима, в котором запускаемый советник будет работать. Здесь важно правильно указать режим, иначе информация будет неточной. Что в итоге и вышло.
Смотрим на релиз-режим.
CL 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Текущий режим: MQL_MODE_RELEASE QD 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Debug mode: no KM 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Profile mode: no EK 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no CS 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no RJ 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no GL 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Frame mode: no
Для релиз-режима флаги всех прочих режимов обнулены. Т.е. функция определила, что это не отладка (Debug mode: no), не профилирование (Profile mode: no) и т.д. Методом отрицания пришли к тому, что работаем в релизе.
Теперь обратимся к режиму отладки.
HG 0 17:27:47.709 Test1_Modes_EA (EURUSD.e,H1) Текущий режим: MQL_MODE_DEBUG LD 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Debug mode: yes RS 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Profile mode: no HE 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no NJ 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no KD 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no RR 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Frame mode: no
Режим отладки был идентифицирован верно.
В любом справочнике по программированию можно найти информацию о том, что отладка способствует поиску и локализации ошибок в коде. Также с ее помощью можно увидеть, чем и как "живет" программа. Более подробно с отладкой в MQL5-среде можно познакомиться в статье "Отладка программ на MQL5".
Данный режим чаще всего используется при формализации и алгоритмизации торговой идеи.
Программным образом отладку определяют с помощью макроса IS_DEBUG_MODE или функции MQLInfoInteger(), идентификатор MQL_DEBUG.
Переходим к режиму профилирования.
GS 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Текущий режим: MQL_MODE_PROFILER OR 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Debug mode: no GE 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Profile mode: yes QM 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no CE 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no FM 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no GJ 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Frame mode: no
Функция точно определила, что работали с Профилировщиком.
В этом режиме можно проверить, насколько быстро работает программа. Профилировщик выведет информацию о временных затратах на блоки программы. Предполагается, что такой инструмент сможет указать на узкие места алгоритма. Не всегда от них можно избавиться, но тем не менее, эта информация может быть полезной.
Программным образом профилирование определяют с помощью макроса IS_PROFILE_MODE или функции MQLInfoInteger(), идентификатор MQL_PROFILER.
Посмотрим теперь на режим тестирования. Информация появится на вкладке "Журнал" Тестера стратегий.
EG 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Текущий режим: MQL_MODE_TESTER OS 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Debug mode: no GJ 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Profile mode: no ER 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Tester mode: yes ED 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Optimization mode: no NL 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Visual mode: no EJ 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Frame mode: no
Режим тестирования был идентифицирован верно.
Этот режим работы советника появляется тогда, когда мы открываем Тестер стратегий.
Макроса для этого режима нет, поэтому средствами MQL5 его можно определить только с помощью функции MQLInfoInteger(), идентификатор MQL_TESTER.
Теперь переходим к оптимизации. Журнал с записями будет находиться в папке агента. В моем случае путь был таким: %Program Files\MetaTrader5\tester\Agent-127.0.0.1-3000\logs
OH 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Текущий режим: MQL_MODE_OPTIMIZATION KJ 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Debug mode: no NO 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Profile mode: no FI 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Tester mode: yes KE 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Optimization mode: yes LS 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Visual mode: no QE 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Frame mode: no
Если режим оптимизации активен, то автоматически включен и режим тестирования.
Режим оптимизации задействуется в Тестере стратегий, если поле "Оптимизация" на вкладке Настройки не отключена.
Узнать о том, что робот тестируется в режиме оптимизации, средствами MQL5 можно путем вызова функции MQLInfoInteger(), идентификатор MQL_OPTIMIZATION.
Обращаемся к режиму визуализации.
JQ 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Текущий режим: MQL_MODE_VISUAL JK 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Debug mode: no KF 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Profile mode: no CP 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Tester mode: yes HJ 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Optimization mode: no LK 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Visual mode: yes KS 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Frame mode: no
Здесь также увидим, что задействованы визуальный режим тестирования и просто режим тестирования.
В этом режиме советник работает в Тестере стратегий, если задано поле "Визуализация" на вкладке Настройки.
Определить факт тестирования MQL5-программы в визуальном режиме можно посредством функции MQLInfoInteger(), идентификатор MQL_VISUAL_MODE.
И последний режим – обработка фреймов.
HI 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Текущий режим: MQL_MODE_FRAME GR 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Debug mode: no JR 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Profile mode: no JG 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Tester mode: yes GM 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Optimization mode: yes HR 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Visual mode: no MI 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Frame mode: no
Любопытно, что функцией обнаружены только режимы тестирования и оптимизации, тогда как флаг фреймов равен нулю. Попробуем перенести вызов функции в обработчик OnTesterInit().
Получим такие записи в журнале "Эксперты":
IO 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Текущий режим: MQL_MODE_FRAME GE 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Debug mode: no ML 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Profile mode: no CJ 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no QR 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no PL 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no GS 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Frame mode: yes
Интересно, что теперь обнаружился только режим сбора фреймов.
Данный режим задействуется в Тестере стратегий, если поле "Оптимизация" на вкладке "Настройки" не отключена. Как показал опыт, режим определяется в теле обработчиков OnTesterInit(), OnTesterPass(), OnTesterDeinit().
Определить факт тестирования робота в режиме сбора фреймов можно при помощи функции MQLInfoInteger() с идентификатором MQL_FRAME_MODE.
Попробуем закодировать сервисную функцию MqlMode(), которая автоматически укажет, в каком режиме работает советник.
//+------------------------------------------------------------------+ //| Определить текущий MQL-режим | //+------------------------------------------------------------------+ ENUM_MQL_MODE MqlMode(void) { ENUM_MQL_MODE curr_mode=WRONG_VALUE; //--- если режим отладки if(MQLInfoInteger(MQL_DEBUG)) curr_mode=MQL_MODE_DEBUG; //--- если режим профилирования кода else if(MQLInfoInteger(MQL_PROFILER)) curr_mode=MQL_MODE_PROFILER; //--- если режим визуального тестирования else if(MQLInfoInteger(MQL_VISUAL_MODE)) curr_mode=MQL_MODE_VISUAL; //--- если режим оптимизации else if(MQLInfoInteger(MQL_OPTIMIZATION)) curr_mode=MQL_MODE_OPTIMIZATION; //--- если режим тестирования else if(MQLInfoInteger(MQL_TESTER)) curr_mode=MQL_MODE_TESTER; //--- если режим сбора фреймов результатов оптимизации else if(MQLInfoInteger(MQL_FRAME_MODE)) curr_mode=MQL_MODE_FRAME; //--- если релиз-режим else curr_mode=MQL_MODE_RELEASE; //--- return curr_mode; }
Раз при оптимизации и визуальном тестировании также будет определяться обычное тестирование, то режим обычного тестирования нужно проверять после режимов оптимизации и визуализации.
Посмотрим на работу функции во втором шаблоне советника Test2_Modes_EA.mq5. При его запуске в журнале появится запись. Например, для режима профилирования была такая запись:
HG 0 11:23:52.992 Test2_Modes_EA (EURUSD.e,H1) Текущий режим: MQL_MODE_PROFILER
Мы разбирались в нюансах режимов работы MQL5-советника для создания модели классов, соответствующих определенному режиму. В следующем разделе попробуем это сделать.
3. Шаблон "режимного советника"
Предлагаю снова вспомнить о том, какие этапы при разработке проходит торговый робот, да и сам разработчик со своим детищем.
На этапе алгоритмизации программист чаще пользуется отладкой и профилированием. При тестировании на истории обращается ко всем режимам, присущим Тестеру стратегий. Финальный режим (релиз) задействуется для онлайн торговли.
На мой взгляд, полноценный робот должен быть многоликим. В том смысле, что требования этапов разработки и тестирования должны быть как-то отражены в его коде.
Тогда, сохраняя основной алгоритм торговой идеи и подчиняясь ему, робот будет иметь некоторые отличия в своем поведении при разных режимах работы. Для решения такой задачи как нельзя лучше подходит инструментарий ООП.
Рис.3. Иерархия классов для "режимного" советника
Иерархия классов с реализацией различных режимов представлена на рис.3.
Базовый класс CModeBase, инкапсулирующий все общее, будет иметь 2 прямых потомка: класс CModeRelease и класс CModeTester. Первый будет родителем для отладочных классов, а второй – для классов, связанных с тестированием на истории.
Попробуем развить идею процедурно-модульного подхода при разработке методов класса в контексте "режимной" темы. В качестве примера рассмотрим такую торговую логику:
- Открытие по сигналу, если нет позиции;
- Закрытие по сигналу, если есть позиция;
- Трал по сигналу, если есть позиция.
Сам торговый сигнал будем ловить на стандартном индикаторе MACD при появлении нового бара.
Сигнал на покупку появляется тогда, когда в отрицательной зоне значений индикатора MACD основная линия пересекает сигнальную снизу вверх (рис.4).
Рис.4. Сигнал на покупку
Сигнал на продажу появляется тогда, когда в положительной зоне значений индикатора основная линия пересекает сигнальную сверху вниз (рис.5).
Рис.5. Сигнал на продажу
Закрываться позиция будет при появлении противоположного сигнала или по стоп-лоссу, который выставляется в случае, если задан режим сопровождения позиции.
Тогда определение базового класса CModeBase может быть таким:
//+------------------------------------------------------------------+ //| Class CModeBase | //| Purpose: a base class for MQL-modes | //+------------------------------------------------------------------+ class CModeBase { //--- === Data members === --- private: //--- a macd object & values CiMACD m_macd_obj; double m_macd_main_vals[2]; double m_macd_sig_vals[2]; protected: long m_pos_id; bool m_is_new_bar; uint m_trailing_stop; uint m_trail_step; //--- trade objects CSymbolInfo m_symbol_info; CTrade m_trade; CPositionInfo m_pos_info; CDealInfo m_deal_info; //--- mql mode ENUM_MQL_MODE m_mql_mode; //--- a new bar object CisNewBar m_new_bar; //--- current tick signal flag bool m_is_curr_tick_signal; //--- close order type ENUM_ORDER_TYPE m_close_ord_type; //--- === Methods === --- public: //--- constructor/destructor void CModeBase(); void ~CModeBase(void){}; //--- initialization virtual bool Init(int _fast_ema,int slow_ema,int _sig,ENUM_APPLIED_PRICE _app_price); virtual void Deinit(void){}; //--- Modules virtual void Main(void){}; //--- Procedures virtual void Open(void){}; virtual void Close(void){}; virtual void Trail(void){}; //--- Service static ENUM_MQL_MODE CheckMqlMode(void); ENUM_MQL_MODE GetMqlMode(void); void SetMqlMode(const ENUM_MQL_MODE _mode); void SetTrailing(const uint _trailing,const uint _trail_step); protected: //--- Functions ENUM_ORDER_TYPE CheckOpenSignal(const ENUM_ORDER_TYPE _open_sig); ENUM_ORDER_TYPE CheckCloseSignal(const ENUM_ORDER_TYPE _close_sig); ENUM_ORDER_TYPE CheckTrailSignal(const ENUM_ORDER_TYPE _trail_sig,double &_sl_pr); //--- double GetMacdVal(const int _idx,const bool _is_main=true); private: //--- Macros bool RefreshIndicatorData(void); //--- Normalization double NormalPrice(double d); double NormalDbl(double d,int n=-1); double NormalSL(const ENUM_ORDER_TYPE _ord_type,double op,double pr, uint SL,double stop); double NormalTP(const ENUM_ORDER_TYPE _ord_type,double op,double pr, uint _TP,double stop); double NormalLot(const double _lot); };
В состав базового класса можно включать все что угодно, лишь бы это потом пригодилось для классов–наследников.
Данные индикатора MACD будут недоступны для потомков. Они представлены приватными членами.
Отмечу, что среди методов есть виртуальные методы: Main(), Open(), Close(), Trail(). Их реализация будет зависеть от текущего режима, в котором работает робот. Для базового класса данные методы останутся пустыми.
Также в базовом классе есть методы, которые сохраняют торговую логику для всех MQL-режимов. К ним относятся все сигнальные методы:
- CModeBase::CheckOpenSignal(),
- CModeBase::CheckCloseSignal(),
- CModeBase::CheckTrailSignal().
Скажу сразу, что в рамках статьи не ставится задача создания кода для всех типов MQL-режима. В качестве примера приведу классы для обычного и визуального тестирования.
3.1. Режим тестирования
После того как алгоритм закодирован и откомпилирован, я обычно обращаюсь к Тестеру стратегий, чтобы прогнать стратегию на истории и посмотреть, так ли все работает, как задумывалось.
Чаще всего нужно проверять, как точно отрабатывает система торговые сигналы. В любом случае, минимальная задача на этом этапе для робота – запуститься и поторговать.
Определение класса CModeTester для обычного тестирования может быть таким:
//+------------------------------------------------------------------+ //| Class CModeTester | //| Purpose: a class for the tester mode | //| Derives from class CModeBase. | //+------------------------------------------------------------------+ class CModeTester : public CModeBase { //--- === Methods === --- public: //--- constructor/destructor void CModeTester(void){}; void ~CModeTester(void){}; //--- Modules virtual void Main(void); //--- Procedures virtual void Open(void); virtual void Close(void); virtual void Trail(void); };
Определение главного модуля представлено следующим образом:
//+------------------------------------------------------------------+ //| Главный модуль | //+------------------------------------------------------------------+ void CModeTester::Main(void) { //--- 1) закрытие this.Close(); //--- 2) открытие this.Open(); //--- 3) трал this.Trail(); }
Создадим для режима обычного тестирования возможность вывода в Журнал информации о появлении торговых сигналов.
Затем дополним ее строками, содержащими значения индикаторов, которые берутся за источник торгового сигнала.
Приведу выдержку из Журнала о сигнале на открытие позиции и ее последующее закрытие.
HE 0 13:34:04.118 Core 1 2014.11.14 22:15:00 ---=== Сигнал на открытие: SELL===--- FI 0 13:34:04.118 Core 1 2014.11.14 22:15:00 Позапрошлый бар, главная: 0.002117; сигнальная: 0.002109 DL 0 13:34:04.118 Core 1 2014.11.14 22:15:00 Прошлый бар, главная: 0.002001; сигнальная: 0.002118 LO 0 13:34:04.118 Core 1 2014.11.14 22:15:00 market sell 0.03 EURUSD.e (1.25242 / 1.25251 / 1.25242) KH 0 13:34:04.118 Core 1 2014.11.14 22:15:00 deal #660 sell 0.03 EURUSD.e at 1.25242 done (based on order #660) GE 0 13:34:04.118 Core 1 2014.11.14 22:15:00 deal performed [#660 sell 0.03 EURUSD.e at 1.25242] OD 0 13:34:04.118 Core 1 2014.11.14 22:15:00 order performed sell 0.03 at 1.25242 [#660 sell 0.03 EURUSD.e at 1.25242] IK 0 13:34:04.118 Core 1 2014.11.14 22:15:00 CTrade::OrderSend: market sell 0.03 EURUSD.e [done at 1.25242] IL 0 13:34:04.118 Core 1 2014.11.17 13:30:20 CJ 0 13:34:04.118 Core 1 2014.11.17 13:30:20 ---=== Сигнал на закрытие: SELL===--- GN 0 13:34:04.118 Core 1 2014.11.17 13:30:20 Позапрошлый бар, главная: -0.001218; сигнальная: -0.001148 QL 0 13:34:04.118 Core 1 2014.11.17 13:30:20 Прошлый бар, главная: -0.001123; сигнальная: -0.001189 EP 0 13:34:04.118 Core 1 2014.11.17 13:30:20 market buy 0.03 EURUSD.e (1.25039 / 1.25047 / 1.25039) FG 0 13:34:04.118 Core 1 2014.11.17 13:30:20 deal #661 buy 0.03 EURUSD.e at 1.25047 done (based on order #661) OJ 0 13:34:04.118 Core 1 2014.11.17 13:30:20 deal performed [#661 buy 0.03 EURUSD.e at 1.25047] PD 0 13:34:04.118 Core 1 2014.11.17 13:30:20 order performed buy 0.03 at 1.25047 [#661 buy 0.03 EURUSD.e at 1.25047] HE 0 13:34:04.118 Core 1 2014.11.17 13:30:20 CTrade::OrderSend: market buy 0.03 EURUSD.e [done at 1.25047]
Нужно отметить, что в Тестере привычного журнала "Эксперты" нет. Вся информация находится на вкладке "Журнал", где регистрируются записи о действиях, выполняемых тестером во время тестирования и оптимизации.
Поэтому приходится искать "свои" строки. Если есть желание как-то обособить информацию для вывода, то можно записывать ее в файл.
Стратегия для обычного режима тестирования воплощена в коде советника TestMode_tester.mq5.
3.2. Режим визуального тестирования
Бывают случаи, когда нужно обратиться к живому графику и посмотреть, как робот обрабатывает текущую ситуацию.
Простая визуализация помогает не только увидеть своими глазами, как торговая система ловит тики, но и сравнить похожие ценовые модели по окончании тестирования.
Определение класса CModeVisual для визуального тестирования может быть таким:
//+------------------------------------------------------------------+ //| Class CModeVisual | //| Purpose: a class for the tester mode | //| Derived from class CModeBase. | //+------------------------------------------------------------------+ class CModeVisual : public CModeTester { //--- === Data members === --- private: CArrayObj m_objects_arr; double m_subwindow_max; double m_subwindow_min; //--- === Methods === --- public: //--- constructor/destructor void CModeVisual(void); void ~CModeVisual(void); //--- Procedures virtual void Open(void); virtual void Close(void); private: bool CreateSignalLine(const bool _is_open_sig,const bool _is_new_bar=true); bool CreateRectangle(const ENUM_ORDER_TYPE _signal); void RefreshRectangles(void); };
В классе есть скрытые члены. Член класса m_objects_arr реализует динамический массив типа CArrayObj, в который попадут графические объекты (линии, прямоугольники). Два других члена класса (m_subwindow_max, m_subwindow_min) контролируют максимальный и минимальный размеры подокна индикатора.
Приватные методы отвечают за работу с графическими объектами.
В данном классе нет методов Main() и Trail(). Вызываться будут их родительские аналоги CModeTester::Main() и CModeTester::Trail() соответственно.
В режиме визуального тестирования можно создавать графические объекты. В других режимах Тестера стратегий это сделать не получится.
Пусть при появлении сигнала на вход будет отрисована на графике красная вертикаль, а на выход – синяя. Пространство между точками входа-выхода заполним прямоугольником соответствующего цвета в подокне индикатора.
Если позиция была длинной, то цвет прямоугольника будет светло-голубым. Если позиция была короткой, то цвет прямоугольника будет розовым (рис.6).
Рис.6. Графические объекты в визуальном режиме тестирования
Высота прямоугольников зависит от значений максимума и минимума подокна графика на момент создания. Чтобы сделать все прямоугольники одинаковыми по размеру, в коде нужно добавить блок изменения координат прямоугольников, если изменились координаты подокна графика.
В итоге в подокне индикатора MACD получим выраженные участки: неокрашенный (позиции нет), розовый (короткая позиция), светло-голубой (длинная позиция).
Стратегия для визуального режима тестирования воплощена в коде советника TestMode_visual_tester.mq5.
Заключение
В данной статье я стремился продемонстрировать режимные возможности терминала MetaTrader 5 и языка MQL5. Нужно сказать, что мультирежимный подход программирования торгового алгоритма отличается бóльшими затратами с одной стороны, а с другой есть возможность последовательно пройтись по каждому этапу создания будущего робота. Еще раз повторюсь, что здесь как нельзя кстати на подмогу программисту приходит ООП.
Режимы оптимизации и сбора фреймов планирую более подробно осветить в будущем статейном материале о статистических свойствах торговой системы.





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования