Опыты написания робота для ФОРТС (обработка ошибок исполнения приказов) - страница 2

 
sergeev:

есть интересные тонкости программирования (которые все в конечном итоге есть в документации по торговым операциям),

но есть просто базовые понятия программирования, это совсем другое.

----

совет - ловить отчет открытия в OnTrade/OnTradeTransaction - правильный.

но если у sanderz пробелы в знаниях именно в программировании, то надо это исправить чем раньше тем лучше.

Думаю, что в программировании я могу многим дать фору ;-) Однако mql мне не знаком, я пишу, можно сказать, с наскока. Мне не был ясен алгоритм взаимодействия с сервером. Теперь понятно, что выполнение программы не останавливается на период ожидания ответа сервера. Буду изучать примеры и переписывать. Спасибо :)

И, конечно, буду исправлять пробелы :)

 
sanderz:

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

не совсем.  открытие ордера происходит в два этапа.

1. Отправка OrderSend/Async. На этом этапе терминал получает ответ от сервера про принятие заявки. То есть функция вам вернет напрямую ответ от сервера. Никаких пауз после вызова OrderSend/Async делать просто не имеет смысла. Она сама по себе уже подождала и дала вам ответ. (Если юзаете просто OrderSend - вам также вернется тикет ордера.)

После вызова OrderSend/Async программа может делать сразу все что угодно. Вам нужно просто перейти на второй этап -

2. Ожидание события в функции OnTrade/OnTradeTransaction. То есть ожидание отчета по сделкам или подтверждение установки отложек, по переданному вам вначале тикета ордера (или если пользовались Async, то косвенно определяете что нужный вам ордер принят и открыт).
Пока вы ждете ответ/подтверждения на втором этапе, то вы можете выполнять другие действия, вплоть до отправки новых ордеров (OrderSend/Async).

 
sergeev:

не совсем.  открытие ордера происходит в два этапа.

1. Отправка OrderSend/Async. На этом этапе терминал получает ответ от сервера про принятие заявки. То есть функция вам вернет напрямую ответ от сервера. Никаких пауз после вызова OrderSend/Async делать просто не имеет смысла. Она сама по себе уже подождала и дала вам ответ. (Если юзаете просто OrderSend - вам также вернется тикет ордера.)

После вызова OrderSend/Async программа может делать сразу все что угодно. Вам нужно просто перейти на второй этап -

2. Ожидание события в функции OnTrade/OnTradeTransaction. То есть ожидание отчета по сделкам или подтверждение установки отложек, по переданному вам вначале тикета ордера (или если пользовались Async, то косвенно определяете что нужный вам ордер принят и открыт).
Пока вы ждете ответ/подтверждения на втором этапе, то вы можете выполнять другие действия, вплоть до отправки новых ордеров (OrderSend/Async).

Спасибо за исчерпывающий ответ! Теперь мне действительно всё понятно! 

(а то приходилось стопы вручную за роботом ставить из-за своих кривых рук) :) :) :)

 

sanderz:

а то приходилось стопы вручную за роботом ставить

поясните что вы имеете ввиду? вы просто эксперту не доверяете выставление стопов или вы считаете, что выставление стопов экспертом невозможно?
 
sergeev:
поясните что вы имеете ввиду? вы просто эксперту не доверяете выставление стопов или вы считаете, что выставление стопов экспертом невозможно?
нет. У меня шло подряд два метода. Установить ордер и тут же поставить по позиции. Но позиции обычно еще не было к тому моменту, когда я пытался поставить по ней стопы. Соответственно, я получал уведомление об открытой позиции и после этого уже сам, вручную, ставил стопы, которые робот, из-за некорректного алгоритма, поставить не мог.
 

Изучил тут статью:

https://www.mql5.com/ru/articles/481

Мне она показалась интересной, потому что я тоже использую класс CTrade.

1. Там для метода OrderSend() используется методы обертки (?) Buy и Sell. Так ведь можно сказать? Я посмотрел библиотеку, и, понимаю, что спокойно могу отказаться от использования голого OrderSend() в своей программе, заменив его методами библиотеки, верно?

2. В статье есть вот такая конструкция:

//--- 1. пример покупки по текущему символу
   if(!trade.Buy(0.1))
     {
      //--- сообщим о неудаче
      Print("Метод Buy() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод Buy() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Я думаю переписать свои функции в одну рекурсивную функцию.

(я с помощью *** выделил в тексте вопросы, пожалуйста, помогите ответом) :)

Спасибо!


//+------------------------------------------------------------------+
//|   Рекурсивная функция для торговли. Сама торгует снова и снова.  |
//+------------------------------------------------------------------+
bool MakeTradeRecursive(CTrade &m_Trade,int Direction,string OrderComment,int TryCounter)
  {

   TryCounter++;

   // Проверим на максимальное число попыток открытия ордера
   if(TryCounter>MaxTry)
     {
      // Пытаться нету больше сил, возвращаем неудачу...
      Print("-------- НЕ УДАЛОСЬ ВЫПОЛНИТЬ ТОРГОВЫЙ ЗАПРОС! ПОЗИЦИЯ НЕ БУДЕТ ОТКРЫТА");
      return false;
     }

   bool Success=false; // Сюда запишем результат отправки ордера на сервер.

   if(Direction==1)  {Success = m_Trade.Buy (Lots,NULL,0,0,0,OrderComment);}
   if(Direction==-1) {Success = m_Trade.Sell(Lots,NULL,0,0,0,OrderComment);}

   if(Success)
     {
      // Отправка торгового запроса на сервер прошла успешно. 
      // *** тут можно проверять результат его исполнения 
      //     с помощью m_Trade.ResultRetcode(), верно?
      

      Print("-------- Попытка: "+IntegerToString(TryCounter)+". УСПЕШНО отправлен торговый запрос!");

      // Чтобы определить нужен ли повтор (по результатам обработки на сервере, 
      // я воспользуюсь функцией из сообщения:
      // https://www.mql5.com/ru/forum/12207#comment_505716

      int RetCode=m_Trade.ResultRetcode();
      string RetCodeStr=ResultRetcodeDescription(RetCode);
      if(ResultRetcodeCheck(RetCode))
        {
         Print("-------- Торговый запрос принят сервером! "+RetCodeStr);
         // все отлично, теперь даже если ордер выполнен хоть частично, 
         // я могу поставить стопы, но надо это делать не здесь, а в событии OnTrade.
        }
      else
        {
         // *** Если результат негативный - значит можно повторить отправку запроса, верно?
         Print("-------- Торговый запрос отвергнут сервером! "+RetCodeStr);
         // *** Разумно ли перед повтором подождать несколько секунд?
         //Sleep(1000*TryCounter); 
         // Отправим еще один запрос, что ли...
         Success=MakeTradeRecursive(m_Trade,Direction,OrderComment,TryCounter);
        }
     }
   else
     {
      // Торговый запрос даже не ушел, значит надо попрбовать еще раз.
      // 
      Print("-------- Попытка: "+IntegerToString(TryCounter)+". ОШИБКА отправки торгового запроса!");
      // *** Разумно ли перед повтором подождать несколько секунд?
      //Sleep(1000*TryCounter);
      Success=MakeTradeRecursive(m_Trade,Direction,OrderComment,TryCounter);
      CTrade m_Trade;
     }
   return Success;

  }

Функции проверки реткодов взял из сообщения https://www.mql5.com/ru/forum/12207#comment_505716

Торговые операции на MQL5 - это просто
Торговые операции на MQL5 - это просто
  • 2012.08.21
  • MetaQuotes Software Corp.
  • www.mql5.com
Почти все трейдеры приходят на рынок для того, чтобы заработать денег, хотя есть и доля тех, кому важен не сам торговый результат, а участие в процессе, драйв. Впрочем, получить удовольствие от процесса можно не только торгуя вручную, но и занимаясь разработкой автоматических торговых систем. Ведь создание торгового робота может быть таким же интересным занятием, как и чтение хорошего детектива.
 

Еще один вопрос по работе с OnTrade()

Вводные. По каждому инструменту у меня позиция формируется только одним экспертом, даже если сигналов несколько. Правильно ли я понимаю, что для установки стоплосса мне достаточно:

1. При успешной отправке ордера на сервер заполнить значения двух общедоступных переменных, например:

   PendingSL = 140000;

   PendigTP = 145000;

2. В событии OnTrade() проверять, что эти переменные не равны нулю и то что есть позиция ( m_Info.Select(Symbol())  ) без SL

3. Модифицировать позицию соответствующими значениями PendinSL и PendingTP. Можно рекурсивно и отправляя Push-сообщения, если что-то не сработало.

4. Если всё успешно - сбрасывать значения PendinSL и PendingTP в ноль, чтобы в следующий раз алгоритм модицификации не вызывался.

Нормально? Или я что-то специфическое не учёл?