Разработчики! Вы вообще тестируете то, что создаёте? - страница 10

 
Mikalas:

Вот те, раз! А в истории она достоверная?

papaklass имел в виду, наверно, что OnTradeTransaction возвращает ошибки?  

Если в  OnTradeTransaction информация может быть не достоверная, то ее приходится брать из истории что бы убедиться что информация достоверная. 

Если в OnTradeTransaction информация не всегда приходит, то информацию приходится брать из истории что бы убедиться что вся информация обработана.

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

 
sergeev:
а зачем слюни на 9 страниц ?

Пожалуйста, не хамите! Кстати, уже 10!

И Вы в праве совсем не читать, что здесь написано! 

 
Mikalas:

С-4, будет обработано, конечно, но зачем нужен OnRefresh()?

Много событий -> один обработчик.
 
C-4:
Много событий -> один обработчик.
Ошибки со всех углов в одну кучу! :)
 
Mikalas:
Ошибки со всех углов в одну кучу! :)

Шлются не ошибки, а данные. Ошибки могут быть в обработчике, но их легко исправить, потому что обработчик один.

papaklass:
Я, именно, об этом. Нужно разделение событий.
Нужно не разделение событий, а разделение обработчиков. События генерируют данные. Каждый тип данных обрабатывает свой обработчик. Неважно кем именно были получены данные, важно что на каждый тип данных существует свой уникальный обработчик.
 
C-4:

Шлются не ошибки, а данные. Ошибки могут быть в обработчике, но их легко исправить, потому что обработчик один.

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

А что здесь не разделено?

void OnTradeTransaction( const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result )
{
 // Print( "Ticket = ", string( trans.order ), " --> ", EnumToString( trans.type ), " --> ", EnumToString(trans.order_state) );
  
  switch( trans.type )
  {
    TRADE_TRANSACTION_ORDER_DELETE:      switch( trans.order_state )
                                         {
                                           Удаление ордера из списка открытых.
                                           Ордер может быть удален из открытых в результате выставления
                                           соответствующего запроса либо в результате исполнения (заливки) и переноса в историю.
 
                                         } 
                                         break;
    
    TRADE_TRANSACTION_ORDER_ADD:         switch( trans.order_state )
                                         {
                                           Добавление нового открытого ордера.
                                         } 
                                         break;
                                          
    TRADE_TRANSACTION_DEAL_ADD:          switch( trans.order_state )
                                         {
                                           Добавление сделки в историю. Осуществляется в результате исполнения ордера или проведения операций с балансом счета.
                                         }
                                         break;
                                                    
    case TRADE_TRANSACTION_HISTORY_ADD:  switch( trans.order_state )
                                         {
                                           Добавление ордера в историю в результате исполнения или отмены.
                                         }
                                         break;
    
    case TRADE_TRANSACTION_ORDER_DELETE:  switch( trans.order_state )
                                         {
                                           Удаление ордера из списка открытых.
                                           Ордер может быть удален из открытых в результате выставления
                                           соответствующего запроса либо в результате исполнения (заливки) и переноса в историю.
                                         }
                                         break;
                                         
    case TRADE_TRANSACTION_ORDER_UPDATE: switch( trans.order_state )
                                         {
                                           Изменение открытого ордера. 
                                           К данным изменениям относятся не только явные изменения
                                           со стороны клиентского терминала или торгового сервера,
                                           но также и изменение его состояния при выставлении
                                           (например, переход из состояния ORDER_STATE_STARTED в ORDER_STATE_PLACED или
                                           из ORDER_STATE_PLACED в ORDER_STATE_PARTIAL и т.д.).
                                         }
                                         break;
                                         
    case TRADE_TRANSACTION_DEAL_UPDATE:  switch( trans.order_state )
                                         {
                                           Изменение сделки в истории. Возможны ситуации, 
                                           когда ранее исполненная сделка изменяется на сервере.
                                           Например, сделка была изменена во внешней торговой системе (бирже),
                                           куда она была выведена брокером.
                                         }
                                         break;
                                         
    case TRADE_TRANSACTION_DEAL_DELETE: switch( trans.order_state )
                                        {
                                          Удаление сделки из истории.
                                          Возможны ситуации, когда ранее исполненная сделка удаляется на сервере.
                                          Например, сделка была удалена во внешней торговой системе (бирже), куда она была выведена брокером.
                                        }
                                        break; 
             
    case TRADE_TRANSACTION_HISTORY_UPDATE: switch( trans.order_state )
                                           {
                                             Изменение ордера, находящегося в истории ордеров.
                                             Данный тип предусмотрен для расширения функциональности на стороне торгового сервера.
                                           }
                                           break;
                                          
    case TRADE_TRANSACTION_HISTORY_DELETE: switch( trans.order_state )
                                           {
                                             Удаление ордера из истории ордеров.
                                             Данный тип предусмотрен для расширения функциональности на стороне торгового сервера.
                                           }
                                           break;
                                                                                 
    case TRADE_TRANSACTION_POSITION:       switch( trans.order_state )
                                           {
                                            Изменение позиции, не связанное с исполнением сделки. 
                                            Данный тип транзакции свидетельствует именно о том,
                                            что позиция была изменена на стороне торгового сервера.
                                            У позиции может быть изменен объем, цена открытия,
                                            а также уровни Stop Loss и Take Profit.
                                            Информация об изменениях передается в структуре MqlTradeTransaction
                                            через обработчик OnTradeTransaction.
                                            Изменение позиции (добавление, изменение или ликвидация) в результате совершения
                                            сделки не влечет за собой появление транзакции TRADE_TRANSACTION_POSITION.
                                           }
                                           break;                                                                                                                                                                                  
  case TRADE_TRANSACTION_REQUEST:  Уведомление о том, что торговый запрос обработан сервером,
                                     и результат его обработки получен.
                                      Для транзакций данного типа в структуре MqlTradeTransaction
                                      необходимо анализировать только одно поле - type (тип транзакции).
                                      Для получения дополнительной информации необходимо анализировать второй
                                      и третий параметры функции OnTradeTransaction (request и result).
                                    break;
}
 

А ведь есть ещё

const MqlTradeRequest &request, const MqlTradeResult &result
 
Mikalas:

А что здесь не разделено?

Очень много комбинаторики. Итог: гигантская простынь в OnTradeTransaction и сложная логика. Я не могу ответить как бы сделал я, потому что мне не известна задача. В любом случае case->case->case... настораживает.
 
papaklass:

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

Я же предлагаю, чтобы у каждого события были свои данные и свой обработчик. Сколько событий, столько и обработчиков. Разделение ИМЕННО событий (открытие позиции, закрытие позиции, выставление ордера, модификация ордера, модификация позиции и т.д.). А какие типы данных приписать какому событию, пусть решают разработчики.

Под словом "обработчик" я понимаю не системную функцию, в которую приходит то или иное событие, а некий модуль эксперта, который это событие анализирует. Плодить множество функций On... каждую на свое событие - бессмысленно, тем более создать пользовательские обработчики в нужном количестве элементарно. Вот как сделано у меня: 

///
/// Принимаем событие.
///
void OnEvent(Event* event)
{
   switch(event.EventId())
   {
       case EVENT_MOUSE_MOVE:
           OnMouseMove(event);
           break;
       case EVENT_KEY_DOWN:
           OnKeyDown(event);
           break;
       case EVENT_ORDER_CHANGE:
           OnOrderChange(event);
           break;
       //etc...
   }
}

Может показаться странным, что  один и тот же некий класс Event передается  совершенно разным обработчикам, которым необходимы совершенно разные типы данных. Так, для OnMouseMove необходима маска нажатых клавиш на мыши и ее координаты, для OnKeyDown() необходим код нажатой клавиши, для OnOrderChange - тикет ордера, который изменился и возможно перечисление, описывающее какое именно изменение произошло. Можно подумать что класс event содержит поля для всех возможных событий. Однако это не так. На самом деле объекта класса event даже не может существовать, т.к. его конструктор скрыт в области protected. Зато в изобилии существуют его потомки - каждый потомок для обработки только своего события. Однако для любого event существует идентификатор указывающий к какому типу он принадлежит. Зная этот идентификатор можно выполнять безопасное преобразование типа от большего к меньшему. Вот именно к  этому типу потомка происходит неявное преобразование в момент передачи обработчика. Смотрим как на самом деле видят event наши обработчики:

///
/// Реагируем на перемещение мыши.
///
OnMouseMove(EventMouseMove* event)
{
   int yCoord = event.YCoord();
   int xCoord = event.XCoord();
   printf("X координата: " + xCoord + "; Y координата: " + yCoord);
}

///
/// Реагируем на перемещение мыши.
///
OnOrderChange(EventOrderChange* event)
{
   int ticket = event.Ticket();
   ENUM_ORDER_STATE state = event.OrderState();
   printf("Ордер с тикетом " + ticket + " изменил свое состояние на " + EnumToString(state));
}

//etc...
Красота... Вроде событие только одно - event, а на самом деле их может быть десятки. Вроде событие не содержит практически ни какой информации, кроме своего типа, а на самом деле обработчики свободно обращаются к только им известным методам.
 

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

papaklass:

Существенное отличие внутренних событий от внешних - это время исполнения. У внутренних оно практически равно нулю, а у внешних оно измеряется от сотен миллисекунд до секунд.

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

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства ордеров - Документация по MQL5
Причина обращения: