Article-13052-MQL5-TradeTra.../Article-13052-MQL5-TradeTransactions-Structs-Print.mq5
2026-03-18 00:20:07 +07:00

2051 lines
136 KiB
MQL5

//+------------------------------------------------------------------+
//| Article-13052-MQL5-TradeTransactions-Structs-Print.mq5 |
//| Copyright 2026, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
//--- input parameters
input double InpLots = 0.1; /* Lots */ // Объём в запросе
input int InpMagic = 1024; /* Magic number */ // Идентификатор эксперта
input int InpDistance = 300; /* Orders placement distance */ // Дистанция установки отложенных ордеров
input uint InpDeviation = 5; /* Price deviation */ // Допустимое отклонение от цены в запросе
input string InpKeyBuy = "B"; /* Key to open Buy */ // Клавиша для открытия позиции Buy (с Shift - Stop, с Ctrl+Shift - Limit)
input string InpKeySell = "S"; /* Key to open Sell */ // Клавиша для открытия позиции Sell (с Shift - Stop, с Ctrl+Shift - Limit)
input string InpKeyClose = "X"; /* Key to close/delete */ // Клавиша для закрытия позиции (без управляющих клавиш) или удаления ордера (с Shift или Shift+Ctrl)
//--- Global variables
ushort key_buy; // Клавиша для отправки приказа на покупку
ushort key_sell; // Клавиша для отправки приказа на продажу
ushort key_close; // Клавиша для закрытия или удаления
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Преобразуем в верхний регистр текст, назначенный на Buy и получаем код первого символа
string tmp=InpKeyBuy;
tmp.Upper();
key_buy=StringGetCharacter(tmp,0);
//--- Преобразуем в верхний регистр текст, назначенный на Sell и получаем код первого символа
tmp=InpKeySell;
tmp.Upper();
key_sell=StringGetCharacter(tmp,0);
//--- Преобразуем в верхний регистр текст, назначенный на Close и получаем код первого символа
tmp=InpKeyClose;
tmp.Upper();
key_close=StringGetCharacter(tmp,0);
//--- Если клавиши, назначенные на Buy и Sell совпадают - сообщаем об этом и уходим с ошибкой
if(key_sell==key_buy)
{
PrintFormat("The key assigned to Sell ('%c') is the same as the key assigned to Buy ('%c')",key_sell,key_buy);
return INIT_PARAMETERS_INCORRECT;
}
//--- Если клавиши, назначенные на Close и Buy совпадают - сообщаем об этом и уходим с ошибкой
if(key_close==key_buy)
{
PrintFormat("The key assigned to Close ('%c') is the same as the key assigned to Buy ('%c')",key_close,key_buy);
return INIT_PARAMETERS_INCORRECT;
}
//--- Если клавиши, назначенные на Close и Sell совпадают - сообщаем об этом и уходим с ошибкой
if(key_close==key_sell)
{
PrintFormat("The key assigned to Close ('%c') is the same as the key assigned to Sell ('%c')",key_close,key_sell);
return INIT_PARAMETERS_INCORRECT;
}
//--- Успешная инициализация. Выведем в лог назначенные клавиши и возвратим успешное выполнение
string kb="Key assigned to Buy: ";
string ks="Key assigned to Sell: ";
string kc="Key assigned to Close: ";
PrintFormat("%-23s%c (key code %lu)\n%-23s%c (key code %lu)\n%-23s%c (key code %lu)",kb,key_buy,key_buy,ks,key_sell,key_sell,kc,key_close,key_close);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- Если нажата клавиша на клавиатуре
if(id==CHARTEVENT_KEYDOWN)
{
//--- Если не удерживаются ни Ctrl, ни Shift
if(!IsCtrlKeyPressed() && !IsShiftKeyPressed())
{
//--- Если кнопка, назначенная на позицию Buy - открываем позицию Buy
if(lparam==key_buy)
OpenBuy(NULL,InpLots,InpMagic,InpDeviation,"TestMqlTradeTransaction");
//--- Если кнопка, назначенная на позицию Sell - открываем позицию Sell
if(lparam==key_sell)
OpenSell(NULL,InpLots,InpMagic,InpDeviation,"TestMqlTradeTransaction");
//--- Если кнопка, назначенная на закрытие позиций - закрываем все позиции
if(lparam==key_close)
ClosePositionsAll(Symbol());
}
//--- Если удерживается только Shift
if(IsShiftKeyPressed() && !IsCtrlKeyPressed())
{
//--- Если кнопка, назначенная на ордер Buy - открываем ордер Buy Stop
if(lparam==key_buy)
SetBuyStop(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
//--- Если кнопка, назначенная на ордер Sell - открываем ордер Sell Stop
if(lparam==key_sell)
SetSellSellStop(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
//--- Если кнопка, назначенная на удаление ордеров - удаляем все ордеры
if(lparam==key_close)
DeleteOrdersAll(NULL);
}
//--- Если удерживается Shift вместе с Ctrl
if(IsShiftKeyPressed() && IsCtrlKeyPressed())
{
//--- Если кнопка, назначенная на ордер Buy - открываем ордер Buy Limit
if(lparam==key_buy)
SetBuyLimit(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
//--- Если кнопка, назначенная на ордер Sell - открываем ордер Sell Limit
if(lparam==key_sell)
SetSellLimit(NULL,InpLots,InpMagic,InpDistance,"TestMqlTradeTransaction");
//--- Если кнопка, назначенная на удаление ордеров - удаляем все ордеры
if(lparam==key_close)
DeleteOrdersAll(Symbol());
}
}
}
//+------------------------------------------------------------------+
//| TradeTransaction function |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction& trans,
const MqlTradeRequest& request,
const MqlTradeResult& result)
{
//--- Пишем в журнал все приходящие торговые транзакции
TradeTransactionInformer(trans,request,result,18,2,true);
}
//+------------------------------------------------------------------+
//| Торговые функции |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Открывает позицию Buy |
//+------------------------------------------------------------------+
bool OpenBuy(const string symbol,const double lots,const uint magic,const ulong deviation=5,const string comment="")
{
//--- Устанавливаем символ для запроса
string symbol_name=(symbol==NULL ? Symbol() : symbol);
//--- Объявляем и инициализируем структуры запроса и результата
MqlTradeRequest request={};
MqlTradeResult result={};
//--- Получаем нормализованную цену
double price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK),(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS));
//--- параметры запроса
request.action = TRADE_ACTION_DEAL; // тип торговой операции
request.symbol = symbol_name; // символ
request.volume = lots; // объем позиции
request.type = ORDER_TYPE_BUY; // тип ордера
request.price = price; // цена для открытия
request.deviation = deviation; // допустимое отклонение от цены
request.magic = magic; // MagicNumber ордера
request.comment = comment; // Комментарий ордера
//--- Если отправить запрос не удалось - сообщим об этом в журнал и вернём false
if(!OrderSend(request,result))
{
PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__,
TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true)
);
return false;
}
//--- OrderSend OK, вернём true
return true;
}
//+------------------------------------------------------------------+
//| Открывает позицию Sell |
//+------------------------------------------------------------------+
bool OpenSell(const string symbol,const double lots,const uint magic,const ulong deviation=5,const string comment="")
{
//--- Устанавливаем символ для запроса
string symbol_name=(symbol==NULL ? Symbol() : symbol);
//--- Объявляем и инициализируем структуры запроса и результата
MqlTradeRequest request={};
MqlTradeResult result={};
//--- Получаем нормализованную цену
double price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID),(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS));
//--- параметры запроса
request.action = TRADE_ACTION_DEAL; // тип торговой операции
request.symbol = symbol_name; // символ
request.volume = lots; // объем позиции
request.type = ORDER_TYPE_SELL; // тип ордера
request.price = price; // цена для открытия
request.deviation = deviation; // допустимое отклонение от цены
request.magic = magic; // MagicNumber ордера
request.comment = comment; // Комментарий ордера
//--- Если отправить запрос не удалось - сообщим об этом в журнал и вернём false
if(!OrderSend(request,result))
{
PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__,
TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true)
);
return false;
}
//--- OrderSend OK, вернём true
return true;
}
//+------------------------------------------------------------------+
//| Закрывает позицию по тикету |
//+------------------------------------------------------------------+
bool ClosePosition(const ulong ticket,const ulong deviation=5)
{
//--- Объявляем структуры запроса и результата
MqlTradeRequest request;
MqlTradeResult result;
//--- Если позицию не удалось выбрать по тикету - сообщаем об ошибке и уходим
ResetLastError();
if(!PositionSelectByTicket(ticket))
{
Print("PositionSelectByTicket failed, error: ",(string)GetLastError());
return false;
}
//--- Получаем данные закрываемой позиции
string position_symbol=PositionGetString(POSITION_SYMBOL); // символ
int digits=(int)SymbolInfoInteger(position_symbol,SYMBOL_DIGITS); // количество знаков после запятой
double volume=PositionGetDouble(POSITION_VOLUME); // объем позиции
ENUM_POSITION_TYPE type=(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); // тип позиции
ulong magic=PositionGetInteger(POSITION_MAGIC); // MagicNumber позиции
//--- Обнуляем значения запроса и результата
ZeroMemory(request);
ZeroMemory(result);
//--- Устанавливаем параметры операции
request.action = TRADE_ACTION_DEAL; // тип торговой операции
request.position = ticket; // тикет позиции
request.symbol = position_symbol; // символ
request.volume = volume; // объем позиции
request.deviation = deviation; // допустимое отклонение от цены
request.magic = magic; // MagicNumber позиции
//--- Устанавливаем цену и тип ордера в зависимости от типа позиции
if(type==POSITION_TYPE_BUY)
{
request.price=NormalizeDouble(SymbolInfoDouble(position_symbol,SYMBOL_BID),digits);
request.type =ORDER_TYPE_SELL;
}
else
{
request.price=NormalizeDouble(SymbolInfoDouble(position_symbol,SYMBOL_ASK),digits);
request.type =ORDER_TYPE_BUY;
}
//--- Если отправить запрос не удалось, сообщим об этом в журнал и вернём false
if(!OrderSend(request,result))
{
PrintFormat("%s: OrderSend for %s %s #%llu error: %s",__FUNCTION__,
TradeActionDescription(request.action),OrderTypeDescription(request.type),ticket,RetcodeDescription(result.retcode,true)
);
return false;
}
//--- OrderSend OK, вернём true
return true;
}
//+------------------------------------------------------------------+
//| Закрывает все позиции по символу |
//+------------------------------------------------------------------+
uint ClosePositionsAll(const string symbol,const ulong magic=0)
{
//--- Объявим переменную для хранения результата и количества закрытых позиций
bool res=true;
uint num=0;
//--- перебор всех открытых позиций
int total=PositionsTotal(); // количество открытых позиций
for(int i=total-1; i>=0; i--)
{
ulong position_ticket=PositionGetTicket(i); // тикет позиции
if(position_ticket==0)
continue;
if(PositionGetInteger(POSITION_MAGIC)!=magic)
continue;
//--- Если MagicNumber не указан (нулевой) или магик позиции соответствует указанному
if(magic==0 || PositionGetInteger(POSITION_MAGIC)==magic)
{
//--- если символ позиции совпадает с переданным или передан NULL - закрываем позицию по тикету
if(symbol==NULL || PositionGetString(POSITION_SYMBOL)==symbol)
{
//--- Получаем результат закрытия позиции по тикету и увеличиваем счётчик закрытых при успехе
res &=ClosePosition(position_ticket);
if(res)
num++;
}
}
}
if(!res)
PrintFormat("%s: Not all positions were able to close without errors",__FUNCTION__);
return num;
}
//+------------------------------------------------------------------+
//| Устанавливает указанный отложенный ордер |
//+------------------------------------------------------------------+
bool SetPending(const string symbol,const ENUM_ORDER_TYPE order_type,const double lots,const uint magic,const int distance,const int stoplimit=0,const string comment="")
{
//--- Устанавливаем символ для запроса
string symbol_name=(symbol==NULL ? Symbol() : symbol);
//--- Объявляем и инициализируем структуры запроса и результата
MqlTradeRequest request={};
MqlTradeResult result={};
//--- Устанавливаем параметры операции
request.action = TRADE_ACTION_PENDING; // тип торговой операции
request.type = order_type; // тип ордера
request.symbol = symbol_name; // символ
request.volume = lots; // объем
request.magic = magic; // MagicNumber ордера
request.comment = comment; // Комментарий ордера
//--- Получаем Point и Digits
double point=SymbolInfoDouble(symbol_name,SYMBOL_POINT);
int digits=(int)SymbolInfoInteger(symbol_name,SYMBOL_DIGITS);
//--- Рассчитываем дистанцию от цены в зависимости от типа ордера
//--- Ордер на покупку
if(order_type==ORDER_TYPE_BUY_STOP)
request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)+distance*point,digits); // нормализованная цена установки
if(order_type==ORDER_TYPE_BUY_LIMIT)
request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)-distance*point,digits); // нормализованная цена установки
if(order_type==ORDER_TYPE_BUY_STOP_LIMIT)
{
request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_ASK)+distance*point,digits); // нормализованная цена срабатывания Stop-ордера
request.stoplimit=NormalizeDouble(request.price-stoplimit*point,digits); // нормализованная цена установки Limit-ордера
}
//--- Ордер на продажу
if(order_type==ORDER_TYPE_SELL_STOP)
request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)-distance*point,digits); // нормализованная цена установки
if(order_type==ORDER_TYPE_SELL_LIMIT)
request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)+distance*point,digits); // нормализованная цена установки
if(order_type==ORDER_TYPE_SELL_STOP_LIMIT)
{
request.price=NormalizeDouble(SymbolInfoDouble(symbol_name,SYMBOL_BID)-distance*point,digits); // нормализованная цена срабатывания Stop-ордера
request.stoplimit=NormalizeDouble(request.price+stoplimit*point,digits); // нормализованная цена установки Limit-ордера
}
//--- Если отправить запрос не удалось, сообщим об этом в журнал и вернём false
if(!OrderSend(request,result))
{
PrintFormat("%s: OrderSend for %s %s error: %s",__FUNCTION__,
TradeActionDescription(request.action),OrderTypeDescription(request.type),RetcodeDescription(result.retcode,true)
);
return false;
}
//--- OrderSend OK, вернём true
return true;
}
//+------------------------------------------------------------------+
//| Устанавливает отложенный ордер BuyStop |
//+------------------------------------------------------------------+
bool SetBuyStop(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
{
//--- Вызываем функцию SetPending с параметрами для BuyStop
return SetPending(symbol,ORDER_TYPE_BUY_STOP,lots,magic,distance,0,comment);
}
//+------------------------------------------------------------------+
//| Устанавливает отложенный ордер BuyLimit |
//+------------------------------------------------------------------+
bool SetBuyLimit(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
{
//--- Вызываем функцию SetPending с параметрами для BuyLimit
return SetPending(symbol,ORDER_TYPE_BUY_LIMIT,lots,magic,distance,0,comment);
}
//+------------------------------------------------------------------+
//| Устанавливает отложенный ордер BuyStopLimit |
//+------------------------------------------------------------------+
bool SetBuyStopLimit(const string symbol,const double lots,const uint magic,const int distance,const int stoplimit,const string comment="")
{
//--- Вызываем функцию SetPending с параметрами для BuyStopLimit
return SetPending(symbol,ORDER_TYPE_BUY_STOP_LIMIT,lots,magic,distance,stoplimit,comment);
}
//+------------------------------------------------------------------+
//| Устанавливает отложенный ордер SellStop |
//+------------------------------------------------------------------+
bool SetSellSellStop(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
{
//--- Вызываем функцию SetPending с параметрами для SellStop
return SetPending(symbol,ORDER_TYPE_SELL_STOP,lots,magic,distance,0,comment);
}
//+------------------------------------------------------------------+
//| Устанавливает отложенный ордер SellLimit |
//+------------------------------------------------------------------+
bool SetSellLimit(const string symbol,const double lots,const uint magic,const int distance,const string comment="")
{
//--- Вызываем функцию SetPending с параметрами для SellLimit
return SetPending(symbol,ORDER_TYPE_SELL_LIMIT,lots,magic,distance,0,comment);
}
//+------------------------------------------------------------------+
//| Устанавливает отложенный ордер SellStopLimit |
//+------------------------------------------------------------------+
bool SetSellStopLimit(const string symbol,const double lots,const uint magic,const int distance,const int stoplimit,const string comment="")
{
//--- Вызываем функцию SetPending с параметрами для SellStopLimit
return SetPending(symbol,ORDER_TYPE_SELL_STOP_LIMIT,lots,magic,distance,stoplimit,comment);
}
//+------------------------------------------------------------------+
//| Удаляет отложенный ордер по тикету |
//+------------------------------------------------------------------+
bool DeleteOrder(const ulong ticket)
{
//-- объявление и инициализация запроса и результата
MqlTradeRequest request={};
MqlTradeResult result={};
ResetLastError();
//--- Если ордер не удалось выбрать по тикету - сообщаем об ошибке и уходим
if(!OrderSelect(ticket))
{
PrintFormat("%s: OrderSelect failed, error: %d",__FUNCTION__,GetLastError());
return false;
}
//--- Обнуляем значения запроса и результата
ZeroMemory(request);
ZeroMemory(result);
//--- Устанавливаем параметры операции
request.action=TRADE_ACTION_REMOVE; // тип торговой операции
request.order = ticket; // тикет ордера
//--- Если отправить запрос не удалось, сообщим об этом в журнал и вернём false
if(!OrderSend(request,result))
{
PrintFormat("%s: OrderSend for %s %s #%llu error: %s",__FUNCTION__,
TradeActionDescription(request.action),OrderTypeDescription((ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE)),ticket,RetcodeDescription(result.retcode,true)
);
return false;
}
//--- OrderSend OK, вернём true
return true;
}
//+------------------------------------------------------------------+
//| Удаляет все отложенные ордера по символу |
//+------------------------------------------------------------------+
uint DeleteOrdersAll(const string symbol,const long magic=WRONG_VALUE)
{
//--- Объявим переменную для хранения результата и количества удалённых ордеров
bool res=true;
uint num=0;
//--- перебор всех установленных отложенных ордеров
int total=OrdersTotal(); // количество установленных отложенных ордеров
for(int i=total-1; i>=0; i--)
{
ulong order_ticket=OrderGetTicket(i); // тикет ордера
if(order_ticket==0)
continue;
//--- Если MagicNumber не указан (нулевой) или магик ордера соответствует указанному
if(magic==WRONG_VALUE || OrderGetInteger(ORDER_MAGIC)==magic)
{
//--- если символ ордера совпадает с переданным или передан NULL - удаляем ордер по тикету
if(symbol==NULL || OrderGetString(ORDER_SYMBOL)==symbol)
{
res &=DeleteOrder(order_ticket);
if(res)
num++;
}
}
}
if(!res)
PrintFormat("%s: Not all orders were able to close without errors",__FUNCTION__);
return num;
}
//+------------------------------------------------------------------+
//| Вспомогательные функции |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает состояние клавиши Ctrl |
//+------------------------------------------------------------------+
bool IsCtrlKeyPressed(void)
{
return(::TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL)<0);
}
//+------------------------------------------------------------------+
//| Возвращает состояние клавиши Shift |
//+------------------------------------------------------------------+
bool IsShiftKeyPressed(void)
{
return(::TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT)<0);
}
//+------------------------------------------------------------------+
//| Возвращает описание кода возврата торгового сервера |
//+------------------------------------------------------------------+
string RetcodeDescription(const uint retcode,bool ext_descr=false)
{
switch(retcode)
{
//--- Выполнено
case 0 : return "OK (0)";
//--- Реквота
case TRADE_RETCODE_REQUOTE : return "10004 REQUOTE"+(ext_descr ? " (Requote)" : "");
//--- Запрос отклонен
case TRADE_RETCODE_REJECT : return "10006 REJECT"+(ext_descr ? " (Request rejected)" : "");
//--- Запрос отменен трейдером
case TRADE_RETCODE_CANCEL : return "10007 CANCEL"+(ext_descr ? " (Request canceled by trader)" : "");
//--- Ордер размещен
case TRADE_RETCODE_PLACED : return "10008 PLACED"+(ext_descr ? " (Order placed)" : "");
//--- Заявка выполнена
case TRADE_RETCODE_DONE : return "10009 DONE"+(ext_descr ? " (Request completed)" : "");
//--- Заявка выполнена частично
case TRADE_RETCODE_DONE_PARTIAL : return "10010 DONE_PARTIAL"+(ext_descr ? " (Only part of the request was completed)" : "");
//--- Ошибка обработки запроса
case TRADE_RETCODE_ERROR : return "10011 ERROR"+(ext_descr ? " (Request processing error)" : "");
//--- Запрос отменен по истечению времени
case TRADE_RETCODE_TIMEOUT : return "10012 TIMEOUT"+(ext_descr ? " (Request canceled by timeout)" : "");
//--- Неправильный запрос
case TRADE_RETCODE_INVALID : return "10013 INVALID"+(ext_descr ? " (Invalid request)" : "");
//--- Неправильный объем в запросе
case TRADE_RETCODE_INVALID_VOLUME : return "10014 INVALID_VOLUME"+(ext_descr ? " (Invalid volume in the request)" : "");
//--- Неправильная цена в запросе
case TRADE_RETCODE_INVALID_PRICE : return "10015 INVALID_PRICE"+(ext_descr ? " (Invalid price in the request)" : "");
//--- Неправильные стопы в запросе
case TRADE_RETCODE_INVALID_STOPS : return "10016 INVALID_STOPS"+(ext_descr ? " (Invalid stops in the request)" : "");
//--- Торговля запрещена
case TRADE_RETCODE_TRADE_DISABLED : return "10017 TRADE_DISABLED"+(ext_descr ? " (Trade is disabled)" : "");
//--- Рынок закрыт
case TRADE_RETCODE_MARKET_CLOSED : return "10018 MARKET_CLOSED"+(ext_descr ? " (Market is closed)" : "");
//--- Нет достаточных денежных средств для выполнения запроса
case TRADE_RETCODE_NO_MONEY : return "10019 NO_MONEY"+(ext_descr ? " (There is not enough money to complete the request)" : "");
//--- Цены изменились
case TRADE_RETCODE_PRICE_CHANGED : return "10020 PRICE_CHANGED"+(ext_descr ? " (Prices changed)" : "");
//--- Отсутствуют котировки для обработки запроса
case TRADE_RETCODE_PRICE_OFF : return "10021 PRICE_OFF"+(ext_descr ? " (There are no quotes to process the request)" : "");
//--- Неверная дата истечения ордера в запросе
case TRADE_RETCODE_INVALID_EXPIRATION : return "10022 INVALID_EXPIRATION"+(ext_descr ? " (Invalid order expiration date in the request)" : "");
//--- Состояние ордера изменилось
case TRADE_RETCODE_ORDER_CHANGED : return "10023 ORDER_CHANGED"+(ext_descr ? " (Order state changed)" : "");
//--- Слишком частые запросы
case TRADE_RETCODE_TOO_MANY_REQUESTS : return "10024 TOO_MANY_REQUESTS"+(ext_descr ? " (Too frequent requests)" : "");
//--- В запросе нет изменений
case TRADE_RETCODE_NO_CHANGES : return "10025 NO_CHANGES"+(ext_descr ? " (No changes in request)" : "");
//--- Автотрейдинг запрещен сервером
case TRADE_RETCODE_SERVER_DISABLES_AT : return "10026 SERVER_DISABLES_AT"+(ext_descr ? " (Autotrading disabled by server)" : "");
//--- Автотрейдинг запрещен клиентским терминалом
case TRADE_RETCODE_CLIENT_DISABLES_AT : return "10027 CLIENT_DISABLES_AT"+(ext_descr ? " (Autotrading disabled by client terminal)" : "");
//--- Запрос заблокирован для обработки
case TRADE_RETCODE_LOCKED : return "10028 LOCKED"+(ext_descr ? " (Request locked for processing)" : "");
//--- Ордер или позиция заморожены
case TRADE_RETCODE_FROZEN : return "10029 FROZEN"+(ext_descr ? " (Order or position frozen)" : "");
//--- Указан неподдерживаемый тип исполнения ордера по остатку
case TRADE_RETCODE_INVALID_FILL : return "10030 INVALID_FILL"+(ext_descr ? " (Invalid order filling type)" : "");
//--- Нет соединения с торговым сервером
case TRADE_RETCODE_CONNECTION : return "10031 CONNECTION"+(ext_descr ? " (No connection with the trade server)" : "");
//--- Операция разрешена только для реальных счетов
case TRADE_RETCODE_ONLY_REAL : return "10032 ONLY_REAL"+(ext_descr ? " (Operation is allowed only for live accounts)" : "");
//--- Достигнут лимит на количество отложенных ордеров
case TRADE_RETCODE_LIMIT_ORDERS : return "10033 LIMIT_ORDERS"+(ext_descr ? " (The number of pending orders has reached the limit)" : "");
//--- Достигнут лимит на объем ордеров и позиций для данного символа
case TRADE_RETCODE_LIMIT_VOLUME : return "10034 LIMIT_VOLUME"+(ext_descr ? " (The volume of orders and positions for the symbol has reached the limit)" : "");
//--- Неверный или запрещённый тип ордера
case TRADE_RETCODE_INVALID_ORDER : return "10035 INVALID_ORDER"+(ext_descr ? " (Incorrect or prohibited order type)" : "");
//--- Позиция с указанным POSITION_IDENTIFIER уже закрыта
case TRADE_RETCODE_POSITION_CLOSED : return "10036 POSITION_CLOSED"+(ext_descr ? " (Position with the specified POSITION_IDENTIFIER has already been closed)" : "");
//--- Закрываемый объем превышает текущий объем позиции
case TRADE_RETCODE_INVALID_CLOSE_VOLUME: return "10038 INVALID_CLOSE_VOLUME"+(ext_descr ? " (A close volume exceeds the current position volume)" : "");
//--- Для указанной позиции уже есть ордер на закрытие
case TRADE_RETCODE_CLOSE_ORDER_EXIST : return "10039 CLOSE_ORDER_EXIST"+(ext_descr ? " (A close order already exists for a specified position)" : "");
//--- Достигнут лимит на количество позиций
case TRADE_RETCODE_LIMIT_POSITIONS : return "10040 LIMIT_POSITIONS"+(ext_descr ? " (The number of positions has reached the limit)" : "");
//--- Запрос на активацию отложенного ордера отклонен, а сам ордер отменен
case TRADE_RETCODE_REJECT_CANCEL : return "10041 REJECT_CANCEL"+(ext_descr ? " (The pending order activation request is rejected, the order is canceled)" : "");
//--- Запрос отклонен, так как на символе разрешены только длинные позиции
case TRADE_RETCODE_LONG_ONLY : return "10042 LONG_ONLY"+(ext_descr ? " (Only long positions are allowed)" : "");
//--- Запрос отклонен, так как на символе разрешены только короткие позиции
case TRADE_RETCODE_SHORT_ONLY : return "10043 SHORT_ONLY"+(ext_descr ? " (Only short positions are allowed)" : "");
//--- Запрос отклонен, так как на символе разрешено только закрывать существующие позиции
case TRADE_RETCODE_CLOSE_ONLY : return "10044 CLOSE_ONLY"+(ext_descr ? " (Only position closing is allowed)" : "");
//--- Запрос отклонен, так как для торгового счета разрешено закрывать существующие позиции только по правилу FIFO
case TRADE_RETCODE_FIFO_CLOSE : return "10045 FIFO_CLOSE"+(ext_descr ? " (Position closing is allowed only by FIFO rule)" : "");
//--- Запрос отклонен, так как для торгового счета запрещено открывать встречные позиции по одному символу
case TRADE_RETCODE_HEDGE_PROHIBITED : return "10046 HEDGE_PROHIBITED"+(ext_descr ? " (Opposite positions on a single symbol are disabled)" : "");
//--- Неизвестный код возврата
default : return "Undefined ("+(string)retcode+")";
}
}
//+------------------------------------------------------------------+
//| Возвращает описание типа ордера |
//+------------------------------------------------------------------+
string OrderTypeDescription(const ENUM_ORDER_TYPE type,const bool ext_descr=false)
{
//--- "Вырезаем" из строки, полученной из enum, только тип ордера
string res=StringSubstr(EnumToString(type),11);
//--- Преобразуем все полученные символы в нижний регистр и
if(res.Lower())
{
//--- заменяем первую букву с маленькой на заглавную
res.SetChar(0,ushort(res.GetChar(0)-0x20));
int total=(int)res.Length(); // Длина текста
int index=0; // индекс начала поиска символов "_" в тексте
//--- В цикле по всем символам ищем в тексте знаки нижнего подчёркивания
for(int i=0;i<total;i++)
{
int pos=StringFind(res,"_",index);
//--- Если подчёркивание найдено,
if(pos>0)
{
//--- заменяем его на пробел и следующую букву переводим в верхний регистр
res.SetChar(pos,' ');
res.SetChar(pos+1,ushort(res.GetChar(pos+1)-0x20));
//--- Устанавливаем новый индекс начала поиска знаков "_"
index=pos;
}
}
}
string descr="";
switch(type)
{
case ORDER_TYPE_BUY : descr=" (Market Buy order)"; break;
case ORDER_TYPE_SELL : descr=" (Market Sell order)"; break;
case ORDER_TYPE_BUY_LIMIT : descr=" (Buy Limit pending order)"; break;
case ORDER_TYPE_SELL_LIMIT : descr=" (Sell Limit pending order)"; break;
case ORDER_TYPE_BUY_STOP : descr=" (Buy Stop pending order)"; break;
case ORDER_TYPE_SELL_STOP : descr=" (Sell Stop pending order)"; break;
case ORDER_TYPE_BUY_STOP_LIMIT : descr=" (Upon reaching the order price, a pending Buy Limit order is placed at the StopLimit price)"; break;
case ORDER_TYPE_SELL_STOP_LIMIT : descr=" (Upon reaching the order price, a pending Sell Limit order is placed at the StopLimit price)";break;
case ORDER_TYPE_CLOSE_BY : descr=" (Order to close a position by an opposite one)"; break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Sell Limit (Sell Limit pending order)
*/
}
//+------------------------------------------------------------------+
//| Возвращает описание типа ордера по исполнению |
//+------------------------------------------------------------------+
string OrderTypeFillingDescription(const ENUM_ORDER_TYPE_FILLING type_filling,const bool ext_descr=false)
{
string res=StringSubstr(EnumToString(type_filling),14);
//--- Преобразуем все полученные символы в нижний регистр и заменяем первую букву с маленькой на заглавную (для ORDER_FILLING_RETURN)
if(type_filling==ORDER_FILLING_RETURN && res.Lower())
res.SetChar(0,ushort(res.GetChar(0)-0x20));
string descr="";
switch(type_filling)
{
case ORDER_FILLING_FOK : descr=" (Fill or Kill. An order can be executed in the specified volume only)"; break;
case ORDER_FILLING_IOC : descr=" (Immediate or Cancel. A deal with the volume maximally available in the market within that indicated in the order)"; break;
case ORDER_FILLING_BOC : descr=" (Passive (Book or Cancel). The order can only be placed in the Depth of Market and cannot be immediately executed)"; break;
case ORDER_FILLING_RETURN : descr=" (In case of partial filling, an order with remaining volume is not canceled but processed further)"; break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
*/
}
//+------------------------------------------------------------------+
//| Возвращает описание типа торговой транзакции |
//+------------------------------------------------------------------+
string TradeTransactionTypeDescription(const ENUM_TRADE_TRANSACTION_TYPE transaction,const bool ext_descr=false)
{
//--- "Вырезаем" из строки, полученной из enum, только тип транзакции
string res=StringSubstr(EnumToString(transaction),18);
//--- Преобразуем все полученные символы в нижний регистр и заменяем первую букву с маленькой на заглавную
if(res.Lower())
res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Заменяем в полученной строке все символы подчёркивания на символ пробела
StringReplace(res,"_"," ");
string descr="";
switch(transaction)
{
case TRADE_TRANSACTION_ORDER_ADD : descr=" (Adding a new open order)"; break;
case TRADE_TRANSACTION_ORDER_UPDATE : descr=" (Updating an open order)"; break;
case TRADE_TRANSACTION_ORDER_DELETE : descr=" (Removing an order from the list of the open ones)"; break;
case TRADE_TRANSACTION_DEAL_ADD : descr=" (Adding a deal to the history)"; break;
case TRADE_TRANSACTION_DEAL_UPDATE : descr=" (Updating a deal in the history)"; break;
case TRADE_TRANSACTION_DEAL_DELETE : descr=" (Deleting a deal from the history)"; break;
case TRADE_TRANSACTION_HISTORY_ADD : descr=" (Adding an order to the history as a result of execution or cancellation)"; break;
case TRADE_TRANSACTION_HISTORY_UPDATE : descr=" (Changing an order located in the orders history)"; break;
case TRADE_TRANSACTION_HISTORY_DELETE : descr=" (Deleting an order from the orders history)"; break;
case TRADE_TRANSACTION_POSITION : descr=" (Changing a position not related to a deal execution)"; break;
case TRADE_TRANSACTION_REQUEST : descr=" (The trade request has been processed by a server and processing result has been received)"; break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Order add (Adding a new open order)
*/
}
//+------------------------------------------------------------------+
//| Возвращает описание состояния ордера |
//+------------------------------------------------------------------+
string OrderStateDescription(const ENUM_ORDER_STATE state,const bool ext_descr=false)
{
//--- "Вырезаем" из строки, полученной из enum, только состояние ордера
string res=StringSubstr(EnumToString(state),12);
//--- Преобразуем все полученные символы в нижний регистр и заменяем первую букву с маленькой на заглавную
if(res.Lower())
res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Заменяем в полученной строке все символы подчёркивания на символ пробела
StringReplace(res,"_"," ");
string descr="";
switch(state)
{
case ORDER_STATE_STARTED : descr=" (Order checked, but not yet accepted by broker)"; break;
case ORDER_STATE_PLACED : descr=" (Order accepted)"; break;
case ORDER_STATE_CANCELED : descr=" (Order canceled by client)"; break;
case ORDER_STATE_PARTIAL : descr=" (Order partially executed)"; break;
case ORDER_STATE_FILLED : descr=" (Order fully executed)"; break;
case ORDER_STATE_REJECTED : descr=" (Order rejected)"; break;
case ORDER_STATE_EXPIRED : descr=" (Order expired)"; break;
case ORDER_STATE_REQUEST_ADD : descr=" (Order is being registered (placing to the trading system))";break;
case ORDER_STATE_REQUEST_MODIFY : descr=" (Order is being modified (changing its parameters))"; break;
case ORDER_STATE_REQUEST_CANCEL : descr=" (Order is being deleted (deleting from the trading system))";break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Placed (Order accepted)
*/
}
//+------------------------------------------------------------------+
//| Возвращает описание типа сделки |
//+------------------------------------------------------------------+
string DealTypeDescription(const ENUM_DEAL_TYPE type,const bool ext_descr=false)
{
//--- "Вырезаем" из строки, полученной из enum, только тип сделки
string res=StringSubstr(EnumToString(type),(type==DEAL_DIVIDEND || type==DEAL_DIVIDEND_FRANKED || type==DEAL_TAX ? 5 : 10));
//--- Преобразуем все полученные символы в нижний регистр и заменяем первую букву с маленькой на заглавную
if(res.Lower())
res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Заменяем в полученной строке все символы подчёркивания на символ пробела
StringReplace(res,"_"," ");
string descr="";
//--- Расширенные описания добавляются только к тем сделкам, чьё описание, полученное из enum, не совпадает с расширенным
switch(type)
{
case DEAL_TYPE_CHARGE : descr=" (Additional charge)"; break;
case DEAL_TYPE_COMMISSION : descr=" (Additional commission)"; break;
case DEAL_TYPE_COMMISSION_DAILY : descr=" (Daily commission)"; break;
case DEAL_TYPE_COMMISSION_MONTHLY : descr=" (Monthly commission)"; break;
case DEAL_TYPE_COMMISSION_AGENT_DAILY : descr=" (Daily agent commission)"; break;
case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: descr=" (Monthly agent commission)"; break;
case DEAL_TYPE_INTEREST : descr=" (Interest rate)"; break;
case DEAL_TYPE_BUY_CANCELED : descr=" (Canceled buy deal)"; break;
case DEAL_TYPE_SELL_CANCELED : descr=" (Canceled sell deal)"; break;
case DEAL_DIVIDEND : descr=" (Dividend operations)"; break;
case DEAL_DIVIDEND_FRANKED : descr=" (Franked (non-taxable) dividend operations)"; break;
case DEAL_TAX : descr=" (Tax charges)"; break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Comission (Additional commission)
*/
}
//+------------------------------------------------------------------+
//| Возвращает описание типа ордера по истечению |
//+------------------------------------------------------------------+
string OrderTypeTimeDescription(const ENUM_ORDER_TYPE_TIME type_time,const bool ext_descr=false)
{
//--- "Вырезаем" из строки, полученной из enum, только тип ордера по истечению
string res=StringSubstr(EnumToString(type_time),6);
//--- Если тип по истечению ORDER_TIME_GTC, то впишем в res "Time GTC"
if(type_time==ORDER_TIME_GTC)
res="Time GTC";
//--- Иначе - преобразуем все полученные символы в нижний регистр и заменяем первую букву с маленькой на заглавную
else
{
if(res.Lower())
res.SetChar(0,ushort(res.GetChar(0)-0x20));
//--- Заменяем в полученной строке все символы подчёркивания на символ пробела
StringReplace(res,"_"," ");
}
string descr="";
switch(type_time)
{
case ORDER_TIME_GTC : descr=" (Good till cancel order)"; break;
case ORDER_TIME_DAY : descr=" (Good till current trade day order)"; break;
case ORDER_TIME_SPECIFIED : descr=" (Good till expired order)"; break;
case ORDER_TIME_SPECIFIED_DAY : descr=" (The order will be effective till 23:59:59 of the specified day)"; break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Time GTC (Good till cancel order)
*/
}
//+------------------------------------------------------------------+
//| Определяет и устанавливает значения принадлежности транзакции |
//+------------------------------------------------------------------+
void SetTransactionBelong(const ENUM_TRADE_TRANSACTION_TYPE type,bool &request_flag,bool &order_flag,bool &deal_flag,bool &position_flag)
{
switch(type)
{
//--- Запрос
case TRADE_TRANSACTION_REQUEST : request_flag=true; order_flag=false; deal_flag=false; position_flag=false; break;
//--- Ордер
case TRADE_TRANSACTION_ORDER_ADD :
case TRADE_TRANSACTION_ORDER_UPDATE :
case TRADE_TRANSACTION_ORDER_DELETE :
case TRADE_TRANSACTION_HISTORY_ADD :
case TRADE_TRANSACTION_HISTORY_UPDATE :
case TRADE_TRANSACTION_HISTORY_DELETE : request_flag=false; order_flag=true; deal_flag=false; position_flag=false; break;
//--- Сделка
case TRADE_TRANSACTION_DEAL_ADD :
case TRADE_TRANSACTION_DEAL_UPDATE :
case TRADE_TRANSACTION_DEAL_DELETE : request_flag=false; order_flag=false; deal_flag=true; position_flag=false; break;
//--- Позиция
case TRADE_TRANSACTION_POSITION : request_flag=false; order_flag=false; deal_flag=false; position_flag=true; break;
//---
default: break;
}
}
//+------------------------------------------------------------------+
//| Возвращает описание типа торговго запроса |
//+------------------------------------------------------------------+
string TradeActionDescription(const ENUM_TRADE_REQUEST_ACTIONS action,const bool ext_descr=false)
{
//--- "Вырезаем" из строки, полученной из enum, только тип операции
string res=StringSubstr(EnumToString(action),13);
//--- Преобразуем все полученные символы в нижний регистр и заменяем первую букву с маленькой на заглавную (кроме TRADE_ACTION_SLTP)
if(action!=TRADE_ACTION_SLTP && res.Lower())
res.SetChar(0,ushort(res.GetChar(0)-0x20));
string descr="";
switch(action)
{
case TRADE_ACTION_DEAL : descr=" (Place a trade order for an immediate execution with the specified parameters (market order))";break;
case TRADE_ACTION_PENDING : descr=" (Place a trade order for the execution under specified conditions (pending order))"; break;
case TRADE_ACTION_SLTP : descr=" (Modify Stop Loss and Take Profit values of an opened position)"; break;
case TRADE_ACTION_MODIFY : descr=" (Modify the parameters of the order placed previously)"; break;
case TRADE_ACTION_REMOVE : descr=" (Delete the pending order placed previously)"; break;
case TRADE_ACTION_CLOSE_BY : descr=" (Close a position by an opposite one)"; break;
default: break;
}
return res+(!ext_descr ? "" : descr);
/* Пример вывода:
Pending (Place a trade order for the execution under specified conditions (pending order)):
*/
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|Функции для работы со структурой торгового запроса MqlTradeRequest|
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип выполняемого действия |
//+------------------------------------------------------------------+
string MqlTradeRequestAction(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Action:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,TradeActionDescription(req.action,ext_descr));
/* Пример вывода:
Action: Pending (Place a trade order for the execution under specified conditions (pending order)):
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки штамп эксперта (magic number) |
//+------------------------------------------------------------------+
string MqlTradeRequestMagic(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Magic:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.magic);
/* Пример вывода:
Magic: 1024
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет ордера |
//+------------------------------------------------------------------+
string MqlTradeRequestOrder(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Order:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.order);
/* Пример вывода:
Order: 1835982676
*/
}
//+------------------------------------------------------------------+
//| Возвращает имя торгового инструмента |
//+------------------------------------------------------------------+
string MqlTradeRequestSymbol(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Symbol:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,req.symbol);
/* Пример вывода:
Symbol: EURUSD
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки запрашиваемый объем сделки в лотах |
//+------------------------------------------------------------------+
string MqlTradeRequestVolume(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Volume:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой в значении лота. Если символ не указан, используем 1
int dg=(int)ceil(fabs(log10(SymbolInfoDouble(req.symbol,SYMBOL_VOLUME_STEP))));
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.volume);
/* Пример вывода:
Volume: 0.10
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки цену |
//+------------------------------------------------------------------+
string MqlTradeRequestPrice(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Price:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(req.price!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.price);
/* Пример вывода:
Price: 1.09586
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки уровень StopLimit ордера |
//+------------------------------------------------------------------+
string MqlTradeRequestStopLimit(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="StopLimit:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(req.stoplimit!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.stoplimit);
/* Пример вывода:
StopLimit: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки уровень Stop Loss ордера |
//+------------------------------------------------------------------+
string MqlTradeRequestStopLoss(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="SL:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(req.sl!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.sl);
/* Пример вывода:
SL: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки уровень Take Profit ордера |
//+------------------------------------------------------------------+
string MqlTradeRequestTakeProfit(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="TP:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(req.tp!=0 ? (int)SymbolInfoInteger(req.symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,req.tp);
/* Пример вывода:
TP: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки максимально приемлемое |
//| отклонение от запрашиваемой цены |
//+------------------------------------------------------------------+
string MqlTradeRequestDeviation(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Deviation:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.deviation);
/* Пример вывода:
Deviation: 5
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип ордера |
//+------------------------------------------------------------------+
string MqlTradeRequestType(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Type:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeDescription(req.type,ext_descr));
/* Пример вывода:
Type: Buy Limit (Buy Limit pending order)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип ордера по исполнению |
//+------------------------------------------------------------------+
string MqlTradeRequestTypeFilling(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Type filling:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeFillingDescription(req.type_filling,ext_descr));
/* Пример вывода:
Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип ордера по времени действия |
//+------------------------------------------------------------------+
string MqlTradeRequestTypeTime(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Type time:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,OrderTypeTimeDescription(req.type_time,ext_descr));
/* Пример вывода:
Type time: Time GTC (Good till cancel order)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки срок истечения ордера |
//+------------------------------------------------------------------+
string MqlTradeRequestExpiration(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Expiration:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,(req.type_time==ORDER_TIME_SPECIFIED || req.type_time==ORDER_TIME_SPECIFIED_DAY ? (string)req.expiration : "0"));
/* Пример вывода:
Expiration: 0
*/
}
//+------------------------------------------------------------------+
//| Возвращает комментарий к ордеру |
//+------------------------------------------------------------------+
string MqlTradeRequestComment(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Comment:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,req.comment);
/* Пример вывода:
Comment: TestMqlTradeTransaction
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет позиции |
//+------------------------------------------------------------------+
string MqlTradeRequestPosition(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Position:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.position);
/* Пример вывода:
Position: 1835982676
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет встречной позиции |
//+------------------------------------------------------------------+
string MqlTradeRequestPositionBy(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Position by:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,req.position_by);
/* Пример вывода:
Position by: 1835987626
*/
}
//+------------------------------------------------------------------+
//| Выводит в журнал описание торгового запроса |
//+------------------------------------------------------------------+
void TradeRequestPrint(const MqlTradeRequest &req,const uint header_width=0,const uint indent=0,bool ext_descr=false)
{
//--- Получаем тип исполнения по символу
ENUM_SYMBOL_TRADE_EXECUTION exemode=(ENUM_SYMBOL_TRADE_EXECUTION)SymbolInfoInteger(req.symbol,SYMBOL_TRADE_EXEMODE);
//--- Заголовок
PrintFormat("Request %s:",TradeActionDescription(req.action,ext_descr));
//--- Установить торговый ордер на немедленное совершение сделки с указанными параметрами (поставить рыночный ордер)
if(req.action==TRADE_ACTION_DEAL)
{
//--- В зависимости от режима заключения сделок
switch(exemode)
{
//--- Торговый ордер на открытие позиции в режиме Request Execution (режим торговли по запросу текущих цен)
//--- Торговый ордер на открытие позиции в режиме Instant Execution (режим торговли по потоковым ценам)
case SYMBOL_TRADE_EXECUTION_REQUEST :
case SYMBOL_TRADE_EXECUTION_INSTANT :
Print(MqlTradeRequestSymbol(req,header_width,indent));
Print(MqlTradeRequestVolume(req,header_width,indent));
Print(MqlTradeRequestPrice(req,header_width,indent));
if(req.position==0) // Только для открытия позиции
Print(MqlTradeRequestStopLoss(req,header_width,indent));
if(req.position==0) // Только для открытия позиции
Print(MqlTradeRequestTakeProfit(req,header_width,indent));
Print(MqlTradeRequestDeviation(req,header_width,indent));
Print(MqlTradeRequestType(req,header_width,indent,ext_descr));
Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr));
Print(MqlTradeRequestMagic(req,header_width,indent));
if(req.position==0) // Только для открытия позиции
Print(MqlTradeRequestComment(req,header_width,indent));
//--- Закрытие
if(req.position!=0)
Print(MqlTradeRequestPosition(req,header_width,indent));
break;
//--- Торговый ордер на открытие позиции в режиме Market Execution (режим исполнения торговых приказов по рынку)
//--- Торговый ордер на открытие позиции в режиме Exchange Execution (биржевой режим исполнения торговых приказов)
case SYMBOL_TRADE_EXECUTION_MARKET :
case SYMBOL_TRADE_EXECUTION_EXCHANGE :
Print(MqlTradeRequestSymbol(req,header_width,indent));
Print(MqlTradeRequestVolume(req,header_width,indent));
Print(MqlTradeRequestType(req,header_width,indent,ext_descr));
Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr));
Print(MqlTradeRequestMagic(req,header_width,indent));
if(req.position==0) // Только для открытия позиции
Print(MqlTradeRequestComment(req,header_width,indent));
//--- Закрытие
if(req.position!=0)
Print(MqlTradeRequestPosition(req,header_width,indent));
break;
default:
break;
}
}
//--- Торговый приказ на закрытие позиции встречной
if(req.action==TRADE_ACTION_CLOSE_BY)
{
Print(MqlTradeRequestSymbol(req,header_width,indent));
Print(MqlTradeRequestPosition(req,header_width,indent));
Print(MqlTradeRequestMagic(req,header_width,indent));
Print(MqlTradeRequestComment(req,header_width,indent));
Print(MqlTradeRequestPositionBy(req,header_width,indent));
}
//--- Торговый приказ на модификацию уровней StopLoss и/или TakeProfit
if(req.action==TRADE_ACTION_SLTP)
{
Print(MqlTradeRequestSymbol(req,header_width,indent));
Print(MqlTradeRequestStopLoss(req,header_width,indent));
Print(MqlTradeRequestTakeProfit(req,header_width,indent));
Print(MqlTradeRequestPosition(req,header_width,indent));
}
//--- Торговый приказ на установку отложенного ордера
if(req.action==TRADE_ACTION_PENDING)
{
Print(MqlTradeRequestSymbol(req,header_width,indent));
Print(MqlTradeRequestVolume(req,header_width,indent));
Print(MqlTradeRequestPrice(req,header_width,indent));
if(req.type==ORDER_TYPE_BUY_STOP_LIMIT || req.type==ORDER_TYPE_SELL_STOP_LIMIT)
Print(MqlTradeRequestStopLimit(req,header_width,indent));
Print(MqlTradeRequestStopLoss(req,header_width,indent));
Print(MqlTradeRequestTakeProfit(req,header_width,indent));
Print(MqlTradeRequestType(req,header_width,indent,ext_descr));
Print(MqlTradeRequestTypeFilling(req,header_width,indent,ext_descr));
Print(MqlTradeRequestTypeTime(req,header_width,indent,ext_descr));
Print(MqlTradeRequestExpiration(req,header_width,indent));
Print(MqlTradeRequestMagic(req,header_width,indent));
Print(MqlTradeRequestComment(req,header_width,indent));
}
//--- Торговый приказ на модификацию уровней цен отложенного ордера
if(req.action==TRADE_ACTION_MODIFY)
{
Print(MqlTradeRequestOrder(req,header_width,indent));
Print(MqlTradeRequestPrice(req,header_width,indent));
if(req.stoplimit!=0)
Print(MqlTradeRequestStopLimit(req,header_width,indent));
Print(MqlTradeRequestStopLoss(req,header_width,indent));
Print(MqlTradeRequestTakeProfit(req,header_width,indent));
Print(MqlTradeRequestTypeTime(req,header_width,indent,ext_descr));
Print(MqlTradeRequestExpiration(req,header_width,indent));
}
//--- Торговый приказ на удаление отложенного ордера
if(req.action==TRADE_ACTION_REMOVE)
{
Print(MqlTradeRequestOrder(req,header_width,indent));
}
/* Пример вывода:
Request Pending (Place a trade order for the execution under specified conditions (pending order)):
Symbol: EURUSD
Volume: 0.10
Price: 1.09586
SL: 0.0
TP: 0.0
Type: Buy Limit (Buy Limit pending order)
Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
Type time: Time GTC (Good till cancel order)
Expiration: 0
Magic: 1024
Comment: TestMqlTradeTransaction
*/
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Функции для работы со структурой |
//| результата проверки торгового запроса MqlTradeCheckResult |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает в виде строки код ответа |
//+------------------------------------------------------------------+
string MqlTradeCheckResultRetcode(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Retcode:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,RetcodeDescription(result.retcode,ext_descr));
/* Пример вывода:
Retcode: OK (0)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки баланс после совершения сделки |
//+------------------------------------------------------------------+
string MqlTradeCheckResultBalance(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Balance:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем валюту счёта
string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Получаем количество знаков после запятой
int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.balance,currency);
/* Пример вывода:
Balance: 10016.80 USD
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки эквити после совершения сделки |
//+------------------------------------------------------------------+
string MqlTradeCheckResultEquity(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Equity:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем валюту счёта
string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Получаем количество знаков после запятой
int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.equity,currency);
/* Пример вывода:
Equity: 10016.80 USD
*/
}
//+------------------------------------------------------------------+
//|Возвращает в виде строки плавающую прибыль после совершения сделки|
//+------------------------------------------------------------------+
string MqlTradeCheckResultProfit(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Profit:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем валюту счёта
string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Получаем количество знаков после запятой
int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.profit,currency);
/* Пример вывода:
Profit: 0.00 USD
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки размер маржи, |
//| необходимый для требуемой торговой операции |
//+------------------------------------------------------------------+
string MqlTradeCheckResultMargin(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Margin:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем валюту счёта
string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Получаем количество знаков после запятой
int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.margin,currency);
/* Пример вывода:
Margin: 128.66 USD
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки размер свободных собственных средств, |
//| которые останутся после выполнения требуемой торговой операции |
//+------------------------------------------------------------------+
string MqlTradeCheckResultMarginFree(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Margin free:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем валюту счёта
string currency=AccountInfoString(ACCOUNT_CURRENCY);
//--- Получаем количество знаков после запятой
int dg=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f %s",indent,"",w,header,dg,result.margin_free,currency);
/* Пример вывода:
Margin free: 9888.14 USD
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки уровень маржи, который установится |
//| после выполнения требуемой торговой операции |
//+------------------------------------------------------------------+
string MqlTradeCheckResultMarginLevel(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Margin level:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.2f %%",indent,"",w,header,result.margin_level);
/* Пример вывода:
Margin level: 7785.48 %
*/
}
//+------------------------------------------------------------------+
//| Возвращает комментарий к коду ответа, описание ошибки |
//+------------------------------------------------------------------+
string MqlTradeCheckResultComment(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Comment:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,result.comment);
/* Пример вывода:
Comment: Done
*/
}
//+------------------------------------------------------------------+
//| Выводит в журнал поля структуры MqlTradeCheckResult |
//| в результате OrderCheck |
//+------------------------------------------------------------------+
void OrderCheckResultPrint(const MqlTradeCheckResult &result,const uint header_width=0,const uint indent=0,bool ext_descr=false)
{
Print("OrderCheck result:");
Print(MqlTradeCheckResultRetcode(result,header_width,indent,ext_descr));
Print(MqlTradeCheckResultBalance(result,header_width,indent));
Print(MqlTradeCheckResultEquity(result,header_width,indent));
Print(MqlTradeCheckResultProfit(result,header_width,indent));
Print(MqlTradeCheckResultMargin(result,header_width,indent));
Print(MqlTradeCheckResultMarginFree(result,header_width,indent));
Print(MqlTradeCheckResultMarginLevel(result,header_width,indent));
Print(MqlTradeCheckResultComment(result,header_width,indent));
/* Пример вывода:
OrderCheck result:
Retcode: Undefined (0)
Balance: 10016.80 USD
Equity: 10016.80 USD
Profit: 0.00 USD
Margin: 128.66 USD
Margin free: 9888.14 USD
Margin level: 7785.48 %
Comment: Done
*/
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Функции для работы со структурой |
//| результата торгового запроса MqlTradeResult |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает в виде строки код результата операции |
//+------------------------------------------------------------------+
string MqlTradeResultRetcode(const MqlTradeResult &result,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Retcode:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,RetcodeDescription(result.retcode,ext_descr));
/* Пример вывода:
Retcode: 10009 DONE (Request completed)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет сделки, если она совершена |
//+------------------------------------------------------------------+
string MqlTradeResultDeal(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Deal:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,result.deal);
/* Пример вывода:
Deal: 0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет ордера, если он выставлен |
//+------------------------------------------------------------------+
string MqlTradeResultOrder(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Order:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,result.order);
/* Пример вывода:
Order: 1821552382
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки объем сделки, подтверждённый брокером |
//+------------------------------------------------------------------+
string MqlTradeResultVolume(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Volume:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой в значении лота
int dg=(int)ceil(fabs(log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP))));
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.volume);
/* Пример вывода:
Volume: 0.10
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки цену в сделке, подтверждённую брокером |
//+------------------------------------------------------------------+
string MqlTradeResultPrice(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Price:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(result.price!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.price);
/* Пример вывода:
Price: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки текущую рыночную цену предложения (Bid) |
//+------------------------------------------------------------------+
string MqlTradeResultBid(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Bid:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(result.bid!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.bid);
/* Пример вывода:
Bid: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки текущую рыночную цену спроса (Ask) |
//+------------------------------------------------------------------+
string MqlTradeResultAsk(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Ask:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой
int dg=(result.ask!=0 ? (int)SymbolInfoInteger(symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,result.ask);
/* Пример вывода:
Ask: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает комментарий брокера к операции |
//+------------------------------------------------------------------+
string MqlTradeResultComment(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Comment:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,result.comment);
/* Пример вывода:
Comment: Request executed
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки идентификатор запроса |
//+------------------------------------------------------------------+
string MqlTradeResultRequestID(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Request ID:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-lu",indent,"",w,header,result.request_id);
/* Пример вывода:
Request ID: 3768213261
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки код ответа внешней торговой системы |
//+------------------------------------------------------------------+
string MqlTradeResultRetcodeExternal(const MqlTradeResult &result,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Retcode External:";
uint w=(header_width==0 ? header.Length()+1 : header_width-1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%- ld",indent,"",w,header,result.retcode_external);
/* Пример вывода:
Retcode External: 0
*/
}
//+------------------------------------------------------------------+
//| Выводит в журнал поля структуры MqlTradeResult |
//| в результате торгового запроса |
//+------------------------------------------------------------------+
void TradeResultPrint(const string symbol,const MqlTradeResult &result,const uint header_width=0,const uint indent=0,bool ext_descr=false)
{
string symbol_name=(symbol==NULL ? Symbol() : symbol);
Print("OrderSend result:");
Print(MqlTradeResultRetcode(result,header_width,indent,ext_descr));
Print(MqlTradeResultDeal(result,header_width,indent));
Print(MqlTradeResultOrder(result,header_width,indent));
Print(MqlTradeResultVolume(symbol_name,result,header_width,indent));
Print(MqlTradeResultPrice(symbol_name,result,header_width,indent));
Print(MqlTradeResultBid(symbol_name,result,header_width,indent));
Print(MqlTradeResultAsk(symbol_name,result,header_width,indent));
Print(MqlTradeResultComment(result,header_width,indent));
Print(MqlTradeResultRequestID(result,header_width,indent));
Print(MqlTradeResultRetcodeExternal(result,header_width,indent));
/* Пример вывода:
OrderSend result:
Retcode: 10009 DONE (Request completed)
Deal: 0
Order: 1821671230
Volume: 0.10
Price: 0.0
Bid: 0.0
Ask: 0.0
Comment: Request executed
Request ID: 3768213265
Retcode External: 0
*/
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Функции для работы со структурой |
//| торговой транзакции MqlTradeTransaction |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет сделки |
//+------------------------------------------------------------------+
string MqlTradeTransactionDeal(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Deal:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.deal);
/* Пример вывода:
Deal: 0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет ордера |
//+------------------------------------------------------------------+
string MqlTradeTransactionOrder(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Order:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.order);
/* Пример вывода:
Order: 1825990224
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки символ ордера |
//+------------------------------------------------------------------+
string MqlTradeTransactionSymbol(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Symbol:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,trans.symbol);
/* Пример вывода:
Symbol: EURUSD
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип торговой транзакции |
//+------------------------------------------------------------------+
string MqlTradeTransactionType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Type:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,TradeTransactionTypeDescription(trans.type,ext_descr));
/* Пример вывода:
Type: Order delete (Removing an order from the list of the open ones)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип ордера |
//+------------------------------------------------------------------+
string MqlTradeTransactionOrderType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Объявляем переменные для указания принадлежности транзакции
bool trans_req=false; // Запрос
bool trans_order=false; // Ордер
bool trans_deal=false; // Сделка
bool trans_pos=false; // Позиция
//--- Устанавливаем принадлежность транзакции
SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Order type:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderTypeDescription(trans.order_type,ext_descr) : "0"));
/* Пример вывода:
Order type: Sell Limit (Sell Limit pending order)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки состояние ордера |
//+------------------------------------------------------------------+
string MqlTradeTransactionOrderState(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Объявляем переменные для указания принадлежности транзакции
bool trans_req=false; // Запрос
bool trans_order=false; // Ордер
bool trans_deal=false; // Сделка
bool trans_pos=false; // Позиция
//--- Устанавливаем принадлежность транзакции
SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Order state:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderStateDescription(trans.order_state,ext_descr) : "0"));
/* Пример вывода:
Order state: Started (Order checked, but not yet accepted by broker)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип сделки |
//+------------------------------------------------------------------+
string MqlTradeTransactionDealType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Объявляем переменные для указания принадлежности транзакции
bool trans_req=false; // Запрос
bool trans_order=false; // Ордер
bool trans_deal=false; // Сделка
bool trans_pos=false; // Позиция
//--- Устанавливаем принадлежность транзакции
SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Deal type:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_deal || trans_pos ? DealTypeDescription(trans.deal_type,ext_descr) : "0"));
/* Пример вывода:
Deal type: Buy
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тип ордера по времени действия |
//+------------------------------------------------------------------+
string MqlTradeTransactionTimeType(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Объявляем переменные для указания принадлежности транзакции
bool trans_req=false; // Запрос
bool trans_order=false; // Ордер
bool trans_deal=false; // Сделка
bool trans_pos=false; // Позиция
//--- Устанавливаем принадлежность транзакции
SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Time type:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,(trans_order ? OrderTypeTimeDescription(trans.time_type,ext_descr) : "0"));
/* Пример вывода:
Order type time: Time GTC (Good till cancel order)
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки срок истечения ордера |
//+------------------------------------------------------------------+
string MqlTradeTransactionTimeExpiration(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Time expiration:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Запишем время экспирации в виде строки. Если 0, то впишем 0
string tm=(trans.time_expiration==0 ? "0" : (string)trans.time_expiration);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-s",indent,"",w,header,tm);
/* Пример вывода:
Time expiration: 0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки цену ордера/сделки/позиции |
//+------------------------------------------------------------------+
string MqlTradeTransactionPrice(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Price:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получим Digits символа. Если символ не указан, используем 1
int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price);
/* Пример вывода:
Price: 1.10331
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки цену срабатывания стоп-лимитного ордера |
//+------------------------------------------------------------------+
string MqlTradeTransactionPriceTrigger(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Price trigger:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получим Digits символа. Если символ не указан или стоп-цена отсутствует, используем 1
int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
if(trans.price_trigger==0)
dg=1;
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_trigger);
/* Пример вывода:
Price trigger: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки цену Stop Loss |
//+------------------------------------------------------------------+
string MqlTradeTransactionPriceSL(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Price SL:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получим Digits символа. Если символ не указан или цена Stop Loss отсутствует, используем 1
int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
if(trans.price_sl==0)
dg=1;
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_sl);
/* Пример вывода:
Price SL: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки цену Take Profit |
//+------------------------------------------------------------------+
string MqlTradeTransactionPriceTP(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Price TP:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получим Digits символа. Если символ не указан или цена Take Profit отсутствует, используем 1
int dg=(trans.symbol!="" ? (int)SymbolInfoInteger(trans.symbol,SYMBOL_DIGITS) : 1);
if(trans.price_tp==0)
dg=1;
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.price_tp);
/* Пример вывода:
Price TP: 0.0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки объём в лотах |
//+------------------------------------------------------------------+
string MqlTradeTransactionVolume(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Volume:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Получаем количество знаков после запятой в значении лота. Если символ не указан, используем 1
int dg=(trans.symbol!="" ? (int)ceil(fabs(log10(SymbolInfoDouble(trans.symbol,SYMBOL_VOLUME_STEP)))) : 1);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,trans.volume);
/* Пример вывода:
Volume: 0.10
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет позиции |
//+------------------------------------------------------------------+
string MqlTradeTransactionPosition(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Position:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.position);
/* Пример вывода:
Position: 0
*/
}
//+------------------------------------------------------------------+
//| Возвращает в виде строки тикет встречной позиции |
//+------------------------------------------------------------------+
string MqlTradeTransactionPositionBy(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0)
{
//--- Определяем текст заголовка и ширину поля заголовка
//--- Если ширина заголовка передана в функцию равной нулю, то шириной будет размер строки заголовка + 1
string header="Position by:";
uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Возвращаем значение свойства с заголовком с нужной шириной и отступом
return StringFormat("%*s%-*s%-llu",indent,"",w,header,trans.position_by);
/* Пример вывода:
Position by: 0
*/
}
//+------------------------------------------------------------------+
//| Выводит в журнал поля структуры MqlTradeTransaction |
//+------------------------------------------------------------------+
void MqlTradeTransactionPrint(const MqlTradeTransaction &trans,const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
Print(MqlTradeTransactionDeal(trans,header_width,indent));
Print(MqlTradeTransactionOrder(trans,header_width,indent));
Print(MqlTradeTransactionSymbol(trans,header_width,indent));
Print(MqlTradeTransactionType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionOrderType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionOrderState(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionTimeType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionTimeExpiration(trans,header_width,indent));
Print(MqlTradeTransactionPrice(trans,header_width,indent));
Print(MqlTradeTransactionPriceTrigger(trans,header_width,indent));
Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
Print(MqlTradeTransactionVolume(trans,header_width,indent));
Print(MqlTradeTransactionPosition(trans,header_width,indent));
Print(MqlTradeTransactionPositionBy(trans,header_width,indent));
/* Пример вывода:
Deal: 0
Order: 1829189788
Symbol: EURUSD
Type: Order add
Order type: Buy Limit
Order state: Started
Deal type: 0
Time type: Time GTC
Time expiration: 0
Price: 1.09861
Price trigger: 0.0
Price SL: 0.0
Price TP: 0.0
Volume: 0.10
Position: 0
Position by: 0
*/
}
//+------------------------------------------------------------------+
//| Информер торговых транзакций |
//+------------------------------------------------------------------+
void TradeTransactionInformer(const MqlTradeTransaction &trans,const MqlTradeRequest& request,const MqlTradeResult& result,
const uint header_width=0,const uint indent=0,const bool ext_descr=false)
{
//--- Объявляем переменные для указания принадлежности транзакции
bool trans_req=false; // Запрос
bool trans_order=false; // Ордер
bool trans_deal=false; // Сделка
bool trans_pos=false; // Позиция
//--- Устанавливаем принадлежность транзакции
SetTransactionBelong(trans.type,trans_req,trans_order,trans_deal,trans_pos);
//--- В зависимости от принадлежности транзакции выводим описания соответствующих полей структуры
//--- Торговый запрос
if(trans_req)
{
//--- Сообщаем тип транзакции "торговый запрос" и указываем, что нужно анализировать поля структуры торгового запроса и ответа сервера
PrintFormat("Transaction %s\n%*sThe second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:",
MqlTradeTransactionType(trans,0,0,true),indent,"");
//--- Выводим в журнал описание торгового запроса и результата этого запроса, полученного от сервера
TradeRequestPrint(request,header_width,indent,ext_descr);
TradeResultPrint(trans.symbol,result,header_width,indent,ext_descr);
}
//--- Иначе, если ордер/сделка/позиция
else
{
//--- Выводим в журнал тип транзакции
PrintFormat("Transaction %s",MqlTradeTransactionType(trans,0,0,true));
//--- Ордер
if(trans_order)
{
Print(MqlTradeTransactionOrder(trans,header_width,indent));
Print(MqlTradeTransactionSymbol(trans,header_width,indent));
Print(MqlTradeTransactionOrderType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionOrderState(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionTimeType(trans,header_width,indent,ext_descr));
if(trans.time_type==ORDER_TIME_SPECIFIED || trans.time_type==ORDER_TIME_SPECIFIED_DAY)
Print(MqlTradeTransactionTimeExpiration(trans,header_width,indent));
Print(MqlTradeTransactionPrice(trans,header_width,indent));
if(trans.order_type==ORDER_TYPE_BUY_STOP_LIMIT || trans.order_type==ORDER_TYPE_SELL_STOP_LIMIT)
Print(MqlTradeTransactionPriceTrigger(trans,header_width,indent));
Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
Print(MqlTradeTransactionVolume(trans,header_width,indent));
if(trans.type!=TRADE_TRANSACTION_ORDER_ADD && (trans.order_type==ORDER_TYPE_BUY || trans.order_type==ORDER_TYPE_SELL))
Print(MqlTradeTransactionPosition(trans,header_width,indent));
if(trans.order_type==ORDER_TYPE_CLOSE_BY)
Print(MqlTradeTransactionPositionBy(trans,header_width,indent));
}
//--- Сделка
if(trans_deal)
{
Print(MqlTradeTransactionDeal(trans,header_width,indent));
Print(MqlTradeTransactionOrder(trans,header_width,indent));
Print(MqlTradeTransactionSymbol(trans,header_width,indent));
Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionPrice(trans,header_width,indent));
Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
Print(MqlTradeTransactionVolume(trans,header_width,indent));
Print(MqlTradeTransactionPosition(trans,header_width,indent));
}
//--- Позиция
if(trans_pos)
{
Print(MqlTradeTransactionSymbol(trans,header_width,indent));
Print(MqlTradeTransactionDealType(trans,header_width,indent,ext_descr));
Print(MqlTradeTransactionPrice(trans,header_width,indent));
Print(MqlTradeTransactionPriceSL(trans,header_width,indent));
Print(MqlTradeTransactionPriceTP(trans,header_width,indent));
Print(MqlTradeTransactionVolume(trans,header_width,indent));
Print(MqlTradeTransactionPosition(trans,header_width,indent));
}
}
/* Пример вывода при установке ордера Sell Limit:
Transaction Type: Order add (Adding a new open order)
Order: 1833072954
Symbol: EURUSD
Order type: Sell Limit (Sell Limit pending order)
Order state: Started (Order checked, but not yet accepted by broker)
Time type: Time GTC (Good till cancel order)
Price: 1.10516
Price SL: 0.0
Price TP: 0.0
Volume: 0.10
Transaction Type: Order update (Updating an open order)
Order: 1833072954
Symbol: EURUSD
Order type: Sell Limit (Sell Limit pending order)
Order state: Placed (Order accepted)
Time type: Time GTC (Good till cancel order)
Price: 1.10516
Price SL: 0.0
Price TP: 0.0
Volume: 0.10
Transaction Type: Request (The trade request has been processed by a server and processing result has been received)
The second and third parameters of OnTradeTransaction function (request and result) must be analyzed for additional data:
Request Pending (Place a trade order for the execution under specified conditions (pending order)):
Symbol: EURUSD
Volume: 0.10
Price: 1.10516
SL: 0.0
TP: 0.0
Type: Sell Limit (Sell Limit pending order)
Type filling: Return (In case of partial filling, an order with remaining volume is not canceled but processed further)
Type time: Time GTC (Good till cancel order)
Expiration: 0
Magic: 1024
Comment: TestMqlTradeTransaction
OrderSend result:
Retcode: 10009 DONE (Request completed)
Deal: 0
Order: 1833072954
Volume: 0.10
Price: 0.0
Bid: 0.0
Ask: 0.0
Comment:
Request ID: 3768213464
Retcode External: 0
//---
Здесь при установке отложенного ордера Buy Limit мы порлучили три транзакции:
1. Запрос - запрос на установку отложенного ордера был принят сервером и был получен ответ.
Для уточнения информации необходимо анализировать поля структуры торгового запроса MqlTradeRequest
и ответа сервера MqlTradeResult – request и result соответственно.
2. Добавление нового отложенного ордера с тикетом #1829788294. Его состояние - Started.
3. Изменение открытого ордера с тикетом #1829788294. Его состояние сменилось со Started на Placed.
Очерёдность транзакций не соблюдена, но об этом явно указано в справке по обработчику OnTradeTransaction:
https://www.mql5.com/ru/docs/event_handlers/ontradetransaction.
*/
}
//+------------------------------------------------------------------+