◆ New — Strategy Validator, Code Fixer & Prop Compliance Checker are live. Try one free →
Home / Indicators / Session Highs & Lows
Session & Time indicator

Session Highs & Lows

Reference levels that track the running high and low of a defined trading session such as Asia, London, or New York.

Illustrative diagram — not live market data.

What it is

Session highs and lows are reference levels that track the highest high and lowest low printed during a defined slice of the trading day — most commonly the Asian, London, and New York sessions in forex, which trades continuously across time zones. Because forex has no single exchange open or close, traders partition the day themselves, and the extremes of each partition become levels that many participants watch: the Asian range before London opens, the London high and low before New York, and so on. To plot them in Pine Script you define a session window (for example 00:00–09:00 in a chosen time zone), detect which bars fall inside it using the time() function with a session string and time-zone argument, and update a running high and low while the session is active. The subtle part is not the max/min logic — it is time handling. Session strings, time-zone names, and daylight-saving transitions are the leading source of silent bugs in session scripts: a hardcoded UTC offset that ignores DST will draw the 'London session' an hour off for half the year. These levels describe where price has traded; they do not predict where it will go. This material is educational only, not financial advice, and trading carries risk of loss.

How it works

The implementation has three parts. First, session membership: Pine's time(timeframe.period, session, timezone) returns na for bars outside the session window, so 'not na(...)' is a clean boolean for whether the current bar belongs to the session. Using an IANA time-zone name such as "Europe/London" or "America/New_York" — rather than a fixed offset like "UTC+1" — is what makes the script survive daylight-saving transitions, because IANA zones encode the DST rules. Second, session-start detection: the first bar where the membership flag turns true after being false marks a new session, and that is where the running high and low reset to the current bar's high and low. Third, accumulation: on every subsequent in-session bar, the stored high is the maximum of itself and the bar's high, and likewise for the low. The stored values persist across bars using var declarations, which is legitimate state-keeping rather than signal manipulation. Plotting with a line-break style keeps the levels from connecting across the gap between sessions. Everything here is deterministic and computable live on bar close — nothing about the construction needs future data, which makes correctly written session levels naturally non-repainting for completed bars (the current session's extremes update while the session is open, by definition).

How traders read it

Common settings

Typical windows (stated in local market time, using IANA zones): Asia roughly 00:00–09:00 Tokyo time, London roughly 08:00–17:00 "Europe/London", New York roughly 08:00–17:00 "America/New_York". Definitions vary by trader and by source, so any script should expose the session string and time zone as inputs rather than hardcoding them. Session levels are intraday tools — they are typically drawn on charts of 1 hour and below, since the session structure is invisible on daily bars.

Strengths

Pitfalls to watch

Pine v6 example

//@version=6
indicator("Session High/Low", overlay = true)

sess = input.session("0800-1700", "Session Window")
tz   = input.string("Europe/London", "IANA Timezone", options = ["Europe/London", "America/New_York", "Asia/Tokyo", "UTC"])

// IANA zone names handle DST correctly; fixed UTC offsets do not
inSess  = not na(time(timeframe.period, sess, tz))
newSess = inSess and not inSess[1]

var float sHi = na
var float sLo = na
if newSess
    sHi := high
    sLo := low
else if inSess
    sHi := math.max(sHi, high)
    sLo := math.min(sLo, low)

plot(inSess ? sHi : na, "Session High", color = color.teal,   style = plot.style_linebr)
plot(inSess ? sLo : na, "Session Low",  color = color.maroon, style = plot.style_linebr)

Pro tip: Validate the time handling before trusting any session level: pick a date just after a daylight-saving change and check on the chart that the session shading still starts at the intended local hour. A script that uses "UTC+1" instead of "Europe/London" will pass this test in winter and fail it in summer. Session extremes are context about where trading happened, not predictions about where it will happen next — this is educational content only, not financial advice, and all trading involves risk of loss.

Built an indicator from this? Run it through the Validator to catch look-ahead bias and repainting, or convert a strategy to Pine Script.

Educational only — not financial advice, not a recommendation to trade. No indicator is predictive; trading involves substantial risk of loss.

Catch the bug that compiles.Run auditGet Pro