English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Tracciare linee di tendenza basate su frattali utilizzando MQL4 e MQL5

Tracciare linee di tendenza basate su frattali utilizzando MQL4 e MQL5

MetaTrader 5Trading | 12 gennaio 2022, 11:40
373 0
Almat Kaldybay
Almat Kaldybay

Sommario


Introduzione

Ultimamente, mi capita di pensare di utilizzare le linee di tendenza. C'è la questione della scelta di un metodo per determinare i punti per tracciare le linee e anche della precisione del tracciato. Ho deciso di usare i frattali come base.

Analizzo spesso i mercati nel mio lavoro principale, dove posso dedicare del tempo al trading. Inoltre, non puoi semplicemente tracciare le linee su un intervallo di tempo più ampio: la linea dovrebbe essere tracciata da punti estremi con una precisione fino a 15 minuti. La ragione di ciò è che il tempo frattale su un intervallo di tempo più ampio non sempre corrisponde al tempo dello stesso punto estremo su M15. E’ qui che l'automazione viene in aiuto. È successo che ho iniziato a scrivere il codice usando MQL5 e poi sono passato a MQL4, perché avevo bisogno di questo programma per MetaTrader 4.

In questo articolo ho presentato la mia soluzione al problema utilizzando MQL4 e MQL5. L'articolo fornisce una visione comparativa, ma sarebbe inappropriato confrontare qui l'efficienza di MQL4 e MQL5. Inoltre, capisco che probabilmente ci sono altre soluzioni, più efficaci della mia. L'articolo può essere utile ai principianti che scrivono script utilizzando MQL4 o MQL5, in particolare a coloro che intendono utilizzare frattali e linee di tendenza.


1. Parametri di input, funzione DeInit() e dichiarazione iniziale delle variabili

Ho usato le seguenti variabili come parametri di input:

input color Resistance_Color=Red;       // setting the resistance line color
input ENUM_LINE_STYLE Resistance_Style; // setting the resistance line style
input int Resistance_Width=1;           // setting the resistance line width
input color Support_Color=Red;          // setting the support line color
input ENUM_LINE_STYLE Support_Style;    // setting the support line style
input int Support_Width=1;              // setting the support line width

Questi parametri sono gli stessi per MQL4 e MQL5.

In MQL5 dobbiamo creare l'indicatore in anticipo:

//--- iFractals indicator handle 
int Fractal;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- getting the iFractals indicator handle
   Fractal=iFractals(Symbol(),PERIOD_D1);
//---
   return(INIT_SUCCEEDED);
  }

Poiché il programma disegnerà oggetti grafici, ha senso rimuoverli quando si rimuove l'Expert Advisor dal grafico:

void OnDeinit(const int reason)
  {
   ObjectDelete(0,"TL_Resistance");
   ObjectDelete(0,"TL_Support");
  }

Tracciare due linee (supporto e resistenza) richiede quattro punti. Per determinare il punto di passaggio della linea abbiamo bisogno di conoscere il tempo e il prezzo.

Le coordinate sono determinate in questo ordine: per prima cosa troviamo la barra estrema, conoscendo la barra estrema possiamo determinare il prezzo e il tempo del punto estremo.

Dichiarazione delle variabili nella funzione OnTick():

MQL4
//--- declaration of variables
int n,UpperFractal_1,UpperFractal_2,LowerFractal_1,LowerFractal_2;
MQL5
//--- declaration of variables
int n,UpperFractal_1,UpperFractal_2,LowerFractal_1,LowerFractal_2;
//--- declaring the arrays for writing values of the iFractal indicator buffer
double FractalDown[],FractalUp[];
double UpFractal_1,UpFractal_2,LowFractal_1,LowFractal_2;

Prima di tutto, ho dichiarato solo quelle variabili che memorizzano indici di barre con frattali formati.

In MQL4:

  1. n - la variabile è necessaria per trovare il frattale noto più vicino utilizzando l'operatore for loop;
  2. UpperFractal_1, UpperFractal_2, LowerFractal_1, LowerFractal_2 - queste variabili memorizzeranno l'indice di una barra al primo e al secondo punto estremo più vicino con il prezzo più alto/più basso (in termini di determinazione dei frattali);

In MQL5 introduciamo variabili aggiuntive:

  1. FractalDown[],FractalUp[]; - dichiarare array di valori double per memorizzare i valori del buffer dell'indicatore iFractals;
  2. Successivamente, le variabili di doppio tipo: UpFractal_1,UpFractal_2,LowFractal_1,LowFractal_2. Memorizzeranno i valori di prezzo dei punti estremi.

2. Ricerca dei frattali più vicini

Per trovare l'indice di una barra con un frattale formato usiamo l'operatore for loop.

Determiniamo gli indici delle prime due barre che corrispondono al primo e al secondo frattale superiore:

MQL4
//--- finding the bar index of the first nearest upper fractal
   for(n=0; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_UPPER,n)!=NULL)
         break;
      UpperFractal_1=n+1;
     }
//--- finding the bar index of the second nearest upper fractal
   for(n=UpperFractal_1+1; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_UPPER,n)!=NULL)
         break;
      UpperFractal_2=n+1;
     }
 MQL5
//--- first, we need to write the Fractal indicator buffer values into the arrays
//--- filling arrays with buffer values
   CopyBuffer(Fractal,0,TimeCurrent(),Bars(Symbol(),PERIOD_D1),FractalUp);
   CopyBuffer(Fractal,1,TimeCurrent(),Bars(Symbol(),PERIOD_D1),FractalDown);
//--- indexing like in timeseries
   ArraySetAsSeries(FractalUp,true);
   ArraySetAsSeries(FractalDown,true);
//--- next, we use the for loop operator to find the first upper fractal
   for(n=0; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      //--- if the value is not empty, break the loop
      if(FractalUp[n]!=EMPTY_VALUE)
         break;
     }
//--- writing the price value of the first fractal into the variable
   UpFractal_1=FractalUp[n];
//--- writing the index of the first fractal into the variable
   UpperFractal_1=n;
//--- finding the second upper fractal 
   for(n=UpperFractal_1+1; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      if(FractalUp[n]!=EMPTY_VALUE) //if the value is not empty, break the loop
         break;
     }
//--- writing the price value of the second fractal into the variable
   UpFractal_2=FractalUp[n];
//--- writing the index of the second fractal into the variable
   UpperFractal_2=n;

Qui ho dimostrato chiaramente una delle differenze chiave tra MQL5 e MQL4: l'utilizzo delle funzioni per l'accesso alle serie temporali.

In MQL4 ho iniziato subito a trovare l'indice della barra con un frattale formato, ma in MQL5 ho specificato gli array FractalUp[] e FractalDown[] per memorizzare i valori di prezzo dei frattali superiore e inferiore accedendo all'indicatore iFractal con la funzione CopyBuffer(). Successivamente, ho impostato l'indicizzazione di questi array come nelle serie temporali utilizzando la funzione ArraySetAsSeries().

In MQL4 ho ottenuto solo gli indici delle barre con frattali noti, ma in MQL5 ho usato la funzione CopyBuffer() per ottenere gli indici delle barre e i valori dei prezzi dei frattali.

Allo stesso modo, troviamo i primi due frattali inferiori:

MQL4
//--- finding the bar index of the first nearest lower fractal
   for(n=0; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_LOWER,n)!=NULL)
         break;
      LowerFractal_1=n+1;
     }
//--- finding the bar index of the second nearest lower fractal
   for(n=LowerFractal_1+1; n<(Bars-1);n++)
     {
      if(iFractals(NULL,1440,MODE_LOWER,n)!=NULL)
         break;
      LowerFractal_2=n+1;
     }
 MQL5
//--- finding the values of the lower fractals
//--- finding the first lower fractal
   for(n=0; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      //--- if the value is not empty, break the loop
      if(FractalDown[n]!=EMPTY_VALUE)
         break;
     }
//--- writing the price value of the first fractal into the variable
   LowFractal_1=FractalDown[n];
//--- writing the index of the first fractal into the variable
   LowerFractal_1=n;
//--- finding the second lower fractal 
   for(n=LowerFractal_1+1; n<Bars(Symbol(),PERIOD_D1); n++)
     {
      if(FractalDown[n]!=EMPTY_VALUE)
         break;
     }
//--- writing the price value of the second fractal into the variable
   LowFractal_2=FractalDown[n];
//--- writing the index of the second fractal into the variable
   LowerFractal_2=n;

Come vedi, il codice è molto simile in MQL4 e MQL5. C'è una leggera differenza nella sintassi.


3. Determinazione del prezzo e dei valori temporali dei frattali

Per tracciare la linea dobbiamo determinare il tempo e il prezzo di un frattale. Naturalmente, in MQL4 potremmo semplicemente utilizzare le serie temporali predefinite High[] e Low[] e la funzione iTime(), tuttavia abbiamo anche bisogno di ottenere coordinate temporali più precise per garantire il corretto tracciamento della linea di tendenza.

La Fig. 1-2 mostra la differenza tra i valori temporali dei punti estremi sui timeframe H4 e M15.

Fig.1. Il valore temporale del punto estremo su H4

Fig.1. Il valore temporale del punto estremo su H4

Fig.2. Il valore temporale del punto estremo su M15

Fig.2. Il valore temporale del punto estremo su M15

Sono giunto alla conclusione che l'estrema precisione del punto di 15 minuti è abbastanza sufficiente per i miei scopi.

In generale, il principio del chiarimento del punto estremo è quasi lo stesso sia per MQL4 che per MQL5, ma ci sono alcune differenze nei dettagli:

MQL4MQL5
  1. Determinare il valore del punto temporale estremo su un intervallo di tempo più ampio;
  2. Utilizzando il valore di tempo trovato, determinare l'indice della barra estrema su un intervallo di tempo più piccolo con la funzione iBarShift();
  3. Poiché 24 ore possono essere rappresentate come un array di 96 barre da 15 minuti, cerchiamo un punto estremo (il valore più alto/più basso) tra questi 96 elementi utilizzando le funzioni iHigh()iLow()iTime(), ArrayMaximum() and ArrayMinimum().
  1. Determinare il valore del punto temporale estremo su un intervallo di tempo più ampio;
  2. Utilizzando il valore dell'ora trovato, determinare l'ora di generazione della barra del giorno successivo. Abbiamo bisogno di questo valore per l'utilizzo nelle funzioni CopyHigh(), CopyLow() e CopyTime();
  3. Dichiarare e compilare gli array per memorizzare i valori di prezzo e tempo per l'intervallo di 15 minuti;
  4. Utilizzando le funzioni ArrayMaximum() e ArrayMinimum(), trovare i valori di prezzo più basso e più alto e i valori temporali dei punti estremi chiariti. 

Il codice per ogni passaggio è mostrato di seguito:

 MQL4
// Step 1. Determining the extreme point time value on a larger timeframe:
//--- determining the time of fractals
   datetime UpFractalTime_1=iTime(NULL, 1440,UpperFractal_1);
   datetime UpFractalTime_2=iTime(NULL, 1440,UpperFractal_2);
   datetime LowFractalTime_1=iTime(NULL, 1440,LowerFractal_1);
   datetime LowFractalTime_2=iTime(NULL, 1440,LowerFractal_2);
// Step 2.  Determining the index of the extreme bar on a smaller timeframe:   
//--- finding the fractal index on M15
   int UpperFractal_1_m15=iBarShift(NULL, 15, UpFractalTime_1,true);
   int UpperFractal_2_m15=iBarShift(NULL, 15, UpFractalTime_2,true);
   int LowerFractal_1_m15=iBarShift(NULL, 15, LowFractalTime_1,true);
   int LowerFractal_2_m15=iBarShift(NULL, 15, LowFractalTime_2,true);

// Step 3. Using the arrays to find the clarified extreme points on М15:
//--- using the arrays to find the clarified extreme points
//--- introducing the i variable to use in the for loop operator
   int i;
//--- 1. First, find the lower extreme points
//--- 3.1 Finding the first lower extreme point
//--- declaring the array for storing the index values of the bars
   int Lower_1_m15[96];
//--- declaring the array for storing the price values
   double LowerPrice_1_m15[96];
//--- starting the for loop:
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Lower_1_m15[i]=LowerFractal_1_m15-i;
      //--- filling the array with the price values
      LowerPrice_1_m15[i]=iLow(NULL,15,LowerFractal_1_m15-i);
     }
//--- determining the minimum price value in the array
   int LowestPrice_1_m15=ArrayMinimum(LowerPrice_1_m15,WHOLE_ARRAY,0);
//--- determining the bar with the lowest price in the array
   int LowestBar_1_m15=Lower_1_m15[LowestPrice_1_m15];
//--- determining the time of the lowest price bar
   datetime LowestBarTime_1_m15=iTime(NULL,15,Lower_1_m15[LowestPrice_1_m15]);

//--- 3.2 Finding the second lower extreme point
   int Lower_2_m15[96];
   double LowerPrice_2_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Lower_2_m15[i]=LowerFractal_2_m15-i;
      //--- filling the array with the price values
      LowerPrice_2_m15[i]=iLow(NULL,15,LowerFractal_2_m15-i);
     }
//--- determining the minimum price value in the array
   int LowestPrice_2_m15=ArrayMinimum(LowerPrice_2_m15,WHOLE_ARRAY,0);
//--- determining the bar with the lowest price in the array
   int LowestBar_2_m15=Lower_2_m15[LowestPrice_2_m15];
//--- determining the time of the lowest price bar
   datetime LowestBarTime_2_m15=iTime(NULL,15,Lower_2_m15[LowestPrice_2_m15]);

//--- 3.3 Finding the first upper extreme point
   int Upper_1_m15[96];
   double UpperPrice_1_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Upper_1_m15[i]=UpperFractal_1_m15-i;
      //--- filling the array with the price values
      UpperPrice_1_m15[i]=iHigh(NULL,15,UpperFractal_1_m15-i);
     }
//--- determining the maximum price value in the array
   int HighestPrice_1_m15=ArrayMaximum(UpperPrice_1_m15,WHOLE_ARRAY,0);
//--- determining the bar with the highest price in the array
   int HighestBar_1_m15=Upper_1_m15[HighestPrice_1_m15];
//--- determining the time of the highest price bar
   datetime HighestBarTime_1_m15=iTime(NULL,15,Upper_1_m15[HighestPrice_1_m15]);

//--- 3.4 Finding the second upper extreme point
   int Upper_2_m15[96];
   double UpperPrice_2_m15[96];
   for(i=0;i<=95;i++)
     {
      //--- filling the array with the bar index values
      Upper_2_m15[i]=UpperFractal_2_m15-i;
      //--- filling the array with the price values
      UpperPrice_2_m15[i]=iHigh(NULL,15,UpperFractal_2_m15-i);
     }
 MQL5
// Step 1. Determining the extreme point time value on a larger timeframe:
//--- declaring the arrays for storing the time values of the corresponding bar index on a larger timeframe
   datetime UpFractalTime_1[],LowFractalTime_1[],UpFractalTime_2[],LowFractalTime_2[];
//--- determining the time of fractals on a larger timeframe
   CopyTime(Symbol(),PERIOD_D1,UpperFractal_1,1,UpFractalTime_1);
   CopyTime(Symbol(),PERIOD_D1,LowerFractal_1,1,LowFractalTime_1);
   CopyTime(Symbol(),PERIOD_D1,UpperFractal_2,1,UpFractalTime_2);
   CopyTime(Symbol(),PERIOD_D1,LowerFractal_2,1,LowFractalTime_2);

// Step 2. Determining the generation time of the next day bar:
//--- determining the generation time of the next day bar (the stop time for CopyHigh(), CopyLow() and CopyTime())
   datetime UpFractalTime_1_15=UpFractalTime_1[0]+86400;
   datetime UpFractalTime_2_15=UpFractalTime_2[0]+86400;
   datetime LowFractalTime_1_15=LowFractalTime_1[0]+86400;
   datetime LowFractalTime_2_15=LowFractalTime_2[0]+86400;

// Step 3. Declaring and filling the arrays for storing the price and time values for the 15-minute timeframe:   
//--- declaring the arrays for storing the maximum and minimum price values
   double High_1_15[],Low_1_15[],High_2_15[],Low_2_15[];
//--- filling the arrays with the CopyHigh() and CopyLow() functions
   CopyHigh(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15,High_1_15);
   CopyHigh(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15,High_2_15);
   CopyLow(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15,Low_1_15);
   CopyLow(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15,Low_2_15);
//--- declaring the arrays for storing the time values corresponding to the extreme bar indexes  
   datetime High_1_15_time[],High_2_15_time[],Low_1_15_time[],Low_2_15_time[];
//--- filling the arrays
   CopyTime(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15,High_1_15_time);
   CopyTime(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15,High_2_15_time);
   CopyTime(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15,Low_1_15_time);
   CopyTime(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15,Low_2_15_time);
// Step 4. Finding the lowest and highest price values, and the time values of the clarified extreme points:
//--- determining the highest and lowest price and time values with the ArrayMaximum() and ArrayMinimum() functions
   int Max_M15_1=ArrayMaximum(High_1_15,0,96);
   int Max_M15_2=ArrayMaximum(High_2_15,0,96);
   int Min_M15_1=ArrayMinimum(Low_1_15,0,96);
   int Min_M15_2=ArrayMinimum(Low_2_15,0,96);

Alla fine, abbiamo determinato le seguenti coordinate della linea di tendenza:

1. Per la linea di supporto:

MQL4MQL5
  1. Coordinata prima volta - LowestBarTime_2_m15;
  2. Prima coordinata del prezzo - LowerPrice_2_m15[LowestPrice_2_m15];
  3. Coordinata del secondo orario - LowestBarTime_1_m15;
  4. Seconda coordinata del prezzo - LowerPrice_1_m15[LowestPrice_1_m15].
  1. Coordinata del primo tempo - Low_2_15_time[Min_M15_2];
  2. Prima coordinata del prezzo - Low_2_15[Min_M15_2];
  3. Seconda coordinata temporale - Low_1_15_time[Min_M15_1];
  4. Seconda coordinata del prezzo - Basso_1_15[Min_M15_1].

2. Per la linea di resistenza:

MQL4MQL5
  1. Coordinata prima volta - HighestBarTime_2_m15;
  2. Prima coordinata del prezzo - UpperPrice_2_m15[HighestPrice_2_m15];
  3. Seconda coordinata temporale - HighestBarTime_1_m15;
  4. Seconda coordinata del prezzo - UpperPrice_1_m15[HighestPrice_1_m15].
  1. Coordinata del primo tempo - High_2_15_time[Max_M15_2];
  2. Prima coordinata del prezzo - High_2_15[Max_M15_2];
  3. Seconda coordinata temporale - High_1_15_time[Max_M15_1];
  4. Seconda coordinata del prezzo - High_1_15[Max_M15_1].


4. Creazione di oggetti e modifica delle loro proprietà. Ridisegnare le linee

Ora, quando conosciamo le coordinate della linea, dobbiamo solo creare gli oggetti grafici:

MQL4
//--- creating the support line
   ObjectCreate(0,"TL_Support",OBJ_TREND,0,LowestBarTime_2_m15,LowerPrice_2_m15[LowestPrice_2_m15],
                LowestBarTime_1_m15,LowerPrice_1_m15[LowestPrice_1_m15]);
   ObjectSet("TL_Support",OBJPROP_COLOR,Support_Color);
   ObjectSet("TL_Support",OBJPROP_STYLE,Support_Style);
   ObjectSet("TL_Support",OBJPROP_WIDTH,Support_Width);
//--- creating the resistance line
   ObjectCreate(0,"TL_Resistance",OBJ_TREND,0,HighestBarTime_2_m15,UpperPrice_2_m15[HighestPrice_2_m15],
                HighestBarTime_1_m15,UpperPrice_1_m15[HighestPrice_1_m15]);
   ObjectSet("TL_Resistance",OBJPROP_COLOR,Resistance_Color);
   ObjectSet("TL_Resistance",OBJPROP_STYLE,Resistance_Style);
   ObjectSet("TL_Resistance",OBJPROP_WIDTH,Resistance_Width);
MQL5
//--- creating the support line
   ObjectCreate(0,"TL_Support",OBJ_TREND,0,Low_2_15_time[Min_M15_2],Low_2_15[Min_M15_2],Low_1_15_time[Min_M15_1],Low_1_15[Min_M15_1]);
   ObjectSetInteger(0,"TL_Support",OBJPROP_RAY_RIGHT,true);
   ObjectSetInteger(0,"TL_Support",OBJPROP_COLOR,Support_Color);
   ObjectSetInteger(0,"TL_Support",OBJPROP_STYLE,Support_Style);
   ObjectSetInteger(0,"TL_Support",OBJPROP_WIDTH,Support_Width);
//--- creating the resistance line
   ObjectCreate(0,"TL_Resistance",OBJ_TREND,0,High_2_15_time[Max_M15_2],High_2_15[Max_M15_2],High_1_15_time[Max_M15_1],High_1_15[Max_M15_1]);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_RAY_RIGHT,true);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_COLOR,Resistance_Color);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_STYLE,Resistance_Style);
   ObjectSetInteger(0,"TL_Resistance",OBJPROP_WIDTH,Resistance_Width);

Quindi ho creato le linee necessarie e ho specificato i loro parametri in base ai parametri di input.

Ora dobbiamo implementare il ridisegno delle linee di tendenza.

Quando la situazione del mercato cambia, ad esempio, quando appare un nuovo punto estremo, possiamo semplicemente rimuovere la linea esistente:

MQL4
//--- redrawing the support line
//--- writing the values of the support line time coordinates into the variables
   datetime TL_TimeLow2=ObjectGet("TL_Support",OBJPROP_TIME2);
   datetime TL_TimeLow1=ObjectGet("TL_Support",OBJPROP_TIME1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeLow2!=LowestBarTime_1_m15 && TL_TimeLow1!=LowestBarTime_2_m15)
     {
      //--- remove the line
      ObjectDelete(0,"TL_Support");
     }
//--- redrawing the resistance line
//--- writing the values of the resistance line time coordinates into the variables
   datetime TL_TimeUp2=ObjectGet("TL_Resistance",OBJPROP_TIME2);
   datetime TL_TimeUp1=ObjectGet("TL_Resistance",OBJPROP_TIME1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeUp2!=HighestBarTime_1_m15 && TL_TimeUp1!=HighestBarTime_2_m15)
     {
      //--- remove the line
      ObjectDelete(0,"TL_Resistance");
     }
MQL5
//--- redrawing the support line
//--- writing the values of the support line time coordinates into the variables
   datetime TL_TimeLow2=(datetime)ObjectGetInteger(0,"TL_Support",OBJPROP_TIME,0);
   datetime TL_TimeLow1=(datetime)ObjectGetInteger(0,"TL_Support",OBJPROP_TIME,1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeLow2!=Low_2_15_time[Min_M15_2] && TL_TimeLow1!=Low_1_15_time[Min_M15_1])
     {
      //--- remove the line
      ObjectDelete(0,"TL_Support");
     }
//--- redrawing the resistance line
//--- writing the values of the resistance line time coordinates into the variables
   datetime TL_TimeUp2=(datetime)ObjectGetInteger(0,"TL_Resistance",OBJPROP_TIME,0);
   datetime TL_TimeUp1=(datetime)ObjectGetInteger(0,"TL_Resistance",OBJPROP_TIME,1);
//--- if the line coordinates don't match the current coordinates
   if(TL_TimeUp2!=High_2_15_time[Max_M15_2] && TL_TimeUp1!=High_1_15_time[Max_M15_1])
     {
      //--- remove the line
      ObjectDelete(0,"TL_Resistance");
     }


5. Controllo del caricamento della cronologia delle barre

Durante il test, mi sono reso conto che le linee non venivano sempre disegnate correttamente.

All'inizio pensavo che ci fosse un bug nel codice o che la mia soluzione non funzionasse affatto, ma poi mi sono reso conto che il problema era causato da un caricamento insufficiente della cronologia della barra su un intervallo di tempo più breve, M15 nel mio caso. Per avvertire l'utente di questi problemi, ho deciso di fare in modo che il programma controlli ulteriormente se esiste una barra su M15.

A questo scopo, in MQL4 ho utilizzato le funzionalità della funzione iBarShift() che originariamente utilizzavo nella sezione "Determinazione dei valori di prezzo e tempo dei frattali".

Se non viene trovata una barra, la funzione iBarShift() restituisce -1. Pertanto, possiamo emettere questo avviso:

MQL4
//--- checking the bars history loading
//--- if at least one bar is not found on M15
   if(UpperFractal_1_m15==-1 || UpperFractal_2_m15==-1
      || LowerFractal_1_m15==-1 || LowerFractal_2_m15==-1)
     {
      Alert("The loaded history is insufficient for the correct work!");
     }

In MQL5 ho utilizzato la funzione Bars() che restituisce un valore vuoto, se i dati delle serie temporali non sono stati generati nel terminale:

 
//--- checking the bars history loading
//--- 1. determining the number of bars on a specified timeframe
   int High_M15_1=Bars(Symbol(),PERIOD_M15,UpFractalTime_1[0],UpFractalTime_1_15);
   int High_M15_2=Bars(Symbol(),PERIOD_M15,UpFractalTime_2[0],UpFractalTime_2_15);
   int Low_M15_1=Bars(Symbol(),PERIOD_M15,LowFractalTime_1[0],LowFractalTime_1_15);
   int Low_M15_2=Bars(Symbol(),PERIOD_M15,LowFractalTime_2[0],LowFractalTime_2_15);
//--- 2. check if the loaded history is insufficient for the correct line drawing
//--- if at least one bar is not found
   if(High_M15_1==0 || High_M15_2==0 || Low_M15_1==0 || Low_M15_2==0)
     {
      Alert("The loaded history is insufficient for the correct work!");
     }


6. Segnali di breakthroughs delle linee di tendenza, notifiche push

Per completare il quadro, ho deciso di implementare un segnale di svolta della linea di tendenza. La linea di tendenza viene tracciata attraverso i punti estremi dell'intervallo di tempo del giorno, ma per identificare prima l'apertura, la barra deve essere chiusa al di sotto o al di sopra della linea di tendenza su H4.

In generale, possiamo suddividere il processo in tre fasi:

  1. Determinare il prezzo di chiusura della barra e il prezzo della linea di tendenza;
  2. Determinare le condizioni in cui il prezzo sfonda la linea di tendenza;
  3. Invia la notifica push sulla svolta.
MQL4
// 1. Getting the price parameters of the trend line 
//--- determining the closing price of a bar with index 1
   double Price_Close_H4=iClose(NULL,240,1);
//--- determining the time of a bar with index 1
   datetime Time_Close_H4=iTime(NULL,240,1);
//--- determining the bar index on H4
   int Bar_Close_H4=iBarShift(NULL,240,Time_Close_H4);
//--- determining the price of the line on H4
   double Price_Resistance_H4=ObjectGetValueByShift("TL_Resistance",Bar_Close_H4);
//--- determining the price of the line on H4   
   double Price_Support_H4=ObjectGetValueByShift("TL_Support",Bar_Close_H4);
// 2. Conditions for trend line breakthroughs
//--- for breaking through the support line
   bool breakdown=(Price_Close_H4<Price_Support_H4);
//--- for braking through the resistance line
   bool breakup=(Price_Close_H4>Price_Resistance_H4);
// 3. Delivering the push notifications
   if(breakdown==true)
     {
      //--- send no more than one notification per 4 hours
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the support line");
        }
     }
   if(breakup==true)
     {
      //--- send no more than one notification per 4 hours
      SleepMinutes=240;
      LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the resistance line");
        }
     }
MQL5
// 1. Getting the price parameters of the trend line
   double Close[];
   CopyClose(Symbol(),PERIOD_H4,TimeCurrent(),10,Close);
//--- setting the array indexing order
   ArraySetAsSeries(Close,true);
//---
   datetime Close_time[];
   CopyTime(Symbol(),PERIOD_H4,TimeCurrent(),10,Close_time);
//--- setting the array indexing order
   ArraySetAsSeries(Close_time,true);
//---
   double Price_Support_H4=ObjectGetValueByTime(0,"TL_Support",Close_time[1]);
   double Price_Resistance_H4=ObjectGetValueByTime(0,"TL_Resistance",Close_time[1]);
// 2. Conditions for trend line breakthroughs
   bool breakdown=(Close[1]<Price_Support_H4);
   bool breakup=(Close[1]>Price_Resistance_H4);
// 3. Delivering the push notifications
   if(breakdown==true)
     {
      //--- send no more than one notification per 4 hours
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=(int)TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the support line");
        }
     }
   if(breakup==true)
     {
      //--- send no more than one notification per 4 hours
      int SleepMinutes=240;
      static int LastTime=0;
      if(TimeCurrent()>LastTime+SleepMinutes*60)
        {
         LastTime=(int)TimeCurrent();
         SendNotification(Symbol()+"The price has broken through the resistance line");
        }
     }

Per identificare una svolta, ho utilizzato la funzione ObjectGetValueByShift() in MQL4 e la funzione ObjectGetValueByTime() in MQL5.

Forse, potrei semplicemente impostare 1 invece di Bar_Close_H4 come parametro per ObjectGetValueByShift(), ma ho deciso di determinare prima l'indice su H4. Ho utilizzato la soluzione per limitare il numero di messaggi inviati pubblicati su questo thread del forum e vorrei ringraziare molto l'autore.


7. Uso pratico delle linee di tendenza nel trading

Il modo più semplice: identificare una svolta, attendere un pullback ed entrare nel mercato dopo di esso.

Idealmente, dovresti ottenere qualcosa del genere:

Fig. 3. Breakthroughs della linea di tendenza

Fig. 3. Svolta della linea di tendenza

 Puoi quindi usare la tua immaginazione e provare a identificare le formazioni, cioè i modelli di analisi tecnica, ad esempio un triangolo:

Fig.4. Motivo a triangolo

Fig.4. Motivo a triangolo

Le linee non sono state chiarite da un lasso di tempo più piccolo sulle immagini sopra.


Conclusione

Questo conclude l'articolo, spero che lo troverete utile. L'articolo era pensato per i principianti nella programmazione, per i dilettanti come me.

Ho imparato molto scrivendo questo articolo: in primo luogo, ho iniziato a fare commenti sul codice più significativi; in secondo luogo, all'inizio avevo una soluzione più ingombrante e complessa per chiarire i punti estremi, ma poi sono arrivato a una soluzione più semplice che ho dimostrato qui.

Grazie per la lettura, qualsiasi feedback è apprezzato.


Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/1201

File allegati |
trendlines.mq4 (19.87 KB)
trendlines.mq5 (20.95 KB)
Grafico liquido Grafico liquido
Ti piacerebbe vedere un grafico orario con le barre che si aprono dal secondo e dal quinto minuto dell'ora? Che aspetto ha un grafico ridisegnato quando l'orario di apertura delle barre cambia ogni minuto? Quali vantaggi ha il trading su tali grafici? Troverai le risposte a queste domande in questo articolo.
Manuale MQL5: Gestione di BookEvent Manuale MQL5: Gestione di BookEvent
Questo articolo parla di BookEvent - un evento Depth of Market e il principio della sua elaborazione. Un programma MQL che serve a gestire gli stati di Depth of Market, servirà da esempio. È scritto utilizzando l'approccio orientato agli oggetti. I risultati della gestione vengono visualizzati sullo schermo come un pannello e livelli di Depth of Market.
Fondamenti di programmazione MQL5: Variabili Globali del Terminale Fondamenti di programmazione MQL5: Variabili Globali del Terminale
Questo articolo evidenzia le capacità orientate agli oggetti del linguaggio MQL5 per la creazione di oggetti che facilitano il lavoro con le variabili globali del terminale. Come esempio pratico considero un caso in cui le variabili globali vengono utilizzate come punti di controllo per l'implementazione delle fasi del programma.
Perché l'hosting virtuale su MetaTrader 4 e MetaTrader 5 è migliore del solito VPS? Perché l'hosting virtuale su MetaTrader 4 e MetaTrader 5 è migliore del solito VPS?
La rete Virtual Hosting Cloud è stata sviluppata appositamente per MetaTrader 4 e MetaTrader 5 e presenta tutti i vantaggi di una soluzione nativa. Approfitta della nostra offerta gratuita 24 ore su 24: prova subito un server virtuale.