Builtins: session profiles, trading sessions and the opening range

Four chart indicators give a script session levels by name: the Session Volume Profile and the Session TPO give each session's point of control and value area, Trading Sessions gives the high and low of each named session, and IVB gives the opening range. Each needs its indicator visible on the chart, and each uses that indicator's own settings.

Session Volume Profile and Session TPO

SignatureReturns
session_profile.available() -> boolWhether a visible Session Volume Profile is on this chart
session_profile.count() -> intHow many sessions this bar can read: its own and up to five before it
session_profile.poc(index: int) -> floatPoint of control of that session
session_profile.vah(index: int) -> floatValue area high
session_profile.val(index: int) -> floatValue area low
session_profile.start(index: int) -> floatStart of the session's first bar, epoch milliseconds
session_profile.end(index: int) -> floatStart of its last bar, epoch milliseconds, nan while it is still developing
session_tpo.available() -> boolWhether a visible Session TPO is on this chart
session_tpo.count() -> intHow many sessions this bar can read: its own and up to five before it
session_tpo.poc(index: int) -> floatPoint of control of that session
session_tpo.vah(index: int) -> floatValue area high
session_tpo.val(index: int) -> floatValue area low
session_tpo.start(index: int) -> floatStart of the session's first bar, epoch milliseconds
session_tpo.end(index: int) -> floatStart of its last bar, epoch milliseconds, nan while it is still developing
  • A session is the futures trading day, 18:00 to 17:00 New York time.
  • Index 0 is this bar's own session, built from its bars up to and including this one, never a later bar. 1 to 5 are the completed sessions before it, newest first. -1 or an index past count() minus 1 answers nan.
  • A finished session's final levels appear only on bars after it ended. On its own bars a script sees the levels as they developed.
  • session_profile uses the value area percent set on the chart's Session Volume Profile; session_tpo uses the bracket length, value area percent and row size set on the Session TPO. The levels are the same at every zoom and on every device.
  • session_profile needs the footprint ladder: where a bar of the session has none, that session reads nan from that bar on.
  • Without the indicator visible, available() is false and the settings under the editor say Session Volume Profile Required or Session TPO Required.
var prior_poc: float = nan
prior_poc := nz(prior_poc[1], nan)
if session_profile.available() && session_profile.count() > 1 {
  prior_poc := session_profile.poc(1)
}
plot.hline(prior_poc, "#F59E0B", 1, "dashed", "Prior POC")
plot.line(session_profile.poc(0), "#E5E7EB", 1, "dotted")

Trading Sessions

SignatureReturns
trading_sessions.available() -> boolWhether a visible Trading Sessions indicator is on this chart
trading_sessions.count() -> intHow many session rows it has enabled
trading_sessions.find(name: string) -> intIndex of the session with exactly that name, or -1
trading_sessions.name(index: int) -> stringThe session's name as set in the indicator
trading_sessions.high(index: int) -> floatIts high: so far while inside it, final once it ended
trading_sessions.low(index: int) -> floatIts low, the same way
trading_sessions.start(index: int) -> floatStart of the session's first bar, epoch milliseconds
trading_sessions.end(index: int) -> floatStart of its last bar, epoch milliseconds, nan while it is still running
  • Every enabled session row of the indicator is one record on every bar, in the indicator's order, so find("London") gives the index to read London by. The name must match the row's label exactly.
  • Inside a session its high and low are the high and low so far and end is nan. Once it ends the record holds its final high and low and its last bar, until that session starts again.
  • Every session on the loaded bars is covered, not only the ones drawn on screen. Before a session's first appearance on the loaded bars, or for one that began before the first loaded bar, the values are nan.
  • Without the indicator visible the settings say Trading Sessions Required.
let london: int = trading_sessions.find("London")
let london_done: bool = !is_nan(trading_sessions.end(london))
plot.line(trading_sessions.high(london), "#22C55E", 1, "dashed")
plot.line(trading_sessions.low(london), "#EF4444", 1, "dashed")
plot.marker(london_done && close > trading_sessions.high(london) && close[1] <= trading_sessions.high(london), high, "#22C55E", "triangle", "above", 9, 3)

IVB, the opening range

SignatureReturns
ivb.available() -> boolWhether a visible IVB indicator is on this chart
ivb.count() -> intHow many opening ranges cover this bar
ivb.high(index: int) -> floatTop of the range
ivb.low(index: int) -> floatBottom of the range
ivb.mid(index: int) -> floatMiddle of the range
  • The range appears only from the first bar that starts at or after the range window has closed, never on the bars inside the window, and it lasts as far as the indicator draws its lines.
  • With the indicator's levels switched off there is no range. Without the indicator visible the settings say IVB Required.
let has_range: bool = ivb.available() && ivb.count() > 0
plot.marker(has_range && close > ivb.high(0) && close[1] <= ivb.high(0), high, "#22C55E", "triangle", "above", 9, 3)
plot.marker(has_range && close < ivb.low(0) && close[1] >= ivb.low(0), low, "#EF4444", "triangle", "below", 9, 3)

Every layer of the market, Orderflow to optionflow, on one chart.

Institutional grade Orderflow data with backtesting and journaling built in. Join the waitlist for early access.

Get Access