Структуры данных

В MQL5 существуют 8 предопределенных структур, предназначенные для хранения и передачи служебной информации:

  • MqlDateTime предназначена для представления даты и времени;
  • MqlParam позволяет передавать входные параметры при создании хэндла индикатора с помощью функции IndicatorCreate();
  • MqlRates предоставляет информацию об исторических данных, содержащих цену, объем и спред;
  • MqlBookInfo для получения информации, отображаемой в стакане цен (окно котировок);
  • MqlTradeRequest для создания торгового запроса при проведении торговых операций;
  • MqlTradeCheckResult позволяет проверить подготовленный торговый запрос перед  его отправкой;
  • MqlTradeResult содержит ответ торгового сервера на торговый запрос, отправленный функцией OrderSend();
  • MqlTradeTransaction содержит описание торговой транзакции;
  • MqlTick  предназначена для быстрого получения наиболее востребованной информации о текущих ценах.

 

MqlDateTime

Структура даты содержит в себе восемь полей типа int.

struct MqlDateTime
{
   int year;           // год
   int mon;            // месяц
   int day;            // день
   int hour;           // час
   int min;            // минуты
   int sec;            // секунды
   int day_of_week;    // день недели (0-воскресенье, 1-понедельник, ... ,6-суббота)
   int day_of_year;    // порядковый номер в году (1 января имеет номер 0)
};

Примечание

Порядковый номер в году day_of_year в високосном году, начиная с марта, будет отличаться от порядкового номера соответствующего дня в невисокосном году.

Пример:

void OnStart()
{
   datetime date1=D'2008.03.01';
   datetime date2=D'2009.03.01';
 
   MqlDateTime str1,str2;
   TimeToStruct(date1,str1);
   TimeToStruct(date2,str2);
   printf("%02d.%02d.%4d, day of year = %d",str1.day,str1.mon,
          str1.year,str1.day_of_year);
   printf("%02d.%02d.%4d, day of year = %d",str2.day,str2.mon,
          str2.year,str2.day_of_year);
}

/*  Результат
   01.03.2008, day of year = 60
   01.03.2009, day of year = 59
*/

 

Структура входных параметров индикатора (MqlParam)

Структура MqlParam специально разработана для передачи входных параметров при создании хэндла технического индикатора с помощью функции IndicatorCreate().

struct MqlParam
{
   ENUM_DATATYPE     type;                    // тип входного параметра, значение перечисления ENUM_DATATYPE
   long              integer_value;           // поле для хранения целочисленного значения
   double            double_value;            // поле для хранения значения double или float
   string            string_value;            // поле для хранения значения строкового типа
};

Все входные параметры индикатора передаются в виде массива типа MqlParam, поле type каждого элемента этого массива указывает тип данных, передаваемых данным элементом. Сами значения параметров индикатора необходимо предварительно поместить в соответствующие поля каждого элемента (в integer_value, в double_value или в string_value) в зависимости от того, какое значение перечисления ENUM_DATATYPE содержится в поле type.

Если функции IndicatorCreate() третьим параметром в качестве типа индикатора передается значение IND_CUSTOM, то первый элемент массива входных параметров должен иметь поле type со значением TYPE_STRING из перечисления ENUM_DATATYPE, а поле string_value должно содержать имя пользовательского индикатора.

 

MqlRates

Структура для хранения информации о ценах, объемах и спреде.

struct MqlRates
{
   datetime time;         // время начала периода
   double   open;         // цена открытия
   double   high;         // наивысшая цена за период
   double   low;          // наименьшая цена за период
   double   close;        // цена закрытия
   long     tick_volume;  // тиковый объем
   int      spread;       // спред
   long     real_volume;  // биржевой объем
};

Пример:

void OnStart()
{
   MqlRates rates[];
   int copied=CopyRates(NULL,0,0,100,rates);
   if(copied<=0)
      Print("Ошибка копирования ценовых данных ",GetLastError());
   else Print("Скопировано ",ArraySize(rates)," баров");
}

 

MqlBookInfo

Структура, предоставляющая информацию в стакане цен.

struct MqlBookInfo
{
   ENUM_BOOK_TYPE   type;       // тип заявки из перечисления ENUM_BOOK_TYPE
   double           price;      // цена
   long             volume;     // объем
};

Примечание

Структура MqlBookInfo является предопределенной, поэтому ее объявление и описание не требуется. Чтобы использовать структуру, достаточно объявить переменную данного типа.

Стакан доступен не для всех финансовых инструментов.

Пример:

MqlBookInfo priceArray[];
bool getBook=MarketBookGet(NULL,priceArray);
if(getBook)
{
   int size=ArraySize(priceArray);
   Print("MarketBookInfo по ",Symbol());
}
else
{
   Print("Не удалось получить содержимое стакана по символу ",Symbol());
}

 

Структура торгового запроса (MqlTradeRequest)

Взаимодействие клиентского терминала и торгового сервера для проведения операций постановки ордеров производится посредством торговых запросов. Запрос представлен специальной предопределенной структурой MqlTradeRequest, которая содержит все поля, необходимые для заключения торговых сделок. Результат обработки запроса представлен структурой MqlTradeResult.

struct MqlTradeRequest
{
   ENUM_TRADE_REQUEST_ACTIONS    action;           // Тип выполняемого действия
   ulong                         magic;            // Штамп эксперта (идентификатор magic number)
   ulong                         order;            // Тикет ордера
   string                        symbol;           // Имя торгового инструмента
   double                        volume;           // Запрашиваемый объем сделки в лотах
   double                        price;            // Цена 
   double                        stoplimit;        // Уровень StopLimit ордера
   double                        sl;               // Уровень Stop Loss ордера
   double                        tp;               // Уровень Take Profit ордера
   ulong                         deviation;        // Максимально приемлемое отклонение от запрашиваемой цены
   ENUM_ORDER_TYPE               type;             // Тип ордера
   ENUM_ORDER_TYPE_FILLING       type_filling;     // Тип ордера по исполнению
   ENUM_ORDER_TYPE_TIME          type_time;        // Тип ордера по времени действия
   datetime                      expiration;       // Срок истечения ордера (для ордеров типа ORDER_TIME_SPECIFIED)
   string                        comment;          // Комментарий к ордеру
   ulong                         position;         // Тикет позиции
   ulong                         position_by;      // Тикет встречной позиции
};

Описание полей

Поле

Описание

action

Тип торговой операции. Значение может быть одним из значений перечисления ENUM_TRADE_REQUEST_ACTIONS

magic

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

order

Тикет ордера. Требуется для модификации отложенных ордеров

symbol

Имя торгового инструмента, по которому выставляется ордер. Не требуется при операциях модификации ордеров и закрытии позиций

volume

Запрашиваемый объем сделки в лотах. Реальное значение объема при открытии сделки будет зависеть от типа ордера по исполнению.

price

Цена, при достижении которой ордер должен быть исполнен. Для рыночных ордеров по инструментам с типом исполнения «Market Execution» (SYMBOL_TRADE_EXECUTION_MARKET), имеющих тип TRADE_ACTION_DEAL, указание цены не требуется

stoplimit

Цена, по которой будет выставлен отложенный Limit ордер, при достижении ценой значения price (это условие является обязательным). До этого момента отложенный ордер в торговую систему не выводится

sl

Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении

tp

Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении

deviation

Максимально приемлемое отклонение от запрашиваемой цены, задаваемое в пунктах

type

Тип ордера. Значение может быть одним из значений перечисления ENUM_ORDER_TYPE

type_filling

Тип ордера по исполнению. Значение может быть одним из значений ENUM_ORDER_TYPE_FILLING

type_time

Тип ордера по по истечению. Значение может быть одним из значений ENUM_ORDER_TYPE_TIME

expiration

Срок истечения отложенного ордера (для ордеров типа ORDER_TIME_SPECIFIED)

comment

Комментарий к ордеру

position

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

position_by

Тикет встречной позиции. Используется при закрытии позиции встречной — открытой по тому же инструменту, но в противоположном направлении.

При модификации или закрытии позиции в системе хеджинга обязательно указывайте ее тикет (MqlTradeRequest::position). В системе неттинга тикет также можно указывать, однако идентификации позиции осуществляется по имени символа.

Для отправки приказов на совершение торговых операций  необходимо использовать функцию OrderSend(). Для каждой торговой операции необходимо указывать обязательные поля и можно заполнять опциональные поля. Всего предусмотрено семь вариантов отправки торгового запроса:

Request Execution

Торговый ордер на открытие позиции в режиме Request Execution (режим торговли по запросу текущих цен). Требуется указание 9 полей:

  • action
  • symbol
  • volume
  • price
  • sl
  • tp
  • deviation
  • type
  • type_filling

Можно также задать значения полей magic и comment.

Instant Execution

Торговый ордер на открытие позиции в режиме Instant Execution (режим торговли по потоковым ценам). Требуется указание 9 полей:

  • action
  • symbol
  • volume
  • price
  • sl
  • tp
  • deviation
  • type
  • type_filling

Можно также задать значения полей magic и comment.

Market Execution

Торговый ордер на открытие позиции в режиме Market Execution (режим исполнения торговых приказов по рынку). Требуется указание 5 полей:

  • action
  • symbol
  • volume
  • type
  • type_filling

Можно также задать значения полей magic и comment.

Exchange Execution

Торговый ордер на открытие позиции в режиме Exchange Execution (биржевой режим исполнения торговых приказов). Требуется указание 5 полей:

  • action
  • symbol
  • volume
  • type
  • type_filling

Можно также задать значения полей magic и comment.

Пример торговой операции TRADE_ACTION_DEAL для открытия позиции Buy:

#define EXPERT_MAGIC 123456   // MagicNumber эксперта
//+------------------------------------------------------------------+
//| Открытие позиции Buy                                             |
//+------------------------------------------------------------------+
void OnStart()
{
   //--- объявление и инициализация запроса и результата
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};

   //--- параметры запроса
   request.action   =TRADE_ACTION_DEAL;                     // тип торговой операции
   request.symbol   =Symbol();                              // символ
   request.volume   =0.1;                                   // объем в 0.1 лот
   request.type     =ORDER_TYPE_BUY;                        // тип ордера
   request.price    =SymbolInfoDouble(Symbol(),SYMBOL_ASK); // цена для открытия
   request.deviation=5;                                     // допустимое отклонение от цены
   request.magic    =EXPERT_MAGIC;                          // MagicNumber ордера

   //--- отправка запроса
   if(!OrderSend(request,result))
      PrintFormat("OrderSend error %d",GetLastError());     // если отправить запрос не удалось, вывести код ошибки

   //--- информация об операции
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
}

Пример торговой операции TRADE_ACTION_DEAL для закрытия позиций:

#define EXPERT_MAGIC 123456   // MagicNumber эксперта
//+------------------------------------------------------------------+
//| Закрытие всех позиций                                            |
//+------------------------------------------------------------------+
void OnStart()
{
   //--- объявление запроса и результата
   MqlTradeRequest request;
   MqlTradeResult  result;
   int total=PositionsTotal(); // количество открытых позиций   

   //--- перебор всех открытых позиций
   for(int i=total-1; i>=0; i--)
   {
      //--- параметры ордера
      ulong  position_ticket=PositionGetTicket(i);                                      // тикет позиции
      string position_symbol=PositionGetString(POSITION_SYMBOL);                        // символ 
      int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);              // количество знаков после запятой
      ulong  magic=PositionGetInteger(POSITION_MAGIC);                                  // MagicNumber позиции
      double volume=PositionGetDouble(POSITION_VOLUME);                                 // объем позиции
      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);    // тип позиции

      //--- вывод информации о позиции
      PrintFormat("#%I64u %s  %s  %.2f  %s [%I64d]",
                  position_ticket,
                  position_symbol,
                  EnumToString(type),
                  volume,
                  DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),
                  magic);

      //--- если MagicNumber совпадает
      if(magic==EXPERT_MAGIC)
      {
         //--- обнуление значений запроса и результата
         ZeroMemory(request);
         ZeroMemory(result);
         //--- установка параметров операции
         request.action   =TRADE_ACTION_DEAL;        // тип торговой операции
         request.position =position_ticket;          // тикет позиции
         request.symbol   =position_symbol;          // символ 
         request.volume   =volume;                   // объем позиции
         request.deviation=5;                        // допустимое отклонение от цены
         request.magic    =EXPERT_MAGIC;             // MagicNumber позиции

         //--- установка цены и типа ордера в зависимости от типа позиции
         if(type==POSITION_TYPE_BUY)
         {
            request.price=SymbolInfoDouble(position_symbol,SYMBOL_BID);
            request.type =ORDER_TYPE_SELL;
         }
         else
         {
            request.price=SymbolInfoDouble(position_symbol,SYMBOL_ASK);
            request.type =ORDER_TYPE_BUY;
         }

         //--- вывод информации о закрытии
         PrintFormat("Close #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));

         //--- отправка запроса
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError());  // если отправить запрос не удалось, вывести код ошибки
         //--- информация об операции   
         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
      }
   }
}

 

SL & TP Modification

Торговый приказ на модификацию уровней StopLoss и/или TakeProfit. Требуется указание 4 полей:

  • action
  • symbol
  • sl
  • tp
  • position

 Пример торговой операции TRADE_ACTION_SLTP для изменения значений Stop Loss и Take Profit у открытой позиции:

#define EXPERT_MAGIC 123456  // MagicNumber эксперта
//+------------------------------------------------------------------+
//| Модификация Stop Loss и Take Profit позиции                      |
//+------------------------------------------------------------------+
void OnStart()
{
   //--- объявление запроса и результата
   MqlTradeRequest request;
   MqlTradeResult  result;
   int total=PositionsTotal(); // количество открытых позиций   

   //--- перебор всех открытых позиций
   for(int i=0; i<total; i++)
   {
      //--- параметры ордера
      ulong  position_ticket=PositionGetTicket(i);// тикет позиции
      string position_symbol=PositionGetString(POSITION_SYMBOL); // символ 
      int    digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // количество знаков после запятой
      ulong  magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber позиции
      double volume=PositionGetDouble(POSITION_VOLUME);    // объем позиции
      double sl=PositionGetDouble(POSITION_SL);  // Stop Loss позиции
      double tp=PositionGetDouble(POSITION_TP);  // Take Profit позиции
      ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);  // тип позиции

      //--- вывод информации о позиции
      PrintFormat("#%I64u %s  %s  %.2f  %s  sl: %s  tp: %s  [%I64d]",
                  position_ticket,
                  position_symbol,
                  EnumToString(type),
                  volume,
                  DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),
                  DoubleToString(sl,digits),
                  DoubleToString(tp,digits),
                  magic);

      //--- если MagicNumber совпадает, Stop Loss и Take Profit не заданы
      if(magic==EXPERT_MAGIC && sl==0 && tp==0)
      {
         //--- вычисление текущих ценовых уровней
         double price=PositionGetDouble(POSITION_PRICE_OPEN);
         double bid=SymbolInfoDouble(position_symbol,SYMBOL_BID);
         double ask=SymbolInfoDouble(position_symbol,SYMBOL_ASK);
         int    stop_level=(int)SymbolInfoInteger(position_symbol,SYMBOL_TRADE_STOPS_LEVEL);
         double price_level;

         //--- если уровень минимально допустимого отступа в пунктах от текущей цены закрытия не задан
         if(stop_level<=0)
            stop_level=150; // зададим отступ в 150 пунктов от текущей цены закрытия
         else
            stop_level+=50; // уровень отступа возьмем равным (SYMBOL_TRADE_STOPS_LEVEL + 50) пунктов для надежности
 
         //--- вычисление и округление значений Stop Loss и Take Profit
         price_level=stop_level*SymbolInfoDouble(position_symbol,SYMBOL_POINT);
         if(type==POSITION_TYPE_BUY)
         {
            sl=NormalizeDouble(bid-price_level,digits);
            tp=NormalizeDouble(ask+price_level,digits);
         }
         else
         {
            sl=NormalizeDouble(ask+price_level,digits);
            tp=NormalizeDouble(bid-price_level,digits);
         }

         //--- обнуление значений запроса и результата
         ZeroMemory(request);
         ZeroMemory(result);
         //--- установка параметров операции
         request.action  =TRADE_ACTION_SLTP; // тип торговой операции
         request.position=position_ticket;   // тикет позиции
         request.symbol=position_symbol;     // символ 
         request.sl      =sl;                // Stop Loss позиции
         request.tp      =tp;                // Take Profit позиции
         request.magic=EXPERT_MAGIC;         // MagicNumber позиции

         //--- вывод информации о модификации
         PrintFormat("Modify #%I64d %s %s",position_ticket,position_symbol,EnumToString(type));

         //--- отправка запроса
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError());  // если отправить запрос не удалось, вывести код ошибки
         //--- информация об операции   

         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
      }
   }
}

 

Pending Order

Торговый приказ на установку отложенного ордера. Требуется указание 11 полей:

  • action
  • symbol
  • volume
  • price
  • stoplimit
  • sl
  • tp
  • type
  • type_filling
  • type_time
  • expiration

Можно также задать значения полей magic и comment.
 
Пример торговой операции TRADE_ACTION_PENDING для установки отложенного ордера:

#property description "Пример установки отложенных ордеров"
#property script_show_inputs
#define EXPERT_MAGIC 123456                             // MagicNumber эксперта
input ENUM_ORDER_TYPE orderType=ORDER_TYPE_BUY_LIMIT;   // тип ордера
//+------------------------------------------------------------------+
//| Установка отложенных ордеров                                     |
//+------------------------------------------------------------------+
void OnStart()
{
   //-- объявление и инициализация запроса и результата
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};

   //--- параметры для установки отложенного ордера
   request.action   =TRADE_ACTION_PENDING;                             // тип торговой операции
   request.symbol   =Symbol();                                         // символ
   request.volume   =0.1;                                              // объем в 0.1 лот
   request.deviation=2;                                                // допустимое отклонение от цены
   request.magic    =EXPERT_MAGIC;                                     // MagicNumber ордера
   int offset = 50;                                                    // отступ от текущей цены для установки ордера, в пунктах
   double price;                                                       // цена срабатывания ордера
   double point=SymbolInfoDouble(_Symbol,SYMBOL_POINT);                // размер пункта
   int digits=SymbolInfoInteger(_Symbol,SYMBOL_DIGITS);                // кол-во знаков после запятой (точность)

   //--- проверка типа операции
   if(orderType==ORDER_TYPE_BUY_LIMIT)
   {
      request.type     =ORDER_TYPE_BUY_LIMIT;                          // тип ордера
      price=SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point;        // цена для открытия 
      request.price    =NormalizeDouble(price,digits);                 // нормализованная цена открытия 
   }
   else if(orderType==ORDER_TYPE_SELL_LIMIT)
   {
      request.type     =ORDER_TYPE_SELL_LIMIT;                          // тип ордера
      price=SymbolInfoDouble(Symbol(),SYMBOL_ASK)+offset*point;         // цена для открытия 
      request.price    =NormalizeDouble(price,digits);                  // нормализованная цена открытия 
   }
   else if(orderType==ORDER_TYPE_BUY_STOP)
   {
      request.type =ORDER_TYPE_BUY_STOP;                                // тип ордера
      price        =SymbolInfoDouble(Symbol(),SYMBOL_ASK)+offset*point; // цена для открытия 
      request.price=NormalizeDouble(price,digits);                      // нормализованная цена открытия 
   }
   else if(orderType==ORDER_TYPE_SELL_STOP)
   {
      request.type     =ORDER_TYPE_SELL_STOP;                           // тип ордера
      price=SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point;         // цена для открытия 
      request.price    =NormalizeDouble(price,digits);                  // нормализованная цена открытия 
   }
   else Alert("Этот пример только для установки отложенных ордеров");   // если выбран не отложенный ордер
   //--- отправка запроса
   if(!OrderSend(request,result))
      PrintFormat("OrderSend error %d",GetLastError());                 // если отправить запрос не удалось, вывести код ошибки

   //--- информация об операции
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
}

 

Modify Pending Order

Торговый приказ на модификацию уровней цен отложенного ордера. Требуется указание 7 полей:

  • action
  • order
  • price
  • sl
  • tp
  • type_time
  • expiration

 Пример торговой операции TRADE_ACTION_MODIFY для модификации уровней цен отложенного ордера:

#define EXPERT_MAGIC 123456  // MagicNumber эксперта
//+------------------------------------------------------------------+
//| Модификация отложенных ордеров                                   |
//+------------------------------------------------------------------+
void OnStart()
{
//-- объявление и инициализация запроса и результата
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};
   int total=OrdersTotal(); // количество установленных отложенных ордеров
//--- перебор всех установленных отложенных ордеров
   for(int i=0; i<total; i++)
   {
      //--- параметры ордера
      ulong  order_ticket=OrderGetTicket(i);                             // тикет ордера
      string order_symbol=Symbol();                                      // символ
      int    digits=(int)SymbolInfoInteger(order_symbol,SYMBOL_DIGITS);  // количество знаков после запятой
      ulong  magic=OrderGetInteger(ORDER_MAGIC);                         // MagicNumber ордера
      double volume=OrderGetDouble(ORDER_VOLUME_CURRENT);                // текущий объем ордера
      double sl=OrderGetDouble(ORDER_SL);                                // текущий Stop Loss ордера
      double tp=OrderGetDouble(ORDER_TP);                                // текущий Take Profit ордера
      ENUM_ORDER_TYPE type=(ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); // тип ордера
      int offset = 50;                                                   // отступ от текущей цены для установки ордера, в пунктах
      double price;                                                      // цена срабатывания ордера
      double point=SymbolInfoDouble(order_symbol,SYMBOL_POINT);          // размер пункта
      //--- вывод информации об ордере
      PrintFormat("#%I64u %s  %s  %.2f  %s  sl: %s  tp: %s  [%I64d]",
                  order_ticket,
                  order_symbol,
                  EnumToString(type),
                  volume,
                  DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN),digits),
                  DoubleToString(sl,digits),
                  DoubleToString(tp,digits),
                  magic);
      //--- если MagicNumber совпадает, Stop Loss и Take Profit не заданы
      if(magic==EXPERT_MAGIC && sl==0 && tp==0)
      {
         request.action=TRADE_ACTION_MODIFY;                           // тип торговой операции
         request.order = OrderGetTicket(i);                            // тикет ордера
         request.symbol   =Symbol();                                   // символ
         request.deviation=5;                                          // допустимое отклонение от цены
        //--- установка уровня цены, тейк-профит и стоп-лосс ордера в зависимости от его типа
         if(type==ORDER_TYPE_BUY_LIMIT)
         {
            price = SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point; 
            request.tp = NormalizeDouble(price+offset*point,digits);
            request.sl = NormalizeDouble(price-offset*point,digits);
            request.price    =NormalizeDouble(price,digits);                // нормализованная цена открытия
         }
       else if(type==ORDER_TYPE_SELL_LIMIT)
         {
           price = SymbolInfoDouble(Symbol(),SYMBOL_BID)+offset*point; 
            request.tp = NormalizeDouble(price-offset*point,digits);
            request.sl = NormalizeDouble(price+offset*point,digits);
            request.price    =NormalizeDouble(price,digits);                 // нормализованная цена открытия
         }
         else if(type==ORDER_TYPE_BUY_STOP)
         {
           price = SymbolInfoDouble(Symbol(),SYMBOL_BID)+offset*point; 
            request.tp = NormalizeDouble(price+offset*point,digits);
            request.sl = NormalizeDouble(price-offset*point,digits);
            request.price    =NormalizeDouble(price,digits);                 // нормализованная цена открытия
         }
         else if(type==ORDER_TYPE_SELL_STOP)
         {
           price = SymbolInfoDouble(Symbol(),SYMBOL_ASK)-offset*point; 
            request.tp = NormalizeDouble(price-offset*point,digits);
            request.sl = NormalizeDouble(price+offset*point,digits);
            request.price    =NormalizeDouble(price,digits);                 // нормализованная цена открытия
         }
         //--- отправка запроса
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError());  // если отправить запрос не удалось, вывести код ошибки
         //--- информация об операции   
         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
         //--- обнуление значений запроса и результата
         ZeroMemory(request);
         ZeroMemory(result);
      }
   }
}

 

Delete Pending Order

Торговый приказ на удаление отложенного ордера. Требуется указание 2 полей:

  • action
  • order

 Пример торговой операции TRADE_ACTION_REMOVE для удаления отложенных ордеров:

#define EXPERT_MAGIC 123456  // MagicNumber эксперта
//+------------------------------------------------------------------+
//| Удаление отложенных ордеров                                      |
//+------------------------------------------------------------------+
void OnStart()
{
//-- объявление и инициализация запроса и результата
   MqlTradeRequest request={0};
   MqlTradeResult  result={0};
   int total=OrdersTotal(); // количество установленных отложенных ордеров
//--- перебор всех установленных отложенных ордеров
   for(int i=total-1; i>=0; i--)
   {
      ulong  order_ticket=OrderGetTicket(i);                   // тикет ордера
      ulong  magic=OrderGetInteger(ORDER_MAGIC);               // MagicNumber ордера
      //--- если MagicNumber совпадает
      if(magic==EXPERT_MAGIC)
      {
         //--- обнуление значений запроса и результата
         ZeroMemory(request);
         ZeroMemory(result);
         //--- установка параметров операции     
         request.action=TRADE_ACTION_REMOVE;                   // тип торговой операции
         request.order = order_ticket;                         // тикет ордера
         //--- отправка запроса
         if(!OrderSend(request,result))
            PrintFormat("OrderSend error %d",GetLastError());  // если отправить запрос не удалось, вывести код ошибки
         //--- информация об операции   
         PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
      }
   }
}

 

Структура результата проверки торгового запроса (MqlTradeCheckResult)

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

struct MqlTradeCheckResult
{
   uint         retcode;             // Код ответа
   double       balance;             // Баланс после совершения сделки
   double       equity;              // Эквити после совершения сделки
   double       profit;              // Плавающая прибыль
   double       margin;              // Маржевые требования
   double       margin_free;         // Свободная маржа
   double       margin_level;        // Уровень маржи
   string       comment;             // Комментарий к коду ответа (описание ошибки)
};

Описание полей

Поле

Описание

retcode

Код возврата

balance

Значение баланса, которое будет после выполнения торговой операции

equity

Значение собственных средств, которое будет после выполнения торговой операции

profit

Значение плавающей прибыли, которое будет после выполнения торговой операции

margin

Размер маржи необходимый для требуемой торговой операции

margin_free

Размер свободных собственных средств, которые останутся после выполнения требуемой торговой операции

margin_level

Уровень маржи, который установится после выполнения  требуемой торговой операции

comment

Комментарий к коду ответа, описание ошибки

 

Структура результата торгового запроса (MqlTradeResult)

В ответ на торговый запрос постановки ордера в торговую систему, торговый сервер возвращает данные, содержащие информацию о результате обработки торгового запроса в виде специальной предопределенной структуры MqlTradeResult.

struct MqlTradeResult
{
   uint     retcode;          // Код результата операции
   ulong    deal;             // Тикет сделки, если она совершена
   ulong    order;            // Тикет ордера, если он выставлен
   double   volume;           // Объем сделки, подтверждённый брокером
   double   price;            // Цена в сделке, подтверждённая брокером
   double   bid;              // Текущая рыночная цена предложения (цены реквота)
   double   ask;              // Текущая рыночная цена спроса (цены реквота)
   string   comment;          // Комментарий брокера к операции (по умолчанию заполняется расшифровкой кода возврата торгового сервера)
   uint     request_id;       // Идентификатор запроса, устанавливается терминалом при отправке 
   uint     retcode_external; // Код ответа внешней торговой системы
};

Описание полей

Поле

Описание

retcode

Код возврата торгового сервера

deal

Тикет сделки, если она совершена. Сообщается при торговой операции TRADE_ACTION_DEAL

order

Тикет ордера, если он выставлен. Сообщается при торговой операции TRADE_ACTION_PENDING

volume

Объем сделки, подтверждённый брокером. Зависит от типа ордера по исполнению

price

Цена в сделке, подтверждённая брокером. Зависит от поля deviation в торговом запросе и/или от типа торговой операции

bid

Текущая рыночная цена предложения (цены реквоты)

ask

Текущая рыночная цена спроса (цены реквоты)

comment

Комментарий брокера к операции (по умолчанию заполняется расшифровкой кода возврата торгового сервера)

request_id

Идентификатор запроса, проставляемый терминалом при отсылке на торговый сервер

retcode_external

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

Результат торговой операции возвращается в переменную типа MqlTradeResult, которая передается вторым параметром в функцию OrderSend() для проведения торговых операций.

Терминал записывает идентификатор запроса в поле request_id при его отправке на торговый сервер функциями OrdersSend() и OrderSendAsync(). От торгового сервера терминал получает сообщения о совершенных торговых транзакциях и передает их на обработку в функцию OnTradeTransaction(), которая содержит в качестве параметров:

  • описание самой торговой транзакции в структуре MqlTradeTransaction;
  • описание торгового запроса, отправленного из функции OrderSend() или OrdersSendAsync(). Идентификатор запроса отправляется терминалом на торговый сервер, а сам запрос и его request_id сохраняются в памяти терминала;
  • результат исполнения торгового запроса в виде структуры MqlTradeResult, в котором поле request_id содержит идентификатор этого самого запроса.

Функция OnTradeTransaction() получает три входных параметра, но последние два параметра имеет смысл анализировать только для торговых транзакций, имеющих тип TRADE_TRANSACTION_REQUEST. Во всех остальных случаях данные о торговом запросе и результате его выполнения не заполняются. Пример анализа параметров приведен в разделе Структура торговой транзакции.

Установка терминалом идентификатора request_id для торгового запроса при его отправке на сервер в первую очередь предназначена для работы с асинхронной функцией OrderSendAsync(). Этот идентификатор позволяет связать выполненное действие (вызов функций OrderSend или OrderSendAsync) с результатом этого действия, передаваемым в OnTradeTransaction().

Пример:

//+------------------------------------------------------------------+
//| Отправка торгового запроса с обработкой результата               |
//+------------------------------------------------------------------+
bool MyOrderSend(MqlTradeRequest request,MqlTradeResult result)
{
//--- сбросим код последней ошибки в ноль
   ResetLastError();
//--- отправим запрос
   bool success=OrderSend(request,result);
//--- если результат неудачный - попробуем узнать в чем дело
   if(!success)
   {
      int answer=result.retcode;
      Print("TradeLog: Trade request failed. Error = ",GetLastError());
      switch(answer)
      {
         //--- реквота
         case 10004:
         {
            Print("TRADE_RETCODE_REQUOTE");
            Print("request.price = ",request.price,"   result.ask = ",
                  result.ask," result.bid = ",result.bid);
            break;
         }
         //--- ордер не принят сервером
         case 10006:
         {
            Print("TRADE_RETCODE_REJECT");
            Print("request.price = ",request.price,"   result.ask = ",
                  result.ask," result.bid = ",result.bid);
            break;
         }
         //--- неправильная цена
         case 10015:
         {
            Print("TRADE_RETCODE_INVALID_PRICE");
            Print("request.price = ",request.price,"   result.ask = ",
                  result.ask," result.bid = ",result.bid);
            break;
         }
         //--- неправильный SL и/или TP
         case 10016:
         {
            Print("TRADE_RETCODE_INVALID_STOPS");
            Print("request.sl = ",request.sl," request.tp = ",request.tp);
            Print("result.ask = ",result.ask," result.bid = ",result.bid);
            break;
         }
         //--- некорректный объем
         case 10014:
         {
            Print("TRADE_RETCODE_INVALID_VOLUME");
            Print("request.volume = ",request.volume,"   result.volume = ",
                  result.volume);
            break;
         }
         //--- не хватает денег на торговую операцию  
         case 10019:
         {
            Print("TRADE_RETCODE_NO_MONEY");
            Print("request.volume = ",request.volume,"   result.volume = ",
                  result.volume,"   result.comment = ",result.comment);
            break;
         }
         //--- какая-то другая причина, сообщим код ответа сервера   
         default:
         {
            Print("Other answer = ",answer);
         }
      }
      //--- сообщим о неудачном результате торгового запроса возвратом false
      return(false);
   }
//--- OrderSend() вернул true - повторим ответ
   return(true);
}

 

Структура торговой транзакции (MqlTradeTransaction)

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

  • Отсылка торгового запроса любым MQL5-приложением в клиентском терминале при помощи функций OrderSend и OrderSendAsync и его последующее исполнение;
  • Отсылка торгового запроса через графический интерфейс терминала и его последующее исполнение;
  • Срабатывания отложенных ордеров и стоп-ордеров на сервере;
  • Выполнения операций на стороне торгового сервера.

В результате данных действий для счета выполняются торговые транзакции:

  • обработка торгового запроса;
  • изменение открытых ордеров;
  • изменение истории ордеров;
  • изменение истории сделок;
  • изменение позиций.

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

Для получения торговых транзакций, примененных к счету, в MQL5 предусмотрен специальный обработчик OnTradeTransaction(). В первый параметр этого обработчика передается структура MqlTradeTransaction, описывающая торговые транзакции.

struct MqlTradeTransaction
{
   ulong                         deal;             // Тикет сделки
   ulong                         order;            // Тикет ордера
   string                        symbol;           // Имя торгового инструмента
   ENUM_TRADE_TRANSACTION_TYPE   type;             // Тип торговой транзакции
   ENUM_ORDER_TYPE               order_type;       // Тип ордера
   ENUM_ORDER_STATE              order_state;      // Состояние ордера
   ENUM_DEAL_TYPE                deal_type;        // Тип сделки
   ENUM_ORDER_TYPE_TIME          time_type;        // Тип ордера по времени действия
   datetime                      time_expiration;  // Срок истечения ордера
   double                        price;            // Цена 
   double                        price_trigger;    // Цена срабатывания стоп-лимитного ордера
   double                        price_sl;         // Уровень Stop Loss
   double                        price_tp;         // Уровень Take Profit
   double                        volume;           // Объем в лотах
   ulong                         position;         // Тикет позиции
   ulong                         position_by;      // Тикет встречной позиции
};

Описание полей

Поле

Описание

deal

Тикет сделки.

order

Тикет ордера.

symbol

Имя торгового инструмента, по которому совершена транзакция.

type

Тип торговой транзакции. Значение может быть одним из значений перечисления ENUM_TRADE_TRANSACTION_TYPE.

order_type

Тип торгового ордера. Значение может быть одним из значений перечисления ENUM_ORDER_TYPE.

order_state

Состояние торгового ордера. Значение может быть одним из значений перечисления ENUM_ORDER_STATE.

deal_type

Тип сделки. Значение может быть одним из значений перечисления ENUM_DEAL_TYPE.

type_time

Тип ордера по истечению. Значение может быть одним из значений ENUM_ORDER_TYPE_TIME.

time_expiration

Срок истечения отложенного ордера (для ордеров типа ORDER_TIME_SPECIFIED и ORDER_TIME_SPECIFIED_DAY).

price

Цена. В зависимости от типа торговой транзакции может быть ценой ордера, сделки или позиции.

price_trigger

Стоп-цена (цена срабатывания) стоп-лимитного ордера (ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT).

price_sl

Цена Stop Loss. В зависимости от типа торговой транзакции может относиться к ордеру, сделке или позиции.

price_tp

Цена Take Profit. В зависимости от типа торговой транзакции может относиться к ордеру, сделке или позиции.

volume

Объем в лотах. В зависимости от типа торговой транзакции может указывать на текущий объем ордера, объем сделки или объем позиции.

position

Тикет позиции, на которую повлияла транзакция.

position_by

Тикет встречной позиции. Используется при закрытии позиции встречной — открытой по тому же инструменту, но в противоположном направлении.

Определяющим параметром для анализа поступившей транзакции является ее тип, который передается в поле type. Например, если транзакция является типом TRADE_TRANSACTION_REQUEST (получен результат обработки торгового запроса сервером), то структура имеет только одно заполненное поле type, остальные поля анализировать не нужно. В этом случае можно произвести анализ двух дополнительных параметров request и result, которые передаются в обработчик OnTradeTransaction(), как это показано в примере ниже.

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

Структура MqlTradeTransaction заполняется по-разному в зависимости от типа торговой транзакции (ENUM_TRADE_TRANSACTION_TYPE):

TRADE_TRANSACTION_ORDER_* и TRADE_TRANSACTION_HISTORY_*

Для торговых транзакций, касающихся обработки открытых ордеров (TRADE_TRANSACTION_ORDER_ADD, TRADE_TRANSACTION_ORDER_UPDATE и TRADE_TRANSACTION_ORDER_DELETE) и истории ордеров (TRADE_TRANSACTION_HISTORY_ADD, TRADE_TRANSACTION_HISTORY_UPDATE, TRADE_TRANSACTION_HISTORY_DELETE), в структуре MqlTradeTransaction заполняются следующие поля:

  • order — тикет ордера;
  • symbol — имя финансового инструмента в ордере;
  • type — тип торговой транзакции;
  • order_type — тип ордера;
  • orders_state — текущее состояние ордера;
  • time_type — тип истечения ордера;
  • time_expiration — время истечения ордера (для ордеров с типом истечения ORDER_TIME_SPECIFIED и ORDER_TIME_SPECIFIED_DAY);
  • price — цена в ордере, указанная клиентом;
  • price_trigger — стоп-цена срабатывания стоп-лимитного ордера (только для ORDER_TYPE_BUY_STOP_LIMIT и ORDER_TYPE_SELL_STOP_LIMIT);
  • price_sl — цена Stop Loss ордера (заполняется, если указана в ордере);
  • price_tp — цена Take Profit ордера (заполняется, если указана в ордере);
  • volume — текущий объем ордера (не исполненный). Изначальный объем ордера можно узнать из истории ордеров при помощи функций HistoryOrders*.
  • position — тикет позиции, открытой, измененной или закрытой в результате исполнения ордера. Заполняется только для рыночных ордеров. Не заполняется для TRADE_TRANSACTION_ORDER_ADD.
  • position_by — тикет встречной позиции. Заполняется только для ордеров на закрытие позиции встречной (close by).

TRADE_TRANSACTION_DEAL_*

Для торговых транзакций, касающихся обработки сделок (TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_DEAL_UPDATE и TRADE_TRANSACTION_DEAL_DELETE), в структуре MqlTradeTransaction заполняются следующие поля:

  • deal — тикет сделки;
  • order — тикет ордера, на основе которого совершена сделка;
  • symbol — имя финансового инструмента в сделке;
  • type — тип торговой транзакции;
  • deal_type — тип сделки;
  • price — цена, по которой совершена сделка;
  • price_sl — цена Stop Loss (заполняется, если указана в ордере, на основе которого совершена сделка);
  • price_tp — цена Take Profit (заполняется, если указана в ордере, на основе которого совершена сделка);
  • volume — объем сделки в лотах.
  • position — тикет позиции, открытой, измененной или закрытой в результате исполнения сделки.
  • position_by — тикет встречной позиции. Заполняется только для сделок на закрытие позиции встречной (out by).

TRADE_TRANSACTION_POSITION

Для торговых транзакций, касающихся изменений позиций, не связанных с исполнением сделок (TRADE_TRANSACTION_POSITION), в структуре MqlTradeTransaction заполняются следующие поля:

  • symbol — имя финансового инструмента позиции;
  • type — тип торговой транзакции;
  • deal_type — тип позиции (DEAL_TYPE_BUY или DEAL_TYPE_SELL);
  • price — средневзвешенная цена открытия позиции;
  • price_sl — цена Stop Loss;
  • price_tp — цена Take Profit;
  • volume — объем позиции в лотах, если он был изменен.
  • position — тикет позиции.

Изменение позиции (добавление, изменение или ликвидация) в результате совершения сделки не влечет за собой появление транзакции TRADE_TRANSACTION_POSITION.

TRADE_TRANSACTION_REQUEST

Для торговых транзакций, описывающих факт, что торговый запрос обработан сервером, и результат его обработки получен (TRADE_TRANSACTION_REQUEST), в структуре MqlTradeTransaction заполняется только одно поле:

  • type — тип торговой транзакции;

Для транзакций данного типа необходимо анализировать только одно поле — type (тип торговой транзакции). Для получения дополнительной информации необходимо анализировать второй и третий параметры функции OnTradeTransaction (request и result).

Пример:

input int MagicNumber=1234567;
 
//--- подключим торговый класс CTrade и объявим переменную этого типа
#include <Trade\Trade.mqh>
CTrade trade;
//--- флаги для установки и удаления отложенного ордера
bool pending_done=false;
bool pending_deleted=false;
//--- здесь будем хранить тикет отложенного ордера
ulong order_ticket;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//--- установим MagicNumber, которым будут помечаться все наши ордера
   trade.SetExpertMagicNumber(MagicNumber);
//--- торговые запросы будем отправлять в асинхронном режиме с помощью функции OrderSendAsync()
   trade.SetAsyncMode(true);
//--- инициализируем переменную нулем
   order_ticket=0;
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//--- установка отложенного ордера
   if(!pending_done)
   {
      double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      double buy_stop_price=NormalizeDouble(ask+1000*_Point,(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS));
      bool res=trade.BuyStop(0.1,buy_stop_price,_Symbol);
      //--- если функция BuyStop() отработала успешно 
      if(res)
      {
         pending_done=true;
         //--- получим результат отправки запроса из ctrade
         MqlTradeResult trade_result;
         trade.Result(trade_result);
         //--- получим request_id для отправленного запроса
         uint request_id=trade_result.request_id;
         Print("Отправлен запрос на установку отложенного ордера. Идентификатор запроса Request_ID=",request_id);
         //--- запомним тикет ордера (при использовании асинхронного режима отправки в CTrade будет равен нулю)
         order_ticket=trade_result.order;
         //--- всё сделано, поэтому досрочно выходим из обработчика OnTick()
         return;
      }
   }
//--- удаление отложенного ордера
   if(!pending_deleted)
      //--- дополнительная проверка
      if(pending_done && (order_ticket!=0))
      {
         //--- попытаемся удалить отложенный ордер
         bool res=trade.OrderDelete(order_ticket);
         Print("OrderDelete=",res);
         //--- при успешной отправке запроса на удаление
         if(res)
         {
            pending_deleted=true;
            //--- получим результат выполнения запроса
            MqlTradeResult trade_result;
            trade.Result(trade_result);
            //--- вытащим из результата идентификатор запроса
            uint request_id=trade_result.request_id;
            //--- выведем в Журнал
            Print("Отправлен запрос на удаление отложенного ордера #",order_ticket,
                  ". Идентификатор запроса Request_ID=",request_id,
                  "\r\n");
            //--- запишем из результата запроса тикет ордера
            order_ticket=trade_result.order;
         }
      }
}
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
//--- получим тип транзакции в виде значения перечисления 
   ENUM_TRADE_TRANSACTION_TYPE type=(ENUM_TRADE_TRANSACTION_TYPE)trans.type;
//--- если транзакция является результатом обработки запроса, выведем только её название
   if(type==TRADE_TRANSACTION_REQUEST)
   {
      Print(EnumToString(type));
      //--- выведем строковое описание обработанного запроса
      Print("------------RequestDescription\r\n",RequestDescription(request));
      //--- выведем описание результата запроса
      Print("------------ResultDescription\r\n",TradeResultDescription(result));
      //--- запомним тикет ордера для его удаления на следующей обработке в OnTick()
      if(result.order!=0)
      {
         //--- удалим этот ордер по его тикету при следующем вызове OnTick()
         order_ticket=result.order;
         Print(" Тикет отложенного ордера ",order_ticket,"\r\n");
      }
   }
   else // для транзакций другого типа выведем полное описание
//--- выведем описание полученной транзакции в Журнал
      Print("------------TransactionDescription\r\n",TransactionDescription(trans));
 
}
//+------------------------------------------------------------------+
//| Возвращает текстовое описание транзакции                         |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans)
{
   string desc=EnumToString(trans.type)+"\r\n";
   desc+="Symbol: "+trans.symbol+"\r\n";
   desc+="Deal ticket: "+(string)trans.deal+"\r\n";
   desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
   desc+="Order ticket: "+(string)trans.order+"\r\n";
   desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
   desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
   desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
   desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
   desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
   desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
   desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
   desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
   desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
   desc+="Position: "+(string)trans.position+"\r\n";
   desc+="Position by: "+(string)trans.position_by+"\r\n";
//--- вернем полученную строку
   return desc;
}
//+------------------------------------------------------------------+
//| Возвращает текстовое описание торгового запроса                  |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request)
{
   string desc=EnumToString(request.action)+"\r\n";
   desc+="Symbol: "+request.symbol+"\r\n";
   desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
   desc+="Order ticket: "+(string)request.order+"\r\n";
   desc+="Order type: "+EnumToString(request.type)+"\r\n";
   desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
   desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
   desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
   desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
   desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
   desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
   desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
   desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
   desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
   desc+="Comment: "+request.comment+"\r\n";
//--- вернем полученную строку
   return desc;
}
//+------------------------------------------------------------------+
//| Возвращает текстовое описание результата обработки запроса       |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result)
{
   string desc="Retcode "+(string)result.retcode+"\r\n";
   desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
   desc+="Order ticket: "+(string)result.order+"\r\n";
   desc+="Deal ticket: "+(string)result.deal+"\r\n";
   desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
   desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
   desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
   desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
   desc+="Comment: "+result.comment+"\r\n";
//--- вернем полученную строку
   return desc;
}

Структура для получения текущих цен (MqlTick)

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

struct MqlTick
{
   datetime     time;          // Время последнего обновления цен
   double       bid;           // Текущая цена Bid
   double       ask;           // Текущая цена Ask
   double       last;          // Текущая цена последней сделки (Last)
   ulong        volume;        // Объем для текущей цены Last
   long         time_msc;      // Время последнего обновления цен в миллисекундах
   uint         flags          // Флаги тиков
};

Переменная типа MqlTick позволяет за один вызов функции SymbolInfoTick() получить значения Ask, Bid, Last и Volume.

У каждого тика всегда заполняются все параметры, независимо от того, изменились ли данные по сравнению с предыдущим тиком. Это позволяет всегда иметь актуальное состояние цен на любой момент времени без поиска предыдущих значений по тиковой истории. Например, с тиком могла измениться только цена бид, но в структуре помимо новой цены будут указаны и остальные параметры: предыдущая цена аск, объем и т.д.

Чтобы узнать, какие именно данные изменились с текущим тиком, анализируйте его флаги:

  • TICK_FLAG_BID – тик изменил цену бид
  • TICK_FLAG_ASK  – тик изменил цену аск
  • TICK_FLAG_LAST – тик изменил цену последней сделки
  • TICK_FLAG_VOLUME – тик изменил объем
  • TICK_FLAG_BUY – тик возник в результате сделки на покупку
  • TICK_FLAG_SELL – тик возник в результате сделки на продажу

Пример:

void OnTick()
{
   MqlTick last_tick;
   if(SymbolInfoTick(Symbol(),last_tick))
   {
      Print(last_tick.time,": Bid = ",last_tick.bid,
            " Ask = ",last_tick.ask,"  Volume = ",last_tick.volume);
   }
   else Print("SymbolInfoTick() failed, error = ",GetLastError());
}