Can a buffer update in the middle of two commands?

 

I've been wondering if I need to do anything about that possibility. Perhaps the odds of it happening are too small, perhaps it's theoretically impossible for a reason that I'm not aware of. And if it can be an issue, I'm wondering what I should do about it and running out of ideas so any help would be appreciated...

As an example, if I run this EA:

bool buffer_can_update_in_the_middle_of_two_commands = false;

void OnTick() {

        datetime TimeArray[];

        CopyTime(_Symbol, PERIOD_M1, 0, 1, TimeArray);
        datetime FirstBufferCopy = TimeArray[0];

        CopyTime(_Symbol, PERIOD_M1, 0, 1, TimeArray);
        datetime SecondBufferCopy = TimeArray[0];

        if (FirstBufferCopy != SecondBufferCopy) {
                buffer_can_update_in_the_middle_of_two_commands = true;
        }    

}

...if I let this run for infinity, either copying times from the current symbol or other symbols in market watch, would it be possible for buffer_can_update_in_the_middle_of_two_commands to ever become true?

I know this is not something you would probably have to do (copying the same buffer twice), this is just a simplified way of asking if it's possible for a new bar to receive its first tick in the middle of two commands in the OnTick function, making it so that the two buffer copies are copying values from different bars even though they use the same index?

Thanks for any help or insight you can give me!

Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
Symbol Properties - Environment State - Constants, Enumerations and Structures - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
The example is completely meaningless.
 
Vladimir Karputov #:
The example is completely meaningless.

I'm not sure what you mean. I just finished making a sort of semi-infinite loop to try to produce the issue of having a buffer update in between two commands. After I got up to 10,000,000 iterations per tick, the issue started being produced pretty much every minute. But did I program the experiment correctly? If so, does anyone have any ideas how to prevent any problems from occuring with this, even though the odds of it happening are slim?

See this code to replicate this issue if you use enough tick iterations to simulate an infinite for loop:

input long maximum_iterations_per_tick = 10000000;

bool copied_buffer_value_did_not_update;
long maximum_iterations;
string symbol_the_EA_runs_on = _Symbol;
string other_symbol_to_copy_buffer_from = "USDCAD";

datetime TimeArray1[];
datetime TimeArray2[];

void OnInit() {
        maximum_iterations = maximum_iterations_per_tick;
        copied_buffer_value_did_not_update = true;
}

void OnTick() {

        if (copied_buffer_value_did_not_update) {

                for (long i = 0; i < maximum_iterations; i++) {

                CopyTime(other_symbol_to_copy_buffer_from, PERIOD_M1, 0, 1, TimeArray1);
                CopyTime(other_symbol_to_copy_buffer_from, PERIOD_M1, 0, 1, TimeArray2);

                if (TimeArray1[0] != TimeArray2[0]) {
                copied_buffer_value_did_not_update = false;
                Print("The buffer updated in the middle of two commands as it received a tick for a new open on USDCAD");
                maximum_iterations = 0;
                break;
                }
                
                CopyTime(symbol_the_EA_runs_on, PERIOD_M1, 0, 1, TimeArray1);
                CopyTime(symbol_the_EA_runs_on, PERIOD_M1, 0, 1, TimeArray2);

                if (TimeArray1[0] != TimeArray2[0]) {
                copied_buffer_value_did_not_update = false;
                Print("The buffer updated in the middle of two commands as it received a tick for a new open on the current chart");
                maximum_iterations = 0;
                break;
                } 
        
                }
        
                Print("Maximum iterations per tick reached");
        
        }
}

ps: I'm testing it on two symbols at the same time in case it would make a difference if accessing a buffer updated by ticks for a symbol different than the one triggering the EA's OnTick function, and it didn't seem to make a difference. Either of the symbols can end up having an issue with the buffer update according to the tests I made with the above code...

Any thoughts or advice to avoid this?

***The only thing that comes to mind as a solution, which I know works but I was wondering if there was a way to avoid having to do that, is to only copy a buffer from a symbol/timeframe immediately after a new bar open, this way you're making it nearly impossible the buffer to update while your code runs... Maybe this is the only way to prevent the issue, unless I'm missing something??***
 

Get that bad idea out of your head. I repeat: Your idea does not make sense. In addition, your code is wrong - you send the command, but do not check the result. You are using an array of an OUTSIDE declared procedure - this is dangerous, as it may leave garbage.

Please throw away your code and never do that again.

 
Vladimir Karputov #:

Get that bad idea out of your head. I repeat: Your idea does not make sense. In addition, your code is wrong - you send the command, but do not check the result. You are using an array of an OUTSIDE declared procedure - this is dangerous, as it may leave garbage.

Please throw away your code and never do that again.

I don't understand why you're saying this... of course the first code wasn't worth compiling, I just used it as a way to explain my thought process. The second code though in my reply can be compiled and proves what I'm saying, you can try it if you want, just attach it to a chart and watch what prints when a new M1 bar opens. I know I'm not checking the results of the command but that's just for the experiment because I want to increase the chances of being between two CopyTime commands when a new M1 bar opens (by limiting the amount of commands in the for loop that the code is purposely stuck in while new ticks are coming in). Maybe I'm not clear enough, I added an extra check that prints the results of the CopyTime command so that you can see more clearly what the experiment is for:

input long maximum_iterations_per_tick = 10000000;

bool copied_buffer_value_did_not_update;
long maximum_iterations;
string symbol_the_EA_runs_on = _Symbol;
string other_symbol_to_copy_buffer_from = "USDCAD";

datetime TimeArray1[];
datetime TimeArray2[];

void OnInit() {
        maximum_iterations = maximum_iterations_per_tick;
        copied_buffer_value_did_not_update = true;
}

void OnTick() {

        if (copied_buffer_value_did_not_update) {

                for (long i = 0; i < maximum_iterations; i++) {

                CopyTime(other_symbol_to_copy_buffer_from, PERIOD_M1, 0, 1, TimeArray1);
                CopyTime(other_symbol_to_copy_buffer_from, PERIOD_M1, 0, 1, TimeArray2);

                if (TimeArray1[0] != TimeArray2[0]) {
                copied_buffer_value_did_not_update = false;
                Print("The buffer updated in the middle of two commands as it received a tick for a new open on USDCAD");
                Print("One CopyTime command copied: ",TimeArray1[0]," and the other copies: ",TimeArray2[0]);
                Print("Both commands should have copied the same date, unless a new M1 bar opened (received tick) just before the second CopyTime command");
                maximum_iterations = 0;
                break;
                }
                
                CopyTime(symbol_the_EA_runs_on, PERIOD_M1, 0, 1, TimeArray1);
                CopyTime(symbol_the_EA_runs_on, PERIOD_M1, 0, 1, TimeArray2);

                if (TimeArray1[0] != TimeArray2[0]) {
                copied_buffer_value_did_not_update = false;
                Print("The buffer updated in the middle of two commands as it received a tick for a new open on the current chart");
                Print("One CopyTime command copied: ",TimeArray1[0]," and the other copies: ",TimeArray2[0]);
                Print("Both commands should have copied the same date, unless a new M1 bar opened (received tick) just before the second CopyTime command");
                maximum_iterations = 0;
                break;
                } 
        
                }
        
                Print("Maximum iterations per tick reached");
        
        }

}

When I run this experiment, as soon as a new M1 bar opens, you should expect the CopyTime results to be different, and the experiment shows that while the EA is stuck in the for loop, this buffer update can happen right between two CopyTime commands. See results below:

2022.04.26 08:40:59.845 Buffer copy test (CHFJPY,M1) The buffer updated in the middle of two commands as it received a tick for a new open on USDCAD

2022.04.26 08:40:59.845 Buffer copy test (CHFJPY,M1) One CopyTime command copied: 2022.04.26 15:40:00 and the other copies: 2022.04.26 15:41:00

Of course, this is just an experiment to get the answer to my question, not an idea to implement in an EA, I hoped there is no confusion...

Maybe there's a flaw with the experiment though, something I missed. If so, do you have any suggestions to make the experiment better?

 
Jeepack:

I've been wondering if I need to do anything about that possibility. Perhaps the odds of it happening are too small, perhaps it's theoretically impossible for a reason that I'm not aware of. And if it can be an issue, I'm wondering what I should do about it and running out of ideas so any help would be appreciated...

As an example, if I run this EA:

...if I let this run for infinity, either copying times from the current symbol or other symbols in market watch, would it be possible for buffer_can_update_in_the_middle_of_two_commands to ever become true?

I know this is not something you would probably have to do (copying the same buffer twice), this is just a simplified way of asking if it's possible for a new bar to receive its first tick in the middle of two commands in the OnTick function, making it so that the two buffer copies are copying values from different bars even though they use the same index?

Thanks for any help or insight you can give me!

Well since you're asking for the opening time of the current bar, at each tick & since the new bar starts with a new tick ... unlikely!

If the new tick happens between cmd 1 & cmd 2, the current OnTick() will return & a new one will start, with the new opening time or the new bar

I don't imagine the mt team could have make the ontick behave differently ... otherwise ... it would have been a big fail ! 

 
Jeepack #: I don't understand why you're saying this... of course the first code wasn't worth compiling, I just used it as a way to explain my thought process. The second code though in my reply can be compiled and proves what I'm saying, you can try it if you want, just attach it to a chart and watch what prints when a new M1 bar opens. I know I'm not checking the results of the command but that's just for the experiment because I want to increase the chances of being between two CopyTime commands when a new M1 bar opens (by limiting the amount of commands in the for loop that the code is purposely stuck in while new ticks are coming in). Maybe I'm not clear enough, I added an extra check that prints the results of the CopyTime command so that you can see more clearly what the experiment is for:

When I run this experiment, as soon as a new M1 bar opens, you should expect the CopyTime results to be different, and the experiment shows that while the EA is stuck in the for loop, this buffer update can happen right between two CopyTime commands. See results below:

2022.04.26 08:40:59.845 Buffer copy test (CHFJPY,M1) The buffer updated in the middle of two commands as it received a tick for a new open on USDCAD

2022.04.26 08:40:59.845 Buffer copy test (CHFJPY,M1) One CopyTime command copied: 2022.04.26 15:40:00 and the other copies: 2022.04.26 15:41:00

Of course, this is just an experiment to get the answer to my question, not an idea to implement in an EA, I hoped there is no confusion...

Please excuse the misunderstanding of others’ comments and posts because of language barriers concerns.

Yes, during the execution of an OnTick() event handling, there can be new ticks arriving before returning from the function. During that time, as new ticks arrive, the close prices of all current bars on all time frames for the current symbol will have new values. Also, should it be on the cusp of the timing of a new bar on multiple time-frames, then yes, new candles will form and the open time of the current bars will change.

However, all this usually has very little impact on most EAs, because strategies are usually made to be synchronised based on the opening of a new bar, and decisions made on past bar history (that no longer changes) and not the current bar. So, in these cases, most of the code will always complete their task long before the next M1 minute bar is formed, and will therefore not be affected by currently incoming ticks (except for the management of orders and positions).

There are obviously other types of EAs that depend on current prices, but those are usually based mostly on the actual tick data on not so much on the bar data.

Irrespective of the EA type or strategy, the aim is to make one’s code as efficient as possible, to minimise the effect the changes in current prices can have on its behaviour.

 
Icham Aidibe #: If the new tick happens between cmd 1 & cmd 2, the current OnTick() will return & a new one will start, with the new opening time or the new bar

Wrong. When a new tick arrives, the event is added to the queue, if it isn't already there. When, and only when, the current event function (OnTick, OnCalculate, OnChart, etc.) returns, will the new event handler be started. This is why you can miss ticks.

 
Fernando Carreiro #:

Please excuse the misunderstanding of others’ comments and posts because of language barriers concerns.

Yes, during the execution of an OnTick() event handling, there can be new ticks arriving before returning from the function. During that time, as new ticks arrive, the close prices of all current bars on all time frames for the current symbol will have new values. Also, should it be on the cusp of the timing of a new bar on multiple time-frames, then yes, new candles will form and the open time of the current bars will change.

However, all this usually has very little impact on most EAs, because strategies are usually made to be synchronised based on the opening of a new bar, and decisions made on past bar history (that no longer changes) and not the current bar. So, in these cases, most of the code will always complete their task long before the next M1 minute bar is formed, and will therefore not be affected by currently incoming ticks (except for the management of orders and positions).

There are obviously other types of EAs that depend on current prices, but those are usually based mostly on the actual tick data on not so much on the bar data.

Irrespective of the EA type or strategy, the aim is to make one’s code as efficient as possible, to minimise the effect the changes in current prices can have on its behaviour.

Yes this all makes sense, thanks for your input. I already control for bar open on all symbols with my EA's so I figured that must be the best way to prevent this issue but I was wondering if that was really necessary, now I see that it is. Also, I now realize that for some special types of functions, I may want to check the time buffer at the start of the function and once again at the end to verify that it wasn't update during the processing just to be safe... thanks for your reply!

 
My two cents.

Windows is an preemptive OS, MT is a multi threaded application. You are most probably using a multi core CPU.

Things should happen parallel. You never know the current state, all you get is a snapshot of the moment of reading data.

This will ultimately always have inconsistencies.

MT does not provide any mutex or semaphore to lock updates to the data into a critical section over their API.

You will have to take measures to overcome this. One possible option is to query by CopyRates, which will give you a complete snapshot of all data available at that particular moment. You won't get closer to that.

Another approach could be to have an EA that only snaps the data in OnTick and writes it away as fast as possible. This way you increase the chances of actually catching every incoming tick.

You will need another EA to read that data and process it according to your strategy.

But I personally don't see any reason for doing so. Maybe it could be a way to implement a multi threaded approach of a very complex strategy. You would at least get multiple threads executing your logic.

This will for sure raise other synchronizing issues.

It all depends on what you actually need. Mostly it is over estimated, what is actually needed and what is technically possible.


 
Dominik Christian Egert #:
My two cents.

Windows is an preemptive OS, MT is a multi threaded application. You are most probably using a multi core CPU.

Things should happen parallel. You never know the current state, all you get is a snapshot of the moment of reading data.

This will ultimately always have inconsistencies.

MT does not provide any mutex or semaphore to lock updates to the data into a critical section over their API.

You will have to take measures to overcome this. One possible option is to query by CopyRates, which will give you a complete snapshot of all data available at that particular moment. You won't get closer to that.

Another approach could be to have an EA that only snaps the data in OnTick and writes it away as fast as possible. This way you increase the chances of actually catching every incoming tick.

You will need another EA to read that data and process it according to your strategy.

But I personally don't see any reason for doing so. Maybe it could be a way to implement a multi threaded approach of a very complex strategy. You would at least get multiple threads executing your logic.

This will for sure raise other synchronizing issues.

It all depends on what you actually need. Mostly it is over estimated, what is actually needed and what is technically possible.

Thanks for your input!

Even CopyRates won't help me though because I'm getting rates from 28 pairs and about 10 timeframes so I need to work with multiple commands and these get executed, like you say, in parallel with the changing quotes in my terminal.

I think, like Fernando says, one of the main ideas around this is waiting until a new bar receives its first tick before placing any queries on that symbol's buffers. I already do that on all multi-symbol EA's. The disadvantage though, for my application, is that if you want to compare data accross many symbols before making any programmatic decisions, you need to wait until every symbol gets its new bar's first tick so 27 symbols could be stuck waiting for 1 symbol who's getting it's first M1 tick a bit late. I'm not sure I can think of any other solutions for working with multi-symbol functions. If I could, I would make my EA run calculations every time the seconds on the server clock would be equal to zero without waiting for the new opens (since I would already have the previous closes).

But also, like Fernando says, you have to think of alternative solutions if you can't solve the issue by controlling for bar opens, depending on the application. So for example if you want to trigger an event instantaneously as you click on a chart object, then you don't want to wait for the next bar to open before performing calculations. My solution for a situation like this, based on the above experimental code, will be to query iTime for index 0 before running the function, then again iTime for index 0 after all the function's commands are executed. Then I'll check if both iTime queries returned the same value and if not, re-process the function until they do. In other words, the function returns valid results only if it was able to start and end without having any of its buffers update.

Example code:

double get_calculation_results() {

        double calculation_result;

        while (true) {

                datetime last_open_time_before_calculations = iTime(_Symbol,PERIOD_CURRENT,0);

                /* insert code for calculations from multiple buffers and store results as calculation_result */
                        
                datetime last_open_time_after_calculations = iTime(_Symbol,PERIOD_CURRENT,0);

                if (last_open_time_before_calculations == last_open_time_after_calculations) {

                        return calculation_result;

                }

        }

}

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

        if (id == CHARTEVENT_OBJECT_CLICK) {
        
                if (sparam == "object_will_trigger_calculations_on_click") {

                        Print(get_calculation_results());                       

                }

        }

}

I think I know what solutions to use now for my current needs but I still have to work within certain limitations so if anyone has any other ideas to share, feel free to let me know. What I'd be looking for, if it exists, is a way to stop any new ticks from being received by the terminal or stop any buffer from being updated until all calculations are processed. So if you know how to "stop the time", I'm interested! By the way I want to keep this within MQL5's possibilities so I'm not looking for a way to "freeze" my internet connection while the EA is processing commands... I'm sure this would work as crazy as it sounds!