LastBar Detector im Tester - Seite 2

 

Du musst nicht so viel rechnen.

Die Woche beginnt immer So 17:00 NY-Zeit und endet Fr 17:00 NY-Zeit. Innerhalb der Woche gibt es keine Zeitumstellung!

Ergo beendet ein normaler Broker die Woche (zB. Fr. 22:59:58) immer zu der Uhrzeit zu der er die Woche begonnen hat (So. 23:01): Broker-Wochenbeginn + 5*24*3600 Sekunden +/- eine gewisse Latenz bzw. Ungenauigkeit.

Wenn Du dazu 1H-Bars nimmst hast Du schon eine gewisse Rundung des Wochenbeginns. So kann man die ganz leicht das Ende der Woche berechnen, danach ist Wochenende bis der nächste Tick kommt.

Suchtest Du so etwas?

 

Gewünscht hätte ich sowas:


maxBars = GetMaxBars(Tester);

Einmal die Anzahl der maximalen Bars die der Tester durchlaufen wird.

Und einfach auf t-1 warten.


Die "Zeit" Lösungen funktionieren natürlich. Ist aber nicht universell einsetzbar.



Es gibt da noch die OnTester()

Die wird direkt vor der OnDeInit() angelaufen um Berechnungen für den Pass zu machen.

Leider ist dort aber Sleep() wie auch in der DeInit nicht erlaubt.

Und ich benötige eine kleine Pause vor DeInit()

Ich probier einfach mal eine große Berechnung die einfach Zeit frist zu nutzen.


Trotzdem Danke an die Ideen.

 
Christian:

Gewünscht hätte ich sowas:

maxBars = GetMaxBars(Tester);

Einmal die Anzahl der maximalen Bars die der Tester durchlaufen wird.

Wenn ich dich richtig verstehe, willst du das in MT4 machen. Da ist das nur manuell möglich. In MT5 geht das meines Wissens nach gar nicht.

In MT4 kann man das direkt in MQL machen (möglich, doch nicht zu empfehlen) oder direkt in C/C++ (ein ernsthafter Trader/Entwickler kommt um eigene DLL's für Statistik/Testanalyse eh' nicht drum herum). Die Links zeigen die C++-Lösung. Wer will, kann das nach MQL konvertieren (mehr Schreibaufwand und langsamer).

- Tester-Setting "To-Date" auslesen: https://github.com/rosasurfer/mt4-expander/blob/f374a00/src/lib/tester.cpp#L150

- History-File "Last Bar" auslesen: https://github.com/rosasurfer/mt4-expander/blob/f374a00/src/lib/tester.cpp#L196

- Prüfen, welcher der beiden Werte näher liegt und am Testende zuerst getriggert werden wird. Das ist nötig, weil eine History-Datei wesentlich weiter als der nächste durchzuführende Test reichen kann, jedoch auch schon vorher aufhören kann (z.B. wenn sie schreibgeschützt ist und vom Tester nicht überschrieben werden soll).

- Letzte Bar bestimmen, indem man intelligent durch die Datei navigiert (nicht mit einer For-Schleife und i++).

Im History-Header sieht das so aus:

erste und letzte Bardaten


Am Ende gibt es auch nochmal die Tester-Settings. Diese sind aber (wie schon erwähnt) nur dann gültig, wenn die Datei nicht schreibgeschützt ist und bei jedem neuen Test aktualisiert wird. Nur in diesem Fall kann man die Tester-Settings auch aus der Datei auslesen (was einige Zeilen Code spart).

Tester-Settings "From"/"To"


Das Format der Test-History ist hier dokumentiert:  https://github.com/rosasurfer/mt4-expander/blob/master/header/struct/mt4/FxtHeader.h


Meine Meinung: Ich würde keine Logik basierend auf der letzten Bar oder dem letzten Tick aufbauen, da du zu viele Randbedingungen beachten mußt. Abhängig vom verwendeten BarModel kann der letzte Tick ein BarOpen-Tick oder ein BarClose-Tick sein. Hast du gerade keine Position offen, wird es beim BarModel "Open Prices" ein BarOpen-Tick sein. Hast du dagegen zum Testende eine offene Position, führt MetaTrader in der letzten Sekunde vor Testende auch mit "Open Prices" einen letzten Tick aus. In diesem Tick wird die offene Position automatisch geschlossen. Du siehst, viele Abhängigkeiten, die es zu beachten gilt, und die die Komplexität einer Strategie unnötig erhöhen.



PS: Wie im letzten Screenshot zu sehen ist, kann man dort auch die zu verwendende Commission des Test konfigurieren.

PSS: Das verwendete Programm zur Anzeige und Bearbeitung ist der hervorragende Hex-Editor "WinHex". Die verwendeten Templates (form definitions) sind hier zu finden:

https://github.com/rosasurfer/mt4-mql/tree/master/etc/windows/winhex

 
Danke für deine konkrete Lösung. Nutze nur MQL5.


 
Christian:
Danke für deine konkrete Lösung. Nutze nur MQL5.


Christian,

vielleicht ginge das:

Es gibt die Funktion UninitializeReason()! Wenn Du die entweder am Ende von OnTick() (unter der Annahmen, dass trotz eines Abbruchs OnTick() noch 'fertig gemacht wird') oder in einem if (IsStopped()) { switch (UninitializeReason()) { case ...

Aber nur so 'ne Idee, ich hab's nicht probiert, aber ich glaube mich zu erinnern, dass trotz eines Abbruchs die Ausführung der Funktion nicht unterbrochen wurde, wahrscheinlich aus Geschwindigkeitsgründen..

Dokumentation zu MQL5: Zustandspruefung / IsStopped
Dokumentation zu MQL5: Zustandspruefung / IsStopped
  • www.mql5.com
Gibt true zurück, wenn es in der Systemvariable _StopFlag den Wert gibt, der sich von 0 unterscheidet. Der Nicht-Nullwert wird in die Variable  _StopFlag geschrieben, wenn mql5-Programm...
 

Als Lösungsansatz ginge auch ein Refresh-Interlock:

.Net-Anwendung setzt ein Flag, welches vom EA ständig (bei jedem Tick) gelöscht wird. .- Wird es nicht mehr gelöscht, dann ist der EA nicht mehr aktiv.


Als Idee, evtl bissl späte.

 
Carl Schreiber:

Christian,

vielleicht ginge das:

Es gibt die Funktion UninitializeReason()! Wenn Du die entweder am Ende von OnTick() (unter der Annahmen, dass trotz eines Abbruchs OnTick() noch 'fertig gemacht wird') oder in einem if (IsStopped()) { switch (UninitializeReason()) { case ...

Aber nur so 'ne Idee, ich hab's nicht probiert, aber ich glaube mich zu erinnern, dass trotz eines Abbruchs die Ausführung der Funktion nicht unterbrochen wurde, wahrscheinlich aus Geschwindigkeitsgründen..

Klingt vielversprechend , schau ich mir morgen mal an. Werde berichten
 
Dominik Egert:

Als Lösungsansatz ginge auch ein Refresh-Interlock:

.Net-Anwendung setzt ein Flag, welches vom EA ständig (bei jedem Tick) gelöscht wird. .- Wird es nicht mehr gelöscht, dann ist der EA nicht mehr aktiv.


Als Idee, evtl bissl späte.

Ist an meinem Problem vorbei.

Möchte nicht einen "toten" EA prüfen sondern wissen wann ich die letzte noch mögliche Funktion aufrufen kann BEVOR OnDeinit angesprungen wird.

Trotzdem danke

 

Der MT5 hat doch kein History File oder doch ? Deswegen hast du sicherlich alle Möglichkeiten ausgeschlossen ?

Meine Meinung: Ich würde keine Logik basierend auf der letzten Bar oder dem letzten Tick aufbauen, da du zu viele Randbedingungen beachten mußt. Abhängig vom verwendeten BarModel kann der letzte Tick ein BarOpen-Tick oder ein BarClose-Tick sein. Hast du gerade keine Position offen, wird es beim BarModel "Open Prices" ein BarOpen-Tick sein. Hast du dagegen zum Testende eine offene Position, führt MetaTrader in der letzten Sekunde vor Testende auch mit "Open Prices" einen letzten Tick aus. In diesem Tick wird die offene Position automatisch geschlossen. Du siehst, viele Abhängigkeiten, die es zu beachten gilt, und die die Komplexität einer Strategie unnötig erhöhen.

Brauche den Zeitpunkt nur um ein Event über .net zu senden mehr eigentlich nicht.

 

Lösung ist gefunden.


@Carl Schreiber

Das _StopFlag wird ja nicht freiwillig gesetzt. Zumindest kommt das bei meinen Tests heraus. Siehe Bilder unten.

Die Funktion  UninitializeReason() lässt sich auch nicht überschreiben. Meckert der Compiler ( System Funktion , kann nicht überschrieben werden)

Auch die Variablen dazu bleiben alle leer in der OnTick()


Nutzen kann man die OnTester() die wird nach verlassen der OnTick() und vor der Deinit() aufgerufen.

Um eine Pause nach dem Senden des .Net Events einzufügen nutze ich eine kleine Krücke mit GetTickCount().

Da Sleep() in Deinit() und OnTester() nicht ausgeführt werden. Beschränkung durch MetaQuotes.


Code:

//+------------------------------------------------------------------+
//| "Tick" event handler function                                    |
//+------------------------------------------------------------------+
void OnTick()
  {
  // ExtExpert.OnTick();
   
   printf("Flag %d: ",_StopFlag);
   printf("LastError: %d",_LastError); 
   printf("UninitReason: %d",_UninitReason); 
   
   if (IsStopped())
    {
      ulong tick = GetTickCount();
      PrintFormat(" Stop Flag Tick: %f",tick); 
    }
  }
//+------------------------------------------------------------------+
//| "Trade" event handler function                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
  // ExtExpert.OnTrade();
  }
//+------------------------------------------------------------------+
//| "Timer" event handler function                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
  // ExtExpert.OnTimer();
  }


double OnTester()
{
  printf(__FUNCSIG__);
  
 
  PrintFormat("Simulate Sleep(300ms)");  
   
  bool noPrint = false;
     
  unsigned int Tick = GetTickCount() + 300; 
  while(GetTickCount() < Tick) 
     {
     
       
       if (!noPrint) 
       {
        printf("Sleeping...300msec");
        noPrint = true;
       }       
     }
          
   PrintFormat("End Simulate"); 
  
  return 1;
}

void OnTesterDeinit()
{
  printf(__FUNCSIG__);
}

void OnTesterPass()
{
  printf(__FUNCSIG__);
}

Ausgabe :


Dateien:
Grund der Beschwerde: