millionchart
فارسی

Time, timeframes and sessions

The time of a bar in a window of the day, the length of the timeframe, calendar parts in a zone, earlier days and weeks, and a declared session.

Everything on this page reads the clock of the bars: where a bar stands in a window of the day, how long the timeframe is, the weekday and hour in a zone, the fields of earlier periods and the members of a declared session. The synthetic market never closes, so there are no gaps at the end of a session.

Window of the day#

The bar time inside a window of the day, the first bar of each day and the last closed bar of the history.

Cuprel
// A window of the day, read from the bar's own time. bar.time_in gives the time the bar opens while it lies inside the window and na outside it; bar.close_time_in does the same for the closing time.
// The first bar of each day and the last closed bar of the history are marked as well.
indicator "Window of the day"
    edition = 1
    display = price

input window: text = "0800-1000", name = "Window (New York time)"
let opens_inside = not is_na(bar.time_in("1h", window, zone = "America/New_York"))
let closes_inside = not is_na(bar.close_time_in("1h", window, zone = "America/New_York"))
chart.background(if opens_inside then color.fade(color.blue, 90) else na, name = "Opens inside")
mark.shape(
    bar.is_first_of_day,
    name = "First bar of the day",
    shape = triangle_up,
    place = below,
    color = color.green,
)
if bar.is_last_history
    label.new(bar.index, high, f"Last closed bar: {bar.index}", style = label_down)
plot(if closes_inside then close else na, name = "Close when the bar ends inside", style = circles)

Bars in a day#

The length of the chart bar in seconds, the same length written as a timeframe text, and a count of the bars of each day.

Cuprel
// The timeframe as numbers and as text. tf.to_seconds is the length of the chart's bar, tf.from_seconds writes a length as a timeframe text,
// and tf.changed is true on the first bar of each new period of a timeframe. This counts the bars of each day and compares them with what a day should hold.
indicator "Bars in a day"
    edition = 1
    display = pane

let expected = 86400 / tf.to_seconds()
state counted = 0
if tf.changed("D")
    counted = 0
counted += 1
if bar.is_last
    let t = table.new(top_right, 2, 3, border_color = color.gray, border_width = 1)
    table.cell(t, 0, 0, "Chart timeframe", h_align = left)
    table.cell(t, 1, 0, tf.id)
    table.cell(t, 0, 1, "Four times longer", h_align = left)
    table.cell(t, 1, 1, tf.from_seconds(tf.to_seconds() * 4))
    table.cell(t, 0, 2, "Intraday", h_align = left)
    table.cell(t, 1, 2, if tf.is_intraday then "yes" else "no")
plot(counted, name = "Bars so far today", style = histogram, color = color.teal)
plot(expected, name = "Bars in a whole day", color = color.gray)

Weekday mornings#

Calendar parts of the bar time in a zone, a start date built from numbers, and the names of the days.

Cuprel
// Calendar parts of a time value, read in a zone. clock.weekday_of and clock.hour_of take the bar's time, clock.timestamp builds the start date of the count,
// and clock.monday and clock.friday name the days. The count grows by one for each working-day morning that starts after the start date.
indicator "Weekday mornings"
    edition = 1
    display = pane

input start: time = clock.timestamp(2026, 1, 12, zone = "America/New_York"), name = "Count from"
let zone = "America/New_York"
let weekday = clock.weekday_of(bar.time, zone = zone)
let hour = clock.hour_of(bar.time, zone = zone)
let working_day = weekday >= clock.monday and weekday <= clock.friday
let morning = working_day and hour >= 8 and hour < 12
state mornings = 0
if morning and not morning[1] and bar.time >= start
    mornings += 1
plot(if morning then 1 else 0, name = "Morning", style = histogram, color = color.blue)
plot(mornings, name = "Mornings counted", color = color.orange)

Earlier days and weeks#

Fields of the current and of earlier days and weeks: the change since yesterday, the range used so far and the position in last week.

Cuprel
// Fields of earlier periods, built from the chart's own bars. current(day) is the trading day that is still forming, prior(day) the last day that finished and prior(week, 2) the week before last.
// This plots the change since yesterday's close, how much of yesterday's range today has used so far, and where the close stands inside last week's range.
indicator "Earlier days and weeks"
    edition = 1
    display = pane

let change = close - prior(day).close
let range_used = (current(day).high - current(day).low) / (prior(day).high - prior(day).low)
let position = (close - prior(week).low) / (prior(week).high - prior(week).low)
plot(change, name = "Change since yesterday's close", style = histogram, color = color.blue)
plot(range_used, name = "Today's range over yesterday's", color = color.purple)
plot(position, name = "Position in last week's range", color = color.orange)
plot(
    prior(week, 2).close - prior(week).close,
    name = "Change of the last two weeks",
    color = color.gray,
)

Session range boxes#

One declared session and all six members: a box over each finished session from its high to its low.

Cuprel
// A box over every finished session, from its high to its low. The members of a declared session tell where the bar stands in it:
// .start is true on its first bar, .end on its last, .active while the bar is inside, .index counts the sessions, and .high and .low are the extremes so far.
indicator "Session range boxes"
    edition = 1
    display = price
    max_boxes = 100

session asia = 00:00 .. 08:00 @ "Asia/Tokyo"
state first_bar = 0
if asia.start
    first_bar = bar.index
if asia.end
    box.new(
        first_bar,
        asia.high,
        bar.index,
        asia.low,
        border_color = color.purple,
        background = color.fade(color.purple, 90),
    )
plot(
    if asia.active then asia.high - asia.low else na,
    name = "Range so far",
    style = histogram,
    color = color.purple,
)
plot(asia.index, name = "Session number", display = none)

A timeframe text the chart does not know#

"1dd" is not a timeframe; it is refused when the script is checked.

Cuprel · error E-TF-UNKNOWN
// A mistake on purpose: "1dd" is not a timeframe the chart knows.
indicator "Bars in a day"
    edition = 1
    display = pane

let expected = 86400 / tf.to_seconds()
state counted = 0
if tf.changed("1dd")
    counted = 0
counted += 1
if bar.is_last
    let t = table.new(top_right, 2, 3, border_color = color.gray, border_width = 1)
    table.cell(t, 0, 0, "Chart timeframe", h_align = left)
    table.cell(t, 1, 0, tf.id)
    table.cell(t, 0, 1, "Four times longer", h_align = left)
    table.cell(t, 1, 1, tf.from_seconds(tf.to_seconds() * 4))
    table.cell(t, 0, 2, "Intraday", h_align = left)
    table.cell(t, 1, 2, if tf.is_intraday then "yes" else "no")
plot(counted, name = "Bars so far today", style = histogram, color = color.teal)
plot(expected, name = "Bars in a whole day", color = color.gray)

A time with no zone#

A date text without a zone is a different moment on every machine, so it is refused.

Cuprel · error E-TS-ZONE
// A mistake on purpose: a date text with no zone is a different moment on every machine.
indicator "Weekday mornings"
    edition = 1
    display = pane

input start: time = clock.timestamp("2026-01-12T09:00"), name = "Count from"
let zone = "America/New_York"
let weekday = clock.weekday_of(bar.time, zone = zone)
let hour = clock.hour_of(bar.time, zone = zone)
let working_day = weekday >= clock.monday and weekday <= clock.friday
let morning = working_day and hour >= 8 and hour < 12
state mornings = 0
if morning and not morning[1] and bar.time >= start
    mornings += 1
plot(if morning then 1 else 0, name = "Morning", style = histogram, color = color.blue)
plot(mornings, name = "Mornings counted", color = color.orange)

A session read by itself#

A session is read through one of its members, never alone.

Cuprel · error E3260
// A mistake on purpose: a session is read through a member, never alone.
indicator "Session range boxes"
    edition = 1
    display = price
    max_boxes = 100

session asia = 00:00 .. 08:00 @ "Asia/Tokyo"
state first_bar = 0
if asia.start
    first_bar = bar.index
if asia.end
    box.new(
        first_bar,
        asia.high,
        bar.index,
        asia.low,
        border_color = color.purple,
        background = color.fade(color.purple, 90),
    )
plot(
    if asia.active then asia.high - asia.low else na,
    name = "Range so far",
    style = histogram,
    color = color.purple,
)
plot(asia, name = "Session number", display = none)