MetaQuotes Software
MetaQuotes Software Блог компании MetaQuotes Software
31 мая 2016, 14:00

Как создать торгового робота для Московской биржи 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), и вы поймете, что создать торгового робота гораздо проще, чем вы думали!
103 Комментария
  • Тимофей Мартынов
    31 мая 2016, 14:08
    У вас крутые содержательные статьи!
    Так держать!!!
    • Тимофей Мартынов, если бы ещё не врали в них (и в документации) =(
        • MetaQuotes Software, много раз уже это всё обсуждалось… К сожалению ничего не меняется.
          Главное проблемное место:
          OrderSend() на самом деле тоже асинхронная. В том смысле, что после выхода из неё (и не важно что бы она не вернула) мы не знаем толком ничего!
          Например:
          1) ордер после OrderSend() почти 100% ещё далеко не на бирже, а где-то там у вас в на серверной части ещё только отправляется на биржу и совсем не факт, что он туда попадёт.
          2) соответственно и удалять сразу после OrderSend() ордер нельзя (придёт абсолютно невнятная ошибка). Потому что в общем-то и удалять с вашей точки зрения нечего. Хотя! Тикет ваш уже есть! То есть надо бы по уму удалить процесс постановки ордера на биржу. Потому что просто чисто из торговой логике приоритет отмены торгового решения должен быть абсолютный! Понимаете? В любой момент выполнения программы я должен иметь контроль хотя бы над действием «удалить ордер!». Что может быть важнее? А вот нет! Ваша система меня благополучно пошлёт подальше.
          3) опять же. Послав запрос «удалить ордер» через ту же OrderSend() и получив якобы положительный ответ я имею обман. На самом деле ордер нифига ещё не удалён с биржи. И опять же нет абсолютной гарантии, что будет удалён. Мало ли у вас там сервак глюкнет. Откуда я знаю? Вот это уже ваще беспредел!

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

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

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


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

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

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

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

                • 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() берём тикет и сразу пытаемся удалить ордер. Результат такого кода будет неопределённый (то работает, то выдаёт ошибку неверного запроса). Вот уже даже это нелогично. Дальше больше.
                  • oreshkinalexey
                    31 мая 2016, 18:44
                    Fry (Антон), Странно. Я всё понял из хелпа, он достаточно подробный, но нюансы согласен, тем не описаны. Для этого отправлял запрос и принтовал все поля структур MqlTradeResult и MqlTradeTransaction из всех событий которые могут иметь отношение к торговле. В итоге стала понятна вся цепочка событий и кодов возврата. Поэтому пока вывод простой — очередная попытка переложить свою лень на кого то другого. Если нужно могу дать этот код для проверки, он не секретный.
                  • oreshkinalexey
                    31 мая 2016, 18:48
                    Fry (Антон), А попытка хоть что то понять приведённым выше кодом конечно смешна, такой код ничего не даст.
                    • DedBoroded, бесполезно продолжать разговор. Вы про своё, я про своё. Вы умный, все дураки.
                      То что Вы мне пытаетесь сказать я и так понимаю… Ну либо из Ваших объяснений всё равно не пойму.
                      То что я написал Вы пропустили мимо ушей полностью и зацепились только за важные лично для Вас моменты.
                      • oreshkinalexey
                        31 мая 2016, 19:59
                        Fry (Антон), Да просто кто то лениться вот и всё. Надо называть вещи своими именами. Я вижу что после OrderSend() идёт проверка кода 10008, что в корне не верно т.к. надо проверять 10009, следовательно и всё сообщение ложно и абсурдно из-за непонимания внутреннего механизма.
                        • DedBoroded, Вы сейчас рассуждаете не как программист (после слова «следовательно»).
                          Зацепились за слово «лень» и конкретный реткод.
                          Да какая разница 8 или 9?
                          Я же показал, что проверяю через функцию свою и даже код её привёл. Она вернёт true если был один из успешных реткодов. Мне вообще всё равно какой в данном случае!
                          Вопрос в другом и проблема совершенно в другом месте, а вы цепляетесь опять за одно и тоже.
                          • oreshkinalexey
                            01 июня 2016, 00:19
                            Fry (Антон), Как какая разница 8 или 9? это же ответ функции, а вы получается спрашиваете у неё тот ответ который она впринципе дать неможет. А если бы вы сделали полную трассировку отправки позиции то поняли бы что во первых OrderSend в случае успеха возвращает 10009, А 10008 вы можете получить только когда делаете асинхронный запрос и этот код означает что сделка размещена в потоке заявок, но это не значит что она будет выполнена. Её могут отменить по массе причин — нет денег, маржи, реквота и т.д. и уже потом вы за ней следите любым удобным способом чтобы понять где ваша сделка и стала ли она установленной позицией или нет. Так что налицо грубое непонимание механизма работы и нежелание в нём разобраться.
                            • Антон Денисков (Fry)
                              01 июня 2016, 00:28
                              DedBoroded, тема закрыта. Проблему, говорят будут решать. Вы разговариваете сами с собой.
              • Миха
                31 мая 2016, 19:27
                Fry (Антон), я TRADE_RETCODE_PLACED вообще поэтому не проверяю. После отправки ордера я ищу его в истории. И если нахожу, что он Rejected, то на всякий уменьшаю объем и отправляю еще раз :))). Можно еще коммент в ордере смотреть (Нехватка средств), тогда сразу понятно, почему ордер отклонен. И этот костыль у меня в небольшом цикле с операцией Sleep (надо же дождаться, когда ордер обработается на сервере и уйдет на биржу и появится в истории). А они еще пишут тут о какой-то быстроте и скорости :)).
                • Миха, я сделал не так. У меня программа продолжает выполнятся без всяких циклов и проверок, но архитектура кода моего движка вышла невероятно запутанная и сложная. А проще вообще не сделать, видимо.
                • MetaQuotes Software, ура! Спасибо! Ну вот, другое дело. А то и заявку в сервисдеске уже год как подал и на форуме вашем проблему мусолили почти год. Никакой реакции. И тут — бах! Сразу.
                  Ура корпоративным блогам! =)
          • Изя 3%
            31 мая 2016, 23:40
            Fry (Антон), ну понятно почему. писалось то все из расчета на то что никакой биржи не будет… ;)
        • Евгений Черных
          31 мая 2016, 15:44
          MetaQuotes Software, ни BUy STOP ни BUY STOP LIMIT Не дает ставить Около цены?
            • Евгений Черных
              31 мая 2016, 15:49
              MetaQuotes Software, Я уже вручную пробовал даже выставлять. НЕ ДАЕТ! Не говоря уже про код
                • Евгений Черных
                  31 мая 2016, 16:22
                  MetaQuotes Software, Вот почему не дает поставить?
                • Евгений Черных
                  31 мая 2016, 16:23
                  MetaQuotes Software, Плюс ко всему — плохая тех поддержка.  Даже на форуме сутки надо ждать ответа. Квики помогают намного оперативнее.
                    • Евгений Черных
                      31 мая 2016, 16:37
                      MetaQuotes Software, Ничего подобного. Я раза три переспрашивал как ставится BUY STOP LIMIT лично у Вас. Вы же все время давали мне ссылку на статью, которую скопипастили в данный топ. Ниодного примера как ставить BUY STOP LIIT тут нет
                • Евгений Черных
                  31 мая 2016, 16:31
                  MetaQuotes Software, Кажется понял. В край спреда можно ставить. Внутрь нельзя, так?
              • oreshkinalexey
                31 мая 2016, 17:18
                kbrobot.ru, если даже вручную неможешь установить то 100% непонимаешь их логику.
            • Миха
              31 мая 2016, 19:30
              MetaQuotes Software, проясните пожалуйста про BUY_STOP / SELL_STOP. В режиме биржевого исполнения можно их ставить ниже/выше рынка? Получится как обычная рыночная заявка?
              Если да, то почему в тестере выдается Invalid price?
                • Миха
                  31 мая 2016, 20:40
                  MetaQuotes Software, извиняюсь, ошибся. STOP ордера я знаю что такое. Я имел в виду LIMIT ордера — то, что их можно ставить по обе стороны от рыночной цены при биржевом исполнении. Но с ними никакой ошибки в тестере я не заметил. Ошибся я :)
    • Евгений Черных
      31 мая 2016, 15:43
      Тимофей Мартынов, Тимофей! Ничего содержательного нет! Это тупо копипаста инструкции
    • moisha
      31 мая 2016, 16:31
      Тимофей Мартынов, Тимофей, вы както писали о попытках освоить программирование. как успехи?
  • Сергей Привалов
    31 мая 2016, 14:22

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

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

      • Сергей Привалов
        31 мая 2016, 14:35

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

      • Евгений Черных
        31 мая 2016, 16:24
        MetaQuotes Software, Вот и другой тип не дает ставить
    • witwayer
      31 мая 2016, 14:32
      Сергей Привалов, не получилось у вас — не следует мешать другим.
      сдался — в сторону.
      • Сергей Привалов
        31 мая 2016, 14:42

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

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

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

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

            • witwayer
              31 мая 2016, 15:01
              Сергей Привалов, может быть не изучив досконально мт вам бы не открылось в последствии С#? ведь только изучив мт и познав все его неудобные для вас стороны, вы поняли что вам нужно и как это должно выглядеть, увидев впоследствии в C#. 
        • Сергей Привалов, всё верно! Так везде. Если что-то бесплатное для клиента, то он никак не может воздействовать на процесс развития. Не будет в такой модели обратной связи качественной.
        • helk3rn
          31 мая 2016, 15:16
          Сергей Привалов, Отчетец-то околонулевой :)
        • Quant-Invest
          31 мая 2016, 18:30
          Сергей Привалов, 
          Есть торговые платформы в 10 раз лучше
          перечень в студию, пожалуйста
    • oreshkinalexey
      31 мая 2016, 17:20
      Сергей Привалов, Эта не та платформа которую стоит изучать много лет. GUI — понятен сразу и без вопросов. мкл — почти С++ поэтому много лет тут тратить не на что. 
  • ELab
    31 мая 2016, 14:23
    Больше мяса!!! ))) 
    Роботы это то что на С++ и крутится на серверах в дата центре с картами Solarflare. Все остальное — мясо
    • matrix
      31 мая 2016, 14:48
      ELab, а почему только SolarFlare? Mellanox уже не в моде?
      • ELab
        31 мая 2016, 14:58
        matrix, не работал. но слышал. смысл, думаю, понятен
      • MetaQuotes Software, что верно, то верно. Система реально радует скоростью.
      • ELab
        31 мая 2016, 15:00
        MetaQuotes Software, смелые фантазии ))) а как шлюз-брокер-мт_шлюз_мт победит шлюз_с++ ??? 
          • ELab
            31 мая 2016, 19:26
            MetaQuotes Software, каким образом вы плаваете в 1-5 миллисекундах, если шлюз брокера добавляет 50-100? Объясните мне как МТ переиграет С++ и onboard исполнение с полным циклом разбор пакета/отсылка в районе 20-30 микросекунд? Я чтото не могу понять. Зачем вы упорно мне доказываете очевидную нелепицу? МТ это софт для ручной торговли. И для каких-то торговых систем совокупность которых составляет для роботов источник существования.
              • ELab
                31 мая 2016, 21:59
                MetaQuotes Software, вам, наверное, нужно с коллегами посоветоваться. Пусть они вам распишут, кто когда и как делает риск контроль, а не расписывать сейчас тут про 0 мс. Ваш внутренний механизм меня не интересует. МТ только как биржа-шлюз_брокера_шлюзМТ_МТ работает. Очень с вашей стороны неосмотрительно тут со мной спорить
  • Сергей Привалов
    31 мая 2016, 15:04

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

    www.mql5.com/ru/forum/38456

    • witwayer
      31 мая 2016, 15:09
      Сергей Привалов, в любом случае вам спасибо за напоминание о сюрпризах мт. если будут затронуты интересы, то будем уходить на другой способ торговли и терминал. 
    • ELab
      31 мая 2016, 15:19
      Сергей Привалов, кесарю кесарево. мт хорошо для своих целей (озвучил их выше) и в целом хорошо справляется с этим. бывает, что на стороне ликвидных провайдеров стоит архаичный софт и(или) большой интерес к ошкуриванию трейдеров от их денег. с этим бороться невозможно. нужно уходить на fix и др.
      • Сергей Привалов
        31 мая 2016, 16:42
        ELab, Сергей Привалов, кесарю кесарево. мт хорошо для своих целей (озвучил их выше) и в целом хорошо справляется с этим. бывает, что на стороне ликвидных провайдеров стоит архаичный софт и(или) большой интерес к ошкуриванию трейдеров от их денег. с этим бороться невозможно. нужно уходить на fix и др.
        Так про это и говорим тут. Я им про fix протокол лет 6 назад говорил (им фиолетово). Могу найти ссылку если нужно. Про тики и тиковую историю уже язык стёр. Сидеть ждать от них подачки… сколько лет нужно. Там много чего не видного на первый взгляд, сверху все гламурно, прилично, а копнешь глубже… не для трейдера этот терминал. Не для нас с вами. Бизнес схема у них такая и про это говорили. Он якобы бесплатный этот терминал, а по факту за него кухни платят, а потом с трейдеров это винимают, бизнес это такой. Бесплатный сыр вы знаете где он. Кухни платят, они и заказывают музыку, а мы так мясо…
        • ELab
          31 мая 2016, 19:27
          Сергей Привалов, зачем им писать про FIX? это же не их профиль. quickfix и вперед. и только С++
      • ignat
        31 мая 2016, 17:44
        MetaQuotes Software, а что, неужели мт5 работает быстрее плазы и фикс\фаст? И какого именно функционала нет в плазе и в фикс\фаст?
        Метатрейдер, кстати, отличная программа — именно сам терминал. Его ниша — начинающие трейдеры и алготрейдеры, поглазеть на графики, быстро потестить идею в грубой прикидке. Если бы еще добавили возможность удобно добавить свои котировки — я бы даже, вероятно, платил немного рублей в месяц. Но это точно терминал не для реальной торговли и не для роботов на реальном счете.
          • ignat
            31 мая 2016, 21:34
            MetaQuotes Software, так на самом деле экстраординарные возможности, кроме скорости получения котировок и скорости работы с котировками и не нужны, все остальное прикрутить несложно к любому апи.
            Вы же не будете спорить, что в настоящее время МТ устойчиво ассоциируется с форекс-кухнями, которые кидают людей, рисуя свои котировки, заваливая реквотами и раздвигая спред.
            Хотите, чтобы на МТ обратили внимание трейдеры, которые торгуют на реальных биржевых торгах, а не на квази-форексе и чтобы они начали спрашивать МТ у своих брокеров — идите с другой стороны, сделайте для начала терминал полезным для таких трейдеров. А для этого нужен свой архив котировок по всем инструментам МБ, в том числе до объединения бирж. Нужна возможность в терминале, а не на серверной стороне, создавать свои инструменты и заливать свои котировки. Реал-тайм котировки можно даже впоследствии поставлять за небольшую сумму денег.
            Тогда метатрейдер может постепенно начать отбирать долю рынка у аналитических программ (амиброкер, метасток и тд). Это позволит также увеличить количество людей, которые хотят торговать через МТ.
              • ignat
                31 мая 2016, 22:55
                MetaQuotes Software, оставьте в статистике google trends только применение МТ на реальных биржевых торгах, без форекс-скама и что тогда покажет данная статистика? Вероятнее всего, процент использования Амиброкера в этом случае окажется выше, чем МТ5.
                Смотрел демо МТ5 лишь мельком, если правильно помню, фьючи видел там склеенные, а хотелось бы реальные без склейки и — свои инструменты без обновления их с сервера МТ.
                  • ignat
                    31 мая 2016, 23:52
                    MetaQuotes Software, посмотрю, как только появятся опционы, без них МТ — как раз отрезанная половина тела.
  • Имя Фамилия
    31 мая 2016, 15:53
    Да давайте все статьи с сайта mql5!
    че нет то?
    Превратим смарт лаб в ресурс копипаста!

    Отличная идея для следующей статьи: скопировать 1 из разделов учебника!
    • helk3rn
      31 мая 2016, 16:33
      Имя Фамилия, он и так в основном ресурс копипаста и унылого околотрейдерского скама.
  • xfo
    31 мая 2016, 17:15
    Спрашивал на форуме MQL, не получил ответа. Спрошу здесь.
    У Открытия и БКС есть MT5 на срочном рынке. При его подключении брокеры напрочь запрещают работу с опционами на том счёте, даже через квик. Объяснить необходимость этого и когда это исправят, их тех. поддержки не могут. На форуме MQL молчат. Даже непонятно, чьё это требование — брокеров или MQ, непонятно, кому писать. Ведущий блога, может, вы что-то знаете?
      • xfo
        31 мая 2016, 17:42
        MetaQuotes Software, ок, а хотя бы примерные сроки включения опционов на боевом MT5 можете озвучить? В этом году хотя бы? Просто номинальная поддержка заявлена уже 2 года как, я так понимаю (точнее, надеюсь), что брокеры занимаются тестированием и отладкой опционов на MT5 и собираются их там включать.

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

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

  • Scriptolog
    04 июня 2016, 16:36

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


     
  • Scriptolog
    05 июня 2016, 19:19
    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 июня, о котором говорилось выше, решает эту проблему или она остается?

      • Scriptolog
        09 июня 2016, 13:36
        MetaQuotes Software, похоже, такая ситуация возможна не только из-за проблем с сетью/реконнектом, но и когда «Авто-торговля» запрещена (соответствующая кнопка в терминале отжата). Советник продолжает работать согласно алгоритма, принимает котировки, проверяет условия, обновляет значения переменных, но когда дело доходит до отправки ордера на сервер, происходит облом. Получается рассогласование, внутреннее состояние среды эксперта уже не соответствует внешнему окружению на стороне сервера/биржи…
          • -- Leonid --
            21 июня 2017, 23:28
            MetaQuotes Software, жаль нету первой картинки.  Можно ее обновить?
          • -- Leonid --
            25 июня 2017, 23:37
            MetaQuotes Software, я так понимаю эта должна быть:

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн