Blog
Pine Script request.security in MQL5: Multi-Timeframe Guide
Quick Answer
request.security in Pine Script reads a value from another timeframe (or another symbol). In MQL5 there is no single call for it. You pass the timeframe directly to the function that needs it, for example iClose(_Symbol, PERIOD_H4, 1) or iMA(_Symbol, PERIOD_H4, 50, 0, MODE_EMA, PRICE_CLOSE).
For a stable signal, read the last closed higher-timeframe bar (shift 1). A value taken from the bar that is still forming (shift 0) changes while the bar builds, which is the same repainting risk that request.security has on live bars.
Key Facts
| Pine Script | MQL5 |
|---|---|
| request.security(sym, "240", close) | iClose(sym, PERIOD_H4, shift) |
| request.security(sym, "240", ta.ema(close, 50)) | iMA(sym, PERIOD_H4, 50, 0, MODE_EMA, PRICE_CLOSE) plus CopyBuffer |
| Timeframe as a string such as "240" or "D" | ENUM_TIMEFRAMES such as PERIOD_H4 or PERIOD_D1 |
| Another symbol | Use that symbol name, and make sure it is in Market Watch |
| Value of the higher bar still forming | Shift 0 on that timeframe (can change) |
| Value of the last closed higher bar | Shift 1 on that timeframe |
The Pine Script Version
//@version=5
strategy("H4 trend filter", overlay = true)
htfEma = request.security(syminfo.tickerid, "240", ta.ema(close, 50))
longOk = close > htfEma
This strategy asks for a 50-period EMA of the 4-hour chart and compares the current chart's close with it. Check the Pine documentation for how your version of request.security treats the lookahead setting, because it decides whether the value can change on live bars.
Why Repainting Matters
On a chart with a lower timeframe than the one you request, a live higher-timeframe bar is still forming. A value read from it can change from one tick to the next, so a condition that was true a moment ago can turn false before the bar closes. A backtest can hide this, because on historical data every higher-timeframe bar is already complete.
The practical rule is to base the decision on the last closed higher-timeframe bar. In MQL5 that is shift 1 on the higher timeframe. The signal then updates only when that bar closes, and it does not flip back.
Full MQL5 Example
This EA reads a 50-period EMA from the H4 timeframe and checks whether the last closed chart bar closed above it. It prints a message once per new bar and does not place trades.
input ENUM_TIMEFRAMES FilterTF = PERIOD_H4;
input int FilterEmaPeriod = 50;
int filterHandle = INVALID_HANDLE;
int OnInit()
{
filterHandle = iMA(_Symbol, FilterTF, FilterEmaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(filterHandle == INVALID_HANDLE)
{
Print("Failed to create filter handle. Error: ", GetLastError());
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
void OnDeinit(const int reason)
{
if(filterHandle != INVALID_HANDLE)
IndicatorRelease(filterHandle);
}
// Reads one value from the handle. Shift counts bars on the handle's own timeframe.
bool ReadValue(int handle, int shift, double &value)
{
if(BarsCalculated(handle) < shift + 1)
return false; // data not ready yet
double buf[];
ArraySetAsSeries(buf, true);
if(CopyBuffer(handle, 0, shift, 1, buf) != 1)
return false;
value = buf[0];
return true;
}
bool IsNewBar()
{
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(_Symbol, _Period, 0);
if(currentBarTime == 0)
return false;
if(currentBarTime == lastBarTime)
return false;
lastBarTime = currentBarTime;
return true;
}
void OnTick()
{
if(!IsNewBar())
return;
double htfEma;
if(!ReadValue(filterHandle, 1, htfEma)) // last closed H4 bar
return;
double chartClose = iClose(_Symbol, _Period, 1); // last closed chart bar
if(chartClose == 0.0)
return;
bool longOk = (chartClose > htfEma);
PrintFormat("Chart close %.5f, %s EMA(%d) %.5f, longOk = %s",
chartClose,
EnumToString(FilterTF),
FilterEmaPeriod,
htfEma,
longOk ? "true" : "false");
}
Notice that the handle is created once in OnInit(), not on every tick. The same CopyBuffer safety checks are explained in the MQL5 CopyBuffer guide.
Reading Another Symbol
Pine can request another symbol, for example request.security("EURUSD", "D", close). In MQL5 you pass that symbol name to the function. The symbol must exist at your broker and be visible in Market Watch, so select it first:
string otherSymbol = "EURUSD";
if(!SymbolSelect(otherSymbol, true))
Print("Could not select ", otherSymbol);
double dailyClose = iClose(otherSymbol, PERIOD_D1, 1);
Broker symbol names often carry a suffix, such as EURUSD.m, so check the exact name in your terminal.
Data May Not Be Ready on the First Tick
The first time an EA asks for another timeframe or symbol, the terminal may need to load or build that history. Early calls can return no data, and CopyBuffer may return -1 or fewer values than requested. The example above handles this by returning false and trying again on the next new bar. Do not read the array without checking, because that leads to an array out of range error.
Why the Values Can Differ From TradingView
- Different bar boundaries. A 4-hour or daily bar starts at a time that depends on the platform's time zone and session settings. Broker server time often differs from TradingView, so the same "H4 bar" can cover a different set of candles.
- Different data feed. Open, high, low and close can differ slightly between sources.
- Shift 0 vs shift 1. A Pine value taken from a forming bar is not the same as the last closed bar in MQL5, by design.
- Different symbol or session. The broker symbol and the TradingView symbol may not be identical instruments.
For a wider list of reasons a converted strategy behaves differently, see why a Pine Script strategy gives different results in MQL5.
Common Mistakes
- Using shift 0 on the higher timeframe. The value changes until the bar closes.
- Creating the indicator handle inside
OnTick(). It wastes resources. Create it once inOnInit(). - Passing the chart timeframe by accident. Writing
_PeriodorPERIOD_CURRENTinstead of the higher timeframe returns chart data. - Assuming the higher-timeframe candles match TradingView. They depend on the platform's time and session settings.
- Not checking data readiness. The first calls on another timeframe can fail.
- Forgetting Market Watch for another symbol. The call may return nothing if the symbol is not selected.
- Mixing shift meanings. On the higher timeframe, shift counts higher-timeframe bars, not chart bars. See Pine Script close[1] in MQL5 for the basics of shifts.
FAQ
What is the MQL5 equivalent of request.security?
There is no single function. You pass the timeframe or symbol to iClose, iMA or another indicator function and read the value at the shift you need.
How do I get the daily close in MQL5?
Use iClose(_Symbol, PERIOD_D1, 1) for the last closed daily bar. Use shift 0 only if you accept that it changes during the day.
Does MQL5 repaint like request.security can?
Reading shift 0 on a higher timeframe can change until that bar closes. Reading shift 1 does not.
Why does my H4 value not match TradingView?
Broker server time and TradingView use different time settings, so H4 candles can start at different times. Data feeds may also differ.
Can I use a higher timeframe inside an EA that runs on M15?
Yes. The EA runs on the chart timeframe, and you read the other timeframe through the function arguments, as in the example above.
Convert Multi-Timeframe Logic Safely
Every request.security call has to become the right timeframe, shift and data check in MQL5, and one wrong shift changes the signal. For the full conversion process, see the Pine Script to MQL5 guide. CodeFlowOS translates Pine Script into MQL5 and lets you review the generated code before you test it in the MT5 Strategy Tester. You can try it on the converter page.
This article is educational. It does not describe trading performance and is not financial advice. Always compile and test code in MetaEditor and the Strategy Tester before using it on a live account.