Indicator shifts when terminal adds/removes chart bars

To add comments, please log in or register
VSc
18
VSc  

Problem:

While it is running, MT4 will load or remove bars in a chart (to achieve/maintain the "Max Bars In Chart" value), and when it does, my "separate window" indicator shifts by the number of bars that are added/removed. My indicator is my own tick chart, and therefore the indicator indexes don’t relate directly to the corresponding bars in the chart window, plus they are based on individual ticks, so I can't simply redraw/recalculate.

I have attached the tick chart mql file for reference. (It simply uses histogram bars for the tick chart, and has a shift function that moves all indicator bars over to the left if ever the next tick chart bar is about to be drawn at Time[0]. This shift function is NOT related to the problem).

Example:

MT4 is set to have max 20000 bars.

Options Showing Max Bars

Once more bars have been added to the chart (564 in this instance, but it varies, and you don't know the value until it happens), the terminal deletes 128 bars (this can be seen by the change to the value of the Bars variable). At this time, the indicator value that I have drawn at (e.g.) buffer index[135] will now appear at index[7] - the indicator values all "shift" to the right in the indicator window. Likewise the value drawn at index[5] will disappear from the indicator window, but it has actually shifted to the right (into negative index values) and will gradually reappear as the chart progresses, which makes the indicator a mess. Then every time "Bars" reaches 20,564 again, the process repeats.

The following screens show the indicator over a period of ~0.8 seconds, at the time the chart adjusts the bars:

New M1 chart bar about to form

New M1 bar formed - Bars value increases

Indicator values have shifted 128 index positions

Conversely, if you increase the "maximum bars" value, it shifts to the left when MT4 downloads more history.

I have tried MT4 installers from 2 different brokers, using each broker’s accounts and trade servers, and on 3 different PC's/Windows versions (8, 10, server 2012 VPS), using different values for “Max bars in chart” (20,000/2,100) and they all do the same thing. I am using Build 1220 right now, but this has been a problem I have been aware of for maybe a year, I have only just isolated the catalyst.

I have searched the forums and documentation and I am now asking for help please.

So what I need to know is – 

is this an error in MT4, or my indicator?

Or is it neither and actually the standard behaviour in MT4?

Is there a fix, a property I can set to overcome it, or do I have to code around it?

Thanks for taking the time to read, and TIA for any assistance.

Vaughan

Files:
TickChart.mq4 10 kb
Alain Verleyen
38676
Alain Verleyen  
VSc:
...

So what I need to know is – 

is this an error in MT4, or my indicator?

Or is it neither and actually the standard behaviour in MT4?

It is the normal behaviour.

Is there a fix, a property I can set to overcome it, or do I have to code around it?

You need to code your indicator properly to deal with it. Suggestion : use a normal buffer to keep your values, and then ArrayCopy() to set the values of your indicator buffer (which is managed automatically by MT4, so you don't have control  on it).

Thanks for taking the time to read, and TIA for any assistance.

Vaughan

Please write correct English, what is the meaning of TIA ?

VSc
18
VSc  
Alain Verleyen:
It is the normal behaviour.

You need to code your indicator properly to deal with it. Suggestion : use a normal buffer to keep your values, and then ArrayCopy() to set the values of your indicator buffer (which is managed automatically by MT4, so you don't have control  on it).

Please write correct English, what is the meaning of TIA ?

Hi Alain,

Thanks for the explanation and guidance. Knowing that it's not a bug is half the battle.

Because I am doing tick-by-tick comparisons for my indicator, I need the code as lean as possible so I don't miss any ticks. Additional processing is undesirable, and I was hoping it was a behaviour that could be overcome by a setting in the terminal rather than with code. I will try ArrayCopy() and see if I can make it run only when the chart shifts.

TIA = "Thanks In Advance".

Vaughan

VSc
18
VSc  
Please help me now to clear the indicator buffer properly, or determine that I can't.

Firstly I have modified my tick chart indicator (as suggested by @Alain Verleyen) so that it loads a regular array and then does an ArrayCopy into the indicator buffer once each tick bar is "full". When the chart shifts due to history being loaded/removed, it does another ArrayCopy to re-draw the indicator. My problem now is that I don't know how to fully clear the indicator array before I redraw it, after this shift has taken place.

I have experimented with various functions, but none of them clear the values that have moved into the negative index positions of the indicator buffer. 

To demonstrate, refer to the second image above (reproduced here):


It's not only the indicator values inside the red box that move to the right - all of the "bars" in the indicator window move to the right, but those outside the red box move off the screen - you can't see them but the values are still held in the indicator buffer. As new M1 bars appear and the terminal moves the chart and indicator windows along one position, these "bars" reappear in the indicator window, at Time[0], one-by-one.

Here's a screenshot showing my updated indicator after the chart has shifted due to bars being removed from history. As the terminal advances the chart window, it's bringing indicator values from negative index positions back into the 0+ indexes where they are visible. You can even see highlighted red where these bars originally came from and have been redrawn by me, to prove they are not random values.


I have tried ArrayFree() but it doesn't appear to do what I thought it might. Either that or I am not using it properly. When I do this:

ArrayFree(IndBuffer1);

All of the values drawn in the indicator window (for this buffer) disappear, but when you ArrayCopy() back into it, nothing shows in the indicator window until you do this:

SetIndexBuffer(0, IndBuffer1);

And then it shows that the indicator has held its values and wasn't actually "freed". The way I read the doco it actually freed the mapping to physical memory. Maybe it does, and SetIndexBuffer() remaps it - I need to blow away what is in memory because I can't seem to get the values out of the indicator buffer any other way.

And ArrayInitialize() doesn't initialise the negative index values.

Finally, as I mentioned above, I do a tick-by-tick comparison, so missing ticks is highly undesirable, that's why I want this code to be as lean as possible, and I don't want to have to run IndBuffer1[0] = EMPTY_VALUE every time a new M1 chart bar is formed, if only I could clear out those shifted values. But if I can't find a way to reset the entire indicator buffer in one go, I don't see any other choice?

Thanks,

Vaughan
Alain Verleyen
38676
Alain Verleyen  
VSc:
...

I am not sure I understand your problem. Why isn't your tick values not drawn from bar 0 ? (on your second screenshot).

I can't find a way to reset the entire indicator buffer in one go

ArrayInitialize(IndBuffer1,EMPTY_VALUE);

"I don't want to have to run IndBuffer1[0] = EMPTY_VALUE every time a new M1 chart bar is formed"

You always have to set a buffer value to a new candle, otherwise it will be random value.

VSc
18
VSc  
Alain Verleyen:

I am not sure I understand your problem. Why isn't your tick values not drawn from bar 0 ? (on your second screenshot).

Unless your tick bars are very large, they will (at times) be drawn faster than the M1 bars. So every time a tick bar completes at bar 0, the indicator values have to shift along one position to draw the next one at bar 0. But I want lean code, so why run code to shift the indicator on every tick bar if I don't have to? Instead when the latest bar is drawn at bar 0, I shift the indicator maybe 15 positions, then draw the next bar at 14, 13 and so on - that way the code that shifts the indicator is not running every tick bar (only every 15 at least). Then for each tick bar other than every 15, I am merely decrementing an int that holds the current position being drawn - a much faster solution.

ArrayInitialize(IndBuffer1, EMPTY_VALUE)

This doesn't initialise IndBuffer1[-1], IndBuffer1[-2] etc. When the chart removes history, it does it 128 bars at a time, so the terminal has pushed values all they way up (down?) to IndBuffer[-128], and ArrayInitialize doesn't reach these negative indicator buffer values. That's what I thought ArrayFree might achieve but it doesn't.

You always have to set a buffer value to a new candle, otherwise it will be random value.

While this may be the case, I have never seen an indicator buffer have a value other than EMPTY_VALUE on a new candle.

My indicator is fast becoming full of code that is written just to handle the chart shifting, which will compromise its accuracy as it misses ticks. I guess the reality is I am just trying to use MT4 indicators in a way they are not designed. All because when the terminal removes history, it shifts the indicator values somewhere that they can't be reached, and has to be redrawn.

Does anyone know if this same behaviour happens in MT5?

Thanks again @Alain Verleyen, your assistance is greatly appreciated.

Vaughan

To add comments, please log in or register