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
- 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.
- While a session is open, track its running high and low.
- 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.
- 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
| Session | Default hours (local) | Time zone |
|---|---|---|
| Asia (Tokyo) | 09:00–18:00 | Asia/Tokyo |
| London | 08:00–17:00 | Europe/London |
| New York | 08:00–17:00 | America/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.
//@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
- Open any chart on TradingView and open the Pine Editor.
- Create a new indicator, delete the template code and paste the script.
- 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.
Related reading
- Smart money concepts explained without the hype
- Pine Script alerts: alertcondition() vs alert(), messages, webhooks and frequency
- Forex Market Hours (free tool)
- Position Size Calculator (free tool)
- Pip Value Calculator (free tool)
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.