Обсуждение статьи "Как написать модуль торговых сигналов для Мастера MQL5" - страница 7

 
t101:
Вручную добавлять в OnInit()? Получается через Мастер никак не сделать того что хочу?
А какие проблемы? Вы ведь вносите дополнительный функционал и поэтому нужно немного поработать руками.
 
Karputov Vladimir:
А какие проблемы? Вы ведь вносите дополнительный функционал и поэтому нужно немного поработать руками.

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

Метод CheckCloseLong() производит генерацию сигнала закрытия длинной позиции с определением уровня выхода. Вызывается экспертом для определения необходимости закрытия длинной позиции. Необходимо переопределить метод в случае, если предполагается генерация сигнала закрытия длинной позиции.

virtual bool CheckCloseLong(double& price);
В любом случае спасибо за помощь.
[Удален]  
Почти 6 лет прошло статья не устарела? просто уверенности нет так как почти каждую неделю терминал вижу обновляется.
 
yerlan Imangeldinov:
Почти 6 лет прошло статья не устарела? просто уверенности нет так как почти каждую неделю терминал вижу обновляется.
Именно по написанию модулей торговых сигналов более свежая статья: "Создай торгового робота за шесть часов!"
 

Привет всем,

Меня интересует, как создать потомка CExpertSignal с двумя паттернами "выход" и "вход" в наблюдаемый торговый диапазон, используя подход, предложенный здесь, а также в Exploring Trading Strategy Classes of the Standard Library - Customizing Strategie by Harvester. Я считаю, что каждый класс сигналов может (должен) быть реализован путем перегрузки

//+------------------------------------------------------------------+
//| "Голосуем", что цена будет расти.|
//| INPUT: no.|
//| ВЫВОД: количество "голосов" за то, что цена вырастет.|
//| REMARK: no.|
//+------------------------------------------------------------------+
int CSignalBreakOutOrIn::LongCondition()
  {
   int result=0;
   int idx   =StartIndex();
//---
   //--- на случай, если нам нужен какой-то шаблон по умолчанию
   if(IS_PATTERN_USAGE(0)) result=m_pattern_0;                                   // "подтверждающий" сигнал номер 0
   //--- если используется модель 1, проверьте условие для детали 1
   if(IS_PATTERN_USAGE(1) && ConditionForPattern1(idx)) result=m_pattern_1;      // сигнал номер 1
   //--- если используется модель 2, проверьте условие для детали 2
   if(IS_PATTERN_USAGE(2) && ConditionForPattern2(idx)) result=m_pattern_2;      // сигнал номер 2
//--- верните результат
   return(result);
  }

и

//+------------------------------------------------------------------+
//| "Голосование", что цена упадет.|
//| INPUT: no.|
//| ВЫХОД: количество "голосов" за то, что цена упадет.|
//| REMARK: no.|
//+------------------------------------------------------------------+
int CSignalBreakOutOrIn::ShortCondition()
  {
   int result=0;
   int idx   =StartIndex();
//---
   //--- на случай, если нам нужен какой-то шаблон по умолчанию
   if(IS_PATTERN_USAGE(0)) result=m_pattern_0;                                   // "подтверждающий" сигнал номер 0
   //--- если используется модель 1, проверьте условие для детали 1
   if(IS_PATTERN_USAGE(1) && ConditionForPattern1(idx)) result=m_pattern_1;      // сигнал номер 1
   //--- если используется модель 2, проверьте условие для детали 2
   if(IS_PATTERN_USAGE(2) && ConditionForPattern2(idx)) result=m_pattern_2;      // сигнал номер 2
//--- верните результат
   return(result);
  }

Затем мы находим

int CExpertSignal::Direction()
  {
   ...
   int result=LongCondition()-ShortCondition();
   ...
  }

результат которого проверяется на соответствие signal.m_threshold_open и signal.m_threshold_close в

  1. bool CExpertSignal::CheckOpenLong(...),
  2. bool CExpertSignal::CheckOpenShort(...),
  3. bool CExpertSignal::CheckCloseLong(...),
  4. bool CExpertSignal::CheckCloseShort(...),
  5. bool CExpertSignal::CheckReverseLong(...), и
  6. bool CExpertSignal::CheckReverseShort(...).

Параметры, задающие уровни для входа в рынок и устанавливающие цены стоп-лосса и тейк-профита, будут возвращаться функциями

//+------------------------------------------------------------------+
//| Определение уровней для покупки|
//+------------------------------------------------------------------+
bool CExpertSignal::OpenLongParams(double &price,double &sl,double &tp,datetime &expiration)
  {
  }
//+------------------------------------------------------------------+
//| Определение уровней для продажи|
//+------------------------------------------------------------------+
bool CExpertSignal::OpenShortParams(double &price,double &sl,double &tp,datetime &expiration)
  {
  }

которые вызываются стандартной реализацией bool CExpertSignal::CheckOpenLong(...) и bool CExpertSignal::CheckOpenShort(...), как определено в базовом классе. Таким образом, достаточно перегрузить

  1. int CExpertSignal::LongCondition(...),
  2. int CExpertSignal::ShortCondition(...),
  3. bool CExpertSignal::OpenLongParams(...),
  4. bool CExpertSignal::OpenShortParams(...),
  5. bool CExpertSignal::CloseLongParams(...), и
  6. bool CExpertSignal::CloseShortParams(...)

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

Однако если торговый диапазон определяется как область между самым высоким максимумом (HH) и самым низким минимумом (LL) за последние n баров, то условие LL < цена < HH всегда истинно. Поэтому и int CExpertSignal::LongCondition(...), и int CExpertSignal::ShortCondition(...) должны всегда определять паттерн 0 "пробой", и какое бы значение мы ни связали с этим паттерном, функция int CExpertSignal::Direction() всегда будет возвращать ноль!

Естественный подход заключается в перегрузке

  1. bool CExpertSignal::CheckOpenLong(...) и
  2. bool CExpertSignal::CheckOpenShort(...)

таким образом, чтобы первый проверял

  1. LongCondition()>m_threshold_open, а второй проверяет
  2. ShortCondition()>m_threshold_open

вместо

  1. m_direction>=m_threshold_open и
  2. -m_direction>=m_threshold_open

пока не удалось превратить в удачную версию. Как уже отмечалось, было бы просто сделать так, чтобы bool CExpertSignal::OpenLongParams(...) возвращала цену входа HH, а bool CExpertSignal::OpenShortParams(...)возвращала цену входа LL для завершения сигнала, постоянно генерирующего 2 стоп-ордера.

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

  1. buy high и sell higher или sell low и buy lower, а также альтернативный вариант
  2. buy low и sell high или sell high и buy low.

предоставляя их в виде паттернов. Буду крайне признателен за помощь в доработке данного подхода.

 
AnonymousTrades:

Привет всем,

Меня интересует, как создать потомка CExpertSignal с двумя паттернами "выход" и "вход" в наблюдаемый торговый диапазон, используя подход, предложенный здесь, а также в Exploring Trading Strategy Classes of the Standard Library - Customizing Strategie by Harvester. Я считаю, что каждый класс сигналов может (должен) быть реализован путем перегрузки двух функций

int CSignalBreakOutOrIn::LongCondition()  { if(IS_PATTERN_USAGE(X) && LongConditionForPatternX(idx)) return(m_pattern_X); }
int CSignalBreakOutOrIn::ShortCondition() { if(IS_PATTERN_USAGE(X) && ShortConditionForPatternX(idx)) return(m_pattern_X); }

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

[...]

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


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

  1. Мастер MQL5: Как создать модуль торговых сигналов (эта) и
  2. Exploring Trading Strategy Classes of the Standard Library - Customizing Strategies от Harvester Trading

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

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

  • Direction()>=m_threshold_open на
  • LongCondition()>=m_threshold_open, например,

но, похоже, это все равно не работает. Это не имеет никакого смысла, потому что я также перегрузил функции OpenLongParams(...) и OpenShortParams(...). Они определяют уровни, на которых нужно размещать желаемые стоп-ордера. Может ли кто-нибудь, кто лучше разбирается в идеях разработчиков MetaQuotes, объяснить, как бы они реализовали эту простейшую стратегию прорыва?

Поскольку исходный код часто рассматривается как лучшая документация к любому программному обеспечению, я потратил некоторое время на анализ класса CExpertSignal в MQL5\Include\Expert\ExpertSignal.mqh.

В результате оказалось, что функции, проверяющие торговые условия, сводятся, по сути, к проверке значения функции Direction() { return(LongCondition()-ShortCondition()); } следующим образом:

bool CExpertSignal::CheckOpenLong(...)     { if(Direction()>=m_threshold_open && OpenLongParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckOpenShort(...)    { if(-Direction()>=m_threshold_open && OpenShortParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckCloseLong(...)    { if(-Direction()>=m_threshold_close && CloseLongParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckCloseShort(...)   { if(Direction()>=m_threshold_close && CloseShortParams(price,sl,tp,expiration)) return(true); return(false); }
bool CExpertSignal::CheckReverseLong(...)  { if(!CheckCloseLong(c_price) || !CheckOpenShort(price,sl,tp,expiration)) return(false); return(true); }
bool CExpertSignal::CheckReverseShort(...) { if(!CheckCloseShort(c_price) || !CheckOpenLong(price,sl,tp,expiration)) return(false); return(true); }

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

Это резюме показывает, что для любого класса стратегии достаточно перегрузить функции

  1. int CExpertSignal::LongCondition(...),
  2. int CExpertSignal::ShortCondition(...),
  3. bool CExpertSignal::OpenLongParams(...),
  4. bool CExpertSignal::OpenShortParams(...),
  5. bool CExpertSignal::CloseLongParams(...), и
  6. bool CExpertSignal::CloseShortParams(...)

а в статье Harvester 2. по ссылке выше объясняется, как использовать макрос IS_PATTERN_USAGE(x) в первых двух из них так, чтобы результирующий сигнал обнаруживал несколько предопределенных паттернов.

Я вижу такую проблему: условие, находится ли цена между самым высоким максимумом и самым низким минимумом за последние n баров, должно быть всегда истинным. Поэтому и LongCondition(...), и ShortCondition(...) возвращают одно и то же значение, связанное с паттерном для торговли на прорывах, а значение Direction() обязательно равно нулю, если только условия в CheckOpenLong(...) и CheckOpenShort(...) не изменены.

Но почему не достаточно использовать LongCondition()>=m_threshold_open и ShortCondition()>=m_threshold_open?

 
yankai0219:

Когда я использую файл, который вы прикрепили к статье, что-то не так.

Я нахожу, что комментарий о Type должен быть следующим:

//| Type=SignalAdvanced                                          |

Спасибо за ваше сообщение. Ваше сообщение решило мою проблему. Будьте здоровы!

Джордж

 

Здравствуйте,

Когда я скомпилировал код, я получил три предупреждения

объявление 'm_open' скрывает член samplesignal.mqh 42 23

Объявление 'm_close' скрывает члена samplesignal.mqh 43 23

Объявление 'm_expiration' скрывает члена samplesignal.mqh 52 23


m_open и m_close были определены в ExpertBase.mqh, но с разным типом.

m_expiratin был определен в ExpertSignal.mqh.

Закомментируйте три вышеприведенные строки. Предупреждения исчезли.

Джордж

 
Если есть возможность переписать точный, полный и исполняемый код этой программы, исправить ошибки и выложить его здесь
 
touhid Qolizadeh #:
Если есть возможность переписать точный, полный и исполняемый код этой программы, исправить ошибки и выложить его здесь

Вот, пожалуйста!

Будьте здоровы, Зарик

Файлы: