Indikator zu langsam

Claudius Marius Walter
629
Claudius Marius Walter  

Hallo ihr Lieben!

bastle gerade an einem Custom Indicator herum.

Der Indikator funktioniert rein logisch einwadnfrei. Für die Berechnung des Indikators habe ich ein Custom Symbol erstellt. Ich arbeite mit dem TickVol[] Array, das sonst üblicherweise leer ist.

Weiterhin wird über das TickVol[] noch die Standardabweichung berechnet.

Mein problem ist, dass der EA 10x so lange als sonst für eine Optimierung braucht. Nach einer Performance analyse kam leider auch nicht viel mehr heraus:



Kann es sein, dass ich bei den Array Resize etwas geschlampt habe oder wo liegt denn das Problem?

Claudius Marius Walter
629
Claudius Marius Walter  

Bin selbst gerade auf folgenden Beitrag gestoßen:


https://www.mql5.com/de/articles/270

Dennoch würde ich mich über eure Unterstützung freuen!

3 Methoden zur Beschleunigung von Indikatoren anhand des Beispiels der linearen Regression
3 Methoden zur Beschleunigung von Indikatoren anhand des Beispiels der linearen Regression
  • www.mql5.com
Dieser Beitrag behandelt die Methoden zur Optimierung der Berechnungsalgorithmen von Indikatoren. Jeder wird eine Methode finden, der seine/ihre Anforderungen am besten erfüllt. Drei Methoden werden hier beschrieben. Eine ist ziemlich simpel, die zweite erfordert solide mathematische Kenntnisse und die dritte benötigt einen gewissen Scharfsinn. Für die Realisierung der meisten beschriebenen Methoden werden Indikatoren oder Designmerkmale des MetaTrader 5 Terminals verwendet. Die Methoden sind weitestgehend universell einsatzfähig und können nicht nur für die Beschleunigung der Berechnung der linearen Regression verwendet werden, sondern auch für viele andere Indikatoren.
Carl Schreiber
Moderator
12354
Carl Schreiber  

Kennst Du das Profiling? Im Editor Debug => Profiling mit hist. Daten.

Aber so auf den ersten Blick hat Du zu viele Schleifen und Schleifen in Schleifen.

Dominik Egert
1727
Dominik Egert  
Dein Fehler:

for(int i =0; ...)

Mal sehen ob du drauf kommst..
Dominik Egert
1727
Dominik Egert  
Zeile 104 sollte außerhalb von for(){} sein und 105 ist nicht erforderlich wenn Zeile 99 richtig ist. Zeile 104 ist dann auch obsolet.

Claudius Marius Walter
629
Claudius Marius Walter  
Carl Schreiber:

Kennst Du das Profiling? Im Editor Debug => Profiling mit hist. Daten.

Aber so auf den ersten Blick hat Du zu viele Schleifen und Schleifen in Schleifen.

Das Profiling habe ich angewendet (siehe erster Post). Eventuell habe ich es nicht korrekt verwendet..

Dominik Egert:
Dein Fehler:

for(int i =0; ...)

Mal sehen ob du drauf kommst..

ich vermute du meinst, dass ich rates_total verwendet habe und der algo somit nach jedem tick die kompletten bars berechnet? Danke!
Habe das ausgebessert, sodass er nach jedem Tick, nurnoch die neueste Kerze berechnet.

Desweiteren habe ich die for-Schleifen weitestgehend eliminiert. Es werden lediglich die ersten Kerzen bis zur Erreichung der Std_Periode mit einer for-Schleife berechnet. Danach  arbeitet das Programm nurnoch mit Array´s.

Hierbei wird nach jedem Tick, oder nach jedem Schleifendurchlauf i das Pink markierte Feld (siehe Abbildung) vom Array subtrahiert und das Blaue addiert. Somit werden nurnoch zwei Berechnungen, statt 10 (bei int Std_Periode = 10) benötigt.

der schnellere Indikator berechnet in etwa die selben Werte wie der alte, langsame Indikator (vermutlich kommen die geringen Abweichungen von Rundingsfehlern).


Sobald ich den Indikator teste, treten Probleme bei der Berechnung neuer Kerzen auf. der Indikator zeigt nichts mehr an, sobald die neu berechneten Kerzen im Chart auftauchen..



//int limit =rates_total ;
   int limit = rates_total - prev_calculated;
   if(limit == 0) limit++;


 for(int i = 0 ; i < limit && !IsStopped(); i++)  
     { 
       if(i<1)continue;
       forceIndex[i] = (close[i] - close[i-1]) * (double)tick_volume[i];
      
       
       
       
       if(i<Std_Periode)continue;
        if(i==Std_Periode) 
         sumForceIndex[i]= 0;
         { 
          for(int r = i - Std_Periode ; r < i ; r++)  // berechne die ersten Std_Periode Kerzen 
           {
            sumForceIndex[i] = sumForceIndex[i] + MathAbs(forceIndex[r]); 
           }
         }
         
         if(i>Std_Periode)  // subtrahiere von der vorherigen Summe den force Index (Pinker Wert in Abbildung) und addiere den blauen force Index Wert
          { 
           //sumForceIndex[i]= 0;
           sumForceIndex[i] =  MathAbs( sumForceIndex[i-1] - MathAbs(forceIndex[i-(Std_Periode+1)]) + MathAbs(forceIndex[i-1])) ;  
          }
         meanvalue[i] = 0; 
         meanvalue[i] = sumForceIndex[i]/Std_Periode; 
      
      
      
        sumForceIndexMeanvalue[i] = 0; 
        if(i<=2*Std_Periode)   // bilde die Summe des Mittelwertes für die ersten Std_Perioden
          {
           for(int l = i - Std_Periode; l < i ; l++)  // l = i-21 = 0, ; l < 20; l++
            {
             sumForceIndexMeanvalue[i] = sumForceIndexMeanvalue[i] + ( MathPow((forceIndex[l] - meanvalue[l]),2)/ (Std_Periode-1) );
            }
          }      
          
        
        if(i>2*Std_Periode)  // subtrahiere von der vorherigen Summe den letzten Wert und addiere den neuesten Wert hinzu
         {
          //sumForceIndexMeanvalue[i] = 0;
          sumForceIndexMeanvalue[i] = sumForceIndexMeanvalue[i-1] - (MathPow((forceIndex[i-(Std_Periode+1)] - meanvalue[i-(Std_Periode+1)]),2)/ (Std_Periode-1)) + (MathPow((forceIndex[i-1] - meanvalue[i-1]),2)/ (Std_Periode-1));
         } 
          stdDeviationPos[i] =  (sqrt(sumForceIndexMeanvalue[i]))+HShift;
          stdDeviationNeg[i] =   stdDeviationPos[i]*(-1);
     }
   return(rates_total);
  }


Carl Schreiber
Moderator
12354
Carl Schreiber  
Das ist doch perfekt um es mit dem Debugger zu prüfen: if (limit - 1 < 2) DebugBreak();
Dominik Egert
1727
Dominik Egert  
Ich habe nicht ganz nachvollzogen was du gemacht hast.

Mein Gedanke war:

for (int i = limit; ...)

Damit sind auch die Zeilen 104 und 105 aus dem OP hinfällig.

Zeile 96 wäre dann:

if(limit < Std_Periode)
{ limit = Std_Periode; }

Das sollte dann auch deine anderen Errungenschaften abdecken.
Dominik Egert
1727
Dominik Egert  
Ich sehe 2 for Schleifen, die den gleichen Bereich abdecken, diese kannst du theoretisch zusammenfassen zu einer Schleife.

Du benutzt mehr MathAbs als notwendig.

Ansonsten ist das schon gut optimiert.

Ich glaube allerdings, du berechnest aktuell die falschen Daten.

Die Zähler scheinen nicht zu stimmen und daher nimmst du immer Werte aus der Vergangenheit (ganz vom Anfang) und bleibst mit der Berechnung auch da.

Ich sehe keine ArrayAsSeries... Deswegen vermute ich das.
Dominik Egert
1727
Dominik Egert  
Die "Ringbuffer-Sum" die du zur Berechnung verwendest finde ich recht innovativ. So berechnet man auch Durchschnitte sehr schnell.

Habe die Technik verstanden. Guter Lösungsansatz.

Hirn statt Code. Das machen gute Programmierer.
Dominik Egert
1727
Dominik Egert  
Das dritte if-Statement in der For Schleife ist unklar geklammert.

Hier glaube ich ist ein Fehler.
Ich benutze grundsätzlich Klammern. Immer. Keine Ausnahme.

Hilft mir sehr.