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

 

Спасибо, Энрико,

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

Например, у меня есть основной сигнал и он дает сигнал на вход Long. Затем проверяется второй сигнал. И если он тоже дает Long, то общий сигнал будет Long. Но если второй сигнал дает Long, а первый нейтрален, то общий сигнал тоже должен быть нейтральным, так как второй сигнал - это просто дополнительный фильтр к первому сигналу и сам по себе не является сигналом входа.

Кроме того, есть ли способ контролировать управление капиталом на основе конкретного сигнала. Например, при таком сигнале лот будет 1, при другом - 2 и так далее. В связи с моим первым вопросом, лот по умолчанию будет для 1-го сигнала, но в случае подтверждения от 2-го сигнала лот будет удвоен, например.

Спасибо.

 
mbjen:

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

Например, у меня есть основной сигнал и он дает сигнал на вход Long. Затем проверяется второй сигнал. И если он тоже дает Long, то общий сигнал будет Long. Но если второй сигнал дает Long, а первый нейтрален, то общий сигнал тоже должен быть нейтральным, так как 2-й сигнал - это просто дополнительный фильтр к 1-му сигналу, и сам по себе он не является сигналом входа.

Это возможно. Самый простой способ - объединить два сигнала в одном экземпляре потомка CSignal. Вы также можете создать экземпляр CSignals внутри потомка CSignal, и пусть подфильтры соответствующим образом изменяют родительский сигнал.

mbjen:

Кроме того, есть ли способ контролировать управление капиталом на основе конкретного сигнала. Например, при этом сигнале лот будет равен 1, при другом сигнале - 2 и так далее. В связи с моим первым вопросом, лот по умолчанию был бы для 1-го сигнала, но в случае подтверждения от 2-го сигнала лот был бы удвоен, например.

Да, это возможно. Контейнером экземпляра CSignals является экземпляр CExpertAdvisor, а каждый экземпляр CSignal имеет в качестве родителя один и тот же экземпляр CSignals. Вам просто нужно продолжать получать родителя/контейнер, пока не доберетесь до экземпляра CExpertAdvisor, получить указатель на его менеджера денег, а затем назначить нужный метод управления деньгами по индексу или имени.

 
Enrico Lambino:

Это возможно. Самый простой способ - объединить два сигнала в одном экземпляре потомка CSignal. Вы также можете создать экземпляр CSignals внутри потомка CSignal, а подфильтры будут соответствующим образом изменять родительский сигнал.

Да, это возможно. Контейнером экземпляра CSignals является экземпляр CExpertAdvisor, а каждый экземпляр CSignal имеет в качестве родителя один и тот же экземпляр CSignals. Вам просто нужно продолжать получать родителя/контейнер, пока не доберетесь до экземпляра CExpertAdvisor, получить указатель на его менеджера денег, а затем назначить нужный метод управления деньгами по индексу или имени.


Спасибо, Энрико, я попробую это сделать.

 

Я только начал использовать кросс-платформенный советник.

Я применил индикаторы TEMA и MA в комбинированном сигналеTEMA_MA. Вычислите и LongCondition и ShortCondition, как показано ниже. Я также приложил код советника.


bool SignalTEMA_MA::Calculate(void)
{
   int   tema_ma_state_current=0;
   bool  ret;
   
   if(m_ma.Main(m_signal_bar) >= m_tema.Main(m_signal_bar))
      tema_ma_state_current = 1;
   else
      tema_ma_state_current = -1;

   if (m_tema_ma_state != tema_ma_state_current) {
      ret = m_tema_ma_state == 0 ? false : true;
      m_tema_ma_state = tema_ma_state_current;
   }
   else {
      ret = false;
   }
   return ret;      
}

bool SignalTEMA_MA::LongCondition(void)
  {
   return m_tema.Main(m_signal_bar) > m_ma.Main(m_signal_bar);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool SignalTEMA_MA::ShortCondition(void)
  {
   return m_tema.Main(m_signal_bar) < m_ma.Main(m_signal_bar);
  }


Советник вроде бы работает, однако я получаю нежелательную задержку между пересечением индикатора TEMA/MA и ордером, как показано ниже.
Этот пример был сделан на MT5 EURUSD с 15-минутным периодом с 4 по 6 декабря 2017 года.

Мой вопрос заключается в том, как я могу заставить ордер вводиться как можно ближе к пересечению, насколько это возможно?

Как только я пройду это, я продолжу реализовывать стратегию советника, чтобы, надеюсь, стать прибыльным с дополнительными условиями входа/выхода и фильтрами, а также управлением капиталом.

/Карл


Файлы:
 

Привет, Карл,

Вы можете использовать >= и <=, а не < и > в торговых условиях:

bool SignalTEMA_MA::LongCondition(void)
  {
   return m_tema.Main(m_signal_bar) >= m_ma.Main(m_signal_bar);
  }
//+------------------------------------------------------------------+
//||
//+------------------------------------------------------------------+
bool SignalTEMA_MA::ShortCondition(void)
  {
   return m_tema.Main(m_signal_bar) <= m_ma.Main(m_signal_bar);

На третьем выделенном круге на вашем снимке экрана советник слишком поздно открыл короткую сделку. Приведенный выше код заставит эту сделку на продажу войти на 1 бар раньше.

Если вы хотите, чтобы советник торговал на самом кресте (2 бара назад, свеча, на которой находится выделенный круг), то вы можете использовать те же настройки, но с m_signal_bar = 0 (текущий бар). Это обеспечит вход в сделку как можно ближе к пересечению, но данные на этом баре часто перерисовываются. Индикаторы могут пересечься во время формирования бара, они могут сохранить это до закрытия бара, а могут и не пересечься.

 
Enrico Lambino:

Привет, Карл,

Вы можете использовать >= и <=, а не < и > в своих торговых условиях:

На третьем выделенном круге на вашем снимке экрана советник слишком поздно заключил короткую сделку. Приведенный выше код заставит эту сделку на продажу войти на 1 бар раньше.

Если вы хотите, чтобы советник торговал на самом кресте (2 бара назад, свеча, на которой находится выделенный круг), то вы можете использовать те же настройки, но с m_signal_bar = 0 (текущий бар). Это обеспечит вход в сделку как можно ближе к пересечению, но данные на этом баре часто перерисовываются. Индикаторы могут пересекаться во время формирования бара, могут сохранять это до закрытия бара, а могут и не пересекаться.


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

Большое спасибо за быстрый ответ. Я попробую воспользоваться вашими рекомендациями.

/Карл

 
Karl Klang:


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

Большое спасибо за быстрый ответ. Я попробую воспользоваться вашими рекомендациями.

/Карл

Привет еще раз, Энрико,

Я провел несколько тестов в эти выходные. Я изменил торговые условия на >= и <=, как вы указали, но торговля не двигается на 1 бар раньше, к сожалению (см. фрагмент ниже).


Я также попробовал установить signal_bar=0. Теперь он торгует на самом кроссе, но я получаю много нежелательных сделок, несмотря на то, что one_trade_per_candle=true и position_reverse=true в вызове expert.Init (см. фрагмент ниже).

Текущий исходный файл эксперта прилагается.

Файлы:
 

Может быть, следующее условие в CExpertAdvisorBase::OnTick(void) неверно?

   if((checkopenlong || checkopenshort)
      && (m_every_tick || IsNewBar(m_symbol_name,m_period))
      && (!CheckPointer(m_times) || m_times.Evaluate()) 
      && (!m_one_trade_per_candle || m_last_trade_time<Time(0))
   )

Оно должно быть таким?

   if((checkopenlong || checkopenshort)
      && (m_every_tick || m_last_trade_time<Time(0))
      && (!CheckPointer(m_times) || m_times.Evaluate()) 
      && (!m_one_trade_per_candle || IsNewBar(m_symbol_name,m_period))
   )


Тогда я получаю следующее :



 
Karl Klang:

Может быть, следующее условие в CExpertAdvisorBase::OnTick(void) неверно?

Оно должно быть таким?


Тогда я получаю следующее :



Привет, Карл,

Это часто бывает проблемой с такими индикаторами, как TEMA. Значения, выдаваемые такими индикаторами, настолько плоские, что иногда довольно сложно подтвердить пересечение. Например, на вашем первом снимке экрана (белый фон), первая и вторая сделки, если вы посмотрите внимательно, два бара назад перед этими сделками, сигнал все еще в противоположном направлении. Таким образом, бар 1 свеча назад является первой свечой, давшей сигнал разворота (что и привело к сделке на следующем баре). Что касается третьей сделки, я не могу утверждать, пока у нас нет значений индикаторов, распечатанных на логах. Визуально индикаторы кажутся непрерывными, но на самом деле данные дискретны.

Что касается CExpertAdvisorBase::OnTick(void), то убедитесь, что при установке сигнального бара = 0, советник имеет m_every_tick = true. Проверка новой свечи отличается от ведения одной сделки на свечу.

 

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

Я нашел способ обработки функции Calculate, включающий функцию гистерезиса, которая, похоже, работает при пересечении MA и индикатора TEMA.

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

Здесь все работает нормально:


Но здесь менеджер ордеров начинает выставлять несколько ордеров:


Когда я отлаживал следующую часть кода COrderManager, оператор orders_total = OrdersTotal(); становится 1, когда он работает, но становится 0, когда он не работает, что приводит к тому, что условие if m_max_order>orders_total всегда оценивается как true.

bool COrderManager::TradeOpen(const string symbol,ENUM_ORDER_TYPE type,double price,bool in_points=true)
  {
   bool ret=false;
   double lotsize=0.0;
   int trades_total =TradesTotal();
   int orders_total = OrdersTotal();
   m_symbol=m_symbol_man.Get(symbol);
   if(!IsPositionAllowed(type))
      return true;
   if(m_max_orders>orders_total && (m_max_trades>trades_total || m_max_trades<=0))

Надеюсь, вы сможете помочь разобраться с этим.

С наилучшими пожеланиями/
Karl