Issue with iBarShift Function for CSV Data

 

I am currently experiencing an issue where the iBarShift function returns a bar position ( pos ) that is outside the expected range when reading date and balance data from a CSV file. Specifically, the bar position often exceeds the actual number of bars. This results in the balance value not being correctly reflected. Here is the relevant part of my code:

int OnInit() { ... int pos = iBarShift(NULL, 0, dt, false); if (pos >= 0 && pos < ArraySize(BalanceBuffer)) { BalanceBuffer[pos] = balance; } ... }

Any advice on how to resolve this issue would be greatly appreciated. Thank you!

 
You may find this comment useful, also this one.
Is there a bug or change in MQL5 update? Having problem with iHighest / iLowest functions
Is there a bug or change in MQL5 update? Having problem with iHighest / iLowest functions
  • 2024.05.24
  • Anil Varma
  • www.mql5.com
Another thread with the same issue in OOP class https://www.mql5...
 
Yuta_N:

I am currently experiencing an issue where the iBarShift function returns a bar position ( pos ) that is outside the expected range when reading date and balance data from a CSV file. Specifically, the bar position often exceeds the actual number of bars. This results in the balance value not being correctly reflected. Here is the relevant part of my code:

int OnInit() { ... int pos = iBarShift(NULL, 0, dt, false); if (pos >= 0 && pos < ArraySize(BalanceBuffer)) { BalanceBuffer[pos] = balance; } ... }

Any advice on how to resolve this issue would be greatly appreciated. Thank you!

The problem is that you used iBarShift during OnInit()
 
Don't try to use any price (or indicator) or server related functions in OnInit (or on load or in OnTimer before you've received a tick), as there may be no connection/chart yet:
  1. Terminal starts.
  2. Indicators/EAs are loaded. Static and globally declared variables are initialized. (Do not depend on a specific order.)
  3. OnInit is called.
  4. For indicators OnCalculate is called with any existing history.
  5. Human may have to enter password, connection to server begins.
  6. New history is received, OnCalculate called again.
  7. A new tick is received, OnCalculate/OnTick is called. Now TickValue, TimeCurrent, account information and prices are valid.
 

Hi everyone,

First off, a big thank you to all who helped me with my previous issue regarding the iBarShift function. Your insights were incredibly helpful and I’ve made some progress, but I’m still running into a few problems and could use some more advice.

I'm working on an indicator in MetaTrader 5 (MT5) to display historical balance data by reading from a CSV file and plotting it on the chart. Despite the improvements, iBarShift still returns some unexpected bar indexes.

Here's the relevant part of my code:

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_width1 2

double BalanceBuffer[];
bool dataLoaded = false;

int OnInit()
{
    SetIndexBuffer(0, BalanceBuffer, INDICATOR_DATA);
    IndicatorSetString(INDICATOR_SHORTNAME, "Balance Display");

    // Set array as series
    ArraySetAsSeries(BalanceBuffer, true);

    // Initialize array
    ArrayInitialize(BalanceBuffer, 0);

    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[])
{
    if (!dataLoaded)
    {
        // Get the number of daily bars and resize the array
        int bars = rates_total;
        ArrayResize(BalanceBuffer, bars);

        string file_path = "tester_balance_history_test.csv";
        int file_handle = FileOpen(file_path, FILE_READ | FILE_CSV | FILE_ANSI);
        if (file_handle == INVALID_HANDLE)
        {
            Print("Failed to open file: ", file_path);
            return (0);
        }

        // Skip header line
        FileReadString(file_handle); // Header: DateTime,Balance

        while (!FileIsEnding(file_handle))
        {
            string line = FileReadString(file_handle);
            if (StringLen(line) == 0)
                continue;

            int delimiter_pos = StringFind(line, ",");
            if (delimiter_pos == -1)
            {
                Print("Invalid line: ", line);
                continue;
            }

            string datetime_str = StringSubstr(line, 0, delimiter_pos);
            string balance_str = StringSubstr(line, delimiter_pos + 1);

            double balance = StringToDouble(balance_str);
            datetime dt = StringToTime(datetime_str);

            // Use iBarShift to find the bar position
            int bar_index = iBarShift(NULL, PERIOD_D1, dt, true);
            if (bar_index == -1)
            {
                Print("No bar found for balance data time: ", datetime_str);
                continue;
            }

            // Ensure the bar index is within array bounds
            if (bar_index >= 0 && bar_index < bars)
            {
                BalanceBuffer[bar_index] = balance;
            }
            else
            {
                Print("Bar index for balance data is out of array bounds: ", bar_index, " bars: ", bars);
            }

            // Output debug information
            Print("datetime_str: ", datetime_str, " balance: ", balance, " dt: ", dt, " bar_index: ", bar_index, " bars: ", bars, " time[bar_index]: ", time[bar_index], " current_time: ", TimeToString(TimeCurrent(), TIME_DATE | TIME_MINUTES));
        }

        FileClose(file_handle);
        dataLoaded = true;
    }

    return (rates_total);
}


Issue:

The debug messages show that the bar index returned by iBarShift and the corresponding time don’t match the expected values. Here are some examples:

2024.06.11 11:47:43.280    Balance_Display_20240610 (AUDUSD,D1)    datetime_str: 2022/01/03 00:00 balance: 5710.02 dt: 2022.01.03 00:00:00 bar_index: 632 bars: 8090 time[bar_index]: 1995.09.28 00:00:00 current_time: 2024.06.11 05:47

2024.06.11 11:47:43.280    Balance_Display_20240610 (AUDUSD,D1)    datetime_str: 2022/06/27 00:00 balance: 5990.2 dt: 2022.06.27 00:00:00 bar_index: 507 bars: 8090 time[bar_index]: 1995.04.06 00:00:00 current_time: 2024.06.11 05:47

2024.06.11 11:47:43.280    Balance_Display_20240610 (AUDUSD,D1)    datetime_str: 2022/11/09 00:00 balance: 4974.48 dt: 2022.11.09 00:00:00 bar_index: 410 bars: 8090 time[bar_index]: 1994.11.22 00:00:00 current_time: 2024.06.11 05:47

2024.06.11 11:47:43.280    Balance_Display_20240610 (AUDUSD,D1)    datetime_str: 2023/06/13 00:00 balance: 5083.52 dt: 2023.06.13 00:00:00 bar_index: 258 bars: 8090 time[bar_index]: 1994.04.22 00:00:00 current_time: 2024.06.11 05:47

2024.06.11 11:47:43.280    Balance_Display_20240610 (AUDUSD,D1)    datetime_str: 2024/05/24 00:00 balance: 3924.95 dt: 2024.05.24 00:00:00 bar_index: 12 bars: 8090 time[bar_index]: 1993.05.13 00:00:00 current_time: 2024.06.11 05:47


Questions:

  1. What adjustments are needed to use the iBarShift function to correctly get the bar index corresponding to the datetime in the CSV file?
  2. Is there anything in the code that I might have overlooked or should improve?
  3. Could the issue be related to the timezone settings of the chart data or any other settings?

I would greatly appreciate any further insights or advice from the community.

Thanks again for your help!


 

When you post code please use the CODE button (Alt-S)!

Use the CODE button

Thank you.

 
Sergey Golubev #:

When you post code please use the CODE button (Alt-S)!

Thank you.

Thank you for the reminder!
 
Yuta_N #:

Hi everyone,

First off, a big thank you to all who helped me with my previous issue regarding the iBarShift function. Your insights were incredibly helpful and I’ve made some progress, but I’m still running into a few problems and could use some more advice.

I'm working on an indicator in MetaTrader 5 (MT5) to display historical balance data by reading from a CSV file and plotting it on the chart. Despite the improvements, iBarShift still returns some unexpected bar indexes.

Here's the relevant part of my code:


Issue:

The debug messages show that the bar index returned by iBarShift and the corresponding time don’t match the expected values. Here are some examples:


Questions:

  1. What adjustments are needed to use the iBarShift function to correctly get the bar index corresponding to the datetime in the CSV file?
  2. Is there anything in the code that I might have overlooked or should improve?
  3. Could the issue be related to the timezone settings of the chart data or any other settings?

I would greatly appreciate any further insights or advice from the community.

Thanks again for your help!


since you use iBarShift index, use iTime to get the correct corresponding open time and print


or bars-bar_index-1

 
Yuta_N #:
        ArrayResize(BalanceBuffer, bars);

The buffers are managed by terminal. Please DO NOT interfere. Avoid using ArrayResize and ArrayInitialize etc on the buffers.

Yuta_N #:
            int delimiter_pos = StringFind(line, ",");

Use StringSplit to split string using delimiters. It is simple and straightforward.

 

I need help with correctly displaying the balance graph using data from a CSV file. Here is my current code and the corresponding debug messages:

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_width1 2

double BalanceBuffer[];
bool data_loaded = false;
const int MAX_BARS = 1000;

int OnInit()
{
    SetIndexBuffer(0, BalanceBuffer, INDICATOR_DATA);
    IndicatorSetString(INDICATOR_SHORTNAME, "Balance Display");
    ArraySetAsSeries(BalanceBuffer, true);
    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[])
{
    int limited_rates_total = MathMin(rates_total, MAX_BARS);

    if (!data_loaded)
    {
        string file_path = "tester_balance_history.csv";
        int file_handle = FileOpen(file_path, FILE_READ | FILE_CSV | FILE_ANSI);
        if (file_handle == INVALID_HANDLE)
        {
            Print("Failed to open file: ", file_path);
            return (prev_calculated);
        }

        FileReadString(file_handle);
        FileReadString(file_handle);

        while (!FileIsEnding(file_handle))
        {
            string line = FileReadString(file_handle);
            string parts[];
            int parts_count = StringSplit(line, ',', parts);
            if (parts_count < 2)
            {
                Print("Invalid line: ", line);
                continue;
            }

            string datetime_str = parts[0];
            string balance_str = parts[1];
            Print("Read line: ", line);

            double balance = StringToDouble(balance_str);
            datetime dt = StringToTime(datetime_str);
            int pos = iBarShift(NULL, 0, dt);

            datetime bar_time = iTime(NULL, 0, pos);
            Print("datetime_str: ", datetime_str, " balance: ", balance, " dt: ", dt, " pos: ", pos, " bar_time: ", bar_time);

            if (pos >= 0 && pos < limited_rates_total)
            {
                int buffer_index = limited_rates_total - 1 - pos;
                if (buffer_index >= 0 && buffer_index < limited_rates_total)
                {
                    BalanceBuffer[buffer_index] = balance;
                    Print("Stored in buffer: BufferIndex = ", buffer_index, " Balance = ", balance);
                }
                else
                {
                    Print("Invalid buffer index: BufferIndex = ", buffer_index);
                }
            }
            else
            {
                Print("Invalid bar position: pos = ", pos, " datetime = ", datetime_str, " dt = ", dt);
            }
        }

        FileClose(file_handle);
        data_loaded = true;
    }

    return (limited_rates_total);
}

Debug messages:

2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Read line: 2023/1/4 0:00,5990.2
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) datetime_str: 2023/1/4 0:00 balance: 5990.2 dt: 2023.01.04 00:00:00 pos: 374 bar_time: 2023.01.04 00:00:00
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Stored in buffer: BufferIndex = 625 Balance = 5990.2
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Read line: 2023/1/5 0:00,4974.48
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) datetime_str: 2023/1/5 0:00 balance: 4974.48 dt: 2023.01.05 00:00:00 pos: 373 bar_time: 2023.01.05 00:00:00
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Stored in buffer: BufferIndex = 626 Balance = 4974.48
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Read line: 2023/1/6 0:00,5083.52
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) datetime_str: 2023/1/6 0:00 balance: 5083.52 dt: 2023.01.06 00:00:00 pos: 372 bar_time: 2023.01.06 00:00:00
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Stored in buffer: BufferIndex = 627 Balance = 5083.52
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Read line: 2023/1/9 0:00,3924.95
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) datetime_str: 2023/1/9 0:00 balance: 3924.95 dt: 2023.01.09 00:00:00 pos: 371 bar_time: 2023.01.09 00:00:00
2024.06.13 09:28:14.861 Balance_Display_20240612_1341_ (AUDUSD,D1) Stored in buffer: BufferIndex = 628 Balance = 3924.95

The data seems to be read correctly and stored in the buffer, but the balance graph does not display correctly. How can I resolve this issue?

Thank you for your help!

 
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1   DRAW_LINE
#property indicator_color1 Red
#property indicator_width1 2

double BalanceBuffer[];
bool data_loaded = false;
const int MAX_BARS = 1000;

int OnInit()
{
    SetIndexBuffer(0, BalanceBuffer, INDICATOR_DATA);
    IndicatorSetString(INDICATOR_SHORTNAME, "Balance Display");
    ArraySetAsSeries(BalanceBuffer, true);
    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[])
{
    int limited_rates_total = MathMin(rates_total, MAX_BARS);

    if (!data_loaded)
    {
        string file_path = "tester_balance_history.csv";
        int file_handle = FileOpen(file_path, FILE_READ | FILE_CSV | FILE_ANSI);
        if (file_handle == INVALID_HANDLE)
        {
            Print("Failed to open file: ", file_path);
            return (prev_calculated);
        }

        FileReadString(file_handle);
        FileReadString(file_handle);

        while (!FileIsEnding(file_handle))
        {
            string line = FileReadString(file_handle);
            string parts[];
            int parts_count = StringSplit(line, ',', parts);
            if (parts_count < 2)
            {
                Print("Invalid line: ", line);
                continue;
            }

            string datetime_str = parts[0];
            string balance_str = parts[1];
            Print("Read line: ", line);

            double balance = StringToDouble(balance_str);
            datetime dt = StringToTime(datetime_str);
            int pos = iBarShift(NULL, 0, dt);

            datetime bar_time = iTime(NULL, 0, pos);
            Print("datetime_str: ", datetime_str, " balance: ", balance, " dt: ", dt, " pos: ", pos, " bar_time: ", bar_time);

            if (pos >= 0 && pos < limited_rates_total)
            {
                int buffer_index = pos; //limited_rates_total - 1 - pos; ==> You do not need to reverse it manually. You already have time-series flag set to true.
                if (buffer_index >= 0 && buffer_index < limited_rates_total)
                {
                    BalanceBuffer[buffer_index] = balance;
                    Print("Stored in buffer: BufferIndex = ", buffer_index, " Balance = ", balance);
                }
                else
                {
                    Print("Invalid buffer index: BufferIndex = ", buffer_index);
                }
            }
            else
            {
                Print("Invalid bar position: pos = ", pos, " datetime = ", datetime_str, " dt = ", dt);
            }
        }

        FileClose(file_handle);
        data_loaded = true;
    }

    return (limited_rates_total);
}

There is more to discuss with this code. However let it work for now.

The CSV I tested with is attached.