Time Scale

The time scale is the horizontal axis at the bottom of a chart. TVL exposes its visibility, label density, border, tick formatting, scroll offset, and the underlying time-value model (UTC timestamps vs. business days) through the tvl.time_scale(...) object, which you pass to chart(time_scale=...). Additional options (BusinessDay, business_day(), is_business_day(), is_utc_timestamp()) are available for when you need to work outside numeric timestamps.

What are the time-scale options useful for?

  • Trading-day charts: Skip non-business days so a five-day work week and ten holidays per year stop pushing data off-screen.
  • Aligning multiple charts: Pin the right edge with fix_right_edge so two charts stacked vertically share a consistent time anchor.
  • Live tail UX: right_offset reserves whitespace on the right so the freshest bar isn’t glued to the price scale.
  • Dense time axes: tick_mark_max_character_length and uniform_distribution keep labels readable on narrow charts.

Examples

Show time and seconds on the axis

The two most common toggles are time_visible (show time-of-day on intra-day data) and seconds_visible (show seconds when zoomed in tight enough). Set both for high-frequency data.

When time_visible=False, the axis shows only the date, which suits daily-bar charts.

Hide the time scale entirely

Set tvl.time_scale(visible=False) to hide the bottom axis when you have several stacked panes and only need the axis on the outermost one.

Combine with pane_index (see multi-pane) to hide the per-pane axis on all but the bottom pane.

Right-offset whitespace for live charts

right_offset adds bars of empty space to the right of the latest data point, keeping the live tip visually separated from the price scale. Use right_offset_pixels for a fixed pixel inset instead. All of these live on tvl.time_scale(...).

bar_spacing (initial pixels per bar) plus min_bar_spacing / max_bar_spacing (zoom limits) let you set the zoom envelope.

Pin the visible range edges

fix_left_edge and fix_right_edge lock the visible range to the data boundaries, so scrolling stops at the first and last bar respectively. lock_visible_time_range_on_resize keeps the same logical window when the widget is resized, and right_bar_stays_on_scroll keeps the latest bar parked at the right.

For live charts you usually want right_bar_stays_on_scroll=True and shift_visible_range_on_new_bar=True so each new bar slides the viewport.

Tune tick density

tick_mark_max_character_length caps how many characters each tick label can use; the chart will drop ticks until the labels fit. uniform_distribution enforces a uniform tick spacing rather than the default “snap to nice intervals” behavior. minimum_height reserves vertical space so the time scale doesn’t shrink below a usable height.

allow_bold_labels lets the chart render bold weight at major boundaries (year, month) for emphasis.

Style the time-scale border

The border between the time scale and the plot area is its own layer. Toggle visibility with tvl.time_scale(border_visible=...) and color with border_color.

Hide the border for borderless dashboard tiles.

Conflate sub-pixel points

enable_conflation=True merges data points that fall on the same pixel column, trading a little precision for faster rendering on dense charts. precompute_conflation_on_init=True does that work upfront at load; precompute_conflation_priority (a PrecomputeConflationPriority value) sets how eagerly it runs ("background", "user-visible", "user-blocking").

Business-day timestamps for trading-hours charts

The BusinessDay TypedDict lets you label points without weekends and holidays; the time scale plots business days as equally-spaced ticks regardless of calendar gaps. Use business_day(year, month, day) to construct them.

BusinessDay instances are dicts, so they round-trip cleanly through tables and JSON. The companion type-guard helpers, is_business_day() and is_utc_timestamp(), let you tell business-day points apart from numeric UTC timestamps:

The two predicates distinguish business-day points from numeric UTC timestamps. The TickMarkType Literal alias names the label kinds the time scale renders at each zoom level; TVL picks the right one per tick automatically.

UTC vs. local timestamps

TVL’s underlying renderer treats numeric time values as seconds since the Unix epoch, UTC. Deephaven Instant columns are encoded with nanosecond precision; the plugin converts them to UTC seconds when serializing. Use is_utc_timestamp() to tell raw numeric times apart from BusinessDay dicts when writing helpers that accept either.

Time zones and daylight saving

Charts render times in the time zone from your Deephaven Settings, falling back to the browser’s zone when unset. The offset is resolved per timestamp, so a series spanning a daylight saving transition keeps correct labels on both sides of it, and day gridlines land on local midnight.

The chart’s underlying coordinate is always UTC. Only the axis ticks and labels are zone-aware, so every row keeps a distinct position even when two instants share the same local wall-clock time. Both instants of an autumn “fall back” hour — for example 05:30 UTC (01:30 EDT) and 06:30 UTC (01:30 EST) in America/New_York — plot separately.

Changing the Settings time zone re-labels and re-ticks the axis in place; the data and your current zoom are unaffected.

API Reference

The time scale is configured with a grouped object: tvl.time_scale(...) returns a TimeScale that you pass to time_scale= on tvl.chart(...).

Create a TimeScale config for tvl.chart(time_scale=...).

Returns: TimeScale A time-scale config for tvl.chart(time_scale=...).

ParametersTypeDefaultDescription
visiblebool |
None
NoneMaster visibility toggle for the time scale.
time_visiblebool |
None
NoneShow the time (not just the date) in labels.
seconds_visiblebool |
None
NoneShow seconds in time labels.
border_visiblebool |
None
NoneShow the time-scale border.
border_colorLiteral['gray-50', 'gray-75', 'gray-100', 'gray-200', 'gray-300', 'gray-400', 'gray-500', 'gray-600', 'gray-700', 'gray-800', 'gray-900', 'red-100', 'red-200', 'red-300', 'red-400', 'red-500', 'red-600', 'red-700', 'red-800', 'red-900', 'red-1000', 'red-1100', 'red-1200', 'red-1300', 'red-1400', 'orange-100', 'orange-200', 'orange-300', 'orange-400', 'orange-500', 'orange-600', 'orange-700', 'orange-800', 'orange-900', 'orange-1000', 'orange-1100', 'orange-1200', 'orange-1300', 'orange-1400', 'yellow-100', 'yellow-200', 'yellow-300', 'yellow-400', 'yellow-500', 'yellow-600', 'yellow-700', 'yellow-800', 'yellow-900', 'yellow-1000', 'yellow-1100', 'yellow-1200', 'yellow-1300', 'yellow-1400', 'chartreuse-100', 'chartreuse-200', 'chartreuse-300', 'chartreuse-400', 'chartreuse-500', 'chartreuse-600', 'chartreuse-700', 'chartreuse-800', 'chartreuse-900', 'chartreuse-1000', 'chartreuse-1100', 'chartreuse-1200', 'chartreuse-1300', 'chartreuse-1400', 'celery-100', 'celery-200', 'celery-300', 'celery-400', 'celery-500', 'celery-600', 'celery-700', 'celery-800', 'celery-900', 'celery-1000', 'celery-1100', 'celery-1200', 'celery-1300', 'celery-1400', 'green-100', 'green-200', 'green-300', 'green-400', 'green-500', 'green-600', 'green-700', 'green-800', 'green-900', 'green-1000', 'green-1100', 'green-1200', 'green-1300', 'green-1400', 'seafoam-100', 'seafoam-200', 'seafoam-300', 'seafoam-400', 'seafoam-500', 'seafoam-600', 'seafoam-700', 'seafoam-800', 'seafoam-900', 'seafoam-1000', 'seafoam-1100', 'seafoam-1200', 'seafoam-1300', 'seafoam-1400', 'cyan-100', 'cyan-200', 'cyan-300', 'cyan-400', 'cyan-500', 'cyan-600', 'cyan-700', 'cyan-800', 'cyan-900', 'cyan-1000', 'cyan-1100', 'cyan-1200', 'cyan-1300', 'cyan-1400', 'blue-100', 'blue-200', 'blue-300', 'blue-400', 'blue-500', 'blue-600', 'blue-700', 'blue-800', 'blue-900', 'blue-1000', 'blue-1100', 'blue-1200', 'blue-1300', 'blue-1400', 'indigo-100', 'indigo-200', 'indigo-300', 'indigo-400', 'indigo-500', 'indigo-600', 'indigo-700', 'indigo-800', 'indigo-900', 'indigo-1000', 'indigo-1100', 'indigo-1200', 'indigo-1300', 'indigo-1400', 'purple-100', 'purple-200', 'purple-300', 'purple-400', 'purple-500', 'purple-600', 'purple-700', 'purple-800', 'purple-900', 'purple-1000', 'purple-1100', 'purple-1200', 'purple-1300', 'purple-1400', 'fuchsia-100', 'fuchsia-200', 'fuchsia-300', 'fuchsia-400', 'fuchsia-500', 'fuchsia-600', 'fuchsia-700', 'fuchsia-800', 'fuchsia-900', 'fuchsia-1000', 'fuchsia-1100', 'fuchsia-1200', 'fuchsia-1300', 'fuchsia-1400', 'magenta-100', 'magenta-200', 'magenta-300', 'magenta-400', 'magenta-500', 'magenta-600', 'magenta-700', 'magenta-800', 'magenta-900', 'magenta-1000', 'magenta-1100', 'magenta-1200', 'magenta-1300', 'magenta-1400', 'negative', 'notice', 'positive', 'info', 'accent', 'accent-100', 'accent-200', 'accent-300', 'accent-400', 'accent-500', 'accent-600', 'accent-700', 'accent-800', 'accent-900', 'accent-1000', 'accent-1100', 'accent-1200', 'accent-1300', 'accent-1400', 'bg', 'content-bg', 'subdued-content-bg', 'surface-bg', 'fg'] |
str |
None
NoneBorder CSS color.
right_offsetint |
None
NoneEmpty bars kept beyond the rightmost data point.
right_offset_pixelsint |
None
NonePixel offset of the right edge.
bar_spacingfloat |
None
NonePixels between adjacent bars.
min_bar_spacingfloat |
None
NoneMinimum bar spacing (zoom-in cap).
max_bar_spacingfloat |
None
NoneMaximum bar spacing (zoom-out cap).
fix_left_edgebool |
None
NonePrevent scrolling past the leftmost data point.
fix_right_edgebool |
None
NonePrevent scrolling past the rightmost data point.
lock_visible_time_range_on_resizebool |
None
NoneKeep the visible range on resize.
right_bar_stays_on_scrollbool |
None
NonePin the rightmost bar while scrolling.
shift_visible_range_on_new_barbool |
None
NoneAuto-scroll when a new bar is added.
allow_shift_visible_range_on_whitespace_replacementbool |
None
NoneShift when whitespace bars are replaced by real data.
ticks_visiblebool |
None
NoneShow tick marks on the time scale.
tick_mark_max_character_lengthint |
None
NoneMax characters in a tick label before truncation.
uniform_distributionbool |
None
NoneForce uniform bar spacing regardless of timestamp gaps.
minimum_heightint |
None
NoneMinimum height of the time-scale area in pixels.
allow_bold_labelsbool |
None
NoneAllow bold time labels.
ignore_whitespace_indicesbool |
None
NoneIgnore whitespace indices in visible-range math.
enable_conflationbool |
None
NoneConflate sub-pixel data points for performance.
conflation_threshold_factorfloat |
None
NoneConflation sensitivity multiplier.
precompute_conflation_on_initbool |
None
NonePrecompute conflation on chart init.
precompute_conflation_priorityLiteral['background', 'user-visible', 'user-blocking'] |
None
NoneScheduling priority for precomputation; see PrecomputeConflationPriority.

Example:

Returns: BusinessDay A dict {"year": year, "month": month, "day": day} suitable for use as the time field in TradingView Lightweight Charts data rows.

ParametersTypeDefaultDescription
yearintFour-digit year (e.g. 2024).
monthintMonth number, 1-12.
dayintDay of month, 1-31.

Example:

Returns: bool True if time is a dict containing year, month, and day integer keys; False otherwise.

ParametersTypeDefaultDescription
timeAnyA time value -- either a BusinessDay dict, a numeric UTC timestamp, or an ISO date string.

Example:

Returns: bool True if time is an int or float (but not a bool); False otherwise.

ParametersTypeDefaultDescription
timeAnyA time value -- either a BusinessDay dict, a numeric UTC timestamp, or an ISO date string.

For the full tvl.chart signature, see the Chart container page.