Pine Script v6: How to Use request.security to Fetch Higher-Timeframe Data
When building multi-timeframe indicators in TradingView, one of the most common needs is to overlay a higher-timeframe signal — such as a daily moving average — onto a lower-timeframe chart like a 15-minute view. The request.security() function is the primary tool for this task in Pine Script v6, and understanding its parameters precisely is essential for writing accurate, non-repainting indicators and strategies.
1. What Is request.security()?
request.security() allows a Pine Script to fetch the value of any expression as it would be calculated on a different symbol or timeframe. The result is then mapped back onto the current chart's bar timeline. This is the foundation of multi-timeframe (MTF) analysis in Pine Script.
For the full official signature, refer to the Reference Manual: request.security() — Pine Script v6 Reference.
2. Core Parameters Explained
The following table describes the most critical parameters you will use in everyday MTF work. Each parameter has been individually verified against the v6 Reference Manual.
| Parameter | Type | Description |
|---|---|---|
symbol |
simple string | The ticker symbol to request data from. Use syminfo.tickerid to reference the current chart's symbol. |
timeframe |
simple string | The resolution string (e.g., "D" for daily, "60" for 1-hour). Can be higher or lower than the chart timeframe. |
expression |
series int/float/bool/color/string or a tuple | The value or expression to evaluate in the requested context. This is computed as if the script were running on the requested timeframe. |
lookahead |
barmerge_lookahead | Controls whether the value of the currently forming HTF bar is used. Accepts barmerge.lookahead_off (default) or barmerge.lookahead_on. |
gaps |
barmerge_gaps | Controls how gaps between HTF bars are filled. barmerge.gaps_off (default) forward-fills the last confirmed value; barmerge.gaps_on returns na between HTF bars. |
3. The Lookahead Parameter: A Critical Detail
The lookahead parameter is the most misunderstood aspect of request.security(). It is essential to understand what it actually does — and does not — do.
barmerge.lookahead_off (Default — Recommended)
With the default setting, each chart bar receives the value of the last fully confirmed HTF bar. For example, on a 15-minute chart requesting daily data, every 15-minute bar within Monday will show Sunday's confirmed daily close. The new daily value only appears once Monday's daily bar closes. This is the correct setting for non-repainting indicators and strategy backtests.
barmerge.lookahead_on (Use with Caution)
With barmerge.lookahead_on, each chart bar receives the value of the currently forming HTF bar — that is, the HTF bar that has not yet closed. For example, on a 15-minute chart, every bar within the current trading day will show the daily bar's value as it is currently forming (its current open, high, low, or close at that moment in real-time). This does not literally provide the final close of the HTF bar in advance during live trading. However, during historical backtesting, because all historical bars are already complete, this setting effectively gives the strategy access to the HTF bar's final value before that bar has closed on the chart — which introduces a significant look-ahead bias and can produce unrealistically optimistic backtest results. Use this setting only when you have a deliberate, well-understood reason to do so.
🔽 [Click to expand] View Full Pine Script Code — barmerge.lookahead_off vs barmerge.lookahead_on
//@version=6
indicator("Lookahead Comparison - Final", overlay=true)
// 1. Data Request
// Lookahead OFF: Standard behavior (No future leak)
dailyCloseOff = request.security(syminfo.tickerid, "D", ta.sma(close, 1)[1], lookahead=barmerge.lookahead_off)
// Lookahead ON: Repainting behavior (Uses future data)
dailyCloseOn = request.security(syminfo.tickerid, "D", ta.sma(close, 1), lookahead=barmerge.lookahead_on)
// 2. Plotting
plot(dailyCloseOff, color=color.red, linewidth=2, title="Lookahead OFF")
plot(dailyCloseOn, color=color.lime, linewidth=2, title="Lookahead ON")
// 3. Labels (Separated to avoid overlapping)
if barstate.islast
// Label for OFF (Positioned below the line)
label.new(bar_index, dailyCloseOff,
text="SAFE: Lookahead OFF\n(Stair-step)",
color=color.red,
textcolor=color.white,
style=label.style_label_up,
yloc=yloc.belowbar)
// Label for ON (Positioned above the line)
label.new(bar_index, dailyCloseOn,
text="WARNING: Lookahead ON\n(Future Leak/Repaint)",
color=color.lime,
textcolor=color.black,
style=label.style_label_down,
yloc=yloc.abovebar)
4. Repainting: Causes and Accurate Mental Model
Repainting in the context of request.security() is often misattributed. It is important to distinguish between two separate concepts:
- Lookahead-induced bias: Using
barmerge.lookahead_onwith a closing price expression on historical data causes the strategy to see the final HTF bar value before it is confirmed. This is the primary source of backtest bias when usingrequest.security(). - Future-dependent expressions: If the
expressionargument itself references future data (e.g., a function that uses future bars), the result will repaint regardless of thelookaheadsetting. - Legitimate lower-timeframe requests: Requesting a lower timeframe than the chart (e.g., requesting 1-minute data on a 15-minute chart) is technically valid and does not inherently cause repainting. The behavior depends on the
barmerge.*settings. However, if you need all intrabar values (not just the last one merged into the chart bar), the correct tool isrequest.security_lower_tf(), which returns an array of all lower-timeframe values within each chart bar.
5. Basic Example: Daily SMA on a 15-Minute Chart
The following script demonstrates the most common use case: fetching a 20-period Simple Moving Average calculated on the daily timeframe and plotting it on a 15-minute chart. The expression ta.sma(close, 20) is evaluated as if the script were running on the daily chart.
🔽 [Click to expand] View Full Pine Script Code — Daily SMA on 15-Minute Chart
//@version=6
indicator("HTF Daily SMA via request.security", overlay = true)
// --- Inputs ---
// Allow the user to configure the higher timeframe and SMA length.
htfInput = input.timeframe("D", title = "Higher Timeframe")
smaLenInput = input.int(20, title = "SMA Length", minval = 1)
// --- HTF Calculation ---
// request.security() evaluates ta.sma(close, smaLenInput) on the daily timeframe.
// barmerge.lookahead_off (default) ensures we only see confirmed daily bars.
// barmerge.gaps_off (default) forward-fills the last confirmed value across all
// 15-minute bars within the same day.
htfSma = request.security(
syminfo.tickerid, // Same symbol as the current chart
htfInput, // The requested timeframe (e.g., "D")
ta.sma(close, smaLenInput),// Expression evaluated on the HTF
lookahead = barmerge.lookahead_off, // Safe default: no look-ahead bias
gaps = barmerge.gaps_off // Forward-fill between HTF bars
)
// --- Plot ---
// Plot the HTF SMA as a thick line on the main chart pane.
plot(
htfSma,
title = "Daily SMA",
color = color.new(color.orange, 0),
linewidth = 2
)
6. Logic Flow Diagram
The following diagram illustrates how request.security() maps higher-timeframe bar data back onto the lower-timeframe chart bars.
7. Fetching Multiple Values with a Tuple
A key efficiency feature of request.security() in v6 is the ability to request multiple values in a single call using a tuple. This avoids the overhead of multiple separate request.security() calls for the same symbol and timeframe.
🔽 [Click to expand] View Full Pine Script Code — Tuple Request (OHLC from Daily)
//@version=6
indicator("HTF OHLC via Tuple Request", overlay = true)
// --- Fetch daily OHLC in a single request.security() call ---
// The expression is a tuple: [open, high, low, close] evaluated on the daily TF.
// Pine Script v6 supports tuple expressions natively in request.security().
[dailyOpen, dailyHigh, dailyLow, dailyClose] = request.security(
syminfo.tickerid,
"D",
[open, high, low, close], // Tuple of four series
lookahead = barmerge.lookahead_off // No look-ahead bias
)
// --- Plot each OHLC level as a horizontal step line ---
plot(dailyOpen, title = "Daily Open", color = color.blue, style = plot.style_stepline)
plot(dailyHigh, title = "Daily High", color = color.green, style = plot.style_stepline)
plot(dailyLow, title = "Daily Low", color = color.red, style = plot.style_stepline)
plot(dailyClose, title = "Daily Close", color = color.orange, style = plot.style_stepline)
8. Lower-Timeframe Requests: A Dedicated Note
While request.security() is most commonly used to fetch higher-timeframe data, it can also be called with a lower timeframe than the current chart. In this case, the behavior is governed by the barmerge.* settings: by default, the value merged into each chart bar is the last lower-timeframe bar's value that falls within that chart bar's time range.
If your use case requires access to all intrabar values — for example, to find the highest high of every 1-minute bar within a 15-minute bar — you should use request.security_lower_tf() instead, which returns an array containing every lower-timeframe value within each chart bar.
🔽 [Click to expand] View Code — Lower-TF Request Comparison
//@version=6
indicator("Lower-TF Request Comparison", overlay = false)
// --- Approach 1: request.security() with a lower TF ---
// Returns the LAST 1-minute close that falls within each 15-minute bar.
// Behavior is controlled by barmerge.* settings.
lastOneMinClose = request.security(
syminfo.tickerid,
"1", // Lower timeframe than a 15-min chart
close,
lookahead = barmerge.lookahead_off,
gaps = barmerge.gaps_off
)
// --- Approach 2: request.security_lower_tf() ---
// Returns an array of ALL 1-minute closes within each 15-minute bar.
// Use array.max() to find the highest close among all intrabar values.
oneMinCloseArray = request.security_lower_tf(syminfo.tickerid, "1", close)
highestIntrabarClose = array.size(oneMinCloseArray) > 0
? array.max(oneMinCloseArray)
: na
// --- Plot both for comparison ---
plot(lastOneMinClose, title = "Last 1-min Close (security)", color = color.blue)
plot(highestIntrabarClose, title = "Highest 1-min Close (lower_tf)", color = color.red)
9. Common Mistakes and How to Avoid Them
| Mistake | Consequence | Correct Approach |
|---|---|---|
Using barmerge.lookahead_on with closing prices in a strategy |
Look-ahead bias in backtests; unrealistically good results | Use barmerge.lookahead_off (default) for all strategy backtests |
Calling request.security() multiple times for the same symbol/TF |
Unnecessary performance overhead | Use a single tuple call to fetch all needed values at once |
Expecting all intrabar values from request.security() on a lower TF |
Only the last merged value is available per chart bar | Use request.security_lower_tf() to get an array of all intrabar values |
Hardcoding the timeframe string (e.g., "D") without an input |
Inflexible indicator; users cannot adjust the HTF | Use input.timeframe() to let users select the timeframe |
10. Conclusion
- Core function:
request.security()evaluates any Pine Script expression on a different symbol or timeframe and maps the result back to the current chart's bar timeline, enabling multi-timeframe analysis. - Lookahead discipline:
barmerge.lookahead_off(the default) ensures only confirmed HTF bar values are used, preventing look-ahead bias in backtests.barmerge.lookahead_onuses the currently forming HTF bar's value, which introduces bias on historical data even though it does not literally predict the future in live trading. - Lower-TF requests: Requesting a lower timeframe is valid, but
request.security()merges only one value per chart bar by default. Userequest.security_lower_tf()when all intrabar values are required.
Ideas for Further Development
- Dynamic MTF Dashboard: Combine tuple requests across three timeframes (e.g., 1H, 4H, Daily) into a single table drawn with
table.new(), showing trend direction (SMA slope) for each timeframe simultaneously. - HTF Volatility Filter: Fetch the daily ATR via
request.security()and use it as a position-sizing denominator in a strategy, ensuring trade size adapts to higher-timeframe volatility rather than intrabar noise.
Comments
Post a Comment