Strategy tester with visual mode enabled applies different precedences to the indicators

 

Hi,

I created an indicator calling another internally indicator. They are called using the iCustom function. If I call with the visual mode enabled, the "OnCalculate" function of the outermost indicator is called first. If I call with the visual mode disabled, the order is reversed.

To explain better, follow the code of the file "Test.mq5":

int OnInit() {
   return(INIT_SUCCEEDED);
}

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[]) {
   Print("1: Test");   
   return(rates_total);
}

And below the source code of "TestWrapper.mq5":

#resource "Test.ex5"

int handler;
double buffer[];

int OnInit() {
   handler = iCustom(Symbol(), PERIOD_M15, "::Test.ex5");
   return
( INIT_SUCCEEDED);
}

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[]) {
   CopyBuffer(handler, 0, 0, 1, buffer);
   Print("2: TestWrapper");
   return(rates_total);
}

And, lastly, the file code of EA "TestEA.mq5":

#resource "TestWrapper.ex5"

int handler;
double buffer[];
int OnInit() {        
   handler = iCustom(Symbol(), Period(), "::TestWrapper.ex5");               
   return
( INIT_SUCCEEDED);         
}

void OnTick() {
   CopyBuffer(handler, 0, 0, 1, buffer);
   Print("3: TestEA");
}

Follow the execution log with Visual Mode Disabled (as expected):

2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:00   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:00   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:00   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:20   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:20   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:20   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:40   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:40   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:40   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:59   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:59   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:09:59   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:00   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:00   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:00   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:20   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:20   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:20   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:40   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:40   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:40   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:59   1: Test
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:59   2: TestWrapper
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:10:59   3: TestEA
2021.09.20 10:57:31.396 Core 01 2019.01.02 09:11:00   1: Test

Follow the execution log with Visual Mode Enabled:

2021.09.20 10:59:30.738 2019.01.02 09:09:00   2: TestWrapper
2021.09.20 10:59:30.738 2019.01.02 09:09:00   1: Test
2021.09.20 10:59:30.738 2019.01.02 09:09:00   3: TestEA
2021.09.20 10:59:30.758 2019.01.02 09:09:20   2: TestWrapper
2021.09.20 10:59:30.758 2019.01.02 09:09:20   1: Test
2021.09.20 10:59:30.758 2019.01.02 09:09:20   3: TestEA
2021.09.20 10:59:30.778 2019.01.02 09:09:40   2: TestWrapper
2021.09.20 10:59:30.778 2019.01.02 09:09:40   1: Test
2021.09.20 10:59:30.778 2019.01.02 09:09:40   3: TestEA
2021.09.20 10:59:30.797 2019.01.02 09:09:59   2: TestWrapper
2021.09.20 10:59:30.797 2019.01.02 09:09:59   1: Test
2021.09.20 10:59:30.797 2019.01.02 09:09:59   3: TestEA
2021.09.20 10:59:30.816 2019.01.02 09:10:00   2: TestWrapper
2021.09.20 10:59:30.816 2019.01.02 09:10:00   1: Test
2021.09.20 10:59:30.816 2019.01.02 09:10:00   3: TestEA
2021.09.20 10:59:30.836 2019.01.02 09:10:20   2: TestWrapper
2021.09.20 10:59:30.836 2019.01.02 09:10:20   1: Test
2021.09.20 10:59:30.836 2019.01.02 09:10:20   3: TestEA
2021.09.20 10:59:30.855 2019.01.02 09:10:40   2: TestWrapper
2021.09.20 10:59:30.855 2019.01.02 09:10:40   1: Test
2021.09.20 10:59:30.855 2019.01.02 09:10:40   3: TestEA
2021.09.20 10:59:30.875 2019.01.02 09:10:59   2: TestWrapper
2021.09.20 10:59:30.875 2019.01.02 09:10:59   1: Test
2021.09.20 10:59:30.875 2019.01.02 09:10:59   3: TestEA
2021.09.20 10:59:30.895 2019.01.02 09:11:00   2: TestWrapper

See that in execution with visual mode enabled, considering the same time in the two executions (9:10:00), running with the visual mode enabled performs the main indicator, "TestWrapper", before running the internal indicator "Test", this generates distortions between backtest results by enabling visual mode or not.

Do you have a way to force the code that the "OnCalculate" method of the "Test" indicator be executed before the "TestWrapper"? Can you specify an order of precedence between the indicators? I wanted the behavior verified in the mode without the visual mode to be the same using visual mode enabled.

 
Since you are using a multithreaded approach in an preemptive environment, you will need to do the synchronisation of your processes yourself inside the code.

You need some sync object to know in which state the objects are.

A possible way could be terminal global variables.

Or a check of the content of the buffers values of each indicator.


 
Dominik Egert #:
Since you are using a multithreaded approach in an preemptive environment, you will need to do the synchronisation of your processes yourself inside the code.

You need some sync object to know in which state the objects are.

A possible way could be terminal global variables.

Or a check of the content of the buffers values of each indicator.


I do not know if I understood your suggestion very well for using terminal global variables. Would I have one global variable by indicator to indicate the last processed candle? If the suggestion is this, I think it could work. But the implementation would be pretty ugly.

Thinking about this approach would not have a form for the functions of MQL5 to identify the last calculated candle?

If you do not have, with this last segester you gave, would you create a new buffer containing the times of the candles?
 
David Guerra #:
I do not know if I understood your suggestion very well for using terminal global variables. Would I have one global variable by indicator to indicate the last processed candle? If the suggestion is this, I think it could work. But the implementation would be pretty ugly.

Thinking about this approach would not have a form for the functions of MQL5 to identify the last calculated candle?

If you do not have, with this last segester you gave, would you create a new buffer containing the times of the candles?

I think she is suggesting that you should use a (Semaphore, mutex, events or something like that) ... they are syncing tools for concurrent processes (threads).

 
karp wak #:

I think she is suggesting that you should use a (Semaphore, mutex, events or something like that) ... they are syncing tools for concurrent processes (threads).

Understand. I'll try something with this approach. Thanks.