Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 713

 
dimnik:
Подскажите, как узнать результат последней одной или нескольких сделок?

Есть два пути:

прямо в советнике использовать OnTradeTransaction() и отлавливать сделки, которые были записаны в историю.

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_DEAL_ADD)
     {
      long     deal_entry        =0;
      double   deal_profit       =0.0;
      double   deal_volume       =0.0;
      string   deal_symbol       ="";
      long     deal_magic        =0;
      if(HistoryDealSelect(trans.deal))
        {
         deal_entry=HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
         deal_profit=HistoryDealGetDouble(trans.deal,DEAL_PROFIT);
         deal_volume=HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
         deal_symbol=HistoryDealGetString(trans.deal,DEAL_SYMBOL);
         deal_magic=HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
        }
      else
         return;
      if(deal_symbol==Symbol() && deal_magic==m_magic)
         if(deal_entry==DEAL_ENTRY_OUT)
           {
            // здесь ваши действия
           }
     }
  }

или обращаться к торговой истории, например что-то вроде этого:

//+------------------------------------------------------------------+
//|                                               HistorySelect.mq5  |
//|                              Copyright © 2016, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2016, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.00"
#property description "Реверс позиции и исследование \"DEAL_POSITION_ID\" истории сделок"
#property script_show_inputs
//---
input datetime start=D'2016.08.05 09:00:00';
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   if(AccountInfoInteger(ACCOUNT_MARGIN_MODE)==ACCOUNT_MARGIN_MODE_RETAIL_HEDGING)
     {
      Print("This script cannot be run on a hedge; Этот скрипт нельзя запускать на хедж");
      return;
     }
   Print_IDs();
  }
//+------------------------------------------------------------------+
//| List all positions and deals                                     |
//+------------------------------------------------------------------+
void Print_IDs(void)
  {
//--- запрашиваем историю сделок и ордеров за указанный период серверного времени
   HistorySelect(start,TimeCurrent()+86400);
   uint     total    =HistoryDealsTotal();   // количество сделок в истории
   ulong    ticket   =0;                     // тикет сделки в истории
   long     type     =0;                     // тип сделки
   long     deal_id=0;   // идентификатор позиции, в открытии, изменении или закрытии которой участвовала эта сделка
   double   volume   =0.0;                   // объём сделки
   double   profit   =0.0;                   // финансовый результат сделки
   double   price    =0.0;                   // цена сделки
   string   symbol   =NULL;                  // имя символа, по которому произведена сделка
   long     entry    =0;                     // направление сделки – вход в рынок, выход из рынка или разворот
//--- for all deals
   for(uint i=0;i<total;i++)
     {
      //--- try to get deals ticket
      if((ticket=HistoryDealGetTicket(i))>0)
        {
         //--- get deals properties
         type     =HistoryDealGetInteger(ticket,DEAL_TYPE);
         deal_id  =HistoryDealGetInteger(ticket,DEAL_POSITION_ID);
         volume   =HistoryDealGetDouble(ticket,DEAL_VOLUME);
         profit   =HistoryDealGetDouble(ticket,DEAL_PROFIT);
         price    =HistoryDealGetDouble(ticket,DEAL_PRICE);
         symbol   =HistoryDealGetString(ticket,DEAL_SYMBOL);
         entry    =HistoryDealGetInteger(ticket,DEAL_ENTRY);
         Print(EnumToString((ENUM_DEAL_ENTRY)entry),
               ", type ",EnumToString((ENUM_DEAL_TYPE)type),
               ", price ",DoubleToString(price,Digits()),
               ", Deal ",symbol," volume ",DoubleToString(volume,2),
               ", DEAL_POSITION_ID #",deal_id,
               ", profit ",DoubleToString(profit,2));
        }
     }
   Print("");
  }
//+------------------------------------------------------------------+


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

Файлы:
 
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   if (trans.type == TRADE_TRANSACTION_DEAL_ADD && trans.symbol == _Symbol)
     {
       if (!HistoryOrderSelect(trans.order)) printf("Ордер не найден");
       if (order.Magic() != MagicNumber) printf("Ошибка: магик неправильный %u",order.Magic());
     }  
    
  }

Обработчик события отслеживает все сделки с магиками советника.

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

Как исправить? Или может по-другому сделать в принципе?

 
dimnik:
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   if (trans.type == TRADE_TRANSACTION_DEAL_ADD && trans.symbol == _Symbol)
     {
       if (!HistoryOrderSelect(trans.order)) printf("Ордер не найден");
       if (order.Magic() != MagicNumber) printf("Ошибка: магик неправильный %u",order.Magic());
     }  
    
  }

Обработчик события отслеживает все сделки с магиками советника.

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

Как исправить? Или может по-другому сделать в принципе?

Вам нужно уйти от оперирования ордерами - это изжитая старая система. Тогда всё получится. "TRADE_TRANSACTION_DEAL_ADD" - Добавление сделки в историю. Осуществляется в результате исполнения ордера или проведения операций с балансом счета. Что ещё нужно? Сделка осуществилась и была записана в историю. 
 
dimnik:

Обработчик события отслеживает все сделки с магиками советника.

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


ну так выведите параметры этой сделки.

в чем проблема узнать её тикет/тип/символ/профит ?

 
o_O:


ну так выведите параметры этой сделки.

в чем проблема узнать её тикет/тип/символ/профит ?

Выдает: 

Сделка 2, Magic 0, Volume 0.000000

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


       deal.Ticket(trans.deal);
       printf("Сделка %f, Magic %u, Volume %f", trans.deal,deal.Magic(),deal.Volume());
 
dimnik:

Выдает: 

Сделка 2, Magic 0, Volume 0.000000

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


       deal.Ticket(trans.deal);
       printf("Сделка %f, Magic %u, Volume %f", trans.deal,deal.Magic(),deal.Volume());

Добавьте вот этот код:

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- получим тип транзакции в виде значения перечисления  
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
   Print(EnumToString(type));
   long     deal_type         =0;
   long     deal_positions_id =0;
   long     deal_ticket       =0;
   double   deal_volume       =0;
   long     deal_entry        =0;
   long     deal_magic        =0;
   string   deal_symbol       ="";
   string   deal_comment      ="";
   if(HistoryDealSelect(trans.deal))
     {
      deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
      deal_positions_id =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);
      deal_ticket       =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
      deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
      deal_entry        =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
      deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
      deal_symbol       =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
      deal_comment      =HistoryDealGetString(trans.deal,DEAL_COMMENT);
      Print("D_TYPE: ",EnumToString((ENUM_DEAL_TYPE)deal_type),", ",
            "D_POSITION_ID: ",deal_positions_id,", ",
            "D_TICKET: ",deal_ticket,", ",
            "D_VOLUME: ",DoubleToString(deal_volume,2),", ",
            "D_ENTRY: ",EnumToString((ENUM_DEAL_ENTRY)deal_entry),", ",
            "_MAGIC: ",deal_magic,", ",
            "D_SYMBOL: ",deal_symbol,", ",
            "D_COMMENT: ",deal_comment);
     }
   else
      return;
  }

 

и Вы увидите какие типы транзакций происходят, а также увидите, что при "TRADE_TRANSACTION_DEAL_ADD" виден и магик и объём.


 
Vladimir Karputov:

Добавьте вот этот код:

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- получим тип транзакции в виде значения перечисления  
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
   Print(EnumToString(type));
   long     deal_type         =0;
   long     deal_positions_id =0;
   long     deal_ticket       =0;
   double   deal_volume       =0;
   long     deal_entry        =0;
   long     deal_magic        =0;
   string   deal_symbol       ="";
   string   deal_comment      ="";
   if(HistoryDealSelect(trans.deal))
     {
      deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
      deal_positions_id =HistoryDealGetInteger(trans.deal,DEAL_POSITION_ID);
      deal_ticket       =HistoryDealGetInteger(trans.deal,DEAL_TICKET);
      deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
      deal_entry        =HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
      deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
      deal_symbol       =HistoryDealGetString(trans.deal,DEAL_SYMBOL);
      deal_comment      =HistoryDealGetString(trans.deal,DEAL_COMMENT);
      Print("D_TYPE: ",EnumToString((ENUM_DEAL_TYPE)deal_type),", ",
            "D_POSITION_ID: ",deal_positions_id,", ",
            "D_TICKET: ",deal_ticket,", ",
            "D_VOLUME: ",DoubleToString(deal_volume,2),", ",
            "D_ENTRY: ",EnumToString((ENUM_DEAL_ENTRY)deal_entry),", ",
            "_MAGIC: ",deal_magic,", ",
            "D_SYMBOL: ",deal_symbol,", ",
            "D_COMMENT: ",deal_comment);
     }
   else
      return;
  }

 

и Вы увидите какие типы транзакций происходят, а также увидите, что при "TRADE_TRANSACTION_DEAL_ADD" виден и магик и объём.


Спасибо, так работает.
 
dimnik:

Выдает: 

Сделка 2, Magic 0, Volume 0.000000

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


       deal.Ticket(trans.deal);
       printf("Сделка %f, Magic %u, Volume %f", trans.deal,deal.Magic(),deal.Volume());

Д Я уже давно заметил что при использовании класса CDealInfo нужно самостоятельно подгружать историю сделок, тогда все функционитрует нормально

 

   if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
     {
      HistorySelect(0,TimeCurrent());
       deal.Ticket(trans.deal);
       printf("Сделка %f, Magic %u, Volume %f", trans.deal,deal.Magic(),deal.Volume());
     }
 
dimnik:
Спасибо, так работает.

Чтобы не печатать все типы транзакций сделайте в OnTradeTransaction такое условие:

//--- получим тип транзакции в виде значения перечисления  
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
   if(type!=TRADE_TRANSACTION_DEAL_ADD)
      return;

   long     deal_type         =0;

то есть, если тип транзакции не "TRADE_TRANSACTION_DEAL_ADD" - значит выходим. 

 

Если нужно отследить размещение (не срабатывание, а именно размещение) отложенного ордера, то OnTradeTransaction примет такой вид:

//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- get transaction type as enumeration value
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
   Print(EnumToString(type));
//--- if transaction is result of addition of the transaction in history
   if(type==TRADE_TRANSACTION_ORDER_ADD)
     {
      long     order_type        =0;
      double   order_price       =0.0;
      double   order_volume      =0.0;
      string   order_symbol      ="";
      long     order_magic       =0;
      if(OrderSelect(trans.order)) // select pending orders
        {
         order_type=OrderGetInteger(ORDER_TYPE);
         order_price=OrderGetDouble(ORDER_PRICE_OPEN);
         order_volume=OrderGetDouble(ORDER_VOLUME_INITIAL);
         order_symbol=OrderGetString(ORDER_SYMBOL);
         order_magic=OrderGetInteger(ORDER_MAGIC);
        }
      else
         return;
      if(order_symbol==m_symbol.Name() && order_magic==m_magic)
        {
         if(order_type==ORDER_TYPE_BUY_LIMIT)
           {
            //
           }
         if(order_type==ORDER_TYPE_SELL_LIMIT)
           {
            //
           }
        }
     }
  }


 

 

С использованием OnTradeTransaction странно изменилось время оптимизации. Система на 15М, очень простая, история годовая, один прогон происходит за 0,3 - 0,4 секунды.

После запуска оптимизации первые 200-300 прогонов идут со скоростью меньше секунды, следующие замедляются вплоть до 15-20 секунд (в 50 раз!);

Перегрева процессора и троттлинга нет, памяти свободно больше половины (из 16 ГБ).

До использования обработчика OnTradeTransaction ничего подобного не было - даже более сложные советники на мелких таймфреймах оптимизировались с примерно одинаковой скоростью каждый прогон.

Это HistoryDealSelect так сильно влияет на скорость? Как можно ликвидировать тормоза?

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   if( trans.type != TRADE_TRANSACTION_DEAL_ADD) return;
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
   long     deal_type         =0;
   double   deal_volume       =0;
   long     deal_magic        =0;
   if(HistoryDealSelect(trans.deal))
     {
      deal_type         =HistoryDealGetInteger(trans.deal,DEAL_TYPE);
      deal_volume       =HistoryDealGetDouble(trans.deal,DEAL_VOLUME);
      deal_magic        =HistoryDealGetInteger(trans.deal,DEAL_MAGIC);
     }
   else
      return;
   if (deal_type == DEAL_TYPE_BUY && deal_magic == MagicNumber) current_position += deal_volume;
   if (deal_type == DEAL_TYPE_SELL && deal_magic == MagicNumber) current_position -= deal_volume;
      
  }


 

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