Hi vaishali2304,
When you plot on M1 but read data from higher TFs, the usual cause of “shifted/misplaced” arrows is bar-index mapping and the processing loop.
Key points
-
Map the M1 bar time to each higher-TF bar
Use the M1 bar time time[i] and find the containing bar on each HTF with iBarShift(..., /*exact=*/false) . Then read OHLC from those HTFs at the returned index, but always write to your M1 buffer at i . -
Process forward, avoid bar 0
In MQL5 indicators you should iterate forward from start to rates_total-1 . Skip i = rates_total-1 (the forming bar). -
Copy HTF series once, set as_series
Copy OHLC arrays for each HTF up front and set them as series so indexing matches.
Template you can drop in
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[]) { // --- prepare HTF data MqlRates m5[], m15[], m30[], h1[], h4[], d1[]; int need = rates_total + 100; // a little extra headroom CopyRates(_Symbol, PERIOD_M5, 0, need, m5); CopyRates(_Symbol, PERIOD_M15, 0, need, m15); CopyRates(_Symbol, PERIOD_M30, 0, need, m30); CopyRates(_Symbol, PERIOD_H1, 0, need, h1); CopyRates(_Symbol, PERIOD_H4, 0, need, h4); CopyRates(_Symbol, PERIOD_D1, 0, need, d1); ArraySetAsSeries(m5, true); ArraySetAsSeries(m15, true); ArraySetAsSeries(m30, true); ArraySetAsSeries(h1, true); ArraySetAsSeries(h4, true); ArraySetAsSeries(d1, true); // --- calc window int start = (prev_calculated > 0 ? prev_calculated-1 : 1); // skip bar 0 for(int i = start; i < rates_total-1; i++) // process forward, avoid forming bar { BuyArrowBuffer[i] = EMPTY_VALUE; SellArrowBuffer[i] = EMPTY_VALUE; datetime t = time[i]; // map M1 bar 'i' to bar indexes on each HTF int i5 = iBarShift(_Symbol, PERIOD_M5, t, false); int i15 = iBarShift(_Symbol, PERIOD_M15, t, false); int i30 = iBarShift(_Symbol, PERIOD_M30, t, false); int iH1 = iBarShift(_Symbol, PERIOD_H1, t, false); int iH4 = iBarShift(_Symbol, PERIOD_H4, t, false); int iD1 = iBarShift(_Symbol, PERIOD_D1, t, false); if(i5<0 || i15<0 || i30<0 || iH1<0 || iH4<0 || iD1<0) continue; bool bull = (m5[i5].close > m5[i5].open) && (m15[i15].close> m15[i15].open) && (m30[i30].close> m30[i30].open) && (h1[iH1].close > h1[iH1].open) && (h4[iH4].close > h4[iH4].open) && (d1[iD1].close > d1[iD1].open); bool bear = (m5[i5].close < m5[i5].open) && (m15[i15].close< m15[i15].open) && (m30[i30].close< m30[i30].open) && (h1[iH1].close < h1[iH1].open) && (h4[iH4].close < h4[iH4].open) && (d1[iD1].close < d1[iD1].open); // IMPORTANT: write to M1 buffer at index 'i' if(bull) BuyArrowBuffer[i] = low[i] - _Point * InpArrowShift; if(bear) SellArrowBuffer[i] = high[i] + _Point * InpArrowShift; } return(rates_total); }
Common pitfalls to avoid
-
Using iBarShift(..., true) (exact match) — M1 times rarely equal an HTF bar open; use false .
-
Writing to BuyArrowBuffer[shift] instead of [i] .
-
Iterating backward with as-series confusion while mixing copied arrays that aren’t ArraySetAsSeries(true) .
-
Using bar 0 (still forming) for decisions/plotting.
If you adopt the mapping above (M1 time[i] → HTF index via iBarShift(..., false) ), your arrows will land exactly on the intended M1 bars. Hope this helps!
Please consider which section is most appropriate — https://www.mql5.com/en/forum/172166/page6#comment_49114893
Hi vaishali2304,
When you plot on M1 but read data from higher TFs, the usual cause of “shifted/misplaced” arrows is bar-index mapping and the processing loop.
Key points
-
Map the M1 bar time to each higher-TF bar
Use the M1 bar time time[i] and find the containing bar on each HTF with iBarShift(..., /*exact=*/false) . Then read OHLC from those HTFs at the returned index, but always write to your M1 buffer at i . -
Process forward, avoid bar 0
In MQL5 indicators you should iterate forward from start to rates_total-1 . Skip i = rates_total-1 (the forming bar). -
Copy HTF series once, set as_series
Copy OHLC arrays for each HTF up front and set them as series so indexing matches.
Template you can drop in
Common pitfalls to avoid
-
Using iBarShift(..., true) (exact match) — M1 times rarely equal an HTF bar open; use false .
-
Writing to BuyArrowBuffer[shift] instead of [i] .
-
Iterating backward with as-series confusion while mixing copied arrays that aren’t ArraySetAsSeries(true) .
-
Using bar 0 (still forming) for decisions/plotting.
If you adopt the mapping above (M1 time[i] → HTF index via iBarShift(..., false) ), your arrows will land exactly on the intended M1 bars. Hope this helps!
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
I coded a custom indicator that plots arrows on M1 candles when all higher timeframes (M5, M15, M30, H1, H4, D1) agree with the candle direction.
The arrows appear shifted or misplaced or don't appear at all. I think the problem is with the loop. I am adding the for loop in OnCalculate function below