Expert Advisors: MQL5 Programming for Traders – Quellcodes aus dem Buch. Teil 6 - Seite 2

 
Stanislav Korotky #:
Aufträge, Geschäfte und Positionen sind ohnehin nicht an Zeitrahmen gebunden. Entweder haben Sie etwas missverstanden oder Ihre Formulierung ist falsch.
Es tut mir leid, dass meine Wortwahl verwirrend ist: Mit"Zeitrahmen" meine ich "Datumsbereich". Angenommen, ich möchte Geschäfte/Aufträge auswählen, die innerhalb eines bestimmten Datumsbereichs getätigt wurden, z. B. Geschäfte vom 2025-10-01 00:00:00 bis 2025-10-22 23:59:59.
 
pauldic #:
Es tut mir leid, dass meine Wortwahl verwirrend ist, denn mit"Zeitrahmen" meine ich "Datumsbereich". Sagen wir, ich möchte Abschlüsse/Bestellungen auswählen, die innerhalb eines bestimmten Datumsbereichs getätigt wurden, z. B. Abschlüsse vom 2025-10-01 00:00:00 bis 2025-10-22 23:59:59.

Wenn Sie einen Teilbereich eines Handelsverlaufs analysieren wollen, ist es effizienter, nur diesen Teil des Verlaufs vor der Filterung abzufragen, ohne den Filterungscode selbst zu beeinflussen:

input datetime SubrangeFrom = 0;
input datetime SubrangeTo = 0;

...

{
   HistorySelect(SubrangeFrom, SubrangeTo);
   // ... Filtercode geht hier unverändert weiter
}

Wenn Sie aus irgendeinem Grund einen (engeren) Teilbereich innerhalb des globalen Bereichs, den Sie mit HistorySelect angewendet haben, auswählen möchten, dann können Sie dies im Filterungscode immer noch wie folgt tun:

{
      // einige von ihnen gehen hier

      // HistorySelect(0, LONG_MAX);
      // HistorySelectByPosition(PositionID);
      ...
      DealTuple deals[];
      if(SubrangeFrom != SubrangeTo && SubrangeFrom < SubrangeTo)
      {
         filter.let(DEAL_TIME, SubrangeFrom - 1, IS::GREATER).let(DEAL_TIME, SubrangeTo + 1, IS::LESS);
      }
      filter.let(DEAL_POSITION_ID, PositionID).select(deals, true);
      ...
}

Die gelb hervorgehobene Zeile setzt 2 Bedingungen für den Datumsbereich [SubrangeFrom, SubrangeTo] unter Verwendung der zusätzlichen Qualifikatoren IS::GREATER und IS::LESS (standardmäßig werden sie in anderen Aufrufen von let() nicht angegeben, und IS::EQUAL wird normalerweise für Einzelwertfelder verwendet).

Ich kenne nur einen Grund für die Anwendung des Subfilters nach Datumsbereich - es ist für die Einrichtungszeit von Aufträgen (ORDER_TIME_SETUP), weil HistorySelect auf eine andere datetime-Eigenschaft von Aufträgen angewendet wird - nämlich die Ausführungszeit von Aufträgen (ORDER_TIME_DONE). Es könnte auch interessant sein, einen Teilbereich von aktiven Aufträgen (nicht in der Historie) zu filtern, wenn es viele davon gibt.

Sie können sich das Beispielskript MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 als Ausgangspunkt ansehen.
 
Stanislav Korotky #:

Wenn Sie einen Teilbereich eines Handelsverlaufs analysieren wollen, ist es effizienter, nur diesen Teil des Verlaufs vor der Filterung abzufragen, ohne den Filterungscode selbst zu beeinflussen:

Wenn Sie aus irgendeinem Grund einen (engeren) Teilbereich innerhalb des globalen Bereichs, den Sie mit HistorySelect angewendet haben, auswählen möchten, können Sie dies im Filterungscode immer noch wie folgt tun:

Die gelb hervorgehobene Zeile setzt 2 Bedingungen für den Datumsbereich [SubrangeFrom, SubrangeTo] unter Verwendung der zusätzlichen Qualifikatoren IS::GREATER und IS::LESS (standardmäßig werden sie in anderen Aufrufen von let() nicht angegeben, und IS::EQUAL wird normalerweise für Einzelwertfelder verwendet).

Ich kenne nur einen Grund für die Anwendung des Subfilters nach Datumsbereich - es ist für die Einrichtungszeit von Aufträgen (ORDER_TIME_SETUP), weil HistorySelect auf eine andere datetime-Eigenschaft von Aufträgen angewendet wird - nämlich die Ausführungszeit von Aufträgen (ORDER_TIME_DONE). Es könnte auch interessant sein, einen Teilbereich von aktiven Aufträgen (nicht in der Historie) zu filtern, wenn es viele davon gibt.

Sie können sich das Beispielskript MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 als Ausgangspunkt ansehen.
@StanislavKorotky Nochmals vielen Dank... Es ist ein großartiger Ausgangspunkt für mich und ich werde anfangen, mit ihm zu arbeiten.
 

Fehlerbehebung MQL5/Include/MQL5Book/TradeUtils.mqh.

   bool Equal(const double v1, const double v2)
   {
      return v1 == v2 || fabs(v1 - v2) < DBL_EPSILON * fmax(1.0, fmax(fabs(v1), fabs(v2)));
   }
Dateien:
TradeUtils.mqh  12 kb
 
pauldic #:

Verwenden Sie dieCODE-Taste (Alt-S), wenn Sie Code einfügen.

Ein Moderator hat den falsch eingefügten Code formatiert. Normalerweise wird solcher Code entfernt.

@StanislavKorotky Bitte können Sie helfen, in diesem Fehler zu suchen, ich glaube, es begann nach MT5 Updates, weil ich wusste, dass der Code funktioniert in den vergangenen Monaten ohne Änderungen.

Parameter Konvertierung Typ 'long[][2]' zu 'string[][] &' ist nicht erlaubt SymbolFilter.mqh 199 20

Parameter conversion type 'double[][2]' to 'string[][] &' is not allowed TradeFilter.mqh 332 20
Parameter Konvertierung Typ 'long[][2]' in 'string[][] &' ist nicht erlaubt TradeFilter.mqh 163 17


Ich vermute, dass der folgende Code helfen wird, das Problem zu lösen:


Hallo @Paul Dick

Versuchen Sie diese https://www.mql5.com/de/code/57233 für die Sortierung von Arrays

Introsort (Introspective sort) using Function Pointers
Introsort (Introspective sort) using Function Pointers
  • 2025.03.18
  • www.mql5.com
A hybrid sorting algorithm that provide fast performance for sorting arrays of simple types, structures or object pointers.
 

Ich füge eine aktualisierte Version der Berechnungsdatei des benutzerdefiniertenOptimierungskriteriums auf der Grundlage von R2 - RSquared.mqh bei, in der die Berechnung für den Fall variabler Lose korrigiert wurde.

Die Qualität der Schätzung wurde deutlich verbessert - nach der Tabelle der Optimierungsergebnisse zu urteilen, wurde die Kombination aus Erholungsfaktor und Sharpe-Parametern erhalten.

Beispiel für die Anwendung.

double OnTester()
{
   HistorySelect(0, LONG_MAX);
   
   #define  STAT_PROPS 5
   
   const ENUM_DEAL_PROPERTY_DOUBLE props[STAT_PROPS] =
   {
      DEAL_PROFIT, DEAL_SWAP, DEAL_COMMISSION, DEAL_FEE, DEAL_VOLUME
   };
   double expenses[][STAT_PROPS];
   ulong tickets[]; // wird hier nur verwendet, um den 'select'-Prototyp abzugleichen, aber nützlich für die Fehlersuche
   
   DealFilter filter;
   filter.let(DEAL_TYPE, (1 << DEAL_TYPE_BUY) | (1 << DEAL_TYPE_SELL), IS::OR_BITWISE)
      .let(DEAL_ENTRY, (1 << DEAL_ENTRY_OUT) | (1 << DEAL_ENTRY_INOUT) | (1 << DEAL_ENTRY_OUT_BY), IS::OR_BITWISE)
      .select(props, tickets, expenses);

   const int n = ArraySize(tickets);
   
   double balance[];
   double volumes[]; // Berücksichtigung des Handelsvolumens bei der Anwendung des R2-Kriteriums
   
   ArrayResize(balance, n + 1);
   balance[0] = 0;
   ArrayResize(volumes, n + 1);
   volumes[0] = 0;
   
   for(int i = 0; i < n; ++i)
   {
      double result = 0;
      for(int j = 0; j < STAT_PROPS - 1; ++j)
      {
         result += expenses[i][j];
      }
      // Volumen als Modell verwenden - mehr Investitionen - mehr erwartete Erträge
      volumes[i + 1] = expenses[i][STAT_PROPS - 1] + volumes[i];
      balance[i + 1] = result + balance[i];
   }
   
   const double r2 = RSquaredTest(balance, volumes);
   
   #undef  STAT_PROPS
   
   return r2 * 100;
}
Dateien:
RSquared.mqh  4 kb
 

Ich habe vor kurzem gelernt, Frame und ich getestet Ihren Code, FrameTransfer.mq5. Diese Zeile löst im aktuellen MT5-Compiler einen Fehler aus. Bitte überprüfen Sie das: #property tester_set "FrameTransfer.set" (ungültige tester set Dateierweiterung, '*.set' erwartet FrameTransfer.mq5)

Sie muss wie folgt geändert werden, damit sie erfolgreich kompiliert werden kann: #property tester_set "\\Presets\\FrameTransfer.set"

Auch `#property tester_set "/Presets/FrameTransfer.set"` wird fehlschlagen.

Vielleicht könnten Sie die Beschreibung im Algorithmusbuch ändern:


 
hini #property tester_set "FrameTransfer.set" (ungültige Tester Set Dateierweiterung, '*.set' wird erwartet FrameTransfer.mq5)

Für eine erfolgreiche Kompilierung sollte sie wie folgt geändert werden: #property tester_set "\\Presets\\FrameTransfer.set"

Auch `#property tester_set "/Presets/FrameTransfer.set"` wird fehlschlagen.

Vielleicht könnten Sie die Beschreibung im Algorithmusbuch ändern:


Dies ist ein offensichtlicher Compiler-Bug - er gibt die Fehlermeldung: "ungültige tester_set-Dateierweiterung, '*.set' erwartet" an den Code:

#property tester_set "FrameTransfer.set"

wo die Datei die erforderliche Erweiterung hat. Der Dateipfad hat damit nichts zu tun.

Der Fehler ist schon lange bekannt, mindestens seit 2024. Warum sich MQ nicht darum kümmert, ihn zu beheben, weiß ich nicht.

Was die Bearbeitungen des Buches angeht, so sind sie in diesem Fall nicht erforderlich, aber in jedem Fall ist das Buch jetzt vollständig unter der Kontrolle von MQ.

 
Stanislav Korotky Kontrolle von MQ.
Bestätigt und gemeldet. Mal sehen, ob der Fehler behoben wird.
 
Stanislav Korotky #:

Dies ist ein offensichtlicher Compilerfehler - er gibt den Fehler: "Ungültige Testersatz-Dateierweiterung, '*.set' erwartet" in den Code:

Danke, behoben!

Um bei Ihrer MetaEditor-Version zu bleiben, fügen Sie eine Null am Ende des Dateinamens hinzu: "myset.set\0"