Multi-Timeframe Analysis#

In technical analysis, Multi-Timeframe Analysis (MTF) is an important concept: confirm the trend direction on a larger timeframe, then find entry opportunities on a smaller timeframe. Pine Script’s request.security() function lets you fetch data from other timeframes regardless of which timeframe the chart is using.

request.security — Fetching Data from Other Timeframes#

request.security(symbol, timeframe, expression, gaps, lookahead)
ParameterDescription
symbolSymbol code; use syminfo.tickerid for the current symbol
timeframeTarget timeframe as a string (see table below)
expressionThe value to retrieve (e.g. close, ta.sma(close, 20))
gapsHow to handle the period when a larger timeframe bar hasn’t closed yet
lookaheadWhether to allow future data (must be off for strategy backtesting)

Timeframe String Format#

StringDescription
"1"1 minute
"5"5 minutes
"15"15 minutes
"60"1 hour
"240"4 hours
"D"Daily
"W"Weekly
"M"Monthly

Basic Usage#

Display the daily MA and high/low on a 5-minute chart:

//@version=6
indicator("Daily MA (on minute chart)", overlay=true)

// Get the daily 20-period MA
dailyMA20 = request.security(syminfo.tickerid, "D", ta.sma(close, 20))

// Get the daily high and low
dailyHigh = request.security(syminfo.tickerid, "D", high)
dailyLow  = request.security(syminfo.tickerid, "D", low)

plot(dailyMA20, "Daily MA20",  color=color.orange, linewidth=2)
plot(dailyHigh, "Daily High",  color=color.green,  style=plot.style_stepline)
plot(dailyLow,  "Daily Low",   color=color.red,    style=plot.style_stepline)

gaps Parameter#

gaps controls how to fill smaller timeframe bar values when the larger timeframe bar hasn’t closed yet:

ConstantDescription
barmerge.gaps_offUse the last confirmed bar’s value (default — value “extends”)
barmerge.gaps_onReturn na when not confirmed
// Before each daily bar closes, all smaller timeframes use the same value (extended)
dailyClose = request.security(syminfo.tickerid, "D", close, gaps=barmerge.gaps_off)

lookahead — Avoiding Future Data#

In strategy backtesting, lookahead must be set to barmerge.lookahead_off (the default). Otherwise the script will peek at the close of the current larger timeframe bar, producing misleading backtest results.

// ❌ Has lookahead bias (lookahead_on)
dailyClose_bad = request.security(syminfo.tickerid, "D", close,
                                   lookahead=barmerge.lookahead_on)

// ✅ Correct: use the previous confirmed daily close
dailyClose_ok = request.security(syminfo.tickerid, "D", close[1],
                                  lookahead=barmerge.lookahead_off)

Correct MTF pattern: When retrieving “confirmed” higher timeframe data, use close[1] (shifted by 1) to ensure you’re using the last fully closed bar’s value.

Practical Example: Daily Trend Filter#

On a minute chart, only allow long entries when the daily trend is up:

//@version=6
strategy("Daily Trend Filter Strategy", overlay=true)

fastLen = input.int(5,  "Fast MA")
slowLen = input.int(20, "Slow MA")

// Current timeframe (e.g., 5-minute) MAs
fastMA = ta.sma(close, fastLen)
slowMA = ta.sma(close, slowLen)

// Daily trend: daily close above 20-day MA
dailyMA20    = request.security(syminfo.tickerid, "D", ta.sma(close, 20))
dailyClose   = request.security(syminfo.tickerid, "D", close[1],
                                 lookahead=barmerge.lookahead_off)
dailyUptrend = dailyClose > dailyMA20

// Only go long when the daily trend is bullish
if ta.crossover(fastMA, slowMA) and dailyUptrend
    strategy.entry("Long", strategy.long, comment="Trend-Aligned Long")

if ta.crossunder(fastMA, slowMA)
    strategy.close("Long", comment="Exit")

// Background color to show daily trend direction
bgcolor(dailyUptrend ? color.new(color.green, 92) : color.new(color.red, 92))

Fetching Multiple Values at Once#

request.security can return multiple values as a tuple:

// Get daily OHLC in one call
[dOpen, dHigh, dLow, dClose] = request.security(syminfo.tickerid, "D",
                                                  [open, high, low, close])

Using request.security_lower_tf#

request.security_lower_tf() retrieves data from a lower timeframe than the current chart, returning an array of all bar values for that timeframe:

//@version=6
indicator("Intraday Bar Stats", overlay=false)

// On the daily chart, get an array of all 5-minute bar closes for the current day
intradayCloses = request.security_lower_tf(syminfo.tickerid, "5", close)

// Count how many 5-minute bars there are today
plot(array.size(intradayCloses), "5-min bar count today")

Reference#