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

 

Всем привет!

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

Мне нужна помощь в обработке ошбок.

Мой код открытия позиции и модифицирования ее:

      CTrade m_Trade;
      CPositionInfo m_Info;
      CSymbolInfo m_Symbol;
      
      //.......

      m_Trade.Sell(Lots,Symbol(),SP,0,0,"продажа");
      InPosition=true;

      m_Trade.PositionModify(Symbol(),m_Symbol.NormalizePrice(SL),m_Symbol.NormalizePrice(TP));

      MyNotificationSend("открыт SELL!");

Итак, вот с чем я столкнулся.

1. Я не проверил результат исполнения запроса, и стал пытаться модифицировать позицию. Конечно, это работает только в тестере. Тут наверное надо использовать ResultRetcode(). Может быть у кого-нибудь есть код разбора возвращаемых вариантов?

2. Исполнение ордера на бирже всегда занимает большее время, чем синхронное исполнение кода. Как мне понять момент, в который следует модифицировать позицию? Может быть использовать возникновение события OnTrade() ?

3. Что обычно надо делать, если ордер не исполнился? Попытаться еще раз в рекурсии? Как обычно делают? :)

В общем, буду благодарен за помощь. Спасибо :)

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров - Документация по MQL5
 
sanderz:

Всем привет!

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

Мне нужна помощь в обработке ошбок.

Мой код открытия позиции и модифицирования ее:

Итак, вот с чем я столкнулся.

1. Я не проверил результат исполнения запроса, и стал пытаться модифицировать позицию. Конечно, это работает только в тестере. Тут наверное надо использовать ResultRetcode(). Может быть у кого-нибудь есть код разбора возвращаемых вариантов?

2. Исполнение ордера на бирже всегда занимает большее время, чем синхронное исполнение кода. Как мне понять момент, в который следует модифицировать позицию? Может быть использовать возникновение события OnTrade() ?

3. Что обычно надо делать, если ордер не исполнился? Попытаться еще раз в рекурсии? Как обычно делают? :)

В общем, буду благодарен за помощь. Спасибо :)

//+------------------------------------------------------------------+
//| возврат стрингового результата торговой операции по его коду     |
//+------------------------------------------------------------------+
string ResultRetcodeDescription(int retcode)
  {
   string str;
//----
   switch(retcode)
     {
      case TRADE_RETCODE_REQUOTE: str="Реквота"; break;
      case TRADE_RETCODE_REJECT: str="Запрос отвергнут"; break;
      case TRADE_RETCODE_CANCEL: str="Запрос отменен трейдером"; break;
      case TRADE_RETCODE_PLACED: str="Ордер размещен"; break;
      case TRADE_RETCODE_DONE: str="Заявка выполнена"; break;
      case TRADE_RETCODE_DONE_PARTIAL: str="Заявка выполнена частично"; break;
      case TRADE_RETCODE_ERROR: str="Ошибка обработки запроса"; break;
      case TRADE_RETCODE_TIMEOUT: str="Запрос отменен по истечению времени";break;
      case TRADE_RETCODE_INVALID: str="Неправильный запрос"; break;
      case TRADE_RETCODE_INVALID_VOLUME: str="Неправильный объем в запросе"; break;
      case TRADE_RETCODE_INVALID_PRICE: str="Неправильная цена в запросе"; break;
      case TRADE_RETCODE_INVALID_STOPS: str="Неправильные стопы в запросе"; break;
      case TRADE_RETCODE_TRADE_DISABLED: str="Торговля запрещена"; break;
      case TRADE_RETCODE_MARKET_CLOSED: str="Рынок закрыт"; break;
      case TRADE_RETCODE_NO_MONEY: str="Нет достаточных денежных средств для выполнения запроса"; break;
      case TRADE_RETCODE_PRICE_CHANGED: str="Цены изменились"; break;
      case TRADE_RETCODE_PRICE_OFF: str="Отсутствуют котировки для обработки запроса"; break;
      case TRADE_RETCODE_INVALID_EXPIRATION: str="Неверная дата истечения ордера в запросе"; break;
      case TRADE_RETCODE_ORDER_CHANGED: str="Состояние ордера изменилось"; break;
      case TRADE_RETCODE_TOO_MANY_REQUESTS: str="Слишком частые запросы"; break;
      case TRADE_RETCODE_NO_CHANGES: str="В запросе нет изменений"; break;
      case TRADE_RETCODE_SERVER_DISABLES_AT: str="Автотрейдинг запрещен сервером"; break;
      case TRADE_RETCODE_CLIENT_DISABLES_AT: str="Автотрейдинг запрещен клиентским терминалом"; break;
      case TRADE_RETCODE_LOCKED: str="Запрос заблокирован для обработки"; break;
      case TRADE_RETCODE_FROZEN: str="Ордер или позиция заморожены"; break;
      case TRADE_RETCODE_INVALID_FILL: str="Указан неподдерживаемый тип исполнения ордера по остатку "; break;
      case TRADE_RETCODE_CONNECTION: str="Нет соединения с торговым сервером"; break;
      case TRADE_RETCODE_ONLY_REAL: str="Операция разрешена только для реальных счетов"; break;
      case TRADE_RETCODE_LIMIT_ORDERS: str="Достигнут лимит на количество отложенных ордеров"; break;
      case TRADE_RETCODE_LIMIT_VOLUME: str="Достигнут лимит на объем ордеров и позиций для данного символа"; break;
      default: str="Неизвестный результат";
     }
//----
   return(str);
  }
//+------------------------------------------------------------------+
//| возврат результата торговой операции для повтора сделки          |
//+------------------------------------------------------------------+
bool ResultRetcodeCheck(int retcode)
  {
   string str;
//----
   switch(retcode)
     {
      case TRADE_RETCODE_REQUOTE: /*Реквота*/ return(false); break;
      case TRADE_RETCODE_REJECT: /*Запрос отвергнут*/ return(false); break;
      case TRADE_RETCODE_CANCEL: /*Запрос отменен трейдером*/ return(true); break;
      case TRADE_RETCODE_PLACED: /*Ордер размещен*/ return(true); break;
      case TRADE_RETCODE_DONE: /*Заявка выполнена*/ return(true); break;
      case TRADE_RETCODE_DONE_PARTIAL: /*Заявка выполнена частично*/ return(true); break;
      case TRADE_RETCODE_ERROR: /*Ошибка обработки запроса*/ return(false); break;
      case TRADE_RETCODE_TIMEOUT: /*Запрос отменен по истечению времени*/ return(false); break;
      case TRADE_RETCODE_INVALID: /*Неправильный запрос*/ return(true); break;
      case TRADE_RETCODE_INVALID_VOLUME: /*Неправильный объем в запросе*/ return(true); break;
      case TRADE_RETCODE_INVALID_PRICE: /*Неправильная цена в запросе*/ return(true); break;
      case TRADE_RETCODE_INVALID_STOPS: /*Неправильные стопы в запросе*/ return(true); break;
      case TRADE_RETCODE_TRADE_DISABLED: /*Торговля запрещена*/ return(true); break;
      case TRADE_RETCODE_MARKET_CLOSED: /*Рынок закрыт*/ return(true); break;
      case TRADE_RETCODE_NO_MONEY: /*Нет достаточных денежных средств для выполнения запроса*/ return(true); break;
      case TRADE_RETCODE_PRICE_CHANGED: /*Цены изменились*/ return(false); return(true); break;
      case TRADE_RETCODE_PRICE_OFF: /*Отсутствуют котировки для обработки запроса*/ return(true); break;
      case TRADE_RETCODE_INVALID_EXPIRATION: /*Неверная дата истечения ордера в запросе*/ return(true); break;
      case TRADE_RETCODE_ORDER_CHANGED: /*Состояние ордера изменилось*/ return(true); break;
      case TRADE_RETCODE_TOO_MANY_REQUESTS: /*Слишком частые запросы*/ return(false); break;
      case TRADE_RETCODE_NO_CHANGES: /*В запросе нет изменений*/ return(false); break;
      case TRADE_RETCODE_SERVER_DISABLES_AT: /*Автотрейдинг запрещен сервером*/ return(true); break;
      case TRADE_RETCODE_CLIENT_DISABLES_AT: /*Автотрейдинг запрещен клиентским терминалом*/ return(true); break;
      case TRADE_RETCODE_LOCKED: /*Запрос заблокирован для обработки*/ return(true); break;
      case TRADE_RETCODE_FROZEN: /*Ордер или позиция заморожены*/ return(true); break;
      case TRADE_RETCODE_INVALID_FILL: /*Указан неподдерживаемый тип исполнения ордера по остатку */ return(true); break;
      case TRADE_RETCODE_CONNECTION: /*Нет соединения с торговым сервером*/ return(true); break;
      case TRADE_RETCODE_ONLY_REAL: /*Операция разрешена только для реальных счетов*/ return(true); break;
      case TRADE_RETCODE_LIMIT_ORDERS: /*Достигнут лимит на количество отложенных ордеров*/ return(true); break;
      case TRADE_RETCODE_LIMIT_VOLUME: /*Достигнут лимит на объем ордеров и позиций для данного символа*/ return(true); break;
      default: /*Неизвестный результат*/ return(false);
     }
//----
   return(true);
  }
//+------------------------------------------------------------------+
 
pako:
О, спасибо, писать уже гораздо меньше :) :) :)
 

Вот еще вопрос:

Я выполнил метод Sell, как скоро мне следует получать результат его выполнения? Следует ли мне сделать, например, Sleep(2000), прежде чем проверять retcode?

 
sanderz:

Всем привет!

Написал я своего робота для торговли на фортс. Сегодня запустил в тест на реале. ...

что вы имеете ввиду, Фортс-Открытия ?
 
Имею ввиду срочную секцию ММВБ (бывш. РТС) - ФОРТС. Да, мой брокер - открытие.
 
sanderz:

Вот еще вопрос:

Я выполнил метод Sell, как скоро мне следует получать результат его выполнения? Следует ли мне сделать, например, Sleep(2000), прежде чем проверять retcode?

Вообще использование sleep(2000) - плохая идея. А что если рынок малоликвиден? А что если это рабочая суббота (да, на ФОРТС может быть и такое)? Помню в одну из таких суббот один из наших роботов выходил из рынка порядка сорока минут (!). Ни какой слип не поможет.

Лучшим решением было бы использование асинхронной версии OrderSend с последующей прослушкой событий в методе OnTradeTransaction. Т.е. надо стремиться к построению событийной а не процедурной модели эксперта. Научите свой эксперт реагировать на события, вместо того, что бы он последовательно ожидал тот или иной ответ. Например, созадайте список виртуальных позиций эксперта. На каждом вызове логики эксперта последовательно прокручивайте этот список позиций, анализируйте изменения и принимайте решения. Понимаю, написал слишком абстрактно, но что бы ответить развернуто на Ваш вопрос надо написать целую статью на эту тему.

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

 
sanderz:

Вот еще вопрос:

Я выполнил метод Sell, как скоро мне следует получать результат его выполнения?

его не надо получать он сам приходит.

Следует ли мне сделать, например, Sleep(2000), прежде чем проверять retcode?

какой то странный вопрос.

вы считаете что переменные сами по себе принимают какое то значение, если немного подождать???

 
C-4:

Вообще использование sleep(2000) - плохая идея. А что если рынок малоликвиден? А что если это рабочая суббота (да, на ФОРТС может быть и такое)? Помню в одну из таких суббот один из наших роботов выходил из рынка порядка сорока минут (!). Ни какой слип не поможет.

Лучшим решением было бы использование асинхронной версии OrderSend с последующей прослушкой событий в методе OnTradeTransaction. Т.е. надо стремиться к построению событийной а не процедурной модели эксперта. Научите свой эксперт реагировать на события, вместо того, что бы он последовательно ожидал тот или иной ответ. Например, созадайте список виртуальных позиций эксперта. На каждом вызове логики эксперта последовательно прокручивайте этот список позиций, анализируйте изменения и принимайте решения. Понимаю, написал слишком абстрактно, но что бы ответить развернуто на Ваш вопрос надо написать целую статью на эту тему.

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

Спасибо! Собтийная логика мне понятна, буду переписывать.

С виртуальной таблицей позиций - тоже к этому пришёл.

А вот насчет стопов не боюсь. Ликвидные контракты и некоторые правила позволяют мне избегать шпилек последние лет 5. Правда я на фортс торговал только руками, но стопы были всегда. В общем - это уже дискуссионный вопрос :) :) :)

Спасибо за ответы. Засяду вечером писать, будет много вопросов - буду писать еще :)

 
sanderz:

Спасибо! Собтийная логика мне понятна, буду переписывать.

С виртуальной таблицей позиций - тоже к этому пришёл.

А вот насчет стопов не боюсь. Ликвидные контракты и некоторые правила позволяют мне избегать шпилек последние лет 5. Правда я на фортс торговал только руками, но стопы были всегда. В общем - это уже дискуссионный вопрос :) :) :)

Спасибо за ответы. Засяду вечером писать, будет много вопросов - буду писать еще :)

В том-то и дело, что шпильки могут появиться и на высоколиквидных контрактах. Ликвидность - не единственная причина появления шпилек.

sergeev:

его не надо получать он сам приходит.

какой то странный вопрос.

вы считаете что переменные сами по себе принимают какое то значение, если немного подождать???

На самом деле на фортсе есть не мало тонкостей которые нужно знать. И вопрос вовсе на так прост как может кому-то показаться.
 
C-4:
На самом деле на фортсе есть не мало тонкостей которые нужно знать. И вопрос вовсе на так прост как может кому-то показаться.

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

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

----

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

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

Причина обращения: