Développeurs ! Est-ce que vous testez au moins ce que vous créez ? - page 10

 
Mikalas:

Oh, mon Dieu ! Est-il valable dans l'histoire ?

papaklass voulait probablement dire que OnTradeTransaction renvoie des erreurs ?

Si les informations contenues dans OnTradeTransaction ne sont pas valides, nous devons les extraire de l'historique pour nous assurer qu'elles le sont.

Si l'information onTradeTransaction n'est pas toujours fiable, nous devons la prendre dans l'historique pour nous assurer que l'information a été traitée.

La question est de savoir pourquoi nous avons besoin de OnTradeTransaction si nous devons de toute façon prendre les informations dans l'historique. - Il n'en a besoin que pour la vérification des erreurs. Le courtier a rejeté l'ordre et nous avons reçu la réponse pourquoi il a été rejeté dans OnTradeTransaction et l'avons analysé.

 
sergeev:
mais pourquoi baver sur 9 pages ?

S'il vous plaît, ne soyez pas grossier ! Au fait, il est déjà 10 heures !

Et vous avez le droit de ne pas lire du tout ce qui est écrit ici !

 
Mikalas:

C-4, seront traitées, bien sûr, mais pourquoi avoir besoin de OnRefresh() ?

Plusieurs événements -> un seul gestionnaire.
 
C-4:
Plusieurs événements -> un seul gestionnaire.
Des erreurs de tous les coins dans une seule pile ! :)
 
Mikalas:
Des erreurs de tous les coins dans une seule pile ! :)

Ce ne sont pas les erreurs qui sont envoyées, mais les données. Les erreurs peuvent se trouver dans le gestionnaire, mais elles sont faciles à corriger car il n'y a qu'un seul gestionnaire.

papaklass:
C'est exactement ce que je veux dire. Vous devez séparer les événements.
Vous n'avez pas besoin d'une séparation des événements, vous avez besoin d'une séparation des gestionnaires. Les événements génèrent des données. Chaque type de données est traité par son propre gestionnaire. Peu importe qui a reçu les données, l'important est qu'il y ait un gestionnaire unique pour chaque type de données.
 
C-4:

Ce ne sont pas les erreurs qui sont envoyées, mais les données. Les erreurs peuvent se trouver dans le gestionnaire, mais elles sont faciles à corriger car il n'y a qu'un seul gestionnaire.

Vous n'avez pas besoin de séparer les événements, vous avez besoin de séparer les gestionnaires. Les événements génèrent des données. Chaque type de données gère son propre gestionnaire. Peu importe qui a reçu les données, l'important est qu'il existe un gestionnaire unique pour chaque type de données.

Qu'est-ce qui n'est pas partagé ici ?

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;
}
 

Et puis il y a

const MqlTradeRequest &request, const MqlTradeResult &result
 
Mikalas:

Qu'est-ce qui n'est pas partagé ici ?

Beaucoup de combinatoire. En résumé : une feuille géante dans OnTradeTransaction et une logique compliquée. Je ne peux pas répondre à la question de savoir comment je m'y prendrais, car je ne connais pas la tâche. De toute façon, cas->cas->cas... est un peu suspect.
 
papaklass:

Ce que vous suggérez (traitement des types de données) est ce dont dispose MK pour le moment. Le gestionnaire OnTradeTransaction gère un certain type de données MqlTradeTransaction. C'est vrai, ils ont mis beaucoup de choses dans ce type de données, c'est-à-dire des types de données correspondant à différents événements.

Je suggère que chaque événement ait ses propres données et son propre gestionnaire. Autant d'événements, autant de gestionnaires. La division des événements (ouverture d'une position, fermeture d'une position, placement d'un ordre, modification d'un ordre, modification d'une position, etc.) Et c'est aux développeurs de décider quels types de données attribuer à quels événements.

Par le mot "gestionnaire", je n'entends pas une fonction système qui reçoit un événement, mais un module Expert Advisor qui analyse tel ou tel événement. Pour multiplier le nombre de fonctions sur... Chacun pour son propre événement - n'a aucun sens, d'autant plus qu'il est élémentaire de créer des gestionnaires d'utilisateurs en quantité suffisante. C'est ainsi que cela se passe dans mon cas :

///
/// Принимаем событие.
///
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...
   }
}

Il peut sembler étrange qu'une seule et même classe d'événement soit transmise à des gestionnaires complètement différents qui nécessitent des types de données complètement différents. Par exemple, OnMouseMove requiert un masque des touches pressées sur la souris et ses coordonnées, OnKeyDown() requiert le code d'une touche pressée, OnOrderChange requiert un ticket de la commande qui a été modifiée et probablement un enum décrivant la modification exacte. Vous pourriez penser que la classe d'événements contient des champs pour tous les événements possibles. Mais ce n'est pas le cas. En fait, l'objet de la classe événement ne peut même pas exister, puisque son constructeur est caché dans la zone protégée. Mais ses descendants existent en abondance - chaque descendant ne gérant qu'un événement différent. Cependant, pour tout événement, il existe un identifiant qui indique à quel type il appartient. En connaissant cet identifiant, vous pouvez passer sans risque d'un type plus grand à un type plus petit. Il s'agit du type de l'enfant pour lequel la conversion implicite se produit lorsque le gestionnaire est passé. Voyons comment nos gestionnaires voient réellement l'événement :

///
/// Реагируем на перемещение мыши.
///
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...
Magnifique... Il semble qu'il n'y ait qu'un seul événement, mais en fait il pourrait y en avoir des dizaines. L'événement semble ne contenir pratiquement aucune information, à l'exception de son type, mais en fait, les gestionnaires font librement référence à des méthodes connues d'eux seuls.
 

Il n'y a pas d'événements "externes" et "internes", juste des événements. Et le nombre de ces événements est potentiellement infini. Un événement peut être n'importe quoi. Un événement peut contenir toutes sortes de données. En suivant cette philosophie, nous atteignons un nouveau niveau, plus élevé, d'abstraction des données. Pourquoi créer des restrictions dans votre tête, pourquoi imposer une classification limitant l'abstraction !

papaklass:

La différence essentielle entre les événements internes et externes est le temps d'exécution. Les événements internes ont un temps d'exécution pratiquement nul, tandis que les événements externes ont des centaines de millisecondes ou de secondes.

Les événements n'ont pas de temps d'exécution. Si un événement est arrivé, il est déjà exécuté. C'est ainsi que le mode asynchrone fonctionne. Il est donc erroné de classer les événements en internes et externes en fonction de la vitesse à laquelle ils sont exécutés. Il est correct de ne pas classer du tout, mais de penser de manière très abstraite à partir de la mise en œuvre concrète.

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