CHARTEVENT_CHART_CHANGE - Missing events (Bug?)

 

Hi,

my understanding of logic regarding this event is, that it is sent when the chart changes. But it does not in many circumstances in MT5:

1. User changes the scale from normal to fixed scale

2. When bars are growing and exceed the current price scale

3. When the scaling (zoom) is changed 

These are all real changes of the chart, but without an event. The missing events force me to check these parameters every n milliseconds to detect such changes and fire the event in OnTimer(), which is just a workaround, but surely not the perfect reason. 

Will this be fixed/enhanced?

Thanks in advance

 

Yes i also check most of these things in the timer.

If one of them changes i just redraw the entire interface with updated dimensions/settings, if necessary. 

Having full control over these separate variables can also have advantages over a universal event listener.

 
rco vd Heijden:

Yes i also check most of these things in the timer.

If one of them changes i just redraw the entire interface with updated dimensions/settings, if necessary. 

Having full control over these separate variables can also have advantages over a universal event listener.

The problem is, that it takes up to and more than 50ms just to check the settings, when the rest of the code gets complex. I built in hundreds of benchmarks in the beta version of my application to find bottlenecks and figured out such stuff, I couldn´t believe it, but its true, 50ms. When I put the same code into sample EA, and do the measurement at the same place, its 0-1 ms. 

Imo, its much easier to check afterwards what happened when the chart event was fired than doing it all the time. 

I´d be glad if MetaQuotes would fix this issue. 

The code is just something like this and fixes also the missing adjustment of the chart when Auto-Scroll is activated.   


//+------------------------------------------------------------------+
//| Global Chart object                                              |
//+------------------------------------------------------------------+   
class CChartExtStd : public CChartExt
   {
   public:
      CChartExtStd()
         {
         #ifdef __DH_OBJECT_CLASS
         m_classname="CChartExtStd";
         #endif
         }
      //+------------------------------------------------------------------+
      //| Chart bug fix                                                    |
      //+------------------------------------------------------------------+   
      protected:
      virtual void OnTimer()
         {
         bool fire=false;
         #ifdef __MQL5__
            static int lastscale=Scale();
            if (lastscale!=Scale())
               {
               if (AutoScroll())
                  {
                  AutoScroll(false);
                  AutoScroll(true);
                  }
               lastscale=Scale();   
               }
            
            static double lastpricemax=PriceMax(m_subwin);
            static double lastpricemin=PriceMin(m_subwin);
            
            if (PriceMax(m_subwin)!=lastpricemax) { lastpricemax=PriceMax(m_subwin); fire=true; }
            if (PriceMin(m_subwin)!=lastpricemin) { lastpricemin=PriceMin(m_subwin); fire=true; }
            
         #endif
         static bool lastscalefix=ScaleFix();
         if (lastscalefix!=ScaleFix()) { lastscalefix=ScaleFix(); fire=true; }

         if (fire)
            FireEventChartChange();   
         }
   };
CChartExtStd __Chart;
 
Doerk Hilger:

Hi,

my understanding of logic regarding this event is, that it is sent when the chart changes. But it does not in many circumstances in MT5:

1. User changes the scale from normal to fixed scale

2. When bars are growing and exceed the current price scale

3. When the scaling (zoom) is changed 

These are all real changes of the chart, but without an event. The missing events force me to check these parameters every n milliseconds to detect such changes and fire the event in OnTimer(), which is just a workaround, but surely not the perfect reason. 

Will this be fixed/enhanced?

Thanks in advance

The code you posted can't be used directly, so I did my own tests.

I could not reproduce points 1 and 3. I am not exactly sure what you mean with your point 2 ? The current market price is moving the chart drawing up or down ?

2020.05.28 23:31:55.194    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:31:55.194    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALE 3
2020.05.28 23:32:03.489    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:32:03.489    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALEFIX_11 true
2020.05.28 23:32:10.830    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:32:10.830    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALEFIX_11 false
2020.05.28 23:32:15.222    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:32:15.224    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALEFIX false
2020.05.28 23:32:18.914    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:32:18.915    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALEFIX true
2020.05.28 23:32:22.639    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:32:22.639    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALEFIX false
2020.05.28 23:32:22.639    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALE_PT_PER_BAR true
2020.05.28 23:32:29.587    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:32:29.588    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALE_PT_PER_BAR false
2020.05.28 23:33:22.054    326220Limited (EURUSD,H1)    CHARTEVENT_CHART_CHANGE
2020.05.28 23:33:22.054    326220Limited (EURUSD,H1)    CHANGE DETECTED on CHART_SCALE 5

//---
struct SChartProperties
  {
  //--- Chart Properties from Dialog
  int              scale;
  bool             isFixedScale;
  bool             isFixed11;
  bool             isScalePtBar;
  } ChartProperties;

bool Init=false;
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(void)
  {
  if(Init) return;
  ChartProperties.isFixed11               = (bool)ChartGetInteger(0,CHART_SCALEFIX_11);
  ChartProperties.isFixedScale            = (bool)ChartGetInteger(0,CHART_SCALEFIX);
  ChartProperties.isScalePtBar            = (bool)ChartGetInteger(0,CHART_SCALE_PT_PER_BAR);
  ChartProperties.scale                   = (int)ChartGetInteger(0,CHART_SCALE);

  Init  = true;
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
  if(!Init) return;
//--- Change of the chart size or modification of chart properties through the Properties dialog
  if(id==CHARTEVENT_CHART_CHANGE)
    {
    printf("CHARTEVENT_CHART_CHANGE");
    }
//--- Detect a change in chart size or properties
  int scale = (int)ChartGetInteger(0,CHART_SCALE);
  if(scale!=ChartProperties.scale)
    {
    Print("CHANGE DETECTED on CHART_SCALE ",scale);
    ChartProperties.scale = scale;
    }
//---
  bool isFixed11 = (bool)ChartGetInteger(0,CHART_SCALEFIX_11);
  if(isFixed11!=ChartProperties.isFixed11)
    {
    Print("CHANGE DETECTED on CHART_SCALEFIX_11 ",isFixed11);
    ChartProperties.isFixed11 = isFixed11;
    }
//---
  bool isFixedScale = (bool)ChartGetInteger(0,CHART_SCALEFIX);
  if(isFixedScale!=ChartProperties.isFixedScale)
    {
    Print("CHANGE DETECTED on CHART_SCALEFIX ",isFixedScale);
    ChartProperties.isFixedScale = isFixedScale;
    }
//---
  bool isScalePtBar = (bool)ChartGetInteger(0,CHART_SCALE_PT_PER_BAR);
  if(isScalePtBar!=ChartProperties.isScalePtBar)
    {
    Print("CHANGE DETECTED on CHART_SCALE_PT_PER_BAR ",isScalePtBar);
    ChartProperties.isScalePtBar = isScalePtBar;
    }
  }
//+------------------------------------------------------------------+
 
Maybe the fixed some of these in the meanwhile, did not check since I was posting it. Some of the other missing chart events (normal mode, not tester) are fixed too. Just recognized this yesterday. 
 

Update:

When the charts max/min is changed due to a candle reaches over the top or below the bottom, the event CHARTEVENT_CHART_CHANGE is still not created. 

 

You should Never call ChartGetInteger() inside Tick() function, because all ChartGet functions are synchronous!

Being synchronous means: when called, those functions  will go to the end of the execution queue, and will only return after they have been finished (along with the time of the other queued executions)

ChartSet, on the oposite, is Asynchronous and can be called anytime, with no performance hit. But not ChartGet functions. (ChartGetInt, ChartGetDouble, etc.. ) 


Here is a simple working example, calling it under OnChartEvent, and is currently working fine:


void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam) {
  
   if (init == 1) {

      if (id==CHARTEVENT_CHART_CHANGE || id == CHARTEVENT_CLICK) {
   
   
         Altera();
         ChartGetInfo();
            
        if(id == CHARTEVENT_CLICK) {
           ChartPosicionaNoCentro(true);
        } else {
           ChartPosicionaNoCentro(false);
        }    
   
   
      }            
   }

}




void ChartGetInfo() {

   leftMost_Bar   = ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);
   visibleBars    = ChartGetInteger(0,CHART_VISIBLE_BARS);
   chartMax       = ChartGetDouble(0, CHART_PRICE_MAX)-1*_Point;
   chartMin       = ChartGetDouble(0, CHART_PRICE_MIN)-1*_Point;   

}




 
rrocchi:

You should Never call ChartGetInteger() inside Tick() function, because all ChartGet functions are synchronous!



I don´t, I do it within the timer. But anyway, actually this should make no difference, because OnTick() would also not be called as long as OnTimer() did not return. 

 

This issue is still not fixed.

Especially number 2 - I need to check if the max price of the chart changed, which happens, when the scale is not fixed and the new candles would exceed the the current chart display, in such a case, the chart is changed - but no event occurs. 

This measurement, which is clearly needed to catch all chart changes, slows down the EA drastically. I do this checking within the timer. I simply buffer the last Max-Price and compare it to the new one, by using ChartGetDouble(). My profiling shows horrible results and this explains stuttering execution.

As shown, it takes up to 4 (FOUR!) seconds until ChartGetDouble() returns. The profiling shows only values which exceed 1ms. 



What is the point of code optimization when bottlenecks like such remain since years ... I don´t get it. 

Reason: