rss

Профиль компании

Финансовые компании

Блог компании MetaQuotes Software | Как создать торгового робота для Московской биржи MOEX на MetaTrader 5?

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

 

Торговать на бирже с помощью роботов — это просто

Язык MQL5 изначально поддерживает все торговые возможности платформы MetaTrader 5 — в нем множество торговых функций для работы с ордерами, позициями и торговыми запросами. При этом не имеет значения, на каком рынке вы торгуете -  фьючерсы, акции, опционы и т.д.

Средствами MQL5 вы можете создать торговый запрос и отослать его на сервер с помощью функций OrderSend() или OrderSendAsync(), получить результат его выполнения, просмотреть торговую историю, узнать спецификацию контракта для инструмента, обработать торговое событие и получить еще множество другой необходимой информации.


MetaTrader 5 предлагает 6 типов торговых операций

Существует несколько основных типов торговых операций, которые вам могут понадобиться в торговом роботе:

  1. покупка/продажа по текущей цене,
  2. установка отложенного ордера на покупку/продажу по некоторому условию,
  3. модификация/удаление отложенного ордера,
  4. закрытие/наращивание/сокращение/переворот позиции.

Все эти операции реализуются с помощью функции OrderSend(), существует также и асинхронный вариант этой функции — OrderSendAsync(). Всё многообразие торговых операций описывается структурой MqlTradeRequest, содержащей описание торгового запроса. Поэтому единственные трудности с торговыми операциями могут заключаться только в правильном заполнении структуры MqlTradeRequest и обработке результата выполнения запроса.

В соответствии с правилами вашей торговой системы вы можете совершить покупку или продажу по цене рынка (BUY или SELL), а можете поместить отложенный ордер на совершение покупки/продажи на некотором расстоянии от текущей цены рынка:

  • BUY STOP, SELL STOP — покупка или продажа при пробитии указанного уровня (хуже текущей цены);
  • BUY LIMIT, SELL LIMIT — покупка или продажа при достижении указанного уровня (лучше текущей цены);
  • BUY STOP LIMIT, SELL STOP LIMIT — установка ордера BUY LIMIT или SELL LIMIT при достижении указанной цены.

Типы этих стандартных ордеров соответствуют перечислению ENUM_ORDER_TYPE

Как создать торгового робота для Московской биржи MOEX на MetaTrader 5?

 

Кроме  того, вам может понадобиться модифицировать или вовсе удалить отложенный ордер, это также делается с помощью функций OrderSend()/OrderSendAsync(). Изменение открытой позиций тоже не представляет сложности, так как происходит в результате совершения всё тех же торговых операций.

В этой статье мы покажем не только, как легко и просто программировать покупки и продажи в MQL5, но также подскажем, как работать с торговым счетом и свойствами символов. В этом нам помогут торговые классы Стандартной библиотеки.

 

Работа с торговым счетом

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

Для работы со счетом есть класс CAccountInfo, который как раз и разрабатывался для этих целей. Добавим в наш код подключение файла  AccountInfo.mqh и объявим переменную этого класса account:

#include <Trade\AccountInfo.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- объект для работы со счетом
  CAccountInfo account;
//--- получим номер счета, на котором запущен советник
   long login=account.Login();
   Print("Login=",login);
//--- выведем валюту счета    
   Print("Валюта счета: ",account.Currency());   
//--- выведем баланс и текущую прибыль на счете
   Print("Balance=",account.Balance(),"  Profit=",account.Profit(),"   Equity=",account.Equity());
//--- выведем тип счета    
   Print("Тип счета: ",account.TradeModeDescription());
//--- выясним, можно ли вообще торговать на данном счете
   if(account.TradeAllowed())
      Print("Торговля на данном счете разрешена");
   else
      Print("Торговля на счете запрещена: возможно, вход был совершен по инвест-паролю");
//--- режим вычисления маржи
   Print("Режим вычисления маржи: ",account.MarginModeDescription());
//--- выясним, разрешено ли торговать на счете с помощью эксперта
   if(account.TradeExpert())
      Print("Автоматическая торговля на счете разрешена");
   else
      Print("Запрещена автоматическая торговля с помощью экспертов и скриптов");
//--- допустимое количество ордеров задано или нет
   int orders_limit=account.LimitOrders();
   if(orders_limit!=0)Print("Максимально допустимое количество действующих отложенных ордеров: ",orders_limit);
//--- выведем имя компании и сервера
   Print(account.Company(),": server ",account.Server());
   Print(__FUNCTION__,"  completed"); //---   
  }

Как видно из приведенного кода, с помощью переменной account в функции OnInit() можно получить много полезной информации. Вы можете добавить этот код в своего эксперта и вам будет гораздо проще разбирать логи при анализе его работы.

Результат запуска скрипта показан на картинке.

Как создать торгового робота для Московской биржи MOEX на MetaTrader 5?

 

Получение свойств финансового инструмента

Информацию о счете мы получили, но для совершения торговых операций нужно знать еще свойства актива, по которому мы собираемся торговать. Для этого предназначен еще один удобный класс CSymbolInfo с большим количеством методов. Мы приведем в примере только небольшую их часть.

#include<Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- объект для получения свойств символа
  CSymbolInfo symbol_info;
//--- зададим имя символа, для которого будем получать информацию
   symbol_info.Name(_Symbol);
//--- получим текущие котировки и выведем
   symbol_info.RefreshRates();
   Print(symbol_info.Name()," (",symbol_info.Description(),")",
         "  Bid=",symbol_info.Bid(),"   Ask=",symbol_info.Ask());
//--- получим количество знаков после запятой и размер пункта
   Print("Digits=",symbol_info.Digits(),
         ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits()));
//--- запросим тип исполнения ордеров, нет ли ограничений
   Print("Ограничения на торговые операции: ",EnumToString(symbol_info.TradeMode()),
         " (",symbol_info.TradeModeDescription(),")");
//--- выясним режим заключения сделок
   Print("Режим исполнения сделок: ",EnumToString(symbol_info.TradeExecution()),
         " (",symbol_info.TradeExecutionDescription(),")");
//--- выясним способ вычисления стоимости контрактов
   Print("Вычисление стоимости контракта: ",EnumToString(symbol_info.TradeCalcMode()),
         " (",symbol_info.TradeCalcModeDescription(),")");
//--- размер контракта
   Print("Размер стандартного контракта: ",symbol_info.ContractSize());
//--- размер начальной маржи для 1 контракта
   Print("Начальная маржа для стандартного контракта: ",symbol_info.MarginInitial()," ",symbol_info.CurrencyBase());
//--- минимальный, максимальный размеры объема в торговых операциях
   Print("Volume info: LotsMin=",symbol_info.LotsMin(),"  LotsMax=",symbol_info.LotsMax(),
         "  LotsStep=",symbol_info.LotsStep());
//--- 
   Print(__FUNCTION__,"  completed");   
  }

И на рисунке показаны свойства символа Si-6.16 из секции срочного рынка Московской биржи (FORTS). Теперь вы готовы перейти непосредственно к торговле.

Как создать торгового робота для Московской биржи MOEX на MetaTrader 5?

 

Программирование торговых операций

Для отправки торговых приказов в языке MQL5 существует две функции — OrderSend() и OrderSendAsync(). На самом деле это две реализации одной функции. Если OrderSend() отправляет торговый запрос и ждет результата его выполнения, то асинхронная OrderSendAsync() просто выстреливает запрос и позволяет работать программе дальше, не дожидаясь ответа торгового сервера. Таким образом, торговать в MQL5 действительно просто, достаточно использовать только одну функцию для всех торговых операций

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

Столь большое количество полей торгового запроса вызвано необходимостью описать множество свойств ордера, которые могут меняться в зависимости от политики исполнения, времени истечения и некоторых других параметров. Вам не понадобится заучивать все эти тонкости, просто используйте готовый класс CTrade. Вот так примерно может выглядеть использование этого класса в вашем торговом роботе:

#include<Trade\Trade.mqh>
//--- объект для проведения торговых операций
CTrade  trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- зададим MagicNumber для идентификации своих ордеров
   int MagicNumber=123456;
   trade.SetExpertMagicNumber(MagicNumber);
//--- установим допустимое проскальзывание в пунктах при совершении покупки/продажи
   int deviation=10;
   trade.SetDeviationInPoints(deviation);
//--- режим заполнения ордера, нужно использовать тот режим, который разрешается сервером
   trade.SetTypeFilling(ORDER_FILLING_RETURN);
//--- режим логирования: лучше не вызывать этот метод вообще, класс сам выставит оптимальный режим
   trade.LogLevel(1); 
//--- какую функцию использовать для торговли: true - OrderSendAsync(), false - OrderSend()
   trade.SetAsyncMode(true);
//---
   return(0);
  }

Для торговли на бирже как правило используется режим исполнения ORDER_FILLING_RETURN. Справка гласит:

Данный режим используется только в режимах «Исполнение по рынку» и «Биржевое исполнение»: для рыночных (ORDER_TYPE_BUY и ORDER_TYPE_SELL), лимитных и стоп-лимитных ордеров (ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT, ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT). В случае частичного исполнения рыночный или лимитный ордер с остаточным объемом не снимается, а продолжает действовать.

Для ордеров ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT при активации будет создан соответствующий лимитный ордер ORDER_TYPE_BUY_LIMIT/ORDER_TYPE_SELL_LIMIT с типом исполнения ORDER_FILLING_RETURN.

 

Ну а теперь пришло время посмотреть, как CTrade помогает в торговых операциях.

Покупка/продажа по текущей цене

Часто в торговых стратегиях необходимо совершить покупку или продажу по текущей цене прямо сейчас. CTrade знаком с такой ситуацией и просит лишь необходимый объем торговой операции. Все остальные параметры — цену открытия и название символа, уровни Stop Loss и Take Profit, комментарий к ордеру — можно не указывать.

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

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

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

Можно указать все параметры ордера: уровни Stop Loss/Take Profit, цена открытия и комментарий.

//--- 3. пример покупки по указанному символу символу с заданными SL и TP
   double volume=1;           // укажем объем торговой операции
   string symbol="Si-6.16";   // укажем символ, на котором проводится операция
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // количество знаков после запятой
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // пункт
   double bid=SymbolInfoDouble(symbol,SYMBOL_BID);             // текущая цена для закрытия LONG
   double SL=bid-100*point;                                    // ненормализованное значение SL
   SL=NormalizeDouble(SL,digits);                              // нормализуем Stop Loss
   double TP=bid+100*point;                                    // ненормализованное значение TP
   TP=NormalizeDouble(TP,digits);                              // нормализуем Take Profit
//--- получим текущую цену открытия для LONG позиций
   double open_price=SymbolInfoDouble(symbol,SYMBOL_ASK);
   string comment=StringFormat("Buy %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(open_price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
   if(!trade.Buy(volume,symbol,open_price,SL,TP,comment))
     {
      //--- сообщим о неудаче
      Print("Метод Buy() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод Buy() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Напомним, MagicNumber и допустимое проскальзывание мы задали при инициализации экземпляра CTrade, поэтому они не требуются. Хотя их тоже можно задавать непосредственно перед каждой торговой операцией, если это необходимо.

Выставление лимитного ордера

Для отправки лимитного ордера используется соответствующий метод класса BuyLimit() или SellLimit(). Для большинства случаев может подойти укороченный вариант, когда указываются только цена открытия и объем. Цена открытия для BuyLimit должна быть ниже текущей цены, а для SellLimit должна быть выше. То есть эти ордера используются для входа в рынок по лучшей цене, например, в стратегиях с расчетом на отскок от уровня поддержки. При этом используется тот символ, на котором запущен эксперт:

//--- 1. пример установки отложенного ордера BuyLimit
   string symbol="Si-6.16";                                    // укажем символ, на котором выставляется ордер
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // количество знаков после запятой
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // пункт
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // текущая цена покупки
   double price=ask-100*point;                                 // ненормализованное цена открытия
   price=NormalizeDouble(price,digits);                        // нормализуем цену открытия
//--- все готово, отправляем на сервер отложенный ордер Buy Limit
   if(!trade.BuyLimit(1,price))
     {
      //--- сообщим о неудаче
      Print("Метод BuyLimit() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод BuyLimit() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Можно использовать и более подробный вариант с указанием всех параметров: уровни SL/TP, время истечения, название инструмента и комментарий к ордеру.

//--- 2. пример установки отложенного ордера BuyLimit со всеми параметрами
   double volume=1;
   string symbol="Si-6.16";                                    // укажем символ, на котором выставляется ордер
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // количество знаков после запятой
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // пункт
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // текущая цена покупки
   double price=ask-100*point;                                 // ненормализованное цена открытия
   price=NormalizeDouble(price,digits);                        // нормализуем цену открытия
   int SL_pips=100;                                            // Stop Loss в пунктах
   int TP_pips=100;                                            // Take Profit в пунктах
   double SL=price-SL_pips*point;                              // ненормализованное значение SL
   SL=NormalizeDouble(SL,digits);                              // нормализуем Stop Loss
   double TP=price+TP_pips*point;                              // ненормализованное значение TP
   TP=NormalizeDouble(TP,digits);                              // нормализуем Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Limit %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- все готово, отправляем на сервер отложенный ордер Buy Limit
   if(!trade.BuyLimit(volume,price,symbol,SL,TP,ORDER_TIME_DAY,expiration,comment))
     {
      //--- сообщим о неудаче
      Print("Метод BuyLimit() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод BuyLimit() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Во втором варианте необходимо правильно указать уровни SL и TP. Не забывайте, что для покупок уровень Take Profit должен быть выше цены открытия, а уровень Stop Loss — ниже цены открытия. Для ордеров SellLimit всё наоборот. Вы легко можете узнать о своей ошибке при тестировании эксперта на исторических данных, класс CTrade автоматически выводит в таких случаях сообщения (если вы сами не вызывали функцию LogLevel).

 

Выставление стопового ордера

Для отправки стопового ордера используются аналогичные методы BuyStop() и SellStop(). Цена открытия для Buy Stop должна быть выше текущей цены, а для SellStop должна быть ниже. Стоповые ордера используются в стратегиях, которые входят на прорыве некоего уровня сопротивления, а также для ограничения убытков. Простой вариант:

//--- 1. пример установки отложенного ордера Buy Stop
   string symbol="RTS-6.16";    // укажем символ, на котором выставляется ордер
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // количество знаков после запятой
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // пункт
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // текущая цена покупки
   double price=ask+100*point;                                 // ненормализованное цена открытия
   price=NormalizeDouble(price,digits);                        // нормализуем цену открытия
//--- все готово, отправляем на сервер отложенный ордер Buy Stop 
   if(!trade.BuyStop(1,price))
     {
      //--- сообщим о неудаче
      Print("Метод BuyStop() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод BuyStop() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

И более подробный, когда нужно указать максимум параметров для отложенного ордера BuyStop:

//--- 2. пример установки отложенного ордера Buy Stop со всеми параметрами
   double volume=1;
   string symbol="RTS-6.16";    // укажем символ, на котором выставляется ордер
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS); // количество знаков после запятой
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);         // пункт
   double ask=SymbolInfoDouble(symbol,SYMBOL_ASK);             // текущая цена покупки
   double price=ask+100*point;                                 // ненормализованное цена открытия
   price=NormalizeDouble(price,digits);                        // нормализуем цену открытия
   int SL_pips=100;                                            // Stop Loss в пунктах
   int TP_pips=100;                                            // Take Profit в пунктах
   double SL=price-SL_pips*point;                              // ненормализованное значение SL
   SL=NormalizeDouble(SL,digits);                              // нормализуем Stop Loss
   double TP=price+TP_pips*point;                              // ненормализованное значение TP
   TP=NormalizeDouble(TP,digits);                              // нормализуем Take Profit
   datetime expiration=TimeTradeServer()+PeriodSeconds(PERIOD_D1);
   string comment=StringFormat("Buy Stop %s %G lots at %s, SL=%s TP=%s",
                               symbol,volume,
                               DoubleToString(price,digits),
                               DoubleToString(SL,digits),
                               DoubleToString(TP,digits));
//--- все готово, отправляем на сервер отложенный ордер Buy Stop 
   if(!trade.BuyStop(volume,price,symbol,SL,TP,ORDER_TIME_DAY,expiration,comment))
     {
      //--- сообщим о неудаче
      Print("Метод BuyStop() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод BuyStop() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Для отправки ордера SellStop применяется соответствующий метод класса CTrade, главное — правильно указывать цены.

Работа с позицией

Вы можете вместо использования методов Buy() и Sell() пользоваться методами для открытия позиции. Правда, в этом случае придется указать больше деталей:

//--- количество знаков после запятой
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- значение пункта
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- получим цену покупки
   double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
//--- вычислим и нормализуем уровни SL и TP
   double SL=NormalizeDouble(price-100*point,digits);
   double TP=NormalizeDouble(price+100*point,digits);
//--- заполним комментарий
   string comment="Buy "+_Symbol+" 1 at "+DoubleToString(price,digits);
//--- все готово, делаем попытку открыть позицию на покупку
   if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,1,price,SL,TP,comment))
     {
      //--- сообщим о неудаче
      Print("Метод PositionOpen() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод PositionOpen() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Для закрытия позиции достаточно указать имя инструмента, остальное класс CTrade сделает сам.

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

У открытой позиции можно изменять уровни StopLoss и TakeProfit. Это делается с помощью метода ModifyPosition().

//--- количество знаков после запятой
   int    digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);
//--- значение пункта
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);
//--- получим текущую цену Bid
   double price=SymbolInfoDouble(_Symbol,SYMBOL_BID);
//--- вычислим и нормализуем уровни SL и TP
   double SL=NormalizeDouble(price-100*point,digits);
   double TP=NormalizeDouble(price+100*point,digits);
//--- все готово, делаем попытку модифицировать позицию на покупку
   if(!trade.PositionModify(_Symbol,SL,TP))
     {
      //--- сообщим о неудаче
      Print("Метод PositionModify() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод PositionModify() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

Модификация и удаление ордера

Для изменения параметров отложенного ордера в классе CTrade предусмотрен метод OrderModify(), которому необходимо передать все требуемые параметры.

//--- проверим наличие ордера  
   if(!OrderSelect(ticket))
     {
      Print("Ордер #",ticket," не найден");
      return;
     }
//--- символ 
   string symbol=OrderGetString(ORDER_SYMBOL);
//--- количество знаков после запятой
   int    digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
//--- значение пункта
   double point=SymbolInfoDouble(symbol,SYMBOL_POINT);
//--- получим цену открытия
   double price=OrderGetDouble(ORDER_PRICE_OPEN);
//--- вычислим и нормализуем уровни SL и TP
   double SL=NormalizeDouble(price-200*point,digits);
   double TP=NormalizeDouble(price+200*point,digits);
//--- все готово, делаем попытку модифицировать ордер 
//   if(!trade.OrderModify(ticket,price,SL,TP,(ENUM_ORDER_TYPE_TIME)OrderGetInteger(ORDER_TYPE_TIME),0))

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

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

Для удаления отложенного ордера достаточно знать его тикет:

//--- проверим наличие ордера  
   if(!OrderSelect(ticket))
     {
      Print("Ордер #",ticket," не найден");
      return;
     }
//--- все готово, делаем попытку удалить ордер
   if(!trade.OrderDelete(ticket))
     {
      //--- сообщим о неудаче
      Print("Метод OrderDelete() потерпел неудачу. Код возврата=",trade.ResultRetcode(),
            ". Описание кода: ",trade.ResultRetcodeDescription());
     }
   else
     {
      Print("Метод OrderDelete() выполнен успешно. Код возврата=",trade.ResultRetcode(),
            " (",trade.ResultRetcodeDescription(),")");
     }

В классе также есть универсальный метод OrderOpen(), который может выставлять отложенные ордера любого типа. В отличие от специализированных методов BuyLimit, BuyStop, SellLimit и SellStop, он требует указывать больше обязательных параметров. Возможно, кому-то он покажется более удобным.


Что еще посмотреть в торговых классах

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

  • COrderInfo — для работы с ордерами;
  • CHistoryOrderInfo — для работы с отработанными ордерами, попавшими в историю торговли;
  • CPositionInfo — для работы с позициями;
  • CDealInfo — для работы со сделками;
  • CTerminalInfo — для получения информации о самом терминале.

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

Начните свой путь в алготрейдинг с простых скриптов

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

Начните с выполнения простых скриптов (https://c.mql5.com/36/9/mql5-moex-first-steps.zip), и вы поймете, что создать торгового робота гораздо проще, чем вы думали!
★48
103 комментария
У вас крутые содержательные статьи!
Так держать!!!
Тимофей Мартынов, если бы ещё не врали в них (и в документации) =(
Fry (Антон), укажите на проблемные места, пожалуйста.

Если же вопрос о маржа/го/плечо плавает, то это не от нас зависит — некоторые шлюзы так работают.
MetaQuotes Software, много раз уже это всё обсуждалось… К сожалению ничего не меняется.
Главное проблемное место:
OrderSend() на самом деле тоже асинхронная. В том смысле, что после выхода из неё (и не важно что бы она не вернула) мы не знаем толком ничего!
Например:
1) ордер после OrderSend() почти 100% ещё далеко не на бирже, а где-то там у вас в на серверной части ещё только отправляется на биржу и совсем не факт, что он туда попадёт.
2) соответственно и удалять сразу после OrderSend() ордер нельзя (придёт абсолютно невнятная ошибка). Потому что в общем-то и удалять с вашей точки зрения нечего. Хотя! Тикет ваш уже есть! То есть надо бы по уму удалить процесс постановки ордера на биржу. Потому что просто чисто из торговой логике приоритет отмены торгового решения должен быть абсолютный! Понимаете? В любой момент выполнения программы я должен иметь контроль хотя бы над действием «удалить ордер!». Что может быть важнее? А вот нет! Ваша система меня благополучно пошлёт подальше.
3) опять же. Послав запрос «удалить ордер» через ту же OrderSend() и получив якобы положительный ответ я имею обман. На самом деле ордер нифига ещё не удалён с биржи. И опять же нет абсолютной гарантии, что будет удалён. Мало ли у вас там сервак глюкнет. Откуда я знаю? Вот это уже ваще беспредел!

Ну в целом вы наверное уже поняли мои претензии.
Я понимаю, что это сделано для того чтобы совместить в одном терминале кухонный механизм сделок и биржевой, плюс это позволяет ускорить работу роботов, однако на выходе мы имеем совсем не то, что заявлено. Роботов которые будут учитывать сложные ситуации протокола связи в МТ5 написать реально сложно! Приходится писать тысячи строк кода собственного торгового движка и в нём куча всяких исключений и противоречий. Красиво вот как вы обещаете не выйдет!
Или это будет работать «не всегда» =)

Fry (Антон), странно это, проверим.

MetaQuotes Software, да уже сто раз проверено.
В документации наглая ложь:

10008 | TRADE_RETCODE_PLACED | Ордер размещен


То есть действие якобы завершено. По факту это не так!

Сегодня мы имеем возврат из OrderSend() так быстро, как только можно вернуть тикет. При этом сам процесс установки/удаления ордера в режиме биржевого исполнения с огромной вероятностью не завершён!
Fry (Антон), проверим.

Fry (Антон), А с каких пор OrderSend() стал возвращать код 10008? Этот код мы можем получить только при асинхронной отправке т.е. OrderSendAsync() , и тогда мы уже проверяем все шаги постановки через события OnTrade() и OnTradeTransaction() которые нам и сообщают где именно наш приказ, а обычный OrderSend() это получение кода возврата 10009.

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

avatar
DedBoroded, а как я его могу понимать, если это «секретная инфа» и нигде не разглашается. Сервис деск как рыба молчит.
Просветите меня пожалуйста, буду благодарен.

Про коды возврата — вообще же бред там полный! Коды по сути для биржевого режима не соответствует описанию и названию константы. Там каша с реткодами и ошибками полнейшая сейчас!
Возможно даже вы и правы. Может быть приходит 10009. Сейчас лень проверять. Просто я-то давно сделал вот такую функцию:
bool IsSuccessRetcode(const uint retcode_){         switch(retcode_)   {      case TRADE_RETCODE_DONE              :                // Выполнено      case TRADE_RETCODE_DONE_PARTIAL      :                // Выполнено частично      case TRADE_RETCODE_PLACED           : return(true);  // Ордер размещен      default                             : return(false); // Остальные коды возврата   }}

И больше не заморачиваюсь. А какой смысл? Всё равно. Всё едино. Сути дела это не меняет. Нам всё равно надо проверять шаги постановки ордера после OrderSend(), через статусы. Потому что ещё раз повторяю — ордер нифига не на бирже и нифига не удалён. Это элементарно подтверждается простейшим кодом. После OrderSend() берём тикет и сразу пытаемся удалить ордер. Результат такого кода будет неопределённый (то работает, то выдаёт ошибку неверного запроса). Вот уже даже это нелогично. Дальше больше.
Fry (Антон), Странно. Я всё понял из хелпа, он достаточно подробный, но нюансы согласен, тем не описаны. Для этого отправлял запрос и принтовал все поля структур MqlTradeResult и MqlTradeTransaction из всех событий которые могут иметь отношение к торговле. В итоге стала понятна вся цепочка событий и кодов возврата. Поэтому пока вывод простой — очередная попытка переложить свою лень на кого то другого. Если нужно могу дать этот код для проверки, он не секретный.
avatar
Fry (Антон), А попытка хоть что то понять приведённым выше кодом конечно смешна, такой код ничего не даст.
avatar
DedBoroded, бесполезно продолжать разговор. Вы про своё, я про своё. Вы умный, все дураки.
То что Вы мне пытаетесь сказать я и так понимаю… Ну либо из Ваших объяснений всё равно не пойму.
То что я написал Вы пропустили мимо ушей полностью и зацепились только за важные лично для Вас моменты.
Fry (Антон), Да просто кто то лениться вот и всё. Надо называть вещи своими именами. Я вижу что после OrderSend() идёт проверка кода 10008, что в корне не верно т.к. надо проверять 10009, следовательно и всё сообщение ложно и абсурдно из-за непонимания внутреннего механизма.
avatar
DedBoroded, Вы сейчас рассуждаете не как программист (после слова «следовательно»).
Зацепились за слово «лень» и конкретный реткод.
Да какая разница 8 или 9?
Я же показал, что проверяю через функцию свою и даже код её привёл. Она вернёт true если был один из успешных реткодов. Мне вообще всё равно какой в данном случае!
Вопрос в другом и проблема совершенно в другом месте, а вы цепляетесь опять за одно и тоже.
Fry (Антон), Как какая разница 8 или 9? это же ответ функции, а вы получается спрашиваете у неё тот ответ который она впринципе дать неможет. А если бы вы сделали полную трассировку отправки позиции то поняли бы что во первых OrderSend в случае успеха возвращает 10009, А 10008 вы можете получить только когда делаете асинхронный запрос и этот код означает что сделка размещена в потоке заявок, но это не значит что она будет выполнена. Её могут отменить по массе причин — нет денег, маржи, реквота и т.д. и уже потом вы за ней следите любым удобным способом чтобы понять где ваша сделка и стала ли она установленной позицией или нет. Так что налицо грубое непонимание механизма работы и нежелание в нём разобраться.
avatar
DedBoroded, тема закрыта. Проблему, говорят будут решать. Вы разговариваете сами с собой.
Fry (Антон), я TRADE_RETCODE_PLACED вообще поэтому не проверяю. После отправки ордера я ищу его в истории. И если нахожу, что он Rejected, то на всякий уменьшаю объем и отправляю еще раз :))). Можно еще коммент в ордере смотреть (Нехватка средств), тогда сразу понятно, почему ордер отклонен. И этот костыль у меня в небольшом цикле с операцией Sleep (надо же дождаться, когда ордер обработается на сервере и уйдет на биржу и появится в истории). А они еще пишут тут о какой-то быстроте и скорости :)).
avatar
Миха, я сделал не так. У меня программа продолжает выполнятся без всяких циклов и проверок, но архитектура кода моего движка вышла невероятно запутанная и сложная. А проще вообще не сделать, видимо.
Fry (Антон), вы правы.

Проверка показала, что для биржевого исполнения OrderSend на самом деле полусинхронно отрабатывался, возвращая более ранний промежуточный код состояния заявки.

Уже переписали, проверили и теперь OrderSend всегда синхронный. Исправление будет доступно в очередной бете на MetaQuotes-Demo в эту пятницу 3 июня.

Спасибо, что подняли вопрос!
MetaQuotes Software, ура! Спасибо! Ну вот, другое дело. А то и заявку в сервисдеске уже год как подал и на форуме вашем проблему мусолили почти год. Никакой реакции. И тут — бах! Сразу.
Ура корпоративным блогам! =)
Fry (Антон), похоже, было недопонимание.

Сегодня как вопрос поставили перед разработчиками, сразу все поняли и тут же исправили.
Fry (Антон), ну понятно почему. писалось то все из расчета на то что никакой биржи не будет… ;)
avatar
MetaQuotes Software, ни BUy STOP ни BUY STOP LIMIT Не дает ставить Около цены?
kbrobot.ru, вот специально для вас примеры же выше приложены, включая картинки.

Прочтите же наконец, чем отличаются типы ордеров.
MetaQuotes Software, Я уже вручную пробовал даже выставлять. НЕ ДАЕТ! Не говоря уже про код

kbrobot.ru, откройте стакан, пожалуйста, включая все режимы и вот вам все возможности ставить ордеры в любом месте, включая внутри спреда:



MetaQuotes Software, Вот почему не дает поставить?
MetaQuotes Software, Плюс ко всему — плохая тех поддержка.  Даже на форуме сутки надо ждать ответа. Квики помогают намного оперативнее.
kbrobot.ru, посмотрите что означает тип ордера buy stop, пожалуйста.

На первой же картинке этого поста графически показан где должен ставиться buy stop ордер.

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

Лично вам было оказано столько внимания, включая выданные примеры кодов, что странно жаловаться на плохой техсаппорт.
MetaQuotes Software, Ничего подобного. Я раза три переспрашивал как ставится BUY STOP LIMIT лично у Вас. Вы же все время давали мне ссылку на статью, которую скопипастили в данный топ. Ниодного примера как ставить BUY STOP LIIT тут нет
MetaQuotes Software, Кажется понял. В край спреда можно ставить. Внутрь нельзя, так?
kbrobot.ru, если даже вручную неможешь установить то 100% непонимаешь их логику.
avatar
MetaQuotes Software, проясните пожалуйста про BUY_STOP / SELL_STOP. В режиме биржевого исполнения можно их ставить ниже/выше рынка? Получится как обычная рыночная заявка?
Если да, то почему в тестере выдается Invalid price?
avatar
Миха, BUY STOP и SELL STOP являются специальными типами ордеров.

Это не рыночные лимитные ордера, а виртуальные. Они активируются на срабатывании при строго определенных условиях:
  — BUY STOP при прорыве цены выше установленного уровня.

Обычно используются как ордеры на прорыв канала вверх. Например, есть ценовой канал 10000 / 11000, сейчас цена 10500/10510 и вы хотите купить на прорыве канала вверх. Для этого ставите BUY STOP 11000 и как только цена касается/пробивает этот уровень, торговый сервер делает BUY MARKET, выкупая что можно с рынка.

  — SELL STOP при прорыве цены ниже установленного уровня.

Все аналогично, только при прорыве канала вниз.

В чем прелесть этих BUY STOP / SELL STOP ордеров? Они позволяют избавиться от написания простейших стратегий когда нужно раскидать несколько канальных/прорывных ордеров. Если еще и expiration использовать, то вообще получается удобно — выставил на пару часов вручную стратегию прорывов и никакого программирования.

Так как эти ордеры срабатывают на прорыв, то конечно же, у них есть жесткие условия их установки. Цены должны быть правильные и вариант «дайте мне выставить любую цену и если что, пусть мгновенно исполняется» для этих типов ордеров не подходит.
MetaQuotes Software, извиняюсь, ошибся. STOP ордера я знаю что такое. Я имел в виду LIMIT ордера — то, что их можно ставить по обе стороны от рыночной цены при биржевом исполнении. Но с ними никакой ошибки в тестере я не заметил. Ошибся я :)
avatar
Миха, можно.

Как раз пару билдов назад ввели. Их даже вручную можно ставить прямо в скальперском стакане.

Например, чтобы поставить SELL LIMIT ниже рынка, надо зажать Ctrl и кликнуть на красной кнопке продажи любого ценового уровня ниже рынка. В результате выставится SELL LIMIT и тут же отработается.

Аналогично и BUY LIMIT.
Тимофей Мартынов, Тимофей! Ничего содержательного нет! Это тупо копипаста инструкции
kbrobot.ru, заметьте, что в этом несодержательном посте находятся детальные ответы на ваш вопрос, который вы уже раз 7 задали в разных форумах и ветках.
Тимофей Мартынов, Тимофей, вы както писали о попытках освоить программирование. как успехи?
avatar
Спасибо!

Жаль только одного что многие просьбы трейдеров которые занимаются программированием роботов. Вы игнорируете. 

Возможно мой опыт кому то пригодится. Не трате время на изучение этой торговой платформы. Я потратил много лет и жалею об этом. 

Сергей Привалов, отжигали с претензиями и оскорблениями на ровном месте вы знатно!

Из бана в бан прыгали.

MetaQuotes Software, Никого не оскорблял. Врать не нужно. вам просто не нравилось многое, а когда нервы сдавали. Отправляли в бан. И слава богу, я рад этому, что больше не использую вашу торговую платформу. Очень рад. Я не просто трейдер, я видел вашу изнанку, видел настройки серверов, что и как вы можете делать с котировками… Хотите выложу, со скринами, с комментариями ?
З.Ы. Тут то мне бан вы не выдадите. Рот не заткнете. Это не ваш ресурс. 

MetaQuotes Software, Вот и другой тип не дает ставить
kbrobot.ru, спасибо, все понятно.

Потроллить решили в режиме «что я делаю не так». Количество повторений одного вопроса на протяжении недели и полное игнорирование детальных ответов не имеет другого вывода.
Сергей Привалов, не получилось у вас — не следует мешать другим.
сдался — в сторону.
avatar

witwayer, с какого перепугу сдался?… хотя если в смысле надоело биться в стену Метаквотовцев. То да надоело ждать у моря погоды. Есть торговые платформы в 10 раз лучше.

Прибыльных роботов я уже 10 лет умею делать.
championship.mql4.com/2006/ru/users/Prival/reports

Искренне когда то считал, что это платформа для трейдеров… ошибался. дураком был. Она не для нас (трейдеров), она для кухонь и дилеров. Они платят, они (кухни) и заказывают музыку...

Сергей Привалов, молодец. чего тогда тут свои советы не заниматься МТ раздаешь?!? то что она заточена под кухни известно, но что заставляет тебя здесь гадить, если нет другой платформы там где ты торгуешь?!?
avatar
witwayer, я бы прислушался к человеку, который 10 лет потратил на изучения платформы и вынужден был отказаться от неё. Пусть даже он в грубой форме выскажет свои претензии.
Я понимаю, что и моя агрессия и других людей возникает не на пустом месте. Просто мы тратили кучу часов своей жизни, чтобы пробиться сквозь «дурдом» той или иной системы. Обидно, когда ты видишь как можно сделать хорошо, а тебе говорят — отойди мальчик.
Fry (Антон), согласен с вами и внимательно прочитал ваш ответ метаквотам. иллюзий нет насчет мт и особо не рассчитываю на него, но мт один единственный терминал у брокера. так что повторюсь, что хотя и известно его предназначение для кухонь и другие проблемные места, но в общем возложенную задачу на него выполняет. может просто не стоит требовать много от продукта, который имеет малые возможности.
avatar
witwayer, стоит! Продукт в целом великолепен, но досадные недороботки портят бочку мёда.
Fry (Антон), вот и я о том — он меня устраивает и его узкие места мне не мешают. все что мне нужно от него я получаю без проблем и разочарований. так что в общем у меня к мт нормальное отношение.
avatar
witwayer,  нет платформы? Есть, уверяю вас есть. Можно самому на C# собрать тут есть и коннекторы и примеры кода. Можно на Lua, можно TSLab, ... 
Лучший вариант потратить время на изучение C#. Еще раз скажу, лучше бы я С# эти годы изучал, чем метаквотовцев. Время самая большая ценность, и мне жаль что я бездарно его потратил.

Сергей Привалов, может быть не изучив досконально мт вам бы не открылось в последствии С#? ведь только изучив мт и познав все его неудобные для вас стороны, вы поняли что вам нужно и как это должно выглядеть, увидев впоследствии в C#. 
avatar
Сергей Привалов, всё верно! Так везде. Если что-то бесплатное для клиента, то он никак не может воздействовать на процесс развития. Не будет в такой модели обратной связи качественной.
Сергей Привалов, Отчетец-то околонулевой :)
avatar
Сергей Привалов, 
Есть торговые платформы в 10 раз лучше
перечень в студию, пожалуйста
avatar
Сергей Привалов, Эта не та платформа которую стоит изучать много лет. GUI — понятен сразу и без вопросов. мкл — почти С++ поэтому много лет тут тратить не на что. 
avatar
Больше мяса!!! ))) 
Роботы это то что на С++ и крутится на серверах в дата центре с картами Solarflare. Все остальное — мясо
avatar
ELab, а почему только SolarFlare? Mellanox уже не в моде?
avatar
matrix, не работал. но слышал. смысл, думаю, понятен
avatar
ELab, с МТ5 и MQL5 большинство трейдеров легко приближаются к вашим решениям вида С++/датацентр.

Ведь пока вы не встанете прямо в соседний порт со шлюзом/исполнителем/биржей с латенси в 0 микросекунд, вы будете работать с такого же порядка латенси 1-2-5 мс, как и остальные.

Другие ведь тоже легко могут поставить софт в датацентре поближе и сетевые карточки получше (вспоминаем аудиофилов с золотыми коннекторами и улыбаемся). И на таком порядке задержек уже и преимущества С++ перед MQL5 нивелируются.

А чтобы совсем порадовать — любой пользователь MT5 прямо из терминала легко в пару кликов отправляет своего робота в виртуальную среду(это ни в коем случае не виртуалка) в датацентр поближе к брокеру.

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

Вот видео на русском языке с детальным объяснением: https://www.youtube.com/playlist?list=PLltlMLQ7OLeKDR7ThKohKnhjApfjc9i2A

А вот как выглядит например хостинг для MOEX через Открытие. Латенси 2 мс (считается честное латенси до ядра торгового сервера в сетевом протоколе, а не банальный UDP пинг):



MetaQuotes Software, что верно, то верно. Система реально радует скоростью.
MetaQuotes Software, смелые фантазии ))) а как шлюз-брокер-мт_шлюз_мт победит шлюз_с++ ??? 
avatar
ELab, а вы уже дошли до 1 микросек до биржевого ядра?

Так как не дошли, то вы находитесь ровно в такой же категории «плаваем в исполнении около 1-5 миллисекунд». А там и сетевые карты и С++ нивелируются на практике.

Мерило именно практика, а не теория.
MetaQuotes Software, каким образом вы плаваете в 1-5 миллисекундах, если шлюз брокера добавляет 50-100? Объясните мне как МТ переиграет С++ и onboard исполнение с полным циклом разбор пакета/отсылка в районе 20-30 микросекунд? Я чтото не могу понять. Зачем вы упорно мне доказываете очевидную нелепицу? МТ это софт для ручной торговли. И для каких-то торговых систем совокупность которых составляет для роботов источник существования.
avatar
ELab, откуда вы взяли «шлюз брокера добавляет 50-100 миллисекунд»?

У нас дай бог 1 мс потерь на шлюзе МТ5 в биржу. В реальности 0-1 мс.

Если на основе форумных домыслов строить рассуждения, то вся картина мира оказывается ошибочной. Реальность такова, что некоторые компании умеют делать свою работу очень хорошо.
MetaQuotes Software, вам, наверное, нужно с коллегами посоветоваться. Пусть они вам распишут, кто когда и как делает риск контроль, а не расписывать сейчас тут про 0 мс. Ваш внутренний механизм меня не интересует. МТ только как биржа-шлюз_брокера_шлюзМТ_МТ работает. Очень с вашей стороны неосмотрительно тут со мной спорить
avatar
ELab, возьмите MetaTrader 5 и докажите, что у него серверные задержки 50-100 миллисекунд на MOEX и тогда ваши слова будут чего-то значить. А потом послушайте комментарии других трейдеров, кто давно исполняет свои сделки через МТ5 за несколько миллисекунд.

Я утверждаю, что серверные потери внутри МТ5 серверов на маршрутизации сделок на MOEX на уровне 0-1 миллисекунды. Там нечему тормозить (и не тормозит), так как шлюз абсолютно прямой без значимой обработки — всем контролем заявок на МОЕХ занимается сама биржа.

Доказательства моих слов с полным приложенным пакетом всех скриптов для публичной проверки будут на следующей неделе опубликованы в отдельном посте тут. Как раз вместе с глубоким разбором скоростных характеристик реального исполнения сделок на MOEX через MT5.
ELab, про 20-30 микросекунд будьте добры технически расписать, что именно вы имеете в виду.

Иначе ведь вышеприведенная фраза заявлена исключительно для доверчивых и непрофессиональных слушателей. Я то знаю, что вы имеете в виду совершенно незначащую часть работы, на что я уже дважды указывал.

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

Гикпорно HFT трейдеров в виде сетевых карточек или FPGA процессоров полностью аналогично вере аудиофилов в специальные кабеля, позолоту и якобы суперзвук от мегажелезки :)

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

www.mql5.com/ru/forum/38456

Сергей Привалов, в любом случае вам спасибо за напоминание о сюрпризах мт. если будут затронуты интересы, то будем уходить на другой способ торговли и терминал. 
avatar
Сергей Привалов, кесарю кесарево. мт хорошо для своих целей (озвучил их выше) и в целом хорошо справляется с этим. бывает, что на стороне ликвидных провайдеров стоит архаичный софт и(или) большой интерес к ошкуриванию трейдеров от их денег. с этим бороться невозможно. нужно уходить на fix и др.
avatar
ELab, Сергей Привалов, кесарю кесарево. мт хорошо для своих целей (озвучил их выше) и в целом хорошо справляется с этим. бывает, что на стороне ликвидных провайдеров стоит архаичный софт и(или) большой интерес к ошкуриванию трейдеров от их денег. с этим бороться невозможно. нужно уходить на fix и др.
Так про это и говорим тут. Я им про fix протокол лет 6 назад говорил (им фиолетово). Могу найти ссылку если нужно. Про тики и тиковую историю уже язык стёр. Сидеть ждать от них подачки… сколько лет нужно. Там много чего не видного на первый взгляд, сверху все гламурно, прилично, а копнешь глубже… не для трейдера этот терминал. Не для нас с вами. Бизнес схема у них такая и про это говорили. Он якобы бесплатный этот терминал, а по факту за него кухни платят, а потом с трейдеров это винимают, бизнес это такой. Бесплатный сыр вы знаете где он. Кухни платят, они и заказывают музыку, а мы так мясо…
Сергей Привалов, зачем им писать про FIX? это же не их профиль. quickfix и вперед. и только С++
avatar
Сергей Привалов, все у вас по-старому. Сейчас же «вас никто не заткнет».

Все что угодно готовы притянуть за уши, чтобы обвинить и навредить. Указанный автор откровенно переборщил с обвинениями, забыл про метод общения на техническом форуме на уровне предоставления технических обоснований, перешел к прямому подлогу и за это был забанен.

Выскажитесь лучше по статье. Смогли хоть МТ5 в скорости исполнения и функционала обогнать?
MetaQuotes Software, а что, неужели мт5 работает быстрее плазы и фикс\фаст? И какого именно функционала нет в плазе и в фикс\фаст?
Метатрейдер, кстати, отличная программа — именно сам терминал. Его ниша — начинающие трейдеры и алготрейдеры, поглазеть на графики, быстро потестить идею в грубой прикидке. Если бы еще добавили возможность удобно добавить свои котировки — я бы даже, вероятно, платил немного рублей в месяц. Но это точно терминал не для реальной торговли и не для роботов на реальном счете.
avatar
ignat, не быстрее, но и не заметно медленнее.

Я выше объяснял, что пока вы не подключитесь к движку биржи на уровне задержек в 0-1 микросекунд, а будете как и все ходить в пределах 1-5 миллисекунд (это в 1000-5000 раз медленнее идеала), то никаких потерь на MT5 не получите.

В рамках 1-5 миллисекунд все примерно равны. Кроме того, могу разочаровать — никакие «профессионалы» в виде десятков или  сотен пользователей не продвинулись дальше возможностей МТ5.

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

Как раз такие платформы как МТ5 революционизируют масс-маркет и поднимают общий уровень технологичности трейдинга. Именно на масс-маркете и открыто, а не для десятка велосипедистов втихую :)
MetaQuotes Software, так на самом деле экстраординарные возможности, кроме скорости получения котировок и скорости работы с котировками и не нужны, все остальное прикрутить несложно к любому апи.
Вы же не будете спорить, что в настоящее время МТ устойчиво ассоциируется с форекс-кухнями, которые кидают людей, рисуя свои котировки, заваливая реквотами и раздвигая спред.
Хотите, чтобы на МТ обратили внимание трейдеры, которые торгуют на реальных биржевых торгах, а не на квази-форексе и чтобы они начали спрашивать МТ у своих брокеров — идите с другой стороны, сделайте для начала терминал полезным для таких трейдеров. А для этого нужен свой архив котировок по всем инструментам МБ, в том числе до объединения бирж. Нужна возможность в терминале, а не на серверной стороне, создавать свои инструменты и заливать свои котировки. Реал-тайм котировки можно даже впоследствии поставлять за небольшую сумму денег.
Тогда метатрейдер может постепенно начать отбирать долю рынка у аналитических программ (амиброкер, метасток и тд). Это позволит также увеличить количество людей, которые хотят торговать через МТ.
avatar
ignat, фраза «все остальное прикрутить несложно» откровенно ошибочна.

Это очень и очень сложно, прикрутить систему данных (по сути громадное и универсальное рыночное окружение), индикаторы, отладку, тестирование и тд. А потом удостовериться, что все работает правильно.

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

Посмотрите внимательнее на MetaTrader 5, пожалуйста. В нем и неограниченная история, и реальные тики и тестер и тд.

С Амиброкером и Метастоком вы на самом деле опоздали лет на 8. Посмотрите Google Trends — там давно и безраздельно MetaTrader. Давно все у всех отобрано:

MetaQuotes Software, оставьте в статистике google trends только применение МТ на реальных биржевых торгах, без форекс-скама и что тогда покажет данная статистика? Вероятнее всего, процент использования Амиброкера в этом случае окажется выше, чем МТ5.
Смотрел демо МТ5 лишь мельком, если правильно помню, фьючи видел там склеенные, а хотелось бы реальные без склейки и — свои инструменты без обновления их с сервера МТ.
avatar
ignat, в соседнем посте про MQL5 недавно предлагали отрезать половину тела «чтобы соревнование было сравнимее».

Посмотрите Метатрейдер 5 внимательнее, пожалуйста. Иначе странно обсуждать и давать советы по системе, которую не знаете.
MetaQuotes Software, посмотрю, как только появятся опционы, без них МТ — как раз отрезанная половина тела.
avatar
Да давайте все статьи с сайта mql5!
че нет то?
Превратим смарт лаб в ресурс копипаста!

Отличная идея для следующей статьи: скопировать 1 из разделов учебника!
Имя Фамилия, он и так в основном ресурс копипаста и унылого околотрейдерского скама.
avatar
Спрашивал на форуме MQL, не получил ответа. Спрошу здесь.
У Открытия и БКС есть MT5 на срочном рынке. При его подключении брокеры напрочь запрещают работу с опционами на том счёте, даже через квик. Объяснить необходимость этого и когда это исправят, их тех. поддержки не могут. На форуме MQL молчат. Даже непонятно, чьё это требование — брокеров или MQ, непонятно, кому писать. Ведущий блога, может, вы что-то знаете?
avatar
xfo, там что-то связано с управлением итоговой позицией и финансами счета.

Пока в МТ5 опционы не включим, проблема не решится.
MetaQuotes Software, ок, а хотя бы примерные сроки включения опционов на боевом MT5 можете озвучить? В этом году хотя бы? Просто номинальная поддержка заявлена уже 2 года как, я так понимаю (точнее, надеюсь), что брокеры занимаются тестированием и отладкой опционов на MT5 и собираются их там включать.

Про управление позицией не совсем понятно. Это связано со сложной формулой ГО при связке опционы + фьючерсы? Но ведь текущую маржу для счёта нам транслирует биржа/брокер. А в терминале можно разрешить управление фьючерсной позицией и запретить опционной, как бы их разделить их.
avatar
вот давайте без разговоров, что КВИК лучше, помогает или еще что-то. ЛУА квика полная Ж! Понять что происходит с ордером абсолютно невозможно. Нет уж! Спасибо Метаквотам за МТ5 на бирже. Да с неровностями, да с глюками. Но вспомните сколько Квик на бирже… но так и остался убогим терминалом с интерфейсом из 90х. А тут реально удобная платформа, с нормальной возможностью визуального управления ордерами, и нормальным высокоуровневым языком.
А меня вот не цепануло. Есть такое слово — репуиация. И этим все сказано. Ни разу не использовал мт для реальных торгов. Ничегл плохого или хорошего сказать не могу. Но мт это для лохов, мое личное мнение. Не подтвержденное ни чем кроме интуиции
avatar
Это все кнечно круто но уменя нет времени на всю эту тематику, а так изучил бы канешн))
По типам «торговых операций».
Нигде не попадается информации какие ордера обрабатывает биржа, а какие — сервер MT

Нигде нет информации торговых операций

avatar

MetaQuotes Software, как по мне, то от добра добра не ищут. Было время, уходил на другие платформы (QUIK, TSLab), но ностальгия по функционалу и что не менее важно интерфейсу MT5 – просто не оставила мне выбора. Может быть, платформа MT5 не слишком проворна, зато удобна и надежна. Конечно, и здесь каждый может найти огрехи и неудобства, но в целом это рабочая лошадка, и хорошо выполняет свою работу.  Но довольно лирики, а теперь непонятки...


 
avatar
MetaQuotes Software,

Я знал о том, что даже если функция OrderSend() возвращает true, это не свидетельствует об успешном выполнении торговой операции. Но оказалось, что верно и обратное утверждение, если функция OrderSend() возвращает false, то это не свидетельствует также и о неуспешном выполнении торговой операции. Получается, неважно что возвращает функция OrderSend(), все равно надо копать глубже и выяснять уже по вторичным половым признакам — состоялась или нет передача ордера на биржу.

Итак, 2 июня 2016 г., в 13:45:54, робот отправляет на сервер рыночный ордер на продажу 1 лот  Si-6.16 с помощью функции OrderSend(). Однако функция OrderSend() возвращает false. Вот небольшой код, который выполняет и контролирует отправку ордера на биржу:

 

   ResetLastError();
   if (!OrderSend(sTradeRequest, sTradeResult)) {
      err=GetLastError();

      Print(«Структура торгового запроса не прошла базовую проверку, err=»,  err, " ", ErrorToString(err));

      return(0);

   }


В результате в журнал попадает сообщение:

13:45:54.611 Si-6.16 sell 1 лот. Структура торгового запроса не прошла базовую проверку, err=4756 Не удалось отправить торговый запрос.

Однако, каким-то непонятным способом ордер все-таки пробирается на биржу, что подтверждается приведенными ниже выписками из таблицы ордеров и сделок:


2016.06.02 13:45:59 #36796287 Si-6.16 sell 1.00 / 1.00 market 2016.06.02 13:45:59 filled

2016.06.02 13:45:59 #25905779 sell 1.00  67159 #36796287

 

Вопрос автору топика, исправление в бете на MetaQuotes-Demo от пятницы 3 июня, о котором говорилось выше, решает эту проблему или она остается?

avatar
Scriptolog, вывод не верен.

Проверьте все логи, включая вкладки Experts и Journal, пожалуйста. Есть ли в Journal реконнект к серверу в этот момент? Приведите два более полных лога за указанное время из Experts и Journal, пожалуйста.

Этот код ответа можно получить во время проблем с сетью/реконнектом, когда пакет улетел, а ответ уже не получен из-за сетевого разрыва.
MetaQuotes Software, похоже, такая ситуация возможна не только из-за проблем с сетью/реконнектом, но и когда «Авто-торговля» запрещена (соответствующая кнопка в терминале отжата). Советник продолжает работать согласно алгоритма, принимает котировки, проверяет условия, обновляет значения переменных, но когда дело доходит до отправки ордера на сервер, происходит облом. Получается рассогласование, внутреннее состояние среды эксперта уже не соответствует внешнему окружению на стороне сервера/биржи…
avatar
Scriptolog, нет.

MetaQuotes Software, жаль нету первой картинки.  Можно ее обновить?
avatar
MetaQuotes Software, я так понимаю эта должна быть:

avatar

теги блога MetaQuotes Software

....все тэги



UPDONW
Новый дизайн