Entwickler! Testen Sie überhaupt, was Sie schaffen? - Seite 10

 
Mikalas:

Oh, mein Gott! Ist sie in der Geschichte gültig?

papaklass meinte wahrscheinlich, dass OnTradeTransaction Fehler zurückgibt?

Wenn die Informationen in OnTradeTransaction möglicherweise nicht gültig sind, müssen wir sie aus der Historie entnehmen, um sicherzustellen, dass sie gültig sind.

Wenn onTradeTransaction-Informationen nicht immer zuverlässig sind, müssen wir sie aus der Historie entnehmen, um sicherzustellen, dass die Informationen verarbeitet wurden.

Die Frage ist, warum zum Teufel brauchen wir OnTradeTransaction, wenn wir die Informationen sowieso aus der Historie nehmen müssen? - Sie wird nur für die Fehlerprüfung benötigt. Der Broker lehnte die Order ab und wir erhielten die Antwort, warum sie abgelehnt wurde, in OnTradeTransaction und analysierten sie.

 
sergeev:
aber warum über 9 Seiten sabbern?

Bitte seien Sie nicht unhöflich! Übrigens, es ist schon 10!

Und es ist Ihr gutes Recht, das, was hier steht, gar nicht zu lesen!

 
Mikalas:

C-4, wird natürlich verarbeitet, aber wozu braucht man OnRefresh()?

Viele Ereignisse -> ein Handler.
 
C-4:
Viele Ereignisse -> ein Handler.
Fehler aus allen Ecken auf einen Haufen! :)
 
Mikalas:
Fehler aus allen Ecken auf einen Haufen! :)

Es sind nicht die Fehler, die gesendet werden, sondern die Daten. Fehler können im Handler liegen, aber sie sind leicht zu beheben, da es nur einen Handler gibt.

papaklass:
Das ist genau das, was ich meine. Sie brauchen eine Trennung der Ereignisse.
Sie brauchen keine Trennung der Ereignisse, sondern eine Trennung der Handler. Ereignisse erzeugen Daten. Jede Art von Daten wird von einem eigenen Handler bearbeitet. Es spielt keine Rolle, wer die Daten erhalten hat, wichtig ist nur, dass es für jede Art von Daten einen eigenen Handler gibt.
 
C-4:

Es sind nicht die Fehler, die gesendet werden, sondern die Daten. Fehler können im Handler liegen, aber sie sind leicht zu beheben, da es nur einen Handler gibt.

Sie müssen nicht die Ereignisse, sondern die Handler voneinander trennen. Ereignisse erzeugen Daten. Jede Art von Daten wird von einem anderen Handler bearbeitet. Es spielt keine Rolle, wer die Daten erhalten hat, wichtig ist nur, dass es für jeden Datentyp einen eigenen Handler gibt.

Was wird hier nicht getrennt?

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

Und dann gibt es noch

const MqlTradeRequest &request, const MqlTradeResult &result
 
Mikalas:

Was wird hier nicht geteilt?

Eine Menge Kombinatorik. Fazit: Riesenblatt in OnTradeTransaction und komplizierte Logik. Ich kann nicht sagen, wie ich es machen würde, weil ich die Aufgabe nicht kenne, aber auf jeden Fall Fall Fall->Fall->Fall... ist ein wenig verdächtig.
 
papaklass:

Was Sie vorschlagen (Verarbeitung von Datentypen) ist das, was MK im Moment hat. Der OnTradeTransaction-Handler behandelt einen bestimmten MqlTradeTransaction-Datentyp. Es stimmt, sie haben viele Dinge in diesen Datentyp gepackt, z.B. Datentypen, die verschiedenen Ereignissen entsprechen.

Ich schlage vor, dass jedes Ereignis seine eigenen Daten und seinen eigenen Handler hat. So viele Ereignisse, so viele Handler. Die Aufteilung der Ereignisse (Eröffnung einer Position, Schließung einer Position, Erteilung eines Auftrags, Änderung eines Auftrags, Änderung einer Position usw.). Und es ist Sache der Entwickler, zu entscheiden, welche Datentypen welchen Ereignissen zugeordnet werden sollen.

Mit dem Wort "Handler" meine ich nicht eine Systemfunktion, die ein Ereignis empfängt, sondern ein Expert Advisor-Modul, das dieses Ereignis analysiert. Um die Anzahl der Funktionen zu multiplizieren... Jeder von ihnen für sein eigenes Ereignis - das macht keinen Sinn, zumal es elementar ist, eine notwendige Anzahl von Custom Handlern zu erstellen. So wird es in meinem Fall gehandhabt:

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

Es mag seltsam erscheinen, dass ein und dieselbe Ereignisklasse an völlig unterschiedliche Handler übergeben wird, die völlig unterschiedliche Datentypen benötigen. OnMouseMove erfordert beispielsweise eine Maske der gedrückten Maustasten und deren Koordinaten, OnKeyDown() erfordert den Code einer gedrückten Taste, OnOrderChange erfordert ein Ticket der geänderten Reihenfolge und wahrscheinlich eine Aufzählung, die die genaue Änderung beschreibt. Man könnte meinen, dass die Ereignisklasse Felder für alle möglichen Ereignisse enthält. Aber das ist nicht der Fall. Tatsächlich kann das Objekt der Ereignisklasse nicht einmal existieren, da sein Konstruktor im geschützten Bereich verborgen ist. Aber es gibt eine Vielzahl von Nachkommen - jeder Nachkomme kann nur ein anderes Ereignis behandeln. Für jedes Ereignis gibt es jedoch eine Kennung, die angibt, zu welchem Typ es gehört. Mit dieser Kennung können Sie sicher von einer größeren auf eine kleinere Schrift umstellen. Dies ist der Typ des untergeordneten Elements, in den die implizite Konvertierung erfolgt, wenn der Handler übergeben wird. Schauen wir uns an, wie unsere Handler das Ereignis tatsächlich sehen:

///
/// Реагируем на перемещение мыши.
///
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...
Schön... Es sieht so aus, als gäbe es nur ein Ereignis, aber in Wirklichkeit könnte es Dutzende davon geben. Das Ereignis scheint fast keine Informationen zu enthalten, mit Ausnahme seines Typs, aber in Wirklichkeit verweisen die Handler frei auf Methoden, die nur ihnen bekannt sind.
 

Es gibt keine "externen" und "internen" Ereignisse, sondern nur Ereignisse. Und die Zahl dieser Ereignisse ist potenziell unendlich. Ein Ereignis kann alles sein. Ein Ereignis kann alle Arten von Daten enthalten. Mit dieser Philosophie erreichen wir eine neue, höhere Ebene der Datenabstraktion. Warum sollte man in seinem Kopf Einschränkungen schaffen, warum sollte man eine Klassifizierung auferlegen, die die Abstraktion einschränkt!

papaklass:

Der wesentliche Unterschied zwischen internen und externen Ereignissen ist die Ausführungszeit. Interne Ereignisse haben praktisch keine Ausführungszeit, während externe Ereignisse Hunderte von Millisekunden bis Sekunden dauern.

Ereignisse haben keine Ausführungszeit. Wenn ein Ereignis eingetroffen ist, wird es bereits ausgeführt. So funktioniert der asynchrone Modus. Es ist also falsch, Ereignisse in interne und externe zu unterteilen, weil sie so schnell ausgeführt werden. Es ist richtig, überhaupt nicht zu klassifizieren, sondern sehr abstrakt von der konkreten Umsetzung her zu denken.

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