Edgoro
Indicator · Signals and price structure

Pine Script daily open line and time functions (v6)

Draw the daily open and the previous day's high and low in Pine Script v6 from chart data, choose the hour the day starts, and shade a weekday with dayofweek.

Short answer

Detect the first bar of each day with timeframe.change("D"), store that bar's open in a var variable, and plot it with plot.style_linebr so each day gets its own segment; the same block can save the finished day's high and low. For a day that starts at another hour, compare dayofmonth(time - hours * 3600000, timezone) with its value on the previous bar.

The script

The daily open and the previous day's high and low, with the day starting either at the exchange's session or at an hour you choose, and an optional weekday shading. Paste it into a new indicator in the Pine Editor, then save and add it to the chart.

Pine Script v6
//@version=6
indicator("Daily open and previous day high/low", overlay = true)

anchor    = input.string("Exchange session", "Day starts at", options = ["Exchange session", "Custom hour"])
startHour = input.int(0, "Custom hour (0-23)", minval = 0, maxval = 23, active = anchor == "Custom hour")
tz        = input.string("UTC", "Time zone of the custom hour", options = ["UTC", "America/New_York", "Europe/London", "Asia/Tokyo"], active = anchor == "Custom hour")
shadeDay  = input.string("None", "Shade a weekday", options = ["None", "Monday", "Friday"])

// A new day, two ways: the exchange's daily session, or a fixed hour in a time zone
bool exchangeNewDay = timeframe.change("D")
int  shifted        = time - startHour * 3600000
bool customNewDay   = dayofmonth(shifted, tz) != dayofmonth(shifted[1], tz)
bool newDay         = anchor == "Exchange session" ? exchangeNewDay : customNewDay

var float dayOpen  = na
var float dayHigh  = na
var float dayLow   = na
var float prevHigh = na
var float prevLow  = na

if newDay
    prevHigh := dayHigh
    prevLow  := dayLow
    dayOpen  := open
    dayHigh  := high
    dayLow   := low
else
    dayHigh := math.max(dayHigh, high)
    dayLow  := math.min(dayLow, low)

// na on the first bar of each day breaks the line between days
plot(newDay ? na : dayOpen, "Daily open", color.orange, 2, plot.style_linebr)
plot(newDay ? na : prevHigh, "Previous day high", color.teal, 1, plot.style_linebr)
plot(newDay ? na : prevLow, "Previous day low", color.red, 1, plot.style_linebr)

bool shade = (shadeDay == "Monday" and dayofweek == dayofweek.monday) or (shadeDay == "Friday" and dayofweek == dayofweek.friday)
bgcolor(shade ? color.new(color.gray, 90) : na, title = "Weekday")

aboveOpen = ta.crossover(close, dayOpen)
alertcondition(aboveOpen, "Close above the daily open", "{{ticker}} closed above the daily open")

How it works

  • timeframe.change("D") is true on the first chart bar of each new daily bar, as the exchange defines the day. For stocks that's the session open; for futures and forex it's often the evening before the calendar day (see the pitfalls).
  • A custom start hour. time is the bar's opening time in milliseconds. Subtracting startHour * 3600000 (that many hours) and taking the day of the month in the chosen time zone gives a "trading date" that changes exactly at that hour, whatever the chart's timeframe. dayofmonth(time, timezone) handles daylight saving.
  • One block for the whole day. On a new day the finished day's high and low become the previous day's, and the new day starts from the current bar. On other bars the high and low only expand. Before the first full day, dayHigh is na and math.max(na, high) stays na, so nothing is drawn from a partial day.
  • plot(newDay ? na : dayOpen, ..., plot.style_linebr). A plain line would draw a vertical jump from one day's level to the next; na on the first bar plus plot.style_linebr leaves a gap instead.
  • dayofweek is the bar's weekday in the exchange's time zone, compared with constants from dayofweek.sunday (1) to dayofweek.saturday (7). For another time zone, call the function form: dayofweek(time, "Europe/London").

Pitfalls

  • Comparing timeframe.period with "D". In v6 timeframe.period returns "1D" for the daily chart, so timeframe.period == "D" is never true. Use timeframe.isdaily, timeframe.isintraday and friends; convert Pine Script v5 to v6 lists this change.
  • Exchange day vs midnight. On futures and on forex with many data feeds, the exchange's day starts the previous evening (for forex usually 17:00 New York). A "daily open" from timeframe.change("D") is then the evening open, not midnight's. That's why the script lets you choose the hour.
  • Time zones. The hour, dayofweek and dayofmonth variables use the exchange's time zone, not yours. Pass a time zone to the function forms (hour(time, "Europe/London")) when it matters.
  • On a daily or weekly chart. Every bar starts a new day there, so the open line has nothing to draw: the script is meant for intraday charts.

Variations

With request.security(). The daily open and yesterday's levels can also come from the daily timeframe. Requesting the open with lookahead_on is safe because the day's open is known from its first bar, and the previous day's values are offset by [1]:

//@version=6
indicator("Daily levels from the daily timeframe", overlay = true)
[dOpen, yHigh, yLow] = request.security(syminfo.tickerid, "D", [open, high[1], low[1]], lookahead = barmerge.lookahead_on)
plot(dOpen, "Daily open", color.orange, 2, plot.style_stepline)
plot(yHigh, "Previous day high", color.teal, 1, plot.style_stepline)
plot(yLow, "Previous day low", color.red, 1, plot.style_stepline)

It costs one data request and always follows the exchange's day. The multi-timeframe guide explains when lookahead_on is safe and when it leaks the future. For trading windows within the day (London, New York, the overlap) see the session and time filter guide.

Questions

How do I get today's open price in Pine Script?

Store the open of the first bar of the day: var float dayOpen = na, then if timeframe.change("D") set dayOpen := open. Or request it: request.security(syminfo.tickerid, "D", open, lookahead = barmerge.lookahead_on).

How do I get yesterday's high and low in Pine Script?

Track the current day's high and low in var variables and copy them to prevHigh and prevLow when a new day starts, as in this script. Or request high[1] and low[1] from the "D" timeframe with lookahead_on.

How do I check the day of the week in Pine Script?

Compare the dayofweek variable with the constants: dayofweek == dayofweek.friday. It uses the exchange's time zone; for another one, use dayofweek(time, "America/New_York").

Every script on this page was checked with Edgoro Pine Check (Pine Script v6 rules). Pine Check is a static checker, not TradingView's compiler: TradingView compiles the script when you save it in the Pine Editor. The scripts are examples to learn from, not trading systems. 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.

Need a different version of this script?

Describe the change in plain English and Edgoro writes the Pine Script v6 for you, checked with Pine Check. For example:

“Draw today's open, yesterday's high and low and the weekly open, with the day starting at 17:00 New York time, and alert me when price closes above yesterday's high.”