Мастер MQL5: Как научить эксперта открывать отложенные ордера по любым ценам
Введение
Эксперт, сгенерированный с помощью Мастера MQL5, может открывать отложенные ордера, но только на фиксированном расстоянии от текущей цены. Это значит, что если изменится ситуация на рынке (например, изменилась волатильность рынка), то придется перезапускать эксперта с новыми параметрами.
Для многих торговых систем такое условие не подходит. В большинстве случаев торговая система определяет уровень цены отложенного ордера динамически, и уровень отступа от текущей цены все время изменяется. В данной статье мы рассмотрим, как нужно модифицировать эксперт, созданный с помощью Мастера MQL5, чтобы он мог открывать отложенные ордера на разном расстоянии от текущей цены.
1. Механизм открытия отложенных ордеров в эксперте, созданном с помощью Мастера MQL5
Сгенерированный эксперт в своей шапке имеет приблизительно следующий код:
//+------------------------------------------------------------------+ //| Inputs | //+------------------------------------------------------------------+ //--- inputs for expert input string Expert_Title="ExpertMySignalEnvelopes.mq5"; // Document name ulong Expert_MagicNumber =3915; // bool Expert_EveryTick =false; // //--- inputs for main signal input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100] input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100] input double Signal_PriceLevel =0.0; // Price level to execute a deal input double Signal_StopLevel =85.0; // Stop Loss level (in points) input double Signal_TakeLevel =195.0; // Take Profit level (in points) input int Signal_Expiration =0; // Expiration of pending orders (in bars) input int Signal_Envelopes_PeriodMA =13; // Envelopes(13,0,MODE_SMA,...) Period of averaging input int Signal_Envelopes_Shift =0; // Envelopes(13,0,MODE_SMA,...) Time shift input ENUM_MA_METHOD Signal_Envelopes_Method =MODE_SMA; // Envelopes(13,0,MODE_SMA,...) Method of averaging input ENUM_APPLIED_PRICE Signal_Envelopes_Applied =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series input double Signal_Envelopes_Deviation=0.2; // Envelopes(13,0,MODE_SMA,...) Deviation input double Signal_Envelopes_Weight =1.0; // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0] //--- inputs for money input double Money_FixLot_Percent =10.0; // Percent input double Money_FixLot_Lots =0.1; // Fixed volume //+------------------------------------------------------------------+
Обратите внимание на параметр Signal_PriceLevel. По умолчанию эксперт генерируется с параметром Signal_PriceLevel=0. Этот параметр отвечает за уровень отступа от текущей цены. При значении, равном нулю, ордер будет открыт по текущей рыночной цене. Чтобы открыть отложенный ордер, следует задать ненулевое значения для параметра Signal_PriceLevel, т.е. Signal_PriceLevel может быть как меньше нуля, так и больше.
Параметр Signal_PriceLevel указывается в "больших" пунктах. На картинках ниже показана разница между отрицательными и положительными значениями:
При Signal_PriceLevel=-50:
Рис. 1. Signal_PriceLevel=-50
При Signal_PriceLevel=50:
Рис. 2. Signal_PriceLevel=50
Таким образом, при Signal_PriceLevel=-50, отложенный ордер будет открываться по цене хуже текущей, а при Signal_PriceLevel=50, отложенный ордер будет открываться по цене лучшей, чем текущая.
В данной версии эксперт открывает sell stop и buy stop ордера.
2. Где хранится запись об уровне отступа от цены для открытия отложенного ордера
Сначала рисунок, а потом комментарии к рисунку:
Рис. 3. Хранение записи об уровне отступа от текущей цены
Комментарии к рисунку.
Эксперт - эксперт, созданный с помощью Мастера MQL5.
- В эксперте в области глобальных объявлений объявляется объект ExtExpert класса CExpert.
- Далее в эксперте в функции OnInit() объявляется указатель объекта signal класса CExpertSignal и сразу создается объект signal при помощи оператора new.
- Находимся все еще в функции OnInit(). Осуществляется вызов функции InitSignal объекта ExtExpert и инициализируется объекта signal.
- Находимся все еще в функции OnInit(). Осуществляется вызов функции PriceLevel объекта signal в которую передается параметр Signal_PriceLevel.
Таким образом, параметр Signal_PriceLevel, в котором хранится уровень отступа от текущей цены и который был объявлен в эксперте, передается в объект signal класса CExpertSignal.
Класс CExpertSignal хранит значение уровня отступа от текущей цены в переменной m_price_level, которая объявлена в области видимости protected класса:
class CExpertSignal : public CExpertBase { protected: //--- variables double m_base_price; // base price for detection of level of entering (and/or exit?) //--- variables for working with additional filters CArrayObj m_filters; // array of additional filters (maximum number of fileter is 64) //--- Adjusted parameters double m_weight; // "weight" of a signal in a combined filter int m_patterns_usage; // bit mask of using of the market models of signals int m_general; // index of the "main" signal (-1 - no) long m_ignore; // bit mask of "ignoring" the additional filter long m_invert; // bit mask of "inverting" the additional filter int m_threshold_open; // threshold value for opening int m_threshold_close;// threshold level for closing double m_price_level; // level of placing a pending orders relatively to the base price double m_stop_level; // level of placing of the "stop loss" order relatively to the open price double m_take_level; // level of placing of the "take profit" order relatively to the open price int m_expiration; // time of expiration of a pending order in bars
3. Структура эксперта, созданного с помощью Мастера MQL5
Эксперт состоит из нескольких блоков, различных по функциональности.
Рис. 4. Структура эксперта
Комментарии к рисунку:
- Эксперт - эксперт, созданный с помощью Мастера MQL5.
- CExpert - базовый класс для реализации торговых стратегий.
- CExpertSignal - базовый класс для создания генераторов торговых сигналов.
- filter0 ... filtern - генераторы торговых сигналов, наследники класса CExpertSignal. Кстати, наша торговая система опирается на генератор торговых сигналов индикатора Envelopes, но сами сигналы внутри генератора изменены. Какие именно изменения произведены, будет сказано в пункте 7.
4. Блоки эксперта, которые целесообразно править
Как вы могли видеть в структуре эксперта, сгенерированного с помощью Мастера MQL5, есть блоки базовых классов. Базовые классы принадлежат Стандартной библиотеке.
Сами классы являются наследниками других базовых классов и одновременно включают в себя один или несколько базовых классов. Приведу ниже код начала всего двух классов - CExpert и CExpertSignal:
//+------------------------------------------------------------------+ //| Expert.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" #include "ExpertTrade.mqh" #include "ExpertSignal.mqh" #include "ExpertMoney.mqh" #include "ExpertTrailing.mqh" //+------------------------------------------------------------------+ . . . class CExpert : public CExpertBase
и
//+------------------------------------------------------------------+ //| ExpertSignal.mqh | //| Copyright 2009-2013, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include "ExpertBase.mqh" . . . class CExpertSignal : public CExpertBase
Править базовые классы категорически не рекомендую:
- После обновления редактора все ваши изменения базовых классов будут затерты и базовые классы будут восстановлены в свое первоначальное состояние.
- Более правильный путь - это наследование. Но в таком случае придется править ВСЮ Стандартную библиотеку.
А вот блок самого эксперта и модули генераторов торговых сигналов - отличные кандидаты на роль редактируемых модулей. Тем более, что в соответствии с нашей торговой системой уже будет использован измененный модуль - генератор торговых сигналов индикатора Envelopes.
Значит, решено: вносить изменения следует в блоки эксперта и в блок генератора торговых сигналов.
5. Схема реализации идеи
Из эксперта будет передаваться указатель в генератор торговых сигналов.
Для этого в генераторе надо дополнительно объявить переменную с областью видимости protected и написать метод, с помощью которого ссылка из эксперта сохраняется во внутреннюю переменную:
Рис. 5. Схема реализации идеи
6. Торговая система
Период графика – D1. Используемый индикатор – Envelopes, период усреднения 13, метод усреднения Exponential. Типы ордеров, которые открывает эксперт, - это sell stop и buy stop ордера.
Если предыдущий бар был бычий, выставляем sell stop ордер. Если предыдущий бар был медвежьим, выставляем buy stop ордер. Другими словами, надеемся на откат цены:
Рис. 6. Торговая система
Для генерации торговых сигналов в соответствии с торговой системой был изменен стандартный модуль генератора торговых сигналов SignalEnvelopes.mqh.
Кстати, можно было брать любой генератор торговых сигналов из Стандартной библиотеки.
7. Редактирование генератора торговых сигналов. Получение цены бара
Итак, приступим. Кстати, я сторонник сохранения своих программ в хранилище MQL5 Storage.
Первое, что нужно для начала правки генератора торговых сигналов, - это создать пустой включаемый файл, затем все в нем удалить и вставить полное содержимое из стандартного генератора торговых сигналов индикатора Envelopes.
По умолчанию генератор торговых сигналов должен находиться в папке ...MQL5\Include\Expert\Signal. Чтобы не засорять папку ...\Signal Стандартной библиотеки, создадим в директории ...\Expert свою папку \MySignals:
Рис. 7. Создаем свою папку MySignals
Следующий шаг - создадим включаемый файл с помощью Мастера MQL5.
Выберете в MetaEditor меню "Файл" пункт "Создать" и отметьте пункт "Включаемый файл (*.mqh)".
Рис. 8. Мастер MQL5. Создаем включаемый файл
Назовем наш класс генератора сигналов MySignalEnvelopes.
Путь к нашему классу будет следующий: Include\Expert\MySignals\MySignalEnvelopes. Укажем это:
Рис. 9. Мастер MQL5. Расположение включаемого файла
После нажатия кнопки "Готово" Мастер MQL5 сгенерирует пустой шаблон.
Далее полученный файл MySignalEnvelopes.mqh нужно добавить в MQL5 Storage:
Рис. 10. MQL5 Storage. Добавление файла
После добавления файла нужно зафиксировать изменение в MQL5 Storage:
Рис. 11. MQL5 Storage. Фиксация изменений
После выполненных действий можно приступить к редактированию нашего генератора торговых сигналов.
Так как наш генератор основан на стандартном файле \Include\Expert\Signal\SignalEnvelopes.mqh, то скопируем его содержимое полностью и вставим в наш файл генератора, заменив в нем все, кроме шапки:
//+------------------------------------------------------------------+ //| MySignalEnvelopes.mqh | //| Copyright © 2013, Vladimir Karputov | //| http://wmua.ru/slesar/ | //+------------------------------------------------------------------+ #property copyright "Copyright © 2013, Vladimir Karputov" #property link "http://wmua.ru/slesar/" #include <Expert\ExpertSignal.mqh> // wizard description start //+------------------------------------------------------------------+ //| Description of the class | //| Title=Signals of indicator 'Envelopes' | //| Type=SignalAdvanced | //| Name=Envelopes | //| ShortName=Envelopes | //| Class=CSignalEnvelopes | //| Page=signal_envelopes | //| Parameter=PeriodMA,int,45,Period of averaging | //| Parameter=Shift,int,0,Time shift | //| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging | //| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series | //| Parameter=Deviation,double,0.15,Deviation | //+------------------------------------------------------------------+ // wizard description end //+------------------------------------------------------------------+ //| Class CSignalEnvelopes. | //| Purpose: Class of generator of trade signals based on | //| the 'Envelopes' indicator. | //| Is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalEnvelopes : public CExpertSignal { protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator double m_limit_in; // threshold sensitivity of the 'rollback zone' double m_limit_out; // threshold sensitivity of the 'break through zone' //--- "weights" of market models (0-100) int m_pattern_0; // model 0 "price is near the necessary border of the envelope" int m_pattern_1; // model 1 "price crossed a border of the envelope" public: CSignalEnvelopes(void); ~CSignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } void LimitIn(double value) { m_limit_in=value; } void LimitOut(double value) { m_limit_out=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } void Pattern_1(int value) { m_pattern_1=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(0.15), m_limit_in(0.2), m_limit_out(0.2), m_pattern_0(90), m_pattern_1(70) { //--- initialization of protected data m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE; } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CSignalEnvelopes::~CSignalEnvelopes(void) { } //+------------------------------------------------------------------+ //| Validation settings protected data. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::ValidationSettings(void) { //--- validation settings of additional filters if(!CExpertSignal::ValidationSettings()) return(false); //--- initial data checks if(m_ma_period<=0) { printf(__FUNCTION__+": period MA must be greater than 0"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| Create indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitIndicators(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- initialization of indicators and timeseries of additional filters if(!CExpertSignal::InitIndicators(indicators)) return(false); //--- create and initialize MA indicator if(!InitMA(indicators)) return(false); //--- ok return(true); } //+------------------------------------------------------------------+ //| Initialize MA indicators. | //+------------------------------------------------------------------+ bool CSignalEnvelopes::InitMA(CIndicators *indicators) { //--- check pointer if(indicators==NULL) return(false); //--- add object to collection if(!indicators.Add(GetPointer(m_env))) { printf(__FUNCTION__+": error adding object"); return(false); } //--- initialize object if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation)) { printf(__FUNCTION__+": error initializing object"); return(false); } //--- ok return(true); } //+------------------------------------------------------------------+ //| "Voting" that price will grow. | //+------------------------------------------------------------------+ int CSignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+ //| "Voting" that price will fall. | //+------------------------------------------------------------------+ int CSignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); } //+------------------------------------------------------------------+
Дальше предстоит работа по замене некоторых участков кода.
Чтобы не запутаться, замененный код я буду выделять с помощью цвета:
//+------------------------------------------------------------------+
//| MySignal.mqh |
//| Copyright © 2013, Vladimir Karputov |
//| http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
Измененный код - это код, который нужно копировать и вставлять в генератор торговых сигналов. Надеюсь, такое выделение поможет вам в восприятии кода.
Так как мы пишем свой класс генератора торговых сигналов, то и название этого класса должно отличаться от базового. Поэтому заменим все вхождения CSignalEnvelopes на CMySignalEnvelopes:
Рис. 12. Переименование класса
Чтобы наш класс генератора торговых сигналов был виден в Мастере MQL5 под своим именем, переименуем в блоке описания название класса
//| Title=Signals of indicator 'Envelopes' |
на
//| Title=Signals of indicator 'MySignalEnvelopes' |
Изменим период скользящей
//| Parameter=PeriodMA,int,45,Period of averaging |
на 13 (это лично мое мнение, вы можете ставить любое свое значение)
//| Parameter=PeriodMA,int,13,Period of averaging |
Еще изменим параметр Deviation (отклонение)
//| Parameter=Deviation,double,0.15,Deviation |
на более крупное значение
//| Parameter=Deviation,double,1.15,Deviation |
В соответствии с нашей схемой реализации идеи необходимо объявить внутреннюю переменную, в которой будет храниться указатель на главный сигнал.
Так как эта переменная должна быть внутренней (с областью видимости только внутри класса генератора торговых сигналов), добавлять ее будем в следующий блок кода:
protected: CiEnvelopes m_env; // object-indicator //--- adjusted parameters int m_ma_period; // the "period of averaging" parameter of the indicator int m_ma_shift; // the "time shift" parameter of the indicator ENUM_MA_METHOD m_ma_method; // the "method of averaging" parameter of the indicator ENUM_APPLIED_PRICE m_ma_applied; // the "object of averaging" parameter of the indicator double m_deviation; // the "deviation" parameter of the indicator //--- "weights" of market models (0-100) int m_pattern_0; // model 0 CExpertSignal *m_signal; // храним ссылку на главный сигнал
Также обратите внимание, что в коде я удалил переменные, которые не будут применяться.
Метод, с помощью которого мы будем сохранять указатель на главный сигнал, объявим в другом блоке кода - "метод установки указателя на главный сигнал". Также были удалены некоторые лишние методы.
public: CMySignalEnvelopes(void); ~CMySignalEnvelopes(void); //--- methods of setting adjustable parameters void PeriodMA(int value) { m_ma_period=value; } void Shift(int value) { m_ma_shift=value; } void Method(ENUM_MA_METHOD value) { m_ma_method=value; } void Applied(ENUM_APPLIED_PRICE value) { m_ma_applied=value; } void Deviation(double value) { m_deviation=value; } //--- methods of adjusting "weights" of market models void Pattern_0(int value) { m_pattern_0=value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking if the market models are formed virtual int LongCondition(void); virtual int ShortCondition(void); //--- метод установки указателя на главный сигнал virtual bool InitSignal(CExpertSignal *signal=NULL);
Пропишем в конструкторе некоторые измененные параметры, а также удалим ставшие ненужными переменные:
//+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13), m_ma_shift(0), m_ma_method(MODE_SMA), m_ma_applied(PRICE_CLOSE), m_deviation(1.15), m_pattern_0(50)
Сейчас займемся изменением логики генерации торговых сигналов в соответствии с нашей торговой системой.
Блок кода, отвечающий за сигнал на покупку:
int CMySignalEnvelopes::LongCondition(void) { int result=0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
после изменений будет выглядеть так:
int CMySignalEnvelopes::LongCondition(void) //---buy
{
int result=0;
int idx =StartIndex();
double open=Open(idx);
double close=Close(idx);
double prlevel;
if(IS_PATTERN_USAGE(0) && close<open)
{
prlevel=GetPriceLevelStopp(open,Open(0));
m_signal.PriceLevel(prlevel);
result=m_pattern_0;
}
//--- return the result
return(result);
}
Блок кода, отвечающий за сигнал на продажу:
int CMySignalEnvelopes::ShortCondition(void) { int result =0; int idx =StartIndex(); double close=Close(idx); double upper=Upper(idx); double lower=Lower(idx); double width=upper-lower; //--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width) result=m_pattern_0; //--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width) result=m_pattern_1; //--- return the result return(result); }
после изменений будет выглядеть так:
int CMySignalEnvelopes::ShortCondition(void) //---sell
{
int result =0;
int idx =StartIndex();
double open=Open(idx);
double close=Close(idx);
double prlevel;
if(IS_PATTERN_USAGE(0) && close>open)
{
prlevel=GetPriceLevelStopp(Open(0),open);
m_signal.PriceLevel(prlevel);
result=m_pattern_0;
}
//--- return the result
return(result);
}
8. Пояснение к коду сигналов
При выполнении условия появления сигнала вызывается метод GetPriceLevelStopp - этот метод возвращает число вида "20" или "15" - уровень отступа от текущей цены.
Затем вызывается метод PriceLevel объекта m_signal (этим методом устанавливается уровень отступа для определения цены отложенного уровня). Напомню, что m_signal - это объект класса CExpertSignal, хранящий указатель на главный сигнал.
Код метода GetPriceLevelStopp привожу ниже:
double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
{
double level;
double temp;
temp-=(price_0-min)/PriceLevelUnit();
level=NormalizeDouble(temp,0);
return(level);
}
Этот метод необходимо объявить в шапке класса:
protected: //--- method of initialization of the indicator bool InitMA(CIndicators *indicators); //--- methods of getting data double Upper(int ind) { return(m_env.Upper(ind)); } double Lower(int ind) { return(m_env.Lower(ind)); } double GetPriceLevelStopp(double price,double min); };
Еще один метод, который понадобится, - это метод передачи ссылки на главный сигнал во внутреннюю переменную:
bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
{
m_signal=signal;
return(true);
}
После этого необходимо создать эксперта в Мастере MQL5 и в нем подключить модуль сигналов Signals of indicator 'MySignalEnvelopes'.
В коде советника, сгенерированного при помощи Мастера MQL5, необходимо добавить вызов метода InitSignal:
//--- Set filter parameters filter0.PeriodMA(Signal_Envelopes_PeriodMA); filter0.Shift(Signal_Envelopes_Shift); filter0.Method(Signal_Envelopes_Method); filter0.Applied(Signal_Envelopes_Applied); filter0.Deviation(Signal_Envelopes_Deviation); filter0.Weight(Signal_Envelopes_Weight); filter0.InitSignal(signal); //...
Для наглядности работы эксперта я включил небольшое видео:
Код эксперта, сгенерированного с помощью Мастера MQL5, и код модуля сигналов приведены в приложении к статье.
Результаты тестирования эксперта с параметрами: период тестирования - с 2013.01.01 по 2013.09.01, период графика - D1, Stop Loss level = 85, Take Profit level = 195 для пар EURUSD и USDJPY представлены ниже:
Рис. 13. Тест EURUSD, период D1
Рис. 14. Тест USDJPY, период D1
Заключение
В статье рассмотрен способ модификации кода модуля торговых сигналов для реализации функционала выставления отложенных ордеров на произвольном расстоянии от текущей цены: это может быть цена Close или Open предыдущего бара, а может быть значение скользящей средней. Вариантов множество – главное, теперь цену открытия отложенного ордера можно выставлять любую.
Показано, как получить доступ к указателю на главный сигнал, а значит и доступ к методам класса CExpertSignal. Думаю, что данная статья станет полезной для тех, кто использует стратегии торговли отложенными ордерами.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Спасибо автору за полезную статью, но ИМХО нужно еще раз проверить код, например я обратил внимание, что в методах CMySignalEnvelopes::LongCondition и CMySignalEnvelopes::ShortCondition выполняется вызов по не проверенному на NULL указателю на объект m_signal, а в методе CMySignalEnvelopes::GetPriceLevelStopp применяется вычитание от текущего значения не инициализированной локальной переменной temp...
Кроме того, прежде чем взять на вооружение предложенный вами механизм изменения параметров открытия ордеров, хотелось бы убедиться в его корректности.
Мои сомнения состоят в следующем:
во-первых ваши изменения параметров нивелирует значение внешней настройки советника Signal_PriceLevel, что может ввести в заблуждение пользователя,
во-вторых это изменение идет через поле главного модуля, что может повлиять на работу других модулей,
в-третьих методы где это делается, функционально служат для определения условий, а не изменения параметров ордеров - LongCondition, ShortCondition.
При этом для изменения параметров открытия ордеров, в базовом классе CExpertSignal есть специфические, виртуальные методы - OpenLongParams, OpenShortParams, которые возможно и предполагались разработчиками для переопределения в классах потомках, модулей пользовательских сигналов, а для включения вызыва этих методов, достаточно при инициализации вызвать метод General и передать ему индекс объекта от своего класса.
А в общем то хотелось, чтобы такие статьи, как ваша или моя, в которых предлагаются расширения для системных библиотек, сопровождались бы, хоть небольшим комментом со стороны MQ разработчиков этих библиотек, ведь таких статей не так много.