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)| Parameter | Description |
|---|---|
symbol | Symbol code; use syminfo.tickerid for the current symbol |
timeframe | Target timeframe as a string (see table below) |
expression | The value to retrieve (e.g. close, ta.sma(close, 20)) |
gaps | How to handle the period when a larger timeframe bar hasn’t closed yet |
lookahead | Whether to allow future data (must be off for strategy backtesting) |
Timeframe String Format#
| String | Description |
|---|---|
"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:
| Constant | Description |
|---|---|
barmerge.gaps_off | Use the last confirmed bar’s value (default — value “extends”) |
barmerge.gaps_on | Return 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")