Edgoro
Volatility indicator

Session highs and lows: Asia, London, New York and Pine Script v6 code

How traders use the Asia, London and New York session highs and lows as levels, how session times and time zones work, and a free session range script.

What it measures

Forex and index futures trade almost around the clock, but activity comes in waves as the main financial centres open and close. A session high and low indicator draws the range of each session: the highest and lowest prices traded during Asian hours, the London session and the New York session. Those levels then serve as references for the rest of the day.

The best-known use is the Asian range: the usually quieter overnight range that is often tested or broken in the first hours of the London session.

The formula in words

  1. Define each session by its local opening hours and its time zone. The script's defaults match the market hours tool: Tokyo 09:00–18:00, London 08:00–17:00 and New York 08:00–17:00, each in local time.
  2. While a session is open, track its running high and low.
  3. When it closes, freeze those values as that session's high and low, and extend them to the right until the same session opens again.
  4. A breakout is the first close above the finished session's high, or below its low, before that session opens again.

Giving each session its own time zone handles daylight saving time automatically: London and New York shift against UTC twice a year, Tokyo doesn't. The sessions overlap, as they do in reality; the London and New York overlap is usually the most active part of the day.

How traders read it

  • Asian range breakouts. A close above the Asian high or below the Asian low during the London morning is read as the day's first directional move.
  • Liquidity above and below. Many traders expect stop orders to cluster just beyond the previous session's high and low. A quick move through the level that reverses back inside is called a sweep in smart money concepts.
  • The previous session as a level. The last New York high and low are watched during the next Asian and London sessions as support and resistance.
  • Range size. An unusually narrow Asian range is sometimes followed by a larger London move; an unusually wide one leaves less room.

Common settings

SessionDefault hours (local)Time zone
Asia (Tokyo)09:00–18:00Asia/Tokyo
London08:00–17:00Europe/London
New York08:00–17:00America/New_York

Many traders use narrower windows, for example 00:00–06:00 UTC for the Asian range, or only the first hours of London and New York. Each session's hours and time zone can be changed in the settings, and each session can be hidden.

Pine Script v6 code

The complete, self-contained script is below. Copy it into a new indicator in TradingView's Pine Editor, or download the .pine file.

Pine Script v6
//@version=6
indicator("Session highs and lows: Asia, London, New York", shorttitle = "Sessions", overlay = true, max_boxes_count = 500, max_lines_count = 500)

showAsia = input.bool(true, "Show", group = "Asia (Tokyo)")
asiaSess = input.session("0900-1800", "Hours (local time)", group = "Asia (Tokyo)")
asiaTz   = input.string("Asia/Tokyo", "Time zone", options = ["Asia/Tokyo", "Asia/Singapore", "Australia/Sydney", "UTC"], group = "Asia (Tokyo)")
asiaCol  = input.color(color.purple, "Colour", group = "Asia (Tokyo)")

showLon = input.bool(true, "Show", group = "London")
lonSess = input.session("0800-1700", "Hours (local time)", group = "London")
lonTz   = input.string("Europe/London", "Time zone", options = ["Europe/London", "Europe/Berlin", "UTC"], group = "London")
lonCol  = input.color(color.blue, "Colour", group = "London")

showNy = input.bool(true, "Show", group = "New York")
nySess = input.session("0800-1700", "Hours (local time)", group = "New York")
nyTz   = input.string("America/New_York", "Time zone", options = ["America/New_York", "America/Chicago", "UTC"], group = "New York")
nyCol  = input.color(color.orange, "Colour", group = "New York")

extendLv = input.bool(true, "Extend each session's high and low until it opens again", group = "Display")

if timeframe.isdwm
    runtime.error("Session ranges need an intraday chart.")

// Tracks one session: draws its range box, extends its finished high and low, and reports the first close beyond them.
sessionLevels(bool show, string sess, string tz, color col, string name, bool extend) =>
    t      = time(timeframe.period, sess, tz)
    inSess = show and not na(t)
    starts = inSess and not inSess[1]
    ends   = not inSess and inSess[1]
    var float hi      = na
    var float lo      = na
    var float doneHi  = na
    var float doneLo  = na
    var bool  upTaken = true
    var bool  dnTaken = true
    var box   rangeBox = na
    var line  hiLine   = na
    var line  loLine   = na
    if starts
        hi := high
        lo := low
        rangeBox := box.new(bar_index, high, bar_index, low, border_color = color.new(col, 40), bgcolor = color.new(col, 90), text = name, text_color = color.new(col, 20), text_size = size.small, text_halign = text.align_left, text_valign = text.align_top)
    else if inSess
        hi := math.max(hi, high)
        lo := math.min(lo, low)
        rangeBox.set_top(hi)
        rangeBox.set_bottom(lo)
        rangeBox.set_right(bar_index)
    if ends
        doneHi  := hi
        doneLo  := lo
        upTaken := false
        dnTaken := false
        if extend
            hiLine := line.new(bar_index - 1, hi, bar_index, hi, color = col, style = line.style_dotted)
            loLine := line.new(bar_index - 1, lo, bar_index, lo, color = col, style = line.style_dotted)
    else if not inSess and extend and not na(hiLine)
        hiLine.set_x2(bar_index)
        loLine.set_x2(bar_index)
    breakUp   = not inSess and not upTaken and close > doneHi
    breakDown = not inSess and not dnTaken and close < doneLo
    if breakUp
        upTaken := true
    if breakDown
        dnTaken := true
    [doneHi, doneLo, breakUp, breakDown]

[asiaHi, asiaLo, asiaUp, asiaDn] = sessionLevels(showAsia, asiaSess, asiaTz, asiaCol, "Asia", extendLv)
[lonHi, lonLo, lonUp, lonDn]     = sessionLevels(showLon, lonSess, lonTz, lonCol, "London", extendLv)
[nyHi, nyLo, nyUp, nyDn]         = sessionLevels(showNy, nySess, nyTz, nyCol, "New York", extendLv)

plot(asiaHi, "Asia high", display = display.data_window)
plot(asiaLo, "Asia low", display = display.data_window)
plot(lonHi, "London high", display = display.data_window)
plot(lonLo, "London low", display = display.data_window)
plot(nyHi, "New York high", display = display.data_window)
plot(nyLo, "New York low", display = display.data_window)

alertcondition(asiaUp, "Close above Asia high", "{{ticker}} closed above the last Asia session high ({{interval}})")
alertcondition(asiaDn, "Close below Asia low", "{{ticker}} closed below the last Asia session low ({{interval}})")
alertcondition(lonUp, "Close above London high", "{{ticker}} closed above the last London session high ({{interval}})")
alertcondition(lonDn, "Close below London low", "{{ticker}} closed below the last London session low ({{interval}})")
alertcondition(nyUp, "Close above New York high", "{{ticker}} closed above the last New York session high ({{interval}})")
alertcondition(nyDn, "Close below New York low", "{{ticker}} closed below the last New York session low ({{interval}})")

Each session is drawn as a shaded, labelled box that grows while the session is open. When it closes, dotted lines extend its high and low until the same session opens again. The latest completed high and low of each session are also in the data window.

Six alert conditions fire on the first close above or below each session's completed high and low. The script needs an intraday chart and stops with a message on daily bars.

Add it to your chart

  1. Open any chart on TradingView and open the Pine Editor.
  2. Create a new indicator, delete the template code and paste the script.
  3. Click Save, then Add to chart. Change lengths and levels from the indicator's settings.

Stuck on an error? See how to add a Pine Script indicator to TradingView.

Pitfalls

  • Time zone mistakes. A session typed in the wrong time zone shifts the box by hours. Check that the boxes start where you expect on a recent day.
  • Large bars. On 4-hour bars the boxes can't start or end at the exact session hours. Use 1-hour bars or smaller.
  • Holidays and thin days. On bank holidays a session can be almost empty, and its range means little.
  • Overlapping sessions. London and New York share hours by default, so one high can belong to both. Narrow the windows if you want separate ranges.
  • Sweep stories. A move through a session high that reverses is a pattern; whether stops were actually there isn't visible on a chart.

The script is an educational example: test it on your own markets before relying on it. Indicators describe the past; they don't predict the future. Trading involves substantial risk of loss and is not suitable for every investor. Edgoro is a software tool, not a broker or financial adviser: nothing it produces is investment advice, and past or backtested performance does not guarantee future results.

Make it yours with Edgoro

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, ready to paste. For example:

“Draw the Asian session range from 00:00 to 06:00 UTC and alert on the first close above its high or below its low between 07:00 and 10:00 London time.”

Build your Session highs and lows indicator