Обсуждение статьи "Кроссплатформенный торговый советник: Стоп-уровни"

 

Опубликована статья Кроссплатформенный торговый советник: Стоп-уровни:

В этой статье рассматривается реализация стоп-уровней в торговом советнике, совместимая с платформами MetaTrader 4 и MetaTrader 5.

Операция по созданию стоп-уровней в общем виде показана на следующей картинке:

Общий вид операции создания стоп-уровней

Как показано на двух предыдущих блок-схемах, новый экземпляр COrder создается сразу же после успешного открытия сделки. После этого для каждого установленного уровня стоп-лосса и тейк-профита создаются экземпляры COrderStop. Если при инициализации советника не объявлен экземпляр СStop, этот этап процесса пропускается. И наоборот, если созданы экземпляры COrderStop, указатели на них будут сохранены в ранее созданном экземпляре COrder.

Автор: Enrico Lambino

 

Какой метод следует использовать для установки SL/TP на определенное значение, но не как расстояние от цены открытия?

 
Это будут методы StopLossCustom и TakeProfitCustom. Эти методы будут рассмотрены в следующей статье.
 

Я попытался использовать несколько стопов в своем советнике. Добавил вашу функцию manage_trades() и вот что я получил после активации последнего стопа (позиция закрыта):

2017.09.10 09:48:25.706 2017.01.03 17:50:23   failed market buy 0.00 EURUSD [Invalid volume]
2017.09.10 09:48:25.706 2017.01.03 17:50:23   CTrade::OrderSend: market buy 0.00 EURUSD [invalid volume]
2017.09.10 09:48:25.706 2017.01.03 17:50:23   position #2  is already closed, closing object..
2017.09.10 09:48:25.706 2017.01.03 17:50:23   failed market buy 0.00 EURUSD [Invalid volume]
2017.09.10 09:48:25.706 2017.01.03 17:50:23   CTrade::OrderSend: market buy 0.00 EURUSD [invalid volume]
2017.09.10 09:48:25.707 2017.01.03 17:50:23   position #2  is already closed, closing object..
2017.09.10 09:48:25.707 2017.01.03 17:50:23   failed market buy 0.00 EURUSD [Invalid volume]
2017.09.10 09:48:25.707 2017.01.03 17:50:23   CTrade::OrderSend: market buy 0.00 EURUSD [invalid volume]

Использую 3 стопа, все они виртуальные.

Это что-то с лотом. Я использую фиксированный лот 0.1. После первого закрытия оставшийся объем 0,06. После последнего закрытия (основной стоп без указанного объема) я получаю вышеуказанную ошибку.

Когда лот выше, все нормально. То же самое с вашими примерами советников.

 
mbjen:

Я попытался использовать несколько стопов в своем советнике. Добавил вашу функцию manage_trades() и вот что я получил после активации последнего стопа (позиция закрыта):

Использую 3 стопа, все они виртуальные.

Это что-то с лотом. Я использую фиксированный лот 0.1. После первого закрытия оставшийся объем 0,06. После последнего закрытия (основной стоп без указанного объема) я получаю вышеуказанную ошибку.

Когда лот выше, все нормально. То же самое и с вашими примерами советников.

Убедитесь, что вы используете последнюю версию библиотеки (ту, что прикреплена в этой статье). Также, если вы можете прикрепить исходный код вашего советника, это очень поможет.

 
Enrico Lambino:

Убедитесь, что вы используете последнюю версию библиотеки (та, что прикреплена в этой статье). Также, если вы можете прикрепить исходный код вашего советника, это очень поможет.


Да, я обновил все файлы, прикрепленные к этой статье. Но я не знаю, может быть, вы обновили их еще раз.

Не могли бы вы попробовать с вашим образцом stop_ha_ma2, изменив ММ на фиксированный лот и изменив размер лота на какое-то небольшое значение?

 
mbjen:

Да, я обновил все файлы, прикрепленные к этой статье. Но я не знаю, может быть, вы обновили их еще раз.

Не могли бы вы попробовать с вашим образцом stop_ha_ma2, изменив ММ на фиксированный лот и изменив размер лота на какое-то небольшое значение?

Не могли бы вы выложить здесь исходный код советника, в котором возникла проблема? Наш разговор является публичным, и ошибка, которую вы опубликовали выше, является серьезной проблемой для советника. Я хотел бы, чтобы другие читатели тоже извлекли пользу из этого разговора, предоставив им возможность протестировать ваш код.
 
Enrico Lambino:
Не могли бы вы опубликовать здесь исходный код советника, в котором возникла эта проблема? Наш разговор публичный, и ошибка, которую вы опубликовали выше, является серьезной проблемой для советника. Я хотел бы, чтобы другие читатели тоже извлекли пользу из этого разговора, предоставив им возможность протестировать ваш код.

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

Спасибо.

 
mbjen:

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

У меня модифицированный советник, созданный из частей одного из примеров советников. Сначала я задался вопросом, что не так с вашим кодом. Но поскольку вы упомянули, что теперь ошибок нет, я не совсем уверен в том, что вызвало проблему, с которой вы столкнулись. Если вы столкнетесь с ней снова, просто дайте мне знать либо здесь, либо в PM.
 

Привет, Энрико,


Хотел обратить внимание, что нашел пару ошибок в вашем коде. в ExpertAdvisorBase функция Time имеет вид;

datetime CExpertAdvisorBase::Time(const int index=0)
  {
   if(index>=0)
     {
      double time[];
      if(CopyTime(m_symbol_name,m_period,index,1,time)>0)
         return(time[0]);
     }
   return(-1);
  }

когда она должна быть такой, как показано ниже. Тип времени выше - double вместо datetime.

datetime CExpertAdvisorBase::Time(const int index=0)
  {
   if(index>=0)
     {
      datetime time[];
      if(CopyTime(m_symbol_name,m_period,index,1,time)>0)
         return(time[0]);
     }
   return(-1);
  }

Кроме того, функция Evaluate в TimesBase не передает значение по умолчанию;

bool CTimesBase::Evaluate(datetime current) const

Если изменить на нижеприведенное, то так и должно быть;

bool CTimesBase::Evaluate(datetime current) const

При компиляции папки Base\Order файлы выдают множество ошибок.

Например, функция CreateStops в OrderBase, см. ниже;

void COrderBase::CreateStops(CStops *stops)
  {
   if(!CheckPointer(stops)) return;
   if(stops.Total()>0)
     {
      for(int i=0;i<stops.Total();i++)
        {
         CStop *stop=stops.At(i);
         if(CheckPointer(stop)==POINTER_INVALID) continue;
         m_order_stops.NewOrderStop(GetPointer(this),stop);
        }
     }
  }

Выбрасывает 'operator=' - ни одна из перегрузок не может быть применена к вызову функции OrderBase.mqh

'At' - ожидается указатель объекта OrderBase.mqh

Base\Stop также имеет те же проблемы с выбросом ряда ошибок, связанных со стопами, типами и т.д.

Спасибо за хорошую работу, Shep

 
Привет, Шеп,
Shephard Mukachi:

Привет Энрико,


Хотел обратить внимание, что я нашел пару ошибок в вашем коде. В ExpertAdvisorBase функция Time имеет вид;

когда она должна быть такой, как показано ниже. Тип времени выше - double вместо datetime.

Шепард Мукачи:

Привет, Энрико,


Кроме того, функция Evaluate в TimesBase не передает значение по умолчанию;

Если изменить ее на приведенную ниже, то она должна передавать;

Спасибо, что указали на это. Я не замечал этого до сих пор. Я обновлю код.

Шепард Мукачи:

При компиляции папки Base\Order файлы выдают много ошибок.

Например, функция CreateStops в OrderBase, ниже;

Выбрасывает 'operator=' - ни одна из перегрузок не может быть применена к вызову функции OrderBase.mqh

'At' - ожидается указатель объекта OrderBase.mqh

Base\Stop также имеет те же проблемы с выбросом ряда ошибок, связанных со стопами, типами и т.д.

Спасибо за хорошую работу, Шеп.

Да, я знаю об этом. Это все еще связано с прямыми объявлениями. CStop требует в своих методах экземпляры COrder и COrderStop. То же самое происходит и при попытке скомпилировать CStop. Все эти классы, которые требуют друг друга, должны быть скомпилированы вместе. При компиляции каждого из них по отдельности будут возникать ошибки. Например:

class Object1
{
public:
   Object2 *m_object2;
   Object1(){}
  ~Object1(){}
};

class Object2
{
public:
   Object1 *m_object1;
   Object2(){}
  ~Object2(){}
};

This не скомпилируется. Вы должны объявить прямое объявление, чтобы компилятор распознал член класса m_object2 внутри класса Object1:

class Object2;
class Object1
{
public:
   Object2 *m_object2;
   Object1(){}
  ~Object1(){}
};

class Object2
{
public:
   Object1 *m_object1;
   Object2(){}
  ~Object2(){}
};

Это нормально, если Object1 и Object2 находятся в одном файле. Если же они находятся в двух разных файлах, то вам нужно сделать прямое объявление для Object2 в файле класса Object1, а для Object1 - в файле класса Object 2. Тогда компилятор не выдаст ошибок, если вы скомпилируете любой из файлов. Это так, пока вы не добавите методы в один из двух классов.

Текущая версия компилятора распознает прямые объявления, но не перечисленные методы класса, объявленного прямо. Именно поэтому вы не получаете сообщений об ошибках типа "CStop - объявление без типа", но получаете сообщения об ошибках компилятора для методов, подобных тому, что вы опубликовали выше. Компилятор распознает класс, но не методы класса, который был объявлен прямо.