Candle Time

//@version=6
indicator("CANDLE_TIME_RD", overlay = true, max_labels_count = 500)

// This tool displays the time of each candle directly on the chart by placing a label below
// the bar with an upward-pointing arrow for clear visual alignment. It helps traders quickly
// identify the exact timestamp of any candle during fast intraday analysis or historical review.
//
// OVERVIEW
// The script adjusts candle times relative to EST using a user-controlled timezone offset.
// It formats the timestamp in AM/PM or military style and can optionally display it vertically
// by stacking each character on its own line. Labels appear based on minute modulo logic for
// clean spacing so the chart does not become overloaded.
//
// FEATURES
// - Timezone offset input relative to EST (example: CST = -1, PST = -3).
// - AM/PM or military time toggle.
// - Vertical text toggle (on by default) that prints HH on first line and MM on second.
// - Modulo-based spacing so labels appear every N-th minute.
// - Clean label placement below candles with an upward-pointing arrow.
// - Manual string construction for hours and minutes to keep formatting consistent.
//
// USE CASES
// - Reviewing setups with ChatGPT where exact candle timing matters.
// - Syncing TradingView data to a chosen timezone for journaling.
// - Studying EMA touches, VWAP interactions, or momentum shifts at specific times.
// - Reducing clutter by showing timestamps at controlled intervals.
//
// Designed for clarity and fast intraday evaluation.

// Inputs
step = input.int(5, "Label every N-th minute (modulo)", minval = 1)
useMilitary = input.bool(false, "Use Military Time?")
tzOffset = input.int(0, "Timezone Offset from EST")
useVertical = input.bool(true, "Display text vertically (HH on top, MM below)")
minuteOnly = input.bool(false, "Print minute only?")
bubbleOpacity = input.int(80, "Bubble Transparency (0 = solid, 100 = invisible)", minval = 0, maxval = 100)
vertOffsetTicks = input.int(1, "Vertical offset (ticks below low)", minval = 0)
labelSize = input.string("small", "Label Size", options = ["tiny", "small", "normal", "large", "huge"])

// Time adjustment
offsetMs = tzOffset * 60 * 60 * 1000
adjTime = time + offsetMs

// Hour and minute
h = hour(adjTime)
m = minute(adjTime)

// Format minute with leading zero
mStr = m < 10 ? "0" + str.tostring(m) : str.tostring(m)

// Format hours WITH leading zero
h24Str = h < 10 ? "0" + str.tostring(h) : str.tostring(h)

h12 = h % 12
h12 := h12 == 0 ? 12 : h12
h12StrRaw = str.tostring(h12)
h12Str = h12 < 10 ? "0" + h12StrRaw : h12StrRaw

ampm = h >= 12 ? " PM" : " AM"

// Base time string
timeText = useMilitary ? h24Str + ":" + mStr : h12Str + ":" + mStr + ampm
if minuteOnly
    timeText := mStr

// Vertical formatting: print as HH\nMM
finalText = timeText
if useVertical
    if minuteOnly
        finalText := mStr
    else
        hourPart = useMilitary ? h24Str : h12Str
        finalText := hourPart + "\n" + mStr

// Label placement
labelPrice = low - vertOffsetTicks * syminfo.mintick

// Convert label size string to enum
sz = labelSize == "tiny" ? size.tiny : labelSize == "small" ? size.small : labelSize == "normal" ? size.normal : labelSize == "large" ? size.large : size.huge

// Draw label (one-liner)
if barstate.isnew and m % step == 0
    label.new(bar_index, labelPrice, finalText, xloc = xloc.bar_index, yloc = yloc.price, style = label.style_label_up, textcolor = color.white, color = color.new(color.black, bubbleOpacity), size = sz)

Leave a Reply

Your email address will not be published. Required fields are marked *