Обсуждение статьи "Реализация мультивалютного режима в MetaTrader 5" - страница 5

 
Lazarev:

скажите,

1. если мне нужет только Bid и Ask c других валют, обьективно ли пользоваться "шпионами"

2. это просто идея, нет ли возможности в функции onChartEvent проверять события с других валют а не только с текущей?

3. нельзя ли в событии onTimer поставить значение таймера меньше еденицы, чтобы он скачивал значение котировок намного чаще и соответственно отставал от времени последнего тика на минимальное время

4. или можно ли с помощью "CHARTEVENT_CUSTOM+n" проверять, в моем случае пересечение машек, на других граффиках? 

1. Пользуюсь.

2. Есть возможность. Событие с другой валюты должно быть отправлено на график, где установлен эксперт с OnChartEvent().

3. Нет. Единица - это минимум.

4. Можно.  

 

Создал простой "индикатор-шпион" SendEvent.mq5, отправляющий событие при поступлении новой котировки:

#property indicator_chart_window
#property indicator_plots 0
int OnInit()
  {
   return(0);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   EventChartCustom(0,1,0,0,_Symbol);
   return(rates_total);
  }

Создал простой советник, который получает события от этого индикатора и пытается совершить торговую операцию (привожу часть, полный текст в приложенном файле):

void OnChartEvent(const int id, // Обработчик события ChartEvent
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)            // sparam содержит название инструмента
  {
      // запрашиваем Digit,Point,Ask,Bid для инструмента, для которого пришло событие
      if(!SymbolInfoInteger(sparam,SYMBOL_DIGITS,dig)) Print("SymbolInfoInteger(SYMBOL_DIGITS) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_POINT,p)) Print("SymbolInfoDouble(SYMBOL_POINT) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_BID,Bid)) Print("SymbolInfoDouble(SYMBOL_BID) ERROR!");
      if(!SymbolInfoDouble(sparam,SYMBOL_ASK,Ask)) Print("SymbolInfoDouble(SYMBOL_ASK) ERROR!");
      d=(int)dig;
      if(1>0) // всегда покупаем
        {
         q.action=TRADE_ACTION_DEAL; // заполняем структуру MqlTradeRequest и пытаемся совершить торговую операцию
         q.symbol=sparam; // sparam содержит имя инструмента
         q.volume=Lot;
         q.price=NormalizeDouble(Ask,d);
         q.sl=NormalizeDouble(Ask-p*StopLoss,d);
         q.tp=NormalizeDouble(Ask+p*TakeProfit,d);
         q.deviation=0;
         q.type=ORDER_TYPE_BUY;
         q.type_filling=ORDER_FILLING_FOK;
         // проверяем текущие свойства инструмента
         Print("Bid=",DoubleToString(Bid,8),", Ask=",DoubleToString(Ask,8),", Digits=",d,", Points=",DoubleToString(p,8));
         // проверяем структуру торгового запроса, который будем отправлять
         Print("q.action=",q.action,", q.symbol=",q.symbol,", q.volume=",q.volume,", q.price=",DoubleToString(q.price,d),", q.sl=",DoubleToString(q.sl,d),", q.tp=",DoubleToString(q.tp,d),", q.deviation=",q.deviation,", q.type=",q.type,", q.type_filling=",q.type_filling);
         Print(OrderCheck(q,ch));                                  // проверка возможности совершить торговую операцию
         Print("ch.retcode=",ch.retcode,", ch.comment=",ch.comment); // результат
         Print("OrderSend:",OrderSend(q,s));                        // попытка совершить торговую операцию
         Print("s.retcode=",s.retcode,", s.comment=",s.comment);     // результат
        }
      if(0>0) // если исправить условие - будем продавать
        {
         // аналогично для продажи
        }
     }
  }

Советник получает события от индикатора, но в тестере (и с визуализацией и без нее) не может выполнить торговую операцию - возвращается ошибка  "Invalid Request", код возврата 10013. В реальном времени работает нормально. Если в советнике торговую операцию совершать из OnTick() вместо OnChartEvent() - тоже работает нормально.

Вставил отправку торгового запроса в шаблон советника, предлагаемый автором статьи в CodeBase - тоже не работают торговые операции (та же ошибка).

Кто-нибудь подскажет в чем причина? Читал в этой ветке, что  в тестере не обрабатывается OnChartEvent(), но, в данном случае события, присылаемые индикатором, в тестере обрабатываются, но невозможно выполнить в тестере торговую операцию из OnChartEvent().

Файлы:
ea.mq5  4 kb
SendEvent.mq5  1 kb
 
zdd:

Создал простой "индикатор-шпион" SendEvent.mq5, отправляющий событие при поступлении новой котировки:

Создал простой советник, который получает события от этого индикатора и пытается совершить торговую операцию (привожу часть, полный текст в приложенном файле):

Советник получает события от индикатора, но в тестере (и с визуализацией и без нее) не может выполнить торговую операцию - возвращается ошибка  "Invalid Request", код возврата 10013. В реальном времени работает нормально. Если в советнике торговую операцию совершать из OnTick() вместо OnChartEvent() - тоже работает нормально.

Вставил отправку торгового запроса в шаблон советника, предлагаемый автором статьи в CodeBase - тоже не работают торговые операции (та же ошибка).

Кто-нибудь подскажет в чем причина? Читал в этой ветке, что  в тестере не обрабатывается OnChartEvent(), но, в данном случае события, присылаемые индикатором, в тестере обрабатываются, но невозможно выполнить в тестере торговую операцию из OnChartEvent().

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

По крайней мере позиции с рынка открывает и в тестере и на демке.

Не знаю по чему (разбираться лень), но Ваш пример у меня при любом раскладе выдавал 10013.

PS

Лучше привязаться к стандартным объектам (таким как CAccountInfo и CTrade). Но, если у Вас терпения хватит самостоятельно все прописать буду только рад.

Кстати, реализацию самого шпиона лучше взять из статьи, либо сделать модифицируемую копию (я, к примеру, предлагаю заменить вот этот год "(long)_Period" на дату-время отправки события или иную полезную инфу). Ваш вариант как-то совсем "сыроват".

Файлы:
DemoEA.mq5  20 kb
 
Interesting:

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

Спасибо, разобрался. Если объявлять структуры MqlTradeRequest и MqlTradeResult на глобальном уровне, то работает!
 
Большое спасибо за статью!
 

Пытаюсь получить цены по трем парам EURUSD, EURGBP, GBPUSD. Все работает хорошо при выборе "Все тики", либо "Только цены открытия" в тестере стратегий. Но если я выбираю "Каждый тик на основе реальных тиков", то почему то в однму минуту по одному инструменту может прийти несколько событий "Новый бар". 

Чтобы повторить, можно выбрать интервал, например с 2016.07.15 по 2016.07.19. Вот пример лога, смотрим 7-ую минуту, 9-ую минуту:

2016.07.15 00:05:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333

2016.07.15 00:05:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.1119

2016.07.15 00:05:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33399

2016.07.15 00:06:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8334

2016.07.15 00:06:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.1119

2016.07.15 00:06:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33394

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33382

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33381

2016.07.15 00:07:19 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.8333700000000001

2016.07.15 00:07:19 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11174

2016.07.15 00:07:19 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33384

2016.07.15 00:08:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83329

2016.07.15 00:08:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11167

2016.07.15 00:08:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33394

2016.07.15 00:09:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83327

2016.07.15 00:09:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11166

2016.07.15 00:09:00 >  -> id=1:  GBPUSD CHARTEVENT_NEWBAR_M1 price=1.33396

2016.07.15 00:09:00 >  -> id=2:  EURGBP CHARTEVENT_NEWBAR_M1 price=0.83327

2016.07.15 00:09:00 >  -> id=0:  EURUSD CHARTEVENT_NEWBAR_M1 price=1.11166

С чем связано такое поведение при выборе режима "Все тики на основе реальных" ?
 
ooparadise:

Пытаюсь получить цены по трем парам EURUSD, EURGBP, GBPUSD. Все работает хорошо при выборе "Все тики", либо "Только цены открытия" в тестере стратегий. Но если я выбираю "Каждый тик на основе реальных тиков", то почему то в однму минуту по одному инструменту может прийти несколько событий "Новый бар". 

Чтобы повторить, можно выбрать интервал, например с 2016.07.15 по 2016.07.19. Вот пример лога, смотрим 7-ую минуту, 9-ую минуту:

С чем связано такое поведение при выборе режима "Все тики на основе реальных" ?

Как отлавливаете событие "Новый бар"? В 1375 билде точность прихода тиков повышена до миллисекунд:

Tester: Добавлена поддержка времени с точностью до миллисекунд. Ранее в тестере стратегий квантом времени являлась одна секунда.

  • Теперь функции EventSetMillisecondTimer и Sleep работают более точно в тестере стратегий.
  • Повысилась точность подачи тиков при тестировании мультивалютных экспертов. Раньше, если в одну секунду укладывалось несколько тиков (тиковый объем минутного бара больше 60), всем им проставлялось одно и то же время. При тестировании моновалютных экспертов это не имеет большого значения, поскольку тики просто последовательно передаются эксперту. Однако при тестировании на нескольких парах важно знать, тик с какой пары пришел первым. Раньше тики по каждому символу передавались эксперту последовательно: сначала все тики за секунду по одному символу, затем - все тики по другому. Теперь они передаются с учетом миллисекунд.

    При тестировании на реальных тиках миллисекунды берутся из исходных тиковых данных. При генерации тиков проставление миллисекунд происходит в соответствии с тиковым объемом. Например, если в одной секунде умещается 3 тика, то им будет проставлено время 000, 333 и 666 миллисекунды.
 

Новый бар отлавливаю так, как написано в статье. То есть индикатор отправляет событие "Новый бар" таким образом (сравнивается с предыдущим временем минуты ,часы, дни, месяцы):

   double price_current=price[rates_total-1];

   TimeCurrent(time);

   if(prev_calculated==0)

     {

      EventCustom(CHARTEVENT_INIT,price_current);

      prev_time=time; 

      return(rates_total);

     }

//--- new tick

   if((flag_event & CHARTEVENT_TICK)!=0) EventCustom(CHARTEVENT_TICK,price_current);       


//--- check change time

   if(time.min==prev_time.min && 

      time.hour==prev_time.hour && 

      time.day==prev_time.day &&

      time.mon==prev_time.mon) return(rates_total);


//--- new minute

   if((flag_event & CHARTEVENT_NEWBAR_M1)!=0) EventCustom(CHARTEVENT_NEWBAR_M1,price_current); 

UPDATE: Проблема ушла при установке билда 1375

 

Спасибо за эту огромную статью. До сих пор я не слышал о EventChartCustom. Я пробовал другие события графика, но они учитывали только события, вызванные действиями человека. Эта статья решает многие вопросы.

Кстати, я работаю на MQL4, там на 98% то же самое.

Будьте здоровы

 

Большое спасибо за это, это так полезно. Отличная работа!