CopyBuffer returns 0

 

Hey guys!


I'm facing an issue with CopyBuffer specifically when using Strategy Tester on non-visual mode. Basically, in some occasions, it fills the target array with 0. This is no indicator problem - at least, that's what I think, because:


1 - On visual testing my EA works just fine;

2 - On non-visual testing, I inserted a few Print calls along my code - including in the indicator - and all buffers are filled with the correct data (non-zero data).


I read somewhere that data may not be available when calling CopyBuffer, but it should return -1 to handle this error. That's not the case.


This is the code I'm using to retrieve the indicator data (it's a class-wrapper around a custom indicator):

double Get(int buffer, int index)
{

    int res = CopyBuffer(m_handle, buffer, index, 1, m_array);
    if(res == -1)
    {
        Print(">>> Indicator result -1 - error = ", GetLastError());

        return 0;
    }

    return m_array[0];
}



CopyBuffer always returns 1 (that would be expected if retrieved data were correct; it should return -1 otherwise, afaik).


Can anyone spot what I'm missing here? It's quite weird this bug only occur in non-visual testing mode and just on some calls - sometimes it works perfectly fine.


Thanks in advance.

The Fundamentals of Testing in MetaTrader 5
The Fundamentals of Testing in MetaTrader 5
  • www.mql5.com
What are the differences between the three modes of testing in MetaTrader 5, and what should be particularly looked for? How does the testing of an EA, trading simultaneously on multiple instruments, take place? When and how are the indicator values calculated during testing, and how are the events handled? How to synchronize the bars from different instruments during testing in an "open prices only" mode? This article aims to provide answers to these and many other questions.
 

The CopyBuffer function returns the number of copied elements or -1 if it fails. When CopyBuffer fails, it doesn't necessarily mean that data is unavailable. It could indicate various errors, such as an invalid handle or incorrect buffer parameters.

In your code snippet, when CopyBuffer returns -1, you're handling it by printing an error message with GetLastError() and returning 0. This is a reasonable approach to handle the error, but it's important to understand the potential reasons for the failure:

  1. Ensure that m_handle is a valid indicator handle.
  2. Check that buffer and index parameters are within valid ranges.
  3. Verify that m_array is properly initialized and has enough space to hold the copied data.

If GetLastError() returns a specific error code, it might give you more insight into the cause of the failure. Common error codes include ERR_INVALID_HANDLE (4051) for an invalid handle, ERR_ARRAY_INDEX_OUT_OF_RANGE (4002) for an out-of-range index, or ERR_PARAMETERS_INVALID (4053) for incorrect function parameters.

Make sure to review your code and the context in which Get function is called to ensure that the inputs are correct and that the error handling adequately covers possible failure scenarios.

 

If you could elaborate a bit more it would have been helpful, however i can try assist on what i see here.

Based on your description, it seems like you're encountering an issue with CopyBuffer returning unexpected results when running your Expert Advisor (EA) in non-visual mode within the Strategy Tester. I can give you a few considerations and potential solutions, however i can not see what the rest of the code looks like, I have highlighted some checks you can do down below:

Check your Data Availability: You mentioned that you've verified that the data is correct by inserting Print calls. However, it's possible that the data may not be fully available at the moment CopyBuffer is called. In non-visual mode, the timing of data availability may differ compared to visual mode due to differences in how data is processed. Ensure that the data you're trying to access is indeed available at the point CopyBuffer is called.
Analyse Timing and Synchronization in your code: In non-visual mode, it's crucial to ensure proper synchronization and timing between different parts of your code, especially if you're relying on asynchronously updating data. Make sure that the indicator data is updated and ready to be copied before calling CopyBuffer .
Check Handling Data or Unavailability: If data is not available when CopyBuffer is called, it might not return -1 as expected. Instead, it may return a value indicating success ( 1 ) and fill the target array with zeros. You may need to implement additional checks to verify data availability before calling CopyBuffer , or handle the case where zeros are returned separately from other errors.
Check Debugging and Logging: Consider adding more detailed logging and debugging statements to trace the execution flow and data values at different points in your code. This can help pinpoint exactly where the issue occurs and provide more insight into the problem.
Review Indicator Logic: Since CopyBuffer is working fine in visual mode but encountering issues in non-visual mode, it's possible that there are differences in how your indicator logic behaves in these modes. Review your indicator logic to ensure it behaves consistently regardless of the testing mode.
Consult your Indicator Documentation: Check the documentation or specifications of the custom indicator you're using to understand any specific behaviors or limitations related to data retrieval, especially in the context of automated testing.

 
I have experienced a few cases where the indicator relied on objects on chart to do calculations of buffers. In that case you usually end up different results in visual and non-visual backtesting.
 

Thanks for your answers, guys.


After further investigation, I managed to fix my code. There was indeed a bug in the indicator code, although it had nothing to do with this specific issue. For public knowledge, I fixed this by adding a UpdateBuffers member function to the indicator class-wrapper that will update m_array (or every array class member that stores each indicator buffer data). Then, in the EA code, I call this method only once every new candle. The Get function now directly returns the desired data for the specified buffer/index. This way I can access the same data multiple times and call CopyBuffer only once every candle.


I believe there's some kind of bug (or I'm really missing something) that makes CopyBuffer 'erase' the indicator data until it gets updated or a new candle occurs. The first call for the Nth candle seems to work fine, but subsequent calls may fail and not return an error code.


Again, thanks, guys.