Markers
Markers are small annotations (circles, squares, or arrows) attached to a series at specific points in time. Use them to flag individual events (a fill, a signal, a regime change) directly on the chart without disrupting the underlying price curve.
There are three ways to put markers on a chart. Use tvl.marker() for static, code-defined markers; tvl.markers_from_table() when each row of a Deephaven table should become one marker (and tick live as the table updates); and tvl.up_down_markers() as a convenience for the common “buys are up arrows, sells are down arrows” pattern.
What are markers useful for?
- Annotating fills: Mark every executed order on the price line so traders can see where positions changed hands.
- Highlighting signals: A strategy that generates buy/sell signals can render them as up/down arrows directly on the candlestick.
- Flagging events: News releases, earnings announcements, or system events can be pinned to their timestamps as labeled circles.
- Picking out levels: Price-based positions (
at_price_top,at_price_middle,at_price_bottom) let a marker float independent of the bar: useful for marking option strikes or support/resistance touches.
Examples
Add a single static marker
tvl.marker() builds one Marker object. Pass a list of them via the markers= keyword on any per-type constructor.
The single marker hovers above the bar for 2024-01-15 with a downward red arrow.
Show every marker shape
MarkerShape has four values: "circle", "square", "arrow_up", "arrow_down". The example below puts one of each on a single chart at staggered times.
The four markers march across the chart, one shape per timestamp.
Show every marker position
MarkerPosition has six values. The three bar-relative positions ("above_bar", "below_bar", "in_bar") anchor to the bar at the given time. The three price-relative positions ("at_price_top", "at_price_bottom", "at_price_middle") float at a specific price regardless of the bar.
All six positions render together. The bar-relative ones move with the candle, the price-relative ones lock to their price.
Drive markers from a Deephaven table
tvl.markers_from_table() builds a MarkerSpec instead of a list. Each row of the table becomes one marker; columns supply per-row values for any property that has a *_column parameter. Because the spec keeps a live reference to the table, markers tick when the table updates.
Pass the spec via the series’ marker_spec= argument. As the source table ticks, new markers appear automatically.
Use fixed defaults with markers_from_table
If every marker shares the same shape and color, omit the per-row column and set the fixed default directly. Mix-and-match is fine. Fixed values fill in for any property without a *_column.
The chart shows one blue circle per event, each labeled with its row’s Note.
Price-driven markers from a table
For at_price_* positions, supply a price_column so each row’s price comes from the data.
The orange squares float at Level, independent of the candle’s High/Low.
Use up_down_markers for buy/sell signals
tvl.up_down_markers() is the shortcut for the most common pattern: a list of up timestamps and a list of down timestamps, rendered as arrows below/above the bar with theme-derived colors.
The helper returns a list[Marker] that drops straight into the series’ markers= argument. The library sorts markers by time, so the order of up_times and down_times doesn’t matter. (Two type-only Literal aliases, MarkerSign and MismatchDirection, are exported for annotations.)
API Reference
Create a single static marker to place on a series.
Returns: Marker A Marker instance with snake_case input
values translated to the camelCase JS form expected by the
wire protocol.
Raises: ValueError -- If position is a price-anchored variant and price is not supplied.
| Parameters | Type | Default | Description |
|---|---|---|---|
| time | Any | Time anchor for the marker. UTC timestamp, ISO string, or BusinessDay dict. | |
| position | MarkerPosition | 'above_bar' | Anchor position. See MarkerPosition. For "at_price_*" positions you must also supply price. |
| shape | MarkerShape | 'circle' | Glyph drawn for the marker. See MarkerShape. |
| color | Optional[Color] | None | CSS color for the glyph fill. |
| text | str | '' | Optional label text drawn near the marker. |
| size | Optional[int] | None | Glyph size multiplier (default 1). |
| id | Optional[str] | None | Optional string identifier. |
| price | Optional[float] | None | Required when position is one of the "at_price_*" variants. |
timestamp is always a column name. For each other property, you may pass a fixed value (e.g. color="#FF0000") that applies to every marker, or a *_column name (e.g. color_column="Color") to read the value per-row from the table. For price-based positions ("at_price_top" etc.) supply either price (same price for every row) or price_column (different price per row).
Returns: MarkerSpec A MarkerSpec ready to attach to a series
via the marker_spec= parameter of any series factory.
Raises: ValueError -- If both price and price_column are supplied, or if a price-anchored position is requested without either.
| Parameters | Type | Default | Description |
|---|---|---|---|
| table | Any | Deephaven table whose rows drive the markers. | |
| timestamp | str | 'Timestamp' | Column name supplying each marker's time value. |
| position | MarkerPosition | 'above_bar' | Default marker position; see MarkerPosition. |
| shape | MarkerShape | 'circle' | Default marker shape; see MarkerShape. |
| color | Optional[Color] | None | Default marker color. |
| text | str | '' | Default label text. |
| size | Optional[int] | None | Default size multiplier. |
| price | Optional[float] | None | Default price for price-anchored positions. |
| position_column | Optional[str] | None | Column supplying per-row MarkerPosition values. |
| shape_column | Optional[str] | None | Column supplying per-row MarkerShape values. |
| color_column | Optional[str] | None | Column supplying per-row CSS color strings. |
| text_column | Optional[str] | None | Column supplying per-row text labels. |
| size_column | Optional[str] | None | Column supplying per-row size values. |
| id_column | Optional[str] | None | Column supplying per-row marker IDs. |
| price_column | Optional[str] | None | Column supplying per-row price values for price-anchored positions. |
The returned list can be passed directly to the markers= parameter of any series factory. The library sorts markers by time, so Python ordering does not matter.
Returns: list[Marker] Flat list of Marker objects — up events followed by down events.
| Parameters | Type | Default | Description |
|---|---|---|---|
| up_times | list[Any] | Time values for bullish / up events. | |
| down_times | list[Any] | Time values for bearish / down events. | |
| up_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 | Fill color for up-markers. Default: theme OHLC increase color. |
| down_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 | Fill color for down-markers. Default: theme OHLC decrease color. |
| up_text | str | '' | Label text for up-markers. Default: "" (no label). |
| down_text | str | '' | Label text for down-markers. Default: "" (no label). |
| up_size | int | None | None | Size multiplier for up-markers. Default: library default (1). |
| down_size | int | None | None | Size multiplier for down-markers. Default: library default (1). |