However, in some more recent code, it is common to see poorly written OnChartEvent code that might appear to 'work' ok, but when combined with *other* indicators on the chart, MT4 performance slows or even hangs!
Quite a few indicators with 'On/Off Button' code will cause problems (in combination with other indicators), because a popular template for how to add the button did not offer a properly written OnChartEvent section.
The key to this interaction between indicators is in the MT4 documentation. It says that a program that enables MOUSE / CREATE / DELETE events will affect *all* indicators on the same chart!
An OnInit() section of some indicator may have one or more of these lines that cause problems for *other* indicators because of chart interactions:
ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1);
ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,1);
ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,1);
If you want to skip the details below, here are step-by-step instructions to test compatibility:
- Download the attached indicator.
- In MT4, File->Open Data Folder
- Navigate to MQL4\Indicators\
- Save the .ex4 and .mq4 files there.
- In MT4, if not already done, open the Navigator window (Ctrl+N)
- In the Nav window, right-click and do 'Refresh'. The new indicator should be on the list. (Alternatively, restart MT4)
(Tip: If you add any .mq4, it should compile, but if there was an error, open the MetaEditor, open the .mq4, and 'Compile'. Check for errors).
- Open a new chart.
- Ctrl+I to see if any indicators are already there, due to your default.tpl template file.
- If yes, then you should right-click in the chart to 'Save template', and give it a name like 'default_save.tpl'
- Then delete everything off your chart
- Then 'Save template' and overwrite the 'default.tpl' file
- RESTART MT4!! Even though you deleted all indicators, the chart will still watch for any chart events it was previously told to activate.
- Fyi, the template files are stored in the 'File->Open Data Folder' under 'templates\' (which is parallel to 'MQL4\' )
Be sure to restore your 'default_save.tpl' back to 'default.tpl' when finished with this testing.
- Add the attached indicator to the chart. (It does not appear to do anything; it silently enables chart events).
- Now one-by-one, add each indicator you want to test. A Live Market with incoming ticks is strongly preferred.
(I would guess you could use the Strategy Tester for this test as well; I don't know why not. However, 'tester.tpl' is the template used for a fresh chart, so be sure it's completely blank with no indicators) - Observe MT4 performance.
If it slows or hangs, then very likely you have found an indicator with a poorly written OnChartEvent section that is wasting a huge amount of time processing events that it likely doesn't need! These events were enabled by my test indicator, but plenty of newer indicators enable the same events. - If you have the source code for the problem indicator, examine the OnChartEvent section. If you're a non-programmer, you could still try putting in the two lines of suggested code (at the very beginning of that section) that will skip all of these enabled events. (It should work unless of course the code uses some of these events, which even non-programmers could check just by 'reading' the flow of the code).
- FYI, the 'CHART_EVENT_MOUSE_MOVE' command that enables mouse events can cause HUNDREDS of events-per-second by just moving the mouse around on the chart!! Therefore, code that wastes time for each of these events will often slow or hang MT4.
=============================
Posts on this topic:
Perhaps the first time I became aware that indicators interactions might cause problems was discussed in this post in the PVSRA thread.
I'm pleased to say that I worked with TraderAtHome to identify and fix the performance problems that were indeed caused by inefficient OnChartEvent code. His latest v2.3 version fixes all such problems.
I mentioned poorly written On/Off button code in this post. The same template has been used in dozens of similar On/Off indicators.
I added a better On/Off button example to 'Daily Lines Boxes v2 BT.mq4' in this post. There is some interesting discussion that follows it.
=============================
Here is the code of the attached indicator. It's extremely simple, and does no action at all, other than to enable the chart events MOUSE / CREATE / DELETE.
At the end is also a commented portion with suggestions how to properly write your 'OnChartEvent' section to fix performance problems.
The best code will watch for specific event id's and ignore all the rest. However, just adding 2 lines of code to OnChartEvent will usually fix most indicators. (Depends on the details, but worth a try).
// P4L_TEST_COMPAT_Enables_chart_events_MOUSE_CREATE_DELETE.mq4 // 2023-Mar-16 v1_00 by pips4life #property description "Run this on your chart. FYI, it does *nothing* except to enable" #property description "MOUSE / CREATE / DELETE events on the chart (for all indicators!)." #property description "\nOne by one, add your other indicators to the chart (Live market preferred)." #property description "Observe the MT4 performance. If very slow, most likely your 'OnChartEvent'" #property description "section in your problem-causing indicator is not properly coded!" #property description "\nTIPS: This source code contains suggestions how to fix your code." #property description "The ONLY way to restore chart is delete this AND restart MT4!" #property description "New TF/template does not work!" #property indicator_chart_window #property version "1.00" #property link "https://www.forexfactory.com/thread/1210964-mt4-slow-test-if-your-onchartevent-is-compatible" int OnInit() { // Fyi, when this indicator enables these events, it will affect ALL indicators on the same chart, // EVEN after you delete and remove this indicator!! Changing TF's, nor loading new template does not help! // ONLY after deleting this indicator from a chart, then restart MT4 to resume as before, without these events enabled. // Until a restart, the chart remembers that at some moment, some indicator enabled these events and will keep doing so! ChartSetInteger(0,CHART_EVENT_MOUSE_MOVE,1); ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,1); ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,1); return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { return; } int OnCalculate(const int rates_total, const int prev_calculated, const datetime& time[], const double& open[], const double& high[], const double& low[], const double& close[], const long& tick_volume[], const long& volume[], const int& spread[]) { // No need to do anything. return(rates_total); } // For this compatibility test, there is no need for an OnChartEvent() section. /* // One suggestion how to code your OnChartEvent section: void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { // If another indy on the same chart has enabled events for mouse-move/create/delete, // just skip these events up front *if* they aren't needed. In the worst case, // your indy might cause MT4 to hang due to *other* indicators!! // Skipping the unused events seems to fix the problem. // However, the VERY BEST solution is for your OnChartEvent code to isolate and using ONLY // the specific 'id' events (and for specific 'sparam' value(s), if applicable). Example: // if(id==CHARTEVENT_OBJECT_CHANGE && sparam == myObjName) {...} // // Another approach would be to at least detect and ignore some specific events: // // If this, or another program, enabled CHART_EVENT_MOUSE_MOVE (in OnInit) // *If* these events are not needed in your code, then skip them: if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_MOUSE_WHEEL) return; // // The next test appears to make this indy compatible with other programs that // enabled CHART_EVENT_OBJECT_CREATE and/or CHART_EVENT_OBJECT_DELETE (in OnInit) // *If* these events are not needed in your code, then skip them: if(id==CHARTEVENT_OBJECT_CREATE || id==CHARTEVENT_OBJECT_DELETE) return; //... The rest of your OnChartEvent code follows... Example: // if(id==CHARTEVENT_OBJECT_CHANGE && sparam == myObjName) {...} // // Or consider using a 'switch' statement for multiple events: //switch(id) //{ // case CHARTEVENT_OBJECT_CHANGE : // if(sparam == myObjName) // { // //(Your code...) // } // break; // case CHARTEVENT_KEYDOWN : // //(Your code...) // break; // case CHARTEVENT_OBJECT_CLICK : // { // int x = (int) lparam; // int y = (int) dparam; // datetime dt = 0; // double price = 0.0; // int window = 0; // string msg= ""; // if(ChartXYToTimePrice(0,x,y,window,dt,price)) // { // msg = StringConcatenate("Window=",window," X=",x," Y=",y, // " => Time=",TimeToString(dt)," Price=",price); // } // Alert("DEBUG Object clicked on: ",sparam," Info: ",msg); // } // break; // default: // break; //} }//end of OnChartEvent() */
As with any indicator, to install this, use the MT4 menu command: File->Open Data Window
Navigate to MQL4\Indicators\ and copy at least the .ex4 file, preferably also the .mq4 file.
In the MT4 Navigator window, right click and choose 'Refresh'. OR, restart MT4.
Open a chart, then add this indicator. THEN, one-by-one, add your other indicators (preferably during Live Market). Observe the performance of MT4.
If it seems to slow down a lot when combined with this indicator, but otherwise works ok on a freshly opened blank(!) chart by itself, then chances are good that your indicator has a poorly written OnChartEvent section that needs improvement!
P.S. I don't use MT5, but I would assume that the same issue is completely relevant for .mq5 files as well. Proper OnChartEvent code is essential for both!