Warten bis der Chart vollständig geladen ist

Phoenix-Trinity
74
Phoenix-Trinity  

Hallo zusammen,

ich bastele gerade ein Custom-Indikator welcher auf Kerzen aus dem D1, M1 etc. angewiesen ist.

Was mir aufgefallen ist, leider bekomme ich bspw. wenn der Markt geschlossen ist und ich den Metatrader starte ein Fehler wegen "Array-Out of Range" und mir wird der Indikator nicht eingezeichnet, weil die Daten bspw. aus dem D1 fehlen.

Das passiert wohl, weil der Chart noch nicht vollständig geladen ist und die D1 Daten noch fehlen. Gibt es eine Funktion, dass der Custom-Indikator erst initialisiert wird bzw. die OnCalculate() Funktion erst durchlaufen wird, wenn der Chart vollständig geladen ist?

Ich könnte natürlich noch prüfen, dass das Array auf jeden Fall gefüllt ist, aber dann werden trotzdem die Objekte nicht eingezeichnet, weil wenn der Markt geschlossen ist, wird der Code ja nur 1-Mal durchlaufen und die befüllten Arrays brauche ich um die Objekte einzuzeichnen.

Hoffe man versteht was ich meine :-) .

Vielen Dank und viele Grüße

Carl Schreiber
Moderator
11659
Carl Schreiber  

Ohne Code versteht niemand nix und so kann auch niemand helfen.

:(

Phoenix-Trinity
74
Phoenix-Trinity  

Okay macht natürlich Sinn :-) ... ich probiere mal es mit Code zu erklären

Der Custom Indikator soll einfach nur definierte Zeitbereiche mit einem Rechteck zeichnen, also so....


Das Coding sieht dazu wie folgt aus (habe nur mal den Teil reingemacht, bis der Fehler kommt)

#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0

input group "------- Setting -------";
input int    g_iDays          = 30;                 //Days
input string g_sTimeStart     = "16:30";           //Start-Time(HH:MM)
input string g_sTimeEnd       = "23:00";           //End-Time(HH:MM)


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit() {

//erst alles zurücksetzen (globale Variablen)
 reset();

//Array-Größe definieren
 ArrayResize(g_aSessions,g_iDays);

//---
 return(INIT_SUCCEEDED);
}


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[]) {

 if(IsStopped()) return 0;

// Nun Sessions einzeichen
 if(!determineSessions()) return(rates_total);

}


//+------------------------------------------------------------------+
//| Sessions bestimmen                              |
//+------------------------------------------------------------------+
bool  determineSessions() {

 MqlRates ratesBarRangeDay[];
 ArraySetAsSeries(ratesBarRangeDay,true);


 for(int i=0; i<ArraySize(g_aSessions); i++) {

  //Tag auslesen und deren Kerzen beschaffen
  getRatesOfDay(i,ratesBarRangeDay);

..........
}


//+------------------------------------------------------------------+
//| Get-Time Range of Day                              |
//+------------------------------------------------------------------+
bool getRatesOfDay(int iIndexOfDay, MqlRates &aRatesM1[]) {

 int iLastBarIndexOfPreDay,iFirstBarIndexOfPreDay;
 MqlRates ratesD1[];
 ArraySetAsSeries(ratesD1,true);

 if(!CopyRates(_Symbol,PERIOD_D1,iIndexOfDay,2,ratesD1)) return false;
 if(ArraySize(ratesD1)<2) return true;
 if(!CopyRates(_Symbol,PERIOD_M1,ratesD1[0].time,2,aRatesM1)) return false;
 iLastBarIndexOfPreDay  = iBarShift(_Symbol,PERIOD_M1,ratesD1[0].time);
 iFirstBarIndexOfPreDay = iBarShift(_Symbol,PERIOD_M1,ratesD1[1].time) - 1;
 if(!CopyRates(_Symbol,PERIOD_M1,iLastBarIndexOfPreDay,iFirstBarIndexOfPreDay-iLastBarIndexOfPreDay+1,aRatesM1))return false;;

 return true;
}

Das Problem ist dann in der Methode getRatesOdDay() in dieser Zeile

if(!CopyRates(_Symbol,PERIOD_D1,iIndexOfDay,2,ratesD1)) return false;

Weil ich bin auf die Tageskerzen angewiesen und wenn der Indikator bspw. auf dem M15 Chart ist, bekomme ich immer beim Start des Metatraders erst mal keine Kerzen vom D1 und somit ist das Array ratesD1[] leer.

Dadurch können die Zeilen danach auch nicht verarbeitet werden und dann knallt es natürlich :-) . Wenn der Markt offen ist und man zieht den Indikator frisch in den Chart, ist alles kein Problem oder wenn man mehrfach das Zeitfenster wechselt, funktioniert es auch.

Ich kann mir aktuell nicht erklären woran das liegt. Daher war meine Idee, irgendwas zu entwickeln, damit der Indikator einfach auf ein paar Werte warten soll und erst dann sich aufbauen soll und erst dann die Rechtecke einzeichnen soll.

Ich hatte in der Methode onCalculate eine DO-Schleife entwickelt, die erst verlassen wird, wenn die D1 Daten vorhanden sind, aber damit habe ich ein Deadlock :-) weil er lädt die Daten des D1 schon gar nicht, solange der Indikator in der Schleife hängt :-) .

Hoffe es wurde etwas verständlicher :-) .

Vielen Dank Euch!

Carl Schreiber
Moderator
11659
Carl Schreiber  

Warum alles selber noch mal machen, wenn es das schon (so ähnlich) gibt?

Such mal unter Trade Session in der Codebase: https://www.mql5.com/de/search#!keyword=Trade%20session

Den Code von dort nehmen und etwas anpassen - ist einfache, schneller, man macht weniger Fehler durch und lernt noch ein bissen :)

Phoenix-Trinity
74
Phoenix-Trinity  

Da hast du natürlich recht :-) .

Learning by doing ... ich probiere es mal mit dieser Ausrede :-P .

Vielen Dank dafür, ich schaue mal, ob ich an dem Code-Beispiel konkret auf meinen eigenen Fehler komme.