Download MetaTrader 5

Toggle (Flush/Redraw) an indicator buffer with keystroke event

To add comments, please log in or register
dazamate
575
dazamate  

Hi guys, 

I am trying to figure out how to flush out, or 'reset' indicator buffers on a keystroke event.

Here is what I have so far

 

void OnChartEvent(const int id,         // Event identifier  
                  const long& lparam,   // Event parameter of long type
                  const double& dparam, // Event parameter of double type
                  const string& sparam) // Event parameter of string type
                  
  {
      if(id==CHARTEVENT_KEYDOWN) {
         
         //Inside Day Toggle
         if (lparam == 73) {
            if(detect_inside_candles) { 
               detect_inside_candles = false; //external bool
               
               //flush out buffers
               ArrayInitialize(Buffer0, 0);
               ArrayInitialize(Buffer1, 0);
               ChartRedraw(ChartID());               
            }
            
            else if(!detect_inside_candles) { 
               detect_inside_candles = true; //external bool
               ChartRedraw(ChartID());
               
            }
         }// "i" key pressed
         
        
      }

 

What happens is the first keystoke does clear the buffers and the indicator from the screen, but the second keystroke doesn't work.

Is it possible to clear the  prev_calculated variable inside OnCalculate()... it's set as a constant so I don't know how that would work.

Can anyone suggest any other approach here. 

Keith Watford
Moderator
9982
Keith Watford  

Move your calculations for the buffers into a separate function with a parameter for the amount of bars to calculate

Call the function from OnCalculate (if detect_inside_candles is true)to calculate on new bars only

Call the function from your if in OnChartEvent to calculate on all bars 
dazamate
575
dazamate  

I think I understand what you're saying.

I am using the histograms to mark a line down the middle of the inside candles. What I want to do is flush out the buffers and remove all markings from the chart  - which I have achieved.

But when the keystroke 'i' turns the switch back on again - I need the indicator to go back through the entire buffer again and re-do it.

What you're saying is to use a custom variable, instead of the prev_calculated to make the code run back through all candles again?

Keith Watford
Moderator
9982
Keith Watford  

Basically, yes.

You may have something like

   int limit=rates_total-prev_calculated
   //Code that loops through and fills buffers

 in OnCalculate

Instead, move your main code into a function

void MainCodeFunction(limit)
   { 
   //Code that loops through and fills buffers
   }  

 Then in OnCalculate

   int limit=rates_total-prev_calculated
   MainCodeFunction(limit);

 You pass limit to the function

 

Then in your OnChartEvent

            else if(!detect_inside_candles) { 
               detect_inside_candles = true; //external bool
               MainCodeFunction(Bars-1);
               ChartRedraw(ChartID());
                

 You can pass Bars-1 or whatever is suitable to the function to redraw all the buffers you need

dazamate
575
dazamate  

Thanks for your help. I've got it working, I did a crude work around so I didn't have to heavily modify the code.

 

I Set a global variable 

bool redraw_buffers = false;

 

Flag it to true when the chart needs updating. I also added the RefreshRates() function, hoping that it will call onCalculate

//Inside Day Toggle
         if (lparam == 73) {
            if(detect_inside_candles) { 
               detect_inside_candles = false;
               
               //flush out buffers
               ArrayInitialize(Buffer0, 0);
               ArrayInitialize(Buffer1, 0);
               
               ChartRedraw(ChartID());               
            }
            
            else if(!detect_inside_candles) { 
               redraw_buffers = true;
               detect_inside_candles = true;               
               RefreshRates(); //try to get onCalculate to run on keystroke   
               ChartRedraw(ChartID());
               
            }
         }// "i" key pressed

 

Then before the indicator loop, I took some of your advice and reset the bar counter...

int OnCalculate( ....
int limit, i;
   int counted_bars = prev_calculated;
   
   //---
   if(counted_bars<0) return(-1);
   //----
   if(counted_bars>0) counted_bars--;
   //----
   if(counted_bars==0) counted_bars=1;
   
   if(redraw_buffers) {
      limit=Bars-1;
      redraw_buffers = false;
   }
   else { limit=rates_total-counted_bars; }
   
    
   for(i=limit-1; i>=0; i--) {   

 

Now it works as intended, however - the indicator will still need a new tick to refresh the chart.

I was hoping that refresh rates function would get onCalculate to run again.

Is there anyway to call onCalculate within the onEvent function...

 

         if (lparam == 73) {
           // 
            else if(!detect_inside_candles) { 
               redraw_buffers = true;
               detect_inside_candles = true;               
               RefreshRates(); //try to get onCalculate to run on keystroke   
               ChartRedraw(ChartID());

               onCalculate() //how will pass all the parameters to get this to work?
            }
         }// "i" key pressed

 

If I can get onCalculate to be called on the keystroke that would be great. A any solution without having to modify the code to heavily would be fantastic (y).

Thank you so much. 

Keith Watford
Moderator
9982
Keith Watford  

With my suggestion, the buffers will be re-calculated without waiting for a tick.

Why would there be any need for heavy modification?

It's a simple matter to move your main code from OnCalculate into a new function, just cut and paste. 

dazamate
575
dazamate  

Ok, help me understand the logic here. 

If I just renamed the onCalculate function to scanCandles()

Then I called scanCandles from within onCalculate and onChartEvent

Why can't I just call onCalculate from within onChartEvent? 

Keith Watford
Moderator
9982
Keith Watford  
dazamate:

Ok, help me understand the logic here. 

If I just renamed the onCalculate function to scanCandles()

Then I called scanCandles from within onCalculate and onChartEvent

Why can't I just call onCalculate from within onChartEvent? 

 

Try it and see what happens.

I've never tried it 

dazamate
575
dazamate  

It worked,

I had to make two dummy arrays to pass as the Tick_volume and Spread parameter as I don't know what global variables are normally passed to onCalculate internally.

 

Thanks very much for your help. 

To add comments, please log in or register