CPU load issue with offline chart updated live by PostMessageA

 

There are many script/EA available generating offline history (Renko, Free-of-Holes, Constant Range Bars, Tick Chart, Time Frame Converter, and so on ...) you can open as offline chart and run indicators on it live.

They all use the "PostMessageA(winHandle, WM_COMMAND, 33324, 0)" Windows function to signal the offline chart fresh data is written in the history, and so trigger the indicators/EAs running on it.

The issue is that PostMessageA doesn't manage (implicitely or explicitely) the bars counted as processed. That is the information returned by the MT4 IndicatorCounted() function will still return 0 each tick upon PostMessageA. Since one standard indicator relies on IndicatorCounted() to not reprocess the whole offline history each tick but the last bar, the side effect is the indicator will actually reprocess the offline history each tick, in the limitation of the "Max bars in chart" option parameter. The CPU demand can then easily saturate a single core with heavy market for all that you run a bunch of indicators on say 10 or less such large offline charts. As a result response time suffers when passing orders.

The history reprocessing can be demonstrated with uploaded S_test_GenOfflineChart script on one M1 chart combined with I_test_M7_start_trace indicator on the M7 offline chart generated. You'll get that kind of trace in the Alert window ...

03:06:15.974: EURUSD_7: start() count=0 Volume[0]=16.00000000 Close[0]=1.44590000 Bars=9999 countedBars=0 ---> for ( i = 9998 ; i >= 0 ; i-- )
03:06:20.872: EURUSD_7: start() count=1 Volume[0]=1.00000000 Close[0]=1.44610000 Bars=9999 countedBars=0 ---> for ( i = 9998 ; i >= 0 ; i-- )
03:06:28.095: EURUSD_7: start() count=2 Volume[0]=2.00000000 Close[0]=1.44600000 Bars=9999 countedBars=0 ---> for ( i = 9998 ; i >= 0 ; i-- )
03:06:29.530: EURUSD_7: start() count=3 Volume[0]=3.00000000 Close[0]=1.44610000 Bars=9999 countedBars=0 ---> for ( i = 9998 ; i >= 0 ; i-- )
03:06:31.074: EURUSD_7: start() count=4 Volume[0]=4.00000000 Close[0]=1.44600000 Bars=9999 countedBars=0 ---> for ( i = 9998 ; i >= 0 ; i-- )
03:06:31.355: EURUSD_7: start() count=5 Volume[0]=5.00000000 Close[0]=1.44610000 Bars=9999 countedBars=0 ---> for ( i = 9998 ; i >= 0 ; i-- )
... showing the indicator running on the offline chart will reprocess the full history each tick signaled by PostMessageA(winHandle, WM_COMMAND, 33324, 0) from within the script running on the M1 chart to generate that offline chart.

Is there another PostMessage command to update the counted bars along with signaling the offline chart to avoid unecessary CPU overload ?
 
berix:
Is there another PostMessage command to update the counted bars along with signaling the offline chart to avoid unecessary CPU load ?

No.

Do you really need 9999 bars for the indicators

 
WHRoeder:

No.

Do you really need 9999 bars for the indicators


Zoom out is about 1850 bars on my single display and about 3750 bars on spanned double display. ;-)

More seriously, even with 3000 bars I already reached CPU overload at the time of the JPY earthquake, running 6 offline generation with a set of indicators.

There should certainly be a method to achieve PostMessageA with proper IndicatorCounted() or by other means ... the Terminal does it well for indicators and current method isn't that clean.

Any other idea ?

 

When you click on a menu item, Windows sends a PostMessageA(hWnd,WM_COMMAND,wparam,0) in the thread message queue read by MetaTrader for processing. "wparam" tells what menu item has been clicked on.

The well known code

#include <WinUser32.mqh>
#import "user32.dll"
    int PostMessageA(int hWnd,int Msg,int wParam,int lParam);
#import
....

    PostMessageA(hWnd, WM_COMMAND, 33324, 0);

will emulate the user selecting the "Refresh" menu item, hence the noticed behaviour above: reprocessing of the history.

Beside of the Windows system-defined messages like WM_COMMAND, there are application-defined messages. They are registered based on a meaningfull string for us as with dedicatedMsgID = RegisterWindowMessageA("MetaTrader4_Internal_Message"). Subsequent messages queued by a PostMessageA(hWnd, dedicatedMsgID, wparam, lparam) will carry that dedicated message ID along with significant wparam and lparam values to be processed in turn by Metatader that reads the message queue.

In that category of messages I only know about two with wparam value 2 and 55:

#import "user32.dll"
    int RegisterWindowMessageA(string lpString);
    int PostMessageA(int hWnd,int Msg,int wParam,int lParam);
#import
....
    int MT4InternalMsg = RegisterWindowMessageA("MetaTrader4_Internal_Message");
    int hWnd = WindowHandle(Symbol(),Period());

    PostMessageA(hWnd,MT4InternalMsg,2,1);                     // generates a tick that triggers start()
    PostMessageA(hWnd,MT4InternalMsg,55,leftMostBarIndex);     // scroll chart to bar

Could it be undocumented MT4 dedicated messages are designed to achieve indicator start with correct IndicatorCounted() setting, or is it unexpectable due to the MetaTrader architecture itself ?

I mean something like:

    PostMessageA(hWnd, MT4InternalMsg, SET_COUNTED, Bars - 1);   // New IndicatorCounted value
    PostMessageA(hWnd, MT4InternalMsg, 2, 1);                    // generates a tick that triggers start()

Do you see ?

 
berix:

When you click on a menu item, Windows sends a PostMessageA(hWnd,WM_COMMAND,wparam,0) in the thread message queue read by MetaTrader for processing. "wparam" tells what menu item has been clicked on.


I want to call Login function in menu File of MT4.

Do you know "wparam" number of this function ?

Thanks !

 
berix:

Do you see ?

Hey berix . . .

I tried . . .

PostMessageA(hWnd, WM_COMMAND, 33324, 0);

and

PostMessageA(hWnd,MT4InternalMsg,2,1); 

and they seemed to have pretty much the same effect . . both seemed to refresh the history from my Broker, I don't really want to do that every 50 ms . . . I was hoping the 2nd snippet would just simulate a tick and I could use it to trigger my code into action when the market was slow and not supplying any ticks. Any ideas ?

Reason: