Draw vertical lines on every crossover in an EA

 

I would like to draw vertical lines for times when a new signal appears in an EA. Signals can be of several natures and are returned by an independent function, but for simplicity lets say a signal is simply the Price close crossover an EMA.

Using a command like:

ObjectCreate(0,"Long", OBJ_VLINE,0, TimeCurrent(),0);

I managed to create a vertical line only on the latest signal. As any new signal appears, all prior Vlines disappear.

Looking over an old POST, I noted that one may have to update the positions of all vertical lines each new candle. The problem with that post, is that it re-runs all the calculations at each new candle, which appears inefficient.

So my solution was to create an array of datetime and store the time each new signal appears, and then loop over that array to place vertical lines over the time of all prior signals. However, the lines do not deploy and I get a warning saying " array out of range in 'BBOnly.mq5' (40,60)". Any thought what could be wrong, or is there any other way to place  such vlines on all crossovers in an EA?

Here is a simplified version of the code:


//General variables
   bool IsNewbar; //Bollean to do calcualtion only on new bar.
   MqlRates Price[]; // to staore price data used in EMA cross over

// Moving average variables
   int              MovAve_Handle;
   double           MovAve_Buffer[]; 

//for marking signals as vertical lines
   int Signals_N_Long=0;  //counter of the number of long signals
   datetime Signals_Time_Longs[]; //Array to store datetimes in which signals where reported


int OnInit()
{
   ArraySetAsSeries(Price,true);
   
   MovAve_Handle= iMA(_Symbol,PERIOD_M1, 100,0, MODE_SMA,PRICE_CLOSE);
   ArraySetAsSeries(MovAve_Buffer,true);
          
   return(INIT_SUCCEEDED);
}



void OnTick()
{
///---check for new bar
      static datetime StartTime;
      datetime ThisBarTime = iTime(_Symbol,PERIOD_M1,0);
      if(StartTime != ThisBarTime) {IsNewbar=true; StartTime = ThisBarTime; } else {IsNewbar=false;}

 
if(IsNewbar==true){
   //Collect data of signal on new candle
         string SignalEntryType= GetSignal_BBCont_MA();
      
    //Check for signal type 
         if (SignalEntryType=="Long") { Signals_Time_Longs[Signals_N_Long]=TimeCurrent(); Signals_N_Long++;       Print(SignalEntryType);} 

   //Draw Vlines for long signals      
      int NSignalsLongs= ArraySize(Signals_Time_Longs);
         if (NSignalsLongs>1)
         {
                for(int i = 0; i<=NSignalsLongs; i++){
                ObjectCreate(0,"Long", OBJ_VLINE,0,Signals_Time_Longs[i],0);
                }
         }
   
   
}   
}


///GETSIGNAL fucntion
string GetSignal_BBCont_MA(){
      
      // close price
            CopyRates(_Symbol,PERIOD_M1,1,2,Price);
            
      //Data from Moving Average
            CopyBuffer(MovAve_Handle,0,1,2,MovAve_Buffer);
               
      //GetSignal  Close Crossover EMA
         if (Price[0].close > MovAve_Buffer[0] && Price[1].close<=MovAve_Buffer[1]) {return("Long");} 
         
      return("None");
}

trying to code a script to draw a line on MACD crossover. Skipping crossovers.
trying to code a script to draw a line on MACD crossover. Skipping crossovers.
  • 2020.10.31
  • www.mql5.com
I'm just learning to code. I'm just trying to write a script right now...
 

I found a problem with the dimensions of the array, but critically the problem of drawing only the latest vline is that the names were not unique.

This fixed the problem for me:

string name = "L" + IntegerToString(i);
// ObjectCreate(0, name, OBJ_VLINE, 0, TimeLong,0 ); //labels at the bottom
ObjectCreate(0,name, OBJ_TRENDBYANGLE, 0, TimeLong, 0, TimeLong, 1); //only lines
                   
 
I higly recommend you to look into the CChartObjectsVline class for this, it wraps the functions of Vlines into a much simpler form. 


#include <ChartObjects\ChartObjectsLines.mqh>      //---we include the meta quotes header (mqh) file from the Include folder
CChartObjectVLine vline[];                         //---and declare a dynamic array of the class that works with vlines

int      vline_number = 5;                         //---how many lines do we want for demonstration?

int OnInit()
  {
//---
   for(int i = 0; i < vline_number; i++)
     {
      ArrayResize(vline, i + 1);     // We create an array of vline obects so we can call them by index and not by name.
                                     // the names are stored in the lines on the chart

      //--- so this is how the class methods(functions) are calles.
      //--- You can look at the methods in the in the CChartObjects base class in the ChartObjects.mqh 

      vline[i].Create(0, "my_vline_" + string(i), 0, iTime(_Symbol, _Period, (7 * i)));
      vline[i].Width(3);               //changing values like this is way more convenient, right?
      vline[i].Color(clrBlue);
     }
//---
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {  }

void OnTick()
  {  }


It uses exactly the same Object functions but you don't have to pass all the parameters each time.

And it is a nice first look at object oriented programming.

'

A totally different thing is that there will be crossovers coming and going between two most recent bars because the most recent bar isn't fully developed yet.

 
Tobias Johannes Zimmer #:
I higly recommend you to look into the CChartObjectsVline class for this, it wraps the functions of Vlines into a much simpler form. 



It uses exactly the same Object functions but you don't have to pass all the parameters each time.

And it is a nice first look at object oriented programming.

'

A totally different thing is that there will be crossovers coming and going between two most recent bars because the most recent bar isn't fully developed yet.

Might I ask how could this work in the onInit? at that time the calculations are not yet done, so how can one draw the lines on crossovers at that insanace?
 
MoraCamilo #:
Might I ask how could this work in the onInit? at that time the calculations are not yet done, so how can one draw the lines on crossovers at that insanace?
No, of course you need to do the calculation first, this was just an example. But the condition check needs to be done for each bar, not just for the last two. You have to use a for loop for running the check across an array. You might search for "cross" on the codebase, find some code, see how it works. Then again there is probably an MA cross indicator that does just that.

Maybe search for a tutorial on how to use loops.
Reason: