Die Konstruktion der fraktalen Linien

Shashev Sergei | 10 Februar, 2016

Einführung

Fraktale werden fast von allen Händlern verwendet. Allerdings, wenn man sie fragt, was ein Fraktal ist, werden sie bestens antworten, dass es ein Indikator aus dem Bill Williams System ist. Die fortgeschrittenen Trader sagen, dass es sich um eine Reihe von 5 Bars handelt, wo Up-Fraktal ist es, wenn High des mittleren Bars höher ist als bei den anderen Bars in der Reihe, und wenn Low des mittleren Bars niedriger ist als bei den anderen Bars, ist es ein Down-Fraktal. Wie sagt man: "Das ist alles, was ich über den Krieg erzählen kann."

Eine kurze Beschreibung von Fraktalen, insbesondere von deren Art und Nutzung, ist im Bill Williams Buch “New Trading Dimensions” geschrieben. Etwas noch dazu kann man auch im Chekulaevs Artikels «Fraktale» finden. Mathematisch wurden Fraktale im Shiryaevs Buch - «Grundlagen der Stochastik Mathematik» beschrieben.

Die Anwendung der Fraktale

Es gibt zwei Arten von dem fraktalen Eindringen - eine einfache Art ist, wenn der Preis den Up-Fraktal überschreitet (niedriger als Down-Fraktal). In diesem Fall wäre es besser, auf den Schlusskurs zu warten und eine Position bei der nächsten Barseröffnung zu öffnen.


Die jeweiligen Fraktale Buy und Sell sind im mit Pfeilen markiert worden. Da haben wir das einfache fraktale Eindringen betrachtet. Ein kompliziertes Eindringen verwendet 2 Fraktale - die letzte und die vorletzte. Es wird durch ihnen eine gerade Linie gezogen, die durch den Schlusskurs eingedrungen werden muss.



Der Eingangspunkt wird durch blaue und rote Pfeile markiert, wenn die fraktale Linie eingedrungen werden. Die Sprache MQL4 wird uns helfen, besser die fraktale Ideologie zu verstehen.


Lassen Sie uns die Aufgabe definieren, um Fraktale zu testen.

ziehen Fraktale buy/sell

Das ist das elementarste Teil. Wir sollten auch den Indikator iFractal in MQL4 (in Omega hatte ich diesen Indikator selbst geschrieben, und es war ziemlich schwierig, aufgrund von Omega-Eigenschaften) berücksichtigen. Die Beispiele, wie dieser Indikator geschrieben werden kann, finden Sie in Code Base.

ziehen horizontal durchdringenden Ebenen

Lassen Sie uns standarten horizontalen Linien verwenden. Wir werden den Preis von einem Fraktal als Preise-Koordinaten eingeben - das Datum der fraktalen Bildung und die aktuelle Zeit werden eingegeben als vorübergehenden Koordinaten.

ObjectCreate("SimpleUp"+Up,OBJ_TREND,0,bufUpDate[Up],
             bufUpPrice[Up],Time[i-1],bufUpPrice[Up]);
ObjectSet("SimpleUp"+Up,OBJPROP_COLOR,Aqua);
ObjectSet("SimpleUp"+Up,OBJPROP_RAY,True);

Fractal-Linien

Der einfachste Weg scheint hier - zwei Punkte durch Trendlinien zu zeichnen. Wir machen einen Strahl von der Linie und warten Sie auf Eindringen. Aber ist es nicht in der Tat möglich, den Schlusspreis und Wert des Preises auf der fraktalen Linie zu vergleichen, denn die Funktion ObjectGet kann nur Werte der Punkten zurückliefern, welche die fraktale Linie gebildet haben. Also, was sollen wir tun?

Erstmal an die analytische Geometrie zurückerinnern. Wir haben zwei Punkte, so haben wir eine lineare Gleichung. Und da wir die Zeit-Koordinaten kennen, können wir den Wert des Preises aus der Geradengleichung leicht erhalten. Die kanonische lineare Gleichung sieht so aus:


Wir ersetzen Preis und Zeitpunkt statt х und у. Die Realisierung davon ist in der Funktion LevelCalculate gegeben, welche die Eindringen-Ebene berechnet und zugleich wird diese Funktion neue Koordinaten der fraktalen Linien definieren, die mit Hilfe der Funktion ObjectSet gesetzt werden.

ObjectCreate("LineUp"+Up,OBJ_TREND,0,bufUpDate[Up],
             bufUpPrice[Up],bufUpDate[Up-1],bufUpPrice[Up-1]); 
ObjectSet("LineUp"+Up,OBJPROP_COLOR,Blue);
ObjectSet("LineUp"+Up,OBJPROP_RAY,False);

Pfeile setzen

Wir bauen alle erforderlichen Linien und dann vergleichen sie zu den aktuellen Preisen. Wenn es eine einfache Linie eindringt, setzen wir einen gelben Pfeil. Wenn es eine fraktale Linie eindringt, dann wird der blau Pfeil für Buy sein, und für Sell - rot.

All das wird als Indikator FractalLines.mq4 realisiert.

//+------------------------------------------------------------------+
//|                                                 FractalLines.mq4 |
//|                      Copyright © 2006, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
 
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Blue
#property indicator_color2 Red
//---- input parameters
extern int       lines=5;  //The amount of visible fractal lines
extern int       MaxFractals=10000; // :)
extern bool       ShowHorisontalLines=true;
extern bool       ShowFractalLines=true; 
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
//--- my variables
double bufUpPrice[10000];  //price array of Up fractals
double bufUpDate[10000];   //date array of Up fractals
double bufDownPrice[10000];   //price array of Down fractals
double bufDownDate[10000]; //date array of Down fractals
int Up = 0; //counter of Up fractals
int Down = 0;  //counter of Down fractals
 
//The function calculates the price value of penetration of the fractal line by the simplest
//equations of analytic geometry
double LevelCalculate(double Price1, double Time1, double Price2, 
                     double Time2, double NewTime)
{
   double level;
   if (Time2!=Time1)// Just in case, to avoid zero divide.
   {
      level=(NewTime-Time1)*(Price2-Price1)/(Time2-Time1)+Price1;
   }
   else
   { 
      return(Price2);
   }
   return(level);
}
 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_ARROW);
   SetIndexArrow(0,217);
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexEmptyValue(0,0.0);
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,218);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexEmptyValue(1,0.0);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//---- the last calculated bar will be recalculated   
   if(counted_bars > 0) 
       counted_bars--;
   int limit = Bars - counted_bars;
// We will rather place arrows at the moment of penetration of fractal lines, 
// estimate efficiency
 // The idea was borrowed from Rosh, hopefully he will not be offended by this :)    
  string arrowName; // here, we will give the arrow a unique name
  
  //The number of the penetrated fractal
  //Penetration of the fractal line
  int FractalUp = 0;
  int FractalDown = 0;
  //Simple penetration of a fractal
  int SimpleFractalUp = 0;
  int SimpleFractalDown = 0;
  
  double BuyFractalLevel = 0;  //penetration level of the Up fractal line
  double SellFractalLevel = 0; //penetration level of the Down fractal line
  double buf = 0; // buffer value of fractal being available; if it is 0, there is no fractal at all
 
//---- the main loop       
   for(int i = limit; i>0; i--)
   {   
   
       //Draw simple fractal levels
       
       //Define the current fractal levels 
 
         BuyFractalLevel=LevelCalculate(bufUpPrice[Up],bufUpDate[Up],
                   bufUpPrice[Up-1],bufUpDate[Up-1],Time[i]);
         //Move the second coordinate of the Up fractal line                              
         ObjectSet("LineUp"+Up,OBJPROP_TIME1,Time[i]);
         ObjectSet("LineUp"+Up,OBJPROP_PRICE1,BuyFractalLevel); 
         SellFractalLevel=LevelCalculate(bufDownPrice[Down],
                          bufDownDate[Down],bufDownPrice[Down-1],
                          bufDownDate[Down-1],Time[i]);
         //Move the second coordinate of the Down fractal line                               
         ObjectSet("LineDown"+Down,OBJPROP_TIME1,Time[i]);
         ObjectSet("LineDown"+Down,OBJPROP_PRICE1,SellFractalLevel);
         
      //Search for a simple penetration
         if (Close[i]>ObjectGet("SimpleUp"+Up,OBJPROP_PRICE1)&&
                          (Up>SimpleFractalUp))
         {
            arrowName="SimleUpArrow"+Up;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         Low[i-1]-Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,241);
            ObjectSet(arrowName,OBJPROP_COLOR,Yellow);
            SimpleFractalUp=Up;             
         }
         
         if (Close[i]<ObjectGet("SimpleDown"+Down,OBJPROP_PRICE1)&&
                          (Down>SimpleFractalDown))
         {
            arrowName="SimleUpArrow"+Down;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         High[i-1]+Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,242);
            ObjectSet(arrowName,OBJPROP_COLOR,Yellow);
            SimpleFractalDown=Down;             
         }                                                                                                                          
 
      //Search for a complex penetration
        if ((Close[i]>BuyFractalLevel)&&(Up>FractalUp)) 
         {
            //Put an up-arrow
            arrowName="UpArrow"+Up;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         Low[i-1]-Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,241);
            ObjectSet(arrowName,OBJPROP_COLOR,Blue);
            FractalUp=Up;        
         }
                                          
        if ((Close[i]<SellFractalLevel)&&(Down>FractalDown))
         {
            //Put a down-arrow
            arrowName="DownArrow"+Down;
            ObjectCreate(arrowName,OBJ_ARROW,0,Time[i-1],
                         High[i-1]+Point*10);
            ObjectSet(arrowName,OBJPROP_ARROWCODE,242);
            ObjectSet(arrowName,OBJPROP_COLOR,Red); 
            FractalDown=Down;       
         }
        //Draw the Up fractal itself
        ExtMapBuffer1[i] = iFractals(NULL, 0, MODE_UPPER, i);
        
        //If it is available, place it in the array of fractals
        buf = iFractals(NULL, 0, MODE_UPPER, i);
        if (buf!=0)
        {
            Up++;
            bufUpPrice[Up]=iFractals(NULL, 0, MODE_UPPER, i);
            bufUpDate[Up]=Time[i];
            //The current fractal penetration level - fractal itself
            BuyFractalLevel=bufUpPrice[Up];
            
            if (Up>1)
            
            {
               //Simple fractal
               ObjectCreate("SimpleUp"+Up,OBJ_TREND,0,bufUpDate[Up],
                   bufUpPrice[Up],Time[i-1],bufUpPrice[Up]);
      ObjectSet("SimpleUp"+Up,OBJPROP_COLOR,Aqua);
      ObjectSet("SimpleUp"+Up,OBJPROP_RAY,True);   
               //Draw fractal lines on 2 coordinates
               ObjectCreate("LineUp"+Up,OBJ_TREND,0,bufUpDate[Up],
                  bufUpPrice[Up],bufUpDate[Up-1],bufUpPrice[Up-1]); 
      ObjectSet("LineUp"+Up,OBJPROP_COLOR,Blue);
      ObjectSet("LineUp"+Up,OBJPROP_RAY,False);
               //Remove the outdated lines
               if (Up>lines+1)
               {
                  ObjectDelete("LineUp"+(Up-lines));
                  ObjectDelete("SimpleUp"+(Up-lines));                  
               }
            }     
        }
         //A similar block, but for Down fractals
        ExtMapBuffer2[i] = iFractals(NULL, 0, MODE_LOWER, i);
        buf = iFractals(NULL, 0, MODE_LOWER, i);    
        if (buf!=0)
        {
            Down++;
            bufDownPrice[Down]=iFractals(NULL, 0, MODE_LOWER, i);
            bufDownDate[Down]=Time[i];
            SellFractalLevel=bufDownPrice[Down];
                                         
            if (Down>1)
            
            {
               ObjectCreate("SimpleDown"+Down,OBJ_TREND,0,bufDownDate[Down],
                   bufDownPrice[Down],Time[i-1],bufDownPrice[Down]);        
               ObjectSet("SimpleDown"+Down,OBJPROP_COLOR,LightCoral);
               ObjectSet("SimpleDown"+Down,OBJPROP_RAY,True);
                                  
               ObjectCreate("LineDown"+Down,OBJ_TREND,0,
                            bufDownDate[Down],bufDownPrice[Down],
                            bufDownDate[Down-1],bufDownPrice[Down-1]);        
               ObjectSet("LineDown"+Down,OBJPROP_COLOR,Red);
               ObjectSet("LineDown"+Down,OBJPROP_RAY,False);
               if (Down>lines+1)
               {
                  ObjectDelete("LineDown"+(Down-lines));
                  ObjectDelete("SimpleDown"+(Down-lines));
               }            
            }
     
        }           
        if (!ShowHorisontalLines)
        {   
            ObjectDelete("SimpleDown"+Down);              
            ObjectDelete("SimpleUp"+Up);                
        }
        if (!ShowFractalLines)
        {
            ObjectDelete("LineDown"+Down);        
            ObjectDelete("LineUp"+Up);
        }          
     }   
//----
   return(0);
  }
//+----------------------------------------------------------------- 

Alte Linien müssen entfernt werden, da sonst das Chart wie eine Palette aussehen wird. Es gibt ein paar zusätzlichen Einstellungen, wie die Sichtbarkeit der verschiedenen Linien oder ihre Anzahl. Das Ergebnis der Aktivitäten des Indikators ist unten gegeben.





Unwechselbares Mittel für diejenigen, die Fraktale lieben!