Fehler, Irrtümer, Fragen - Seite 2452

 
A100:

Das Kopieren der Arrays erfolgt nicht nach den Regeln a = b, sondern nach den Regeln vonArrayCopy( a, b )

Haben Sie sich das selbst ausgedacht oder steht das irgendwo geschrieben?
Ich möchte Sie daran erinnern, dass dies ein impliziter Zuweisungsoperator für Strukturen mit dynamischen Arrays ist.

 
Sergey Dzyublik:

Haben sie es selbst erfunden oder steht es irgendwo geschrieben?
Ich möchte Sie daran erinnern, dass dies die Arbeit des impliziten Zuweisungsoperators für Strukturen mit dynamischen Feldern ist.

Es war nicht meine Idee, es war die der Entwickler.

        uchar a[], b[]; a = b; //Error: invalid array access
Warum liegt ein Fehler vor? Sie haben es in eine Struktur eingewickelt und der Fehler ist verschwunden? Und warum? Was hat sich grundlegend geändert? Meine Antworten oben
 
Alexey Viktorov:

Es geht nur darum, die Abfolge der Aktionen und Ereignisse zu organisieren.

Sie haben selbst aus dem Handbuch zitiert, in dem es heißt, dass die Konsistenz nicht garantiert ist. Deshalb ist es auch riskant.

Ich habe bereits begonnen, den Code nach Vladimirs Rat umzuschreiben, aber ich stolperte über einen Fall, wenn das Schließen länger als ein Tick ist - wieder doppelt gezählt (der Filterknoten beim Zählen ist sehr schwerfällig). Bislang ist mir noch nichts Besseres eingefallen, als als Kompromiss mit der Optimierungsgeschwindigkeit vor dem vollständigen Schließen anzuhalten.

Es ist Freitag :) Vielleicht fällt mir nach etwas Ruhe etwas ein.

Auf jeden Fall danke für die Ideen - sie werden nicht verloren gehen!

 
A100:

Es war nicht meine Idee, es war die der Entwickler.

Ich habe nie verstanden, wo das geschrieben wurde, aber egal...
Danke für das Gespräch.

Er stützte sich mit einer Krücke ab und lief weiter:

struct MyArray{
   uchar data[];
   
   void operator=(MyArray &bytes){
      ArrayCopy(this.data, bytes.data);
      ArrayResize(this.data, ArraySize(bytes.data));
   }
};


MyArray GetArray(int i){
   MyArray arr;
   
   if (i%2 == 0){
      ArrayResize(arr.data, 8);
      ArrayInitialize(arr.data, 0x8);
   }else{
      ArrayResize(arr.data, 4);
      ArrayInitialize(arr.data, 0x4);
   }
   return arr;
}


void OnStart(){
   MyArray arr_1 = GetArray(1);
   ArrayPrint(arr_1.data);        // 4 4 4 4
   
   MyArray arr_2 = GetArray(2);
   ArrayPrint(arr_2.data);        // 8 8 8 8 8 8 8 8
   
   arr_2 = arr_1;
   ArrayPrint(arr_2.data);        // 4 4 4 4            
}
 
Igor Zakharov:

Sie haben selbst aus dem Handbuch zitiert, in dem es heißt, dass die Konsistenz nicht garantiert ist. Deshalb ist es auch riskant.

Ich habe bereits begonnen, den Code nach Vladimirs Rat umzuschreiben, aber ich stolperte über einen Fall, in dem das Schließen länger als ein Tick ist - wieder doppelt gezählt (Filterknoten in der Zählung ist sehr schwerfällig). Bislang ist mir noch nichts Besseres eingefallen, als als Kompromiss mit der Optimierungsgeschwindigkeit vor dem vollständigen Schließen anzuhalten.

Es ist Freitag :) Vielleicht fällt mir nach etwas Ruhe etwas ein.

Wie auch immer, danke für die Ideen - sie werden nicht vergeudet werden!

Ich habe von meiner eigenen Beständigkeit gesprochen.

Nach meinen Beobachtungen stellt sich heraus, dass nach OnTick, wenn eine Transaktion stattfindet, die Codeausführung an die Funktion OnTradeTransaction übergeben wird, ohne auf den nächsten Tick zu warten. Es macht daher keinen Unterschied, ob der Abschluss durch eigene Funktionen oder durch OnTradeTransaction verarbeitet wird .Aber ich bevorzuge die Arbeit mit OnTradeTransaction. Die Hauptsache ist, die Abfolge der Operationen richtig zu gestalten, ohne von der Abfolge der vom Server kommenden Transaktionen abzuhängen. Und es ist wichtig , diese Reihenfolgerichtig zu verstehen . Nach meinen eigenen Beobachtungen kann die Reihenfolge in der Vorgangsart unterbrochen werden. D.h. TRADE_TRANSACTION_DEAL_ADD kann zuerst ausgeführt werden und dann TRADE_TRANSACTION_HISTORY_ADD, aber logischerweise sollte zuerst ein Auftrag zur Historie hinzugefügt werden und dann eine Transaktion.

ps; Dann können Sie, wie gesagt, durch das Screening der Transaktion TRADE_TRANSACTION_DEAL_ADD nach Positionseröffnung und Positionsschließung screenen. Schließlich geht es um einen Expert Advisor für den Forex-Markt und ein Konto, nicht wahr? Daher ist es nicht erforderlich, alle Positionen bei jedem Niesen neu zu berechnen. Es genügt, eine hinzuzufügen, wenn sie geöffnet wurde, oder eine aus der Liste zu löschen, wenn sie geschlossen wurde.
 
Alexey Viktorov:

des Devisenmarktes und des Kontos, richtig?

Raster :) Ja.

Die derzeitige Logik sieht folgendermaßen aus: Es gibt eine Struktur, die alle Informationen über jedes Raster speichert: Symbol - Anzahl der Positionen - Lot-Gewinn und ein paar andere unwichtige Dinge... Der Gewinn wird vom Timer neu berechnet, wenn es Aufträge gibt (Multisymbol-Roboter). Aber Lots und Menge wurden in OnTradeTransaction neu berechnet (falls der Benutzer "nachgeholfen" hat).

Ich wollte einen Fall prüfen, in dem ein Raster z.B. einen Gewinn von 100$ und ein anderes einen Verlust von 50$ aufweist - um beide mit einem Gewinn von 50$ zu schließen, um zu verhindern, dass er wächst.

Im Moment habe ich dies getan:

void  OnTradeTransaction(
   const MqlTradeTransaction&    trans,     // trade transaction structure 
   const MqlTradeRequest&        reqst,     // request structure 
   const MqlTradeResult&         reslt      // response structure 
    )
{
 int index=-1;
 for(index=0;index<symbols_total;index++)
  if(ARRAY[index].symbol==trans.symbol) break; //нашли индекс символа по которому прошла трансакция в массиве структур
 
 if(index>=0) CountOrders(index); //пересчитали элемент
}

Bisher habe ichCountOrders() hinzugefügt, nachdem ich einige Raster geschlossen hatte.Für einen Strategietester funktioniert das. Für ein echtes Konto werde ich das Schema von Vladimir verwenden (mit einer Reihe von geschlossenen Tickets).

Übrigens, das Schließen des Paares hat sich nicht gerechtfertigt - der Drawdown nimmt nicht wesentlich ab, während der Gewinn dezent sinkt.

 
Vladimir Karputov:

Ich würde ALLE while, Sleep und OnTimer für die Aufgabe aufgeben , Positionen zu schließen. Ich würde wie folgt vorgehen: Schießen von Aufträgen zum Schließen - Ausstieg OnTick, beim nächsten Tick prüfen: ob Positionen mit benötigten Tickets noch am Leben sind - erneut Schießen von Aufträgen zum Schließen und so weiter in einem Kreis durch Einstieg/Ausstieg zu OnTick.

Die Logik ist wie folgt: Das Schließen einer Position hat oberste Priorität, also steht die Schließungsschleife ganz am Anfang von OnTick. Und die Bildung einer Reihe von Abschlusskarten kann an jeder beliebigen Stelle von OnTick erfolgen - sogar ganz am Ende.

Früher oder später werden Sie mit folgendem Problem konfrontiert: Sie müssen eine Position schließen, ein Schließungsauftrag wird gesendet (MQL5), d. h. ein Auftrag des entgegengesetzten Typs wird gesendet, da Sie die Handelsaktionen nicht im entsprechenden Handler verfolgen (oder den Positionsstatus in Ihrem EA nicht speichern), und beim nächsten Tick wird möglicherweise ein Schließungsauftrag gesendet, und Sie werden einen weiteren Auftrag senden. Das Ergebnis ist eine Position in die entgegengesetzte Richtung.

 
Alexey Kozitsyn:

Früher oder später werden Sie mit folgendem Problem konfrontiert: Sie müssen eine Position schließen, Sie senden einen Schließungsauftrag (MQL5), d. h. Sie senden einen Auftrag des entgegengesetzten Typs, da Sie die Handelsaktionen im entsprechenden Handler nicht verfolgen (oder den Positionsstatus in Ihrem EA nicht speichern), und beim nächsten Tick wird vielleicht gerade ein Schließungsauftrag gesendet, aber Sie senden einen anderen Auftrag. Das Ergebnis ist eine Position in die entgegengesetzte Richtung.

Für einen solchen Fall haben wir:

10036

TRADE_RETCODE_POSITION_CLOSED

DiePosition mit dem angegebenen POSITION_IDENTIFIER wurde bereits geschlossen

Die Schließungsposition wird mit dem Ticket der zu schließenden Position gesendet, so dass es unwahrscheinlich ist, dass die von Ihnen beschriebene Position geschlossen wird.

 
Sergey Dzyublik:

Ich habe nie verstanden, wo das geschrieben steht, aber egal...
Danke für das Gespräch.

Er stützte sich mit einer Krücke ab und lief weiter:

Nun, es ist seltsam, wie Arrays kopiert werden, aber manche Leute mögen das sogar...

Ich habe eine mehr oder weniger adäquate Umhüllung über ein Array gemacht und habe keine Probleme.

https://www.mql5.com/ru/forum/221917/page26#comment_11233214

 
A100:

Es war nicht meine Idee, es war die der Entwickler.

Ich kann mich nicht erinnern, dass sie das jemals gesagt haben.

Der Zuweisungsoperator ist dazu gedacht, eine identische Kopie eines Objekts zu erstellen. Das ist sein Zweck. Wenn man etwas mit etwas gleichsetzt, sollte man offensichtlich eine vollständige Kopie auf der linken Seite erhalten, nicht etwas anderes. Hier liegt also offensichtlich ein Fehler vor.