Бета-версия платформы MetaTrader 5 build 1625: Пользовательские финансовые инструменты - страница 7

 

Вопрос по DEAL_REASON_SL.

В OnInit DEAL_REASON_SL имеет значение 9

OnInit, ExtLot 0.10
, DEAL_REASON_CLIENT: 0, DEAL_REASON_MOBILE: 1
, DEAL_REASON_WEB: 2 DEAL_REASON_EXPERT: 3
, DEAL_REASON_SL: 9, DEAL_REASON_TP: 5
, DEAL_REASON_SO: 6, DEAL_REASON_ROLLOVER: 7
, DEAL_REASON_VMARGIN: 8

а в OnTradeTransaction при срабатывании Stop Loss DEAL_REASON HistoryDealGetInteger:

deal_reason=HistoryDealGetInteger(trans.deal,DEAL_REASON);

возвращает уже значение 4

OnTradeTransaction, #1: DEAL_ENTRY_IN, deal_reason 0
OnTradeTransaction, #1: DEAL_ENTRY_OUT, deal_reason 4
OnTradeTransaction, #2: deal_reason: 4, DEAL_REASON_SL: 9, DEAL_REASON_TP: 5
OnTradeTransaction, #3: DEAL_ENTRY_OUT, deal_reason 4

Полный код:

//+------------------------------------------------------------------+
//|                                             Test_DEAL_REASON.mq5 |
//|                              Copyright © 2017, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2017, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#property version   "1.000"
#property description "Test DEAL_REASON"
//---
double ExtLot=0.0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ExtLot=0.1;
   Print(__FUNCTION__,", ExtLot ",DoubleToString(ExtLot,2),
         "\n, DEAL_REASON_CLIENT: ",DEAL_REASON_CLIENT,", DEAL_REASON_MOBILE: ",DEAL_REASON_MOBILE,
         "\n, DEAL_REASON_WEB: ",DEAL_REASON_WEB," DEAL_REASON_EXPERT: ",DEAL_REASON_EXPERT,
         "\n, DEAL_REASON_SL: ",DEAL_REASON_SL,", DEAL_REASON_TP: ",DEAL_REASON_TP,
         "\n, DEAL_REASON_SO: ",DEAL_REASON_SO,", DEAL_REASON_ROLLOVER: ",DEAL_REASON_ROLLOVER,
         "\n, DEAL_REASON_VMARGIN: ",DEAL_REASON_VMARGIN/*,", DEAL_REASON_SPLIT: ",DEAL_REASON_SPLIT*/);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
  }
//+------------------------------------------------------------------+
//| 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;
      long     deal_reason       =-1;
      if(HistoryDealSelect(trans.deal))
        {
         deal_entry=HistoryDealGetInteger(trans.deal,DEAL_ENTRY);
         deal_reason=HistoryDealGetInteger(trans.deal,DEAL_REASON);
        }
      else
         return;

      Print(__FUNCTION__,", #1: ",EnumToString((ENUM_DEAL_ENTRY)deal_entry),
            ", deal_reason ",/*EnumToString((ENUM_DEAL_REASON)*/deal_reason/*)*/);

      if(deal_entry==DEAL_ENTRY_OUT)
        {
         Print(__FUNCTION__,", #2: deal_reason: ",deal_reason,
               ", DEAL_REASON_SL: ",DEAL_REASON_SL,
               ", DEAL_REASON_TP: ",DEAL_REASON_TP);
         if(deal_reason==DEAL_REASON_SL)
           {
            ExtLot*=2.0;
            Print(__FUNCTION__,", #2.1: ",TimeToString(TimeCurrent(),TIME_SECONDS),"; deal_reason==DEAL_REASON_SL",
                  ", ExtLot=",DoubleToString(ExtLot,2));
           }
         else if(deal_reason==DEAL_REASON_TP)
           {
            ExtLot=0.01;
            Print(__FUNCTION__,", #2.2: ",TimeToString(TimeCurrent(),TIME_SECONDS),"; deal_reason==DEAL_REASON_TP",
                  ", ExtLot=",DoubleToString(ExtLot,2));
           }
         Print(__FUNCTION__,", #3: ",EnumToString((ENUM_DEAL_ENTRY)deal_entry),
               ", deal_reason ",/*EnumToString((ENUM_DEAL_REASON)*/deal_reason/*)*/);
        }
     }
  }
//+------------------------------------------------------------------+
Файлы:
 

При тестировании происходит Crash:

Crash

Windows 7 x64, повторяемость на двух машинах. Компиляция советника с оптимизацией и без оптимизации.

 
Vladimir Karputov:

Вопрос по DEAL_REASON_SL.

В OnInit DEAL_REASON_SL имеет значение 9

а в OnTradeTransaction при срабатывании Stop Loss DEAL_REASON HistoryDealGetInteger:

возвращает уже значение 4

Полный код:

На числовые значения кодов лучше не закладываться

 
Rashid Umarov:

На числовые значения кодов лучше не закладываться

Там явная ошибка

void OnStart()
{
        ENUM_DEAL_REASON x = 4;
        Print( EnumToString( x ), "==", EnumToString( DEAL_REASON_SL ), "?", x == DEAL_REASON_SL );
}
Результат: DEAL_REASON_SL==DEAL_REASON_SL ? false
 
Rashid Umarov:

На числовые значения кодов лучше не закладываться


Так проверку по числовому значению ввёл в пример, чтобы понять, почему после Stopp loss нет захода в 

      if(deal_entry==DEAL_ENTRY_OUT)
        {
         Print(__FUNCTION__,", #2: deal_reason: ",deal_reason,
               ", DEAL_REASON_SL: ",DEAL_REASON_SL,
               ", DEAL_REASON_TP: ",DEAL_REASON_TP);
         if(deal_reason==DEAL_REASON_SL)
           {
            ExtLot*=2.0;
            Print(__FUNCTION__,", #2.1: ",TimeToString(TimeCurrent(),TIME_SECONDS),"; deal_reason==DEAL_REASON_SL",
                  ", ExtLot=",DoubleToString(ExtLot,2));
           }

и оказалось, что DEAL_REASON_SL имеет значение '9', но вот внутри OnTradeTransaction()

HistoryDealGetInteger(trans.deal,DEAL_REASON);

возвращает '4', а должно возвращать '9'.

 
Vladimir Karputov:

Так проверку по числовому значению ввёл в пример, чтобы понять, почему после Stopp loss нет захода в 

и оказалось, что DEAL_REASON_SL имеет значение '9', но вот внутри OnTradeTransaction()

возвращает '4', а должно возвращать '9'.

Причину нашли и исправили, спасибо за сообщение!

 
Renat Fatkhullin:

Не пользователь, а программист.

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

Сам язык в обязательном порядке проверяет все указатели перед использованием и выдает критическую ошибку при попытке обращения к ранее удаленным объектам.


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

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

Я веду речь об объектно-ориентированном подходе. Одним из основополагающих принципов тут является инкапсуляция, если вам знакомо это понятие.  В рамках этой парадигмы конкретная реализация любого объекта скрыта от посторонних глаз и является исключительно внутренним делом этого объекта.  А пользователь довольствуется тем функционалом, который предоставляет этот объект с помощью публичных методов. Внутренности нас вообще не касаются. Тем более что реализацию этих внутренностей возможно программировал другой человек.  В общем странно, что я тут вынужден объяснять эти азы, хотя казалось бы, вы должны быть знакомы с ними не понаслышке.

Ситуация такова, что объект не предоставляет методов копирования через оператор=, и вдобавок он является сложным (содержит внутри объекты и указатели).  Однако вы позволяете наплевать на все правила и просто скопировать содержимое такого объекта - фактически через memcpy (суть та же самая) и работать с ним как с новым объектом.  Я вам уже привёл пример в прошлом сообщении, какие возможны последствия от такой безконтрольной самодеятельности:  динамические private объекты, созданные и используемые исключительно внутри класса, вдруг в одночасье оказываются удалёнными, либо вдруг начинают "чудить", самопроизвольно изменяться - а всё потому, что где-то кто-то скопировал содержимое нашего объекта через memcopy и теперь управляет нашими внутренними private-объектами.  Это нонсенс.

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

 

До сих пор осталась старая проблема - удаляются некоторые не выделенные объекты при нажатии на del. При этом они не возвращаются обратно при попытке откатить действие. Обычно это происходит с объектами с которыми ты недавно работал. То ли терминал их не показывает выделенными, а на самом деле они такими остаются, то ли еще какая причина. Это очень не удобно, приходится постоянно жать на "сохранить шаблон".

 
Alexey Navoykov:

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

Я веду речь об объектно-ориентированном подходе. Одним из основополагающих принципов тут является инкапсуляция, если вам знакомо это понятие.  В рамках этой парадигмы конкретная реализация любого объекта скрыта от посторонних глаз и является исключительно внутренним делом этого объекта.  А пользователь довольствуется тем функционалом, который предоставляет этот объект с помощью публичных методов. Внутренности нас вообще не касаются. Тем более что реализацию этих внутренностей возможно программировал другой человек.  В общем странно, что я тут вынужден объяснять эти азы, хотя казалось бы, вы должны быть знакомы с ними не понаслышке.

Ситуация такова, что объект не предоставляет методов копирования через оператор=, и вдобавок он является сложным (содержит внутри объекты и указатели).  Однако вы позволяете наплевать на все правила и просто скопировать содержимое такого объекта - фактически через memcpy (суть та же самая) и работать с ним как с новым объектом.  Я вам уже привёл пример в прошлом сообщении, какие возможны последствия от такой безконтрольной самодеятельности:  динамические private объекты, созданные и используемые исключительно внутри класса, вдруг в одночасье оказываются удалёнными, либо вдруг начинают "чудить", самопроизвольно изменяться - а всё потому, что где-то кто-то скопировал содержимое нашего объекта через memcopy и теперь управляет нашими внутренними private-объектами.  Это нонсенс.

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

Если правильно понимаю, проблема возникнет с объектами, схожими с синглтоном. Лучший аргумент в данном случае - привести короткий код в качестве демонстрации сказанного

 

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

Неявный оператор копирования - это не memcpy, а реальное конструирование каждого сложного объекта внутри структуры или класса.

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