Line crossing not detected

 

Hi coders,


I am about to code my first EA. One of the basics is detecting line crossing.

My draft program detects them nearly always, but not 100%, although the code is quite simple:


// the first line crosses the second from down to up
bool line_crossing_down_up(double line1_prev, double line2_prev, double line1_cur, double line2_cur){
   if(line1_prev < line2_prev && line1_cur >= line2_cur) return true;
      else return false;
   }
// the first line crosses the second from up to down
bool line_crossing_up_down(double line1_prev, double line2_prev, double line1_cur, double line2_cur){
   if(line1_prev > line2_prev && line1_cur <= line2_cur) return true;
      else return false;

In the two pictures added, you can see in the data window that at time = 03:00 triggerline is under trendline and 03:15 triggerline is above trendline. Nevertheless the crossing is not detected. May it be caused by the small difference between trigger and trend in 03.15 (0.00005)?


If yes, what have I to do to fix the bug?


Thank you in advance.


Kurt

Dateien:
 

Hallo,

  1. wir können hier Deutsch sprechen :)
  2. Code und auch Pseudocode als Code editieren, entweder mit </> aus der Editierzeile oder mit Alt+S.
  3. Aus dem bisschen Code ist der Fehler nicht ersichtlich.
  4. Such mal hier nach Ma crossing in der CodeBase (linke Spalte): https://www.mql5.com/de/code/21515
    Von funktionierenden Beispielen auszugehen ist schneller und weniger frustrierend!
Crossing Moving Average
Crossing Moving Average
  • www.mql5.com
Der EA basiert auf zwei iMAs (gleitender Durchschnitt, MA) und dem iMomentum (Momentum) Filter.
 

Hallo Carl,


danke für die Hinweise. Hier noch einige ergänzende Infos:

Ich benutze die Instantaneous Trendlines (Trend und Trigger) nach John F. Ehlers als Custom-Indikator . Das Programm soll zunächst nur die Zuverlässigkeit der Signalentdeckung testen (mehr Code weiter unten).

Dabei habe ich auch - wie Vladimir Karputov (oder Rosh?) - mit Minimalabständen zwischen den Linien experimentiert (ohne gute Ergebnisse).


Hier der Code von Karputov:
if(MA_First[1]>MA_Second[1]+ExtMA_MinimumDistance && MA_First[2]<MA_Second[2]-ExtMA_MinimumDistance)
      if(curMom>InpMOM_Filter && curMom>prevMom)

Hier mein Code:

//+------------------------------------------------------------------+
//| Einzelsignal function                                             |
//+------------------------------------------------------------------+
// die erste Linie kreuzt die zweite von unten nach oben
bool line_crossing_down_up(double line1_prev, double line2_prev, double line1_cur, double line2_cur){
   if(line1_prev < line2_prev && line1_cur >= line2_cur) return true;
      else return false;
   }
// die erste Linie kreuzt die zweite von oben nach unten
bool line_crossing_up_down(double line1_prev, double line2_prev, double line1_cur, double line2_cur){
   if(line1_prev > line2_prev && line1_cur <= line2_cur) return true;
      else return false;
   }
bool line_distance_too_small(double line1, double line2){
   if(MathAbs(line2 - line1)< 0.00001) return true;
      else return false;
}

Was ich nicht verstehe, ist, warum man diese Berücksichtigung eines Minimalabstandes überhaupt braucht, wenn die Werte, die gerechnet werden eindeutig (wenn auch minimal) über oder unter einander liegen (siehe die Bilder mit den Datenfenstern).

Hier nochmal - wie gewünscht - der Code im Kontext:

void OnTick()
  {
//---
   static datetime timestamp=0;                   // bewirkt, dass nur bei abgeschlossener Kerze agiert wird
   datetime time = iTime(_Symbol,_Period,0);
   
   if(time != timestamp){
      timestamp = time;
      // kopiert die Werte aus den Custom-Indicators in die Buffer und setzt sie als Serie
      CopyBuffer(LaGuerre_Handle,0,0,3,LaGuerre_Buffer);     
      CopyBuffer(Instant_Linien_Handle,0,0,3,Instant_Linien_Buffer1); // Trendline
      CopyBuffer(Instant_Linien_Handle,1,0,3,Instant_Linien_Buffer2); // Triggerline
     
      ArraySetAsSeries(LaGuerre_Buffer,true);
      ArraySetAsSeries(Instant_Linien_Buffer1,true);
      ArraySetAsSeries(Instant_Linien_Buffer2,true);
      
      
      // Umbenennung der Werte:
      double LaGuerre_cur = LaGuerre_Buffer[0];
      double LaGuerre_prev1 = LaGuerre_Buffer[1];
      double LaGuerre_prev2 = LaGuerre_Buffer[2];
      double Trend_cur = Instant_Linien_Buffer1[0];
      double Trend_prev1 = Instant_Linien_Buffer1[1];
      double Trend_prev2 = Instant_Linien_Buffer1[2];
      double Trigger_cur = Instant_Linien_Buffer2[0];
      double Trigger_prev1 = Instant_Linien_Buffer2[1];
      double Trigger_prev2 = Instant_Linien_Buffer2[2];
                  
      // Aufrufen der Signal_Check_Funktion :
      string trade_action = "";
      trade_action = getOrderfromSignal(LaGuerre_cur,
                                        LaGuerre_prev1,
                                        LaGuerre_prev2,
                                        Trigger_cur,
                                        Trigger_prev1,
                                        Trigger_prev2,
                                        Trend_cur,
                                        Trend_prev1,
                                        Trend_prev2
                                        
                                        );
      
          if(trade_action == "draw_long" )DrawDot("long");
          if(trade_action == "draw_short" )DrawDot("short");
       
           
      } // time != timestamp
   return;
  }

//+------------------------------------------------------------------+
//| Signalerkennung                                            |
//+------------------------------------------------------------------+
string getOrderfromSignal(   double laguerre_cur,
                             double laguerre_prev1,
                             double laguerre_prev2,
                             double trigger_cur,
                             double trigger_prev1,
                             double trigger_prev2,
                             double trend_cur,
                             double trend_prev1,
                             double trend_prev2)
          {
                             
    string todo= "";        
                  
         if      (line_crossing_up_down (trigger_prev1, trend_prev1,trigger_cur, trend_cur))  todo = "draw_short";
         else if (line_crossing_down_up (trigger_prev1, trend_prev1,trigger_cur, trend_cur))  todo = "draw_long";
         // zur Sicherheit:
         else todo = ""; 
    
    return todo;
   
        }
 //+------------------------------------------------------------------+
//| Einzelsignal Function                                             |
//+------------------------------------------------------------------+
// die erste Linie kreuzt die zweite von unten nach oben
bool line_crossing_down_up(double line1_prev, double line2_prev, double line1_cur, double line2_cur){
   if(line1_prev < line2_prev && line1_cur >= line2_cur) return true;
      else return false;
   }
// die erste Linie kreuzt die zweite von oben nach unten
bool line_crossing_up_down(double line1_prev, double line2_prev, double line1_cur, double line2_cur){
   if(line1_prev > line2_prev && line1_cur <= line2_cur) return true;
      else return false;
   }
 // wird gegenwärtig nicht benutzt:
bool line_distance_too_small(double line1, double line2){
   if(MathAbs(line2 - line1)< 0.00001) return true;
      else return false;
}

Gibt es einen Thread über verschiedene Methoden der Line-crossing-Methoden? Karputov schreibt ja: "Das Kreuzen ist sehr einfach umgesetzt (vieleicht nicht die genaueste Methode, aber die einfachste) "

Beste Grüße

Kurt

 
Was ich nicht verstehe, ist, warum man diese Berücksichtigung eines Minimalabstandes überhaupt braucht, wenn die Werte, die gerechnet werden eindeutig (wenn auch minimal) über oder unter einander liegen (siehe die Bilder mit den Datenfenstern)

Ganz einfach, wenn es keinen Abstand gibt, würde, wenn der Preis oder der Indikator sich gerade bei dem Preislevel eher seitwärts bewegt, ständig auf, dann ab, dann wieder auf etc. ausgelöst werden. Eine andere Lösung wäre, wenn der Indikator sich erst dann bewegt, wenn seine Veränderung einen Schwellenwert überschreitet.

 
Kenn da jemand mit nem guten Artikel darüber :p

https://www.mql5.com/de/articles/9527
Clusteranalyse (Teil I): Die Steigung von Indikatorlinien
Clusteranalyse (Teil I): Die Steigung von Indikatorlinien
  • www.mql5.com
Die Clusteranalyse ist eines der wichtigsten Elemente der künstlichen Intelligenz. In diesem Artikel versuche ich, mit der Clusteranalyse die Steigung eines Indikators zu analysieren, um Schwellenwerte zu erhalten für die Bestimmung, ob ein Markt sich seitwärts bewegt (flat) oder ob er einem Trend folgt.
 

Vielen Dank für Eure Hinweise. Was ich meinte: bevor ich anfange, Signale wegzufiltern (wegen Flatmarket oder aus sonstigem Grund), würde ich gerne sicherstellen, dass Linecrossing zuverlässig gefunden wird. Dies sollte doch eigentlich möglich sein, wenn die gerechneten Werte (Indikatorwertepaar1 in t0 und Indikatorwertepaar t-1) eindeutig sind.

 
https://www.mql5.com/de/articles/654
Abschnitt 2.) Debugging wäre glaube ich was für Dich.
 
pennyhunter #:
https://www.mql5.com/de/articles/654
Abschnitt 2.) Debugging wäre glaube ich was für Dich.
Danke, ich versuch es.
 
Brazzelhuber #:
Danke, ich versuch es.

Ach warte mal:

https://www.youtube.com/watch?v=DeuSixlmvDs&amp;t=492s

Ich meine das geht auch mit HLines