Multiple timeframes
Combine the chart with confirmed or developing higher-timeframe values.
Declare another subscription when an indicator needs a different timeframe:
script "Higher-timeframe EMA"
data chart = subscribe(data.ohlcv)
data h4 = subscribe(data.ohlcv, timeframe: tf("4h"))
input length = input.int(21, title: "H4 EMA Length", min: 2, max: 200)
plot (
confirmed = plot.line(title: "H4 EMA", color: color.blue, width: 2)
developing = plot.line(title: "H4 EMA (forming)", color: color.gray, style: linestyle.dashed)
)
on chart.update {
confirmed.plot(ta.ema(h4.close, length))
developing.plot(ta.ema(h4.forming.close, length))
}Use the confirmed value when a signal must remain stable after the higher-timeframe candle closes. Use the forming value when seeing the current developing candle is more important than avoiding intrabar changes. Label the distinction clearly so users know what they are viewing.
Read repainting and confirmed values for practical rules on choosing between the two views.
Drawing at the live edge
To show only the latest higher-timeframe levels, calculate them on every bar in on chart.update and draw them under chart.isLast in that handler.
chart.isLast is false throughout history replay and inside on chart.close. Drawing under that condition in a close handler never runs and produces warning T449.
Use h4.forming.high for the developing level and h4.high for the latest confirmed level. The confirmed value does not need a [1] offset.
Where values are plotted
Subscriptions keep their own candle periods. For example, a script can calculate separate averages on 3-minute and 10-minute candles and read both values during updates of a 15-minute chart. Each handler runs for its own subscription's events; adding a subscription does not change the chart's timeframe. A subscription finer than the chart does change how history is replayed, as described in the next section.
Plots on the chart or its panes use the chart's time axis. A plot in a window chart panel uses that panel's subscription timeframe. Several writes can therefore land on one target bar: value plots keep the last non-null value, while markers and labels can retain several points on one target bar. Repeated writes to the same plot within one evaluation step still keep only the last write. Updates are placed inside the period being updated; close, open, and trade handlers use their event time. An event exactly on a target bar boundary belongs to the bar opening there.
Finer subscriptions and history replay
While a script loads history, it steps through time on the finest timeframe
among its candle, open-interest, volume-delta, CVD, and stats subscriptions,
not only the chart's. Order-book, volume-profile, and trades subscriptions do
not affect this. A 15-minute chart with a one-second subscription therefore
replays its history second by second. The one-second data starts later than
the chart's, so at its first bar the chart's handlers catch up every older
15-minute bar, running once for each. Those catch-up runs cost calculation
steps and loading time like bars do; see
stay inside the step budget.
When a replay stops at the limit, the budget_exceeded message names the
timeframe history was replayed on and the number of catch-up runs.
If the finer subscription only serves as a live clock, give it
history: 0s:
script "Live one-second clock"
data chart = subscribe(data.ohlcv)
data second = subscribe(data.ohlcv, timeframe: tf("1s"), history: 0s)
state liveSeconds = 0
plot count = plot.line(title: "Live Seconds")
on second.close {
liveSeconds += 1
}
on chart.update {
count.plot(liveSeconds)
}A live-only subscription loads no history and takes no part in the replay:
history replays on the 15-minute bars exactly as it does without it, and
second's handlers first run once the script is live. See
live-only subscriptions.
Volume profiles and order books
data.volume and data.book also accept timeframe:. This lets a one-minute chart read daily volume profiles or weekly order-book snapshots without loading that history as minute data:
script "Higher-timeframe depth"
input profileTimeframe = input.timeframe(1D, title: "Profile timeframe")
data chart = subscribe(data.ohlcv)
data volume = subscribe(data.volume, timeframe: profileTimeframe, history: 30)
data book = subscribe(data.book, timeframe: tf("1W"), history: 12)
plot (
poc = plot.line(title: "Profile POC")
bid = plot.line(title: "Weekly Best Bid")
)
on chart.update {
let point = volume.poc()
let price: float? = null
if point != null {
price = point.price
}
poc.plot(price)
bid.plot(book.bestBid())
}Omitting timeframe: or passing null uses the current context's timeframe. A timeframe input or setup expression follows the same rules as a candle subscription.
These sources are read from another subscription's handler; they do not have their own open, update, or close handlers. Reads use confirmed source buckets as of the handler's time. With a daily volume source on a minute chart, volume.summary() reads the most recent completed day, and volume.summary(1) reads the day before it. Today's unfinished profile is not exposed through a forming view. A returned snapshot's time is its bucket's opening time, even though the bucket becomes readable only after it closes. A missing scheduled snapshot returns null.
history: 30 requests at least 30 periods of the source, which means 30 daily snapshots here. A positive value can increase the default warmup but cannot reduce it. A duration such as history: 30D requests a time span instead. history: 0 or history: 0s loads no earlier snapshots; reads then return snapshots from the period the script started in onward.
Snapshot warmup is limited to 250 source periods and is loaded separately from the chart's history. Available history also depends on the source's retention limit.
barsAgo: and volume.profile(bars: 30) also count source periods. Rolling profiles combine the snapshots available within that window; missing snapshots add no activity.
Order-book buckets use the latest selected HD heatmap snapshot in each period. They describe sampled liquidity, not average depth or the sum of snapshots over the period. Volume buckets sum trading activity and may use wider price bins at higher timeframes. Read volume.binSize() or the returned level's binSize; do not assume the chart's price-bin width or reuse a level index across different sources.
Timeframe units retain their meaning end to end: W, M, and Y use UTC calendar boundaries, including multi-unit periods such as 2W and 3M; D is a fixed number of days. A month is not a fixed 30-day window. tf("1W") and tf("7D") can therefore select different buckets.
Multi-week groups run continuously from Monday 1969-12-29. Multi-month groups use a continuous month count from January of year 0, and multi-year groups start at year 0. The groups do not reset at each January, so timeframes such as 5M remain continuous across year boundaries.