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_edgeso two charts stacked vertically share a consistent time anchor. - Live tail UX:
right_offsetreserves whitespace on the right so the freshest bar isn’t glued to the price scale. - Dense time axes:
tick_mark_max_character_lengthanduniform_distributionkeep 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=...).
| Parameters | Type | Default | Description |
|---|---|---|---|
| visible | bool | None | None | Master visibility toggle for the time scale. |
| time_visible | bool | None | None | Show the time (not just the date) in labels. |
| seconds_visible | bool | None | None | Show seconds in time labels. |
| border_visible | bool | None | None | Show the time-scale border. |
| border_color | Literal['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 | None | Border CSS color. |
| right_offset | int | None | None | Empty bars kept beyond the rightmost data point. |
| right_offset_pixels | int | None | None | Pixel offset of the right edge. |
| bar_spacing | float | None | None | Pixels between adjacent bars. |
| min_bar_spacing | float | None | None | Minimum bar spacing (zoom-in cap). |
| max_bar_spacing | float | None | None | Maximum bar spacing (zoom-out cap). |
| fix_left_edge | bool | None | None | Prevent scrolling past the leftmost data point. |
| fix_right_edge | bool | None | None | Prevent scrolling past the rightmost data point. |
| lock_visible_time_range_on_resize | bool | None | None | Keep the visible range on resize. |
| right_bar_stays_on_scroll | bool | None | None | Pin the rightmost bar while scrolling. |
| shift_visible_range_on_new_bar | bool | None | None | Auto-scroll when a new bar is added. |
| allow_shift_visible_range_on_whitespace_replacement | bool | None | None | Shift when whitespace bars are replaced by real data. |
| ticks_visible | bool | None | None | Show tick marks on the time scale. |
| tick_mark_max_character_length | int | None | None | Max characters in a tick label before truncation. |
| uniform_distribution | bool | None | None | Force uniform bar spacing regardless of timestamp gaps. |
| minimum_height | int | None | None | Minimum height of the time-scale area in pixels. |
| allow_bold_labels | bool | None | None | Allow bold time labels. |
| ignore_whitespace_indices | bool | None | None | Ignore whitespace indices in visible-range math. |
| enable_conflation | bool | None | None | Conflate sub-pixel data points for performance. |
| conflation_threshold_factor | float | None | None | Conflation sensitivity multiplier. |
| precompute_conflation_on_init | bool | None | None | Precompute conflation on chart init. |
| precompute_conflation_priority | Literal['background', 'user-visible', 'user-blocking'] | None | None | Scheduling 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.
| Parameters | Type | Default | Description |
|---|---|---|---|
| year | int | Four-digit year (e.g. 2024). | |
| month | int | Month number, 1-12. | |
| day | int | Day of month, 1-31. |
Example:
Returns: bool True if time is a dict containing year, month, and
day integer keys; False otherwise.
| Parameters | Type | Default | Description |
|---|---|---|---|
| time | Any | A 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.
| Parameters | Type | Default | Description |
|---|---|---|---|
| time | Any | A 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.