Candlestick
Creates a candlestick (or OHLC bar) chart of financial periods, from rows
with a date and open, high, low, and close values. Each row’s date is read
by x (default "date"): a Date, a timestamp, or a date string.
Basic example
Section titled “Basic example”Each row is one period with a date, open, high, low, and close (the default keys). The wick runs from the high to the low and the body from the open to the close. Periods that closed at or above their open are drawn as green outlines, and periods that fell are filled red, so direction reads from the fill as well as the color. Hover anywhere over the plot to see the nearest period’s values and its change from open to close.
How each period draws: "candlestick" (default), a wick from the high to the low around a body from the open to the close; or "ohlc", a line from the high to the low with the open ticked to the left and the close ticked to the right.
Draws rising candles as outlines and falling candles filled (default true), so direction reads without relying on color; false fills both. OHLC bars are never filled. An unfilled candle or bar takes no shapeConfig.texture or shapeConfig.backgroundImage; filled ones take both, with a texture's lines a shade darker than the body unless the texture sets its own stroke.
The color of periods that closed at or above their open: a color string, or an accessor of the row. Defaults to green.
The color of periods that closed below their open: a color string, or an accessor of the row. Defaults to red.
The share of each period's room the candle body (or OHLC ticks) spans, from 0 to 1. Defaults to 0.7.
OHLC bars
Section titled “OHLC bars”variant: "ohlc" draws each period as an OHLC bar: a line from the high to the low, with the open ticked to the left and the close ticked to the right.
How each period draws: "candlestick" (default), a wick from the high to the low around a body from the open to the close; or "ohlc", a line from the high to the low with the open ticked to the left and the close ticked to the right.
The share of each period's room the candle body (or OHLC ticks) spans, from 0 to 1. Defaults to 0.7.
Custom accessors
Section titled “Custom accessors”Point x, open, high, low, and close at your own keys (or accessor functions). hollow: false fills every candle, and upColor/downColor swap the palette, here for a blue/orange pair that stays distinct for red-green color blindness. A yConfig.tickFormat formats the prices in the tooltip as well as on the axis.
Accessor (or data key) for each period's opening value. Defaults to "open"; a row without one opens at its close. Rows that share a series and a period merge into one candle, taking the first row's open (in data order, so sort rows oldest first). Override with an aggs entry on the data key, or, for a function accessor, on "open".
Accessor (or data key) for each period's highest value. Defaults to "high"; the high always reaches the open and close. Merged rows take the highest high; aggs overrides it as it does for open.
Accessor (or data key) for each period's lowest value. Defaults to "low"; the low always reaches the open and close. Merged rows take the lowest low; aggs overrides it as it does for open.
Accessor (or data key) for each period's closing value. Defaults to "close". The close is the chart's y: setting y sets it, rows without one are skipped, and hover snaps to it. Merged rows take the last row's close; aggs overrides it as it does for open.
Draws rising candles as outlines and falling candles filled (default true), so direction reads without relying on color; false fills both. OHLC bars are never filled. An unfilled candle or bar takes no shapeConfig.texture or shapeConfig.backgroundImage; filled ones take both, with a texture's lines a shade darker than the body unless the texture sets its own stroke.
The color of periods that closed at or above their open: a color string, or an accessor of the row. Defaults to green.
The color of periods that closed below their open: a color string, or an accessor of the row. Defaults to red.
With volume
Section titled “With volume”volume draws a strip of volume bars under the candles, one per candle in its up or down color, on its own small axis with abbreviated ticks (e.g. 1.2M). The price axis shrinks to make room, the x axis sits under the strip, and the tooltip adds a Volume row. Bars stay filled when candles are hollow, so short bars remain easy to read. volumeConfig sets the strip’s height (a share of the plot, default 0.2), the gap above it, and axisConfig/shapeConfig for its axis and bars. When rows merge, volumes add up; aggs overrides it.
Accessor (or data key) for each period's traded volume. Off by default; when set, a strip under the candles draws one bar per candle, as tall as its volume on the strip's own axis (ticks abbreviated, e.g. "1.2M"), in its candle's up or down color, and the tooltip adds a Volume row. Bars are always filled, hollow candles included, and take shapeConfig.texture and shapeConfig.backgroundImage like filled candles; they hover with their candle. The price axis shrinks to make room, and the x axis sits under the strip. Merged rows add their volumes; an aggs entry overrides it as it does for open. Set false to turn it off.
How each period draws: "candlestick" (default), a wick from the high to the low around a body from the open to the close; or "ohlc", a line from the high to the low with the open ticked to the left and the close ticked to the right.
Draws rising candles as outlines and falling candles filled (default true), so direction reads without relying on color; false fills both. OHLC bars are never filled. An unfilled candle or bar takes no shapeConfig.texture or shapeConfig.backgroundImage; filled ones take both, with a texture's lines a shade darker than the body unless the texture sets its own stroke.
Intraday rollup
Section titled “Intraday rollup”Rows that share a series and a period merge into one candle: the first row’s open, the highest high, the lowest low, and the last row’s close. Rows merge in data order, so sort them oldest first. Here seven hourly rows a day, with x pointed at their day, roll up to daily candles. An aggs entry overrides any of the four, keyed by the data key (or, for a function accessor, by the field name: aggs: {close: (rows, value) => ...}).
const config = {
data: (() => {
let seed = 7;
const random = () => (seed = (seed * 16807) % 2147483647) / 2147483647;
const round = v => Math.round(v * 100) / 100;
const rows = [];
const day = new Date(2024, 0, 1);
let price = 120,
n = 0;
while (n < 30) {
if (day.getDay() % 6) {
const date = [day.getFullYear(), day.getMonth() + 1, day.getDate()]
.map(v => String(v).padStart(2, "0"))
.join("-");
for (let hour = 10; hour <= 16; hour++) {
const open = price;
price = open * (1 + (random() - 0.49) * 0.012);
rows.push({
symbol: "ACME",
day: date,
time: date + "T" + hour + ":00",
open: round(open),
high: round(Math.max(open, price) * (1 + random() * 0.004)),
low: round(Math.min(open, price) * (1 - random() * 0.004)),
close: round(price),
});
}
n++;
}
day.setDate(day.getDate() + 1);
}
return rows;
})(),
groupBy: "symbol",
x: "day",
};
Calendar gaps
Section titled “Calendar gaps”By default periods are spaced evenly in date order, so weekends and holidays leave no gaps, and the axis ticks the first period of each week, month, quarter, or year. skipGaps: false places each period at its date on a continuous time axis instead, which shows the gaps.
Places periods one slot apart in date order (default true), so days without data (weekends, holidays) leave no gap; false places each period at its date on a continuous time axis, where xConfig.rangeBreaks can hide weekends, holidays, or off-hours.
Many periods
Section titled “Many periods”Two years of daily candles. The Canvas renderer draws dense charts quickly while keeping the snapped tooltip; candles narrow to fit, down to a single pixel.
Selects which @d3plus/render backend paints the visible output. "svg" = SvgRenderer (default), "canvas" = CanvasRenderer. Boolean arguments both normalize to "svg".
Places periods one slot apart in date order (default true), so days without data (weekends, holidays) leave no gap; false places each period at its date on a continuous time axis, where xConfig.rangeBreaks can hide weekends, holidays, or off-hours.
The share of each period's room the candle body (or OHLC ticks) spans, from 0 to 1. Defaults to 0.7.
Small multiples
Section titled “Small multiples”facet draws one panel per ticker. With facetConfig.scales: "independent", each panel’s value axis fits its own price range.
Splits the chart into small multiples: a grid of equally sized panels, one per distinct value of this data key or accessor, each drawing the chart for that value's rows. The panels share one legend, color scale, title, and timeline, color each series the same way, and hover, tooltips, and legend clicks apply across all of them. Pass false to draw a single chart. See facetConfig for the grid's layout and shared scales.
Configuration
import {Candlestick} from "@d3plus/core";
activefalse|functionThe active callback function for highlighting shapes.
annotationsunknownDefaultunknownAllows drawing custom shapes to be used as annotations in the provided x/y plot. This method accepts custom config objects for the Shape class, either a single config object or an array of config objects. Each config object requires an additional parameter, the "shape", which denotes which Shape sub-class to use (Rect, Line, etc).
Additionally, each config object can also contain an optional "layer" key, which defines whether the annotations will be displayed in "front" or in "back" of the primary visualization shapes. This value defaults to "back" if not present ("front" for callouts).
Three more kinds draw chart notes:
"Callout"anchors wrapped text in a box at each data row'sx/y(in data units, or plot-area fractions withxRef/yRef: "plot"), offset bydx/dypixels and joined to its anchor by a connector ending in an arrowhead or dot (seeCalloutAnnotation);"ReferenceLine"and"ReferenceBand"draw whatreferenceLinesandreferenceBandsentries expand into. All annotations follow zoom and never respond to the pointer or keyboard.axisPersistbooleanDefaultunknownDetermines whether the x and y axes should have their scales persist while users filter the data, the timeline being the prime example (set this to
trueto make the axes stay consistent when the timeline changes).backgroundConfigrecordDefault{duration: 0, fill: transparent}A d3plus-shape configuration Object used for styling the background rectangle of the inner x/y plot (behind all of the shapes and gridlines).
bodyWidthnumberDefault0.7The share of each period's room the candle body (or OHLC ticks) spans, from 0 to 1. Defaults to 0.7.
bufferboolean|recordDefaultassign({}, defaultBuffers, {Bar: false, Line: false})Determines whether or not to add additional padding at the ends of x or y scales. The most commone use for this is in Scatter Plots, so that the shapes do not appear directly on the axis itself. The value provided can either be
trueorfalseto toggle the behavior for all shape types, or a keyed Object for each shape type (ie.{Bar: false, Circle: true, Line: false}).classNamestring|array.<string>|undefinedCSS classes added to the outermost element this chart or component draws into, next to its fixed d3plus classes, so page CSS can target it: a chart's root
<svg class="d3plus-viz">(its<canvas>with the Canvas renderer) and a standalone component's<svg>. Takes a space-separated string or an array. A new value replaces the classes the previous one added; unset adds none. Tooltips take their owntooltipConfig.className.closestring|functionDefault"close"Accessor (or data key) for each period's closing value. Defaults to
"close". The close is the chart'sy: settingysets it, rows without one are skipped, and hover snaps to it. Merged rows take the last row's close;aggsoverrides it as it does foropen.colorDefaultscolordefaultsconfigOverrides the default colors used when assigning fills from data and choosing legible text colors:
darkandlight(the text colors picked for contrast against a background),missing(null/undefined values),on/off(true/falsevalues),sequential(the anchor hue for magnitude ramps), andscale(the categorical palette, given as a d3 ordinal scale or an array of colors). Keys are merged into the current defaults, and a Viz passes its overrides down to the shapes and components it draws.configd3plusconfigMethods that correspond to the key/value pairs and returns this class.
crosshairConfigrecordDefaultfunction{stroke: () => themed(this._theme, (t) => t.textMuted, colorGray.500), strokeDasharray: 4 3, strokeWidth: 1}Paint for the shared tooltip's crosshair guide line (
stroke,strokeWidth,strokeDasharray,strokeOpacity, …). Merged into the current config.datastring|array.<datapoint>|objectThe primary data array used to draw the visualization. The value passed should be an Array of objects or a String representing a filepath or URL to be loaded. The following filetypes are supported:
csv,tsv,txt, andjson.If your data URL needs specific headers to be set, an Object with a "url" and "headers" (or any other
fetchrequest option) may also be passed. An Object with any other key is a data row, not a request.Additionally, a custom formatting function can be passed as a second argument to this method. This custom function will be passed the data that has been loaded, as long as there are no errors. This function should return the final array of obejcts to be used as the primary data array. For example, some JSON APIs return the headers split from the data values to save bandwidth. These would need be joined using a custom formatter.
If you would like to specify certain configuration options based on the yet-to-be-loaded data, you can also return a full
configobject from the data formatter (including the newdataarray as a key in the object).To re-fetch a URL on an interval and redraw when its data changes, set
dataPollingInterval; each poll runs the same formatter.Defaults to an empty array (
[]).downColorstring|functionDefault"#e03131"The color of periods that closed below their open: a color string, or an accessor of the row. Defaults to red.
facetstring|false|functionSplits the chart into small multiples: a grid of equally sized panels, one per distinct value of this data key or accessor, each drawing the chart for that value's rows. The panels share one legend, color scale, title, and timeline, color each series the same way, and hover, tooltips, and legend clicks apply across all of them. Pass
falseto draw a single chart. SeefacetConfigfor the grid's layout and shared scales.facetConfigfacetconfigConfiguration for small multiples (see
facet), merged into the current config: -columns/rows: the grid's shape. Chosen by default to make the panels as large as the chart's shape allows. -padding: the space between panels, in pixels (default20). -sort: panel order —"ascending"(default),"descending","data"(first appearance), a comparator over facet values, or an Array of values. -scales:"shared"(default) gives every panel of a chart with axes the same x/y domains;"independent"fits each panel to its own rows. Funnel defaults to"independent"(each panel sized to its own widest stage);"shared"sizes every panel against the widest stage across all panels. PolarArea and RadialBar default to"independent"(each panel's rings and ticks fit its own values);"shared"gives every panel the same value domain. -axes: with shared scales,"outer"(default) labels the axes only along the grid's left and bottom edges;"all"labels every panel. An object sets each axis on its own, as in{x: "all", y: "outer"}: every panel labels its x axis, only the left column labels its y axis, and the panels' plot areas line up. BumpChart defaults to"all", and Marimekko labels its categories on every panel and its 0–100% share axis only along the outer edge, even with independent scales. -title: a(value, data) => stringfunction for each panel's title, orfalseto hide panel titles. -titleConfig: TextBox config for the panel titles (fontSize,fontWeight,fontColor,textAnchor,padding, …).fontFamilystring|array.<string>The font family used throughout the visualization.
groupBystring|function|array.<string|function>Defines the mapping between data and shape. The value can be a String matching a key in each data point (default is "id"), or an accessor Function that returns a unique value for each data point. Additionally, an Array of these values may be provided if the visualization supports nested hierarchies.
highstring|functionDefault"high"Accessor (or data key) for each period's highest value. Defaults to
"high"; the high always reaches the open and close. Merged rows take the highest high;aggsoverrides it as it does foropen.highlightfalse|functionPersistently emphasizes the data points matching the given predicate: the matching marks keep their color while every other mark is de-emphasized to a neutral gray (the "emphasis" form — highlight one series, gray the rest). Unlike
hover/active(transient, opacity-based),highlightis a standing state that survives pointer movement. Passfalseto clear it.hollowbooleanDefaulttrueDraws rising candles as outlines and falling candles filled (default
true), so direction reads without relying on color;falsefills both. OHLC bars are never filled. An unfilled candle or bar takes noshapeConfig.textureorshapeConfig.backgroundImage; filled ones take both, with a texture's lines a shade darker than the body unless the texture sets its ownstroke.hoverfalse|functionThe hover callback function for highlighting shapes on mouseover.
legendboolean|functionDefaultfalseWhether to display the legend. By default, the legend shows when it has more than one entry and each entry stands for a single group (or two groups at most), or when the entries are colored by a category that isn't a
groupBylevel (seecolor), in which case each entry is labelled by its category. Passfalseto hide it,trueto always show it, or a(config, data) => booleanfunction to decide.localestring|objectThe locale used for all text and number formatting. Supports the locales defined in d3plus-format. The locale can be a complex Object, a locale code (like "en-US"), or a 2-digit language code (like "en"). If a 2-digit code is provided, the "findLocale" function is used to identify the most approximate locale.
lowstring|functionDefault"low"Accessor (or data key) for each period's lowest value. Defaults to
"low"; the low always reaches the open and close. Merged rows take the lowest low;aggsoverrides it as it does foropen.onstringEvent listener for the specified event typenames. Mirrors the core d3-selection behavior.
openstring|functionDefault"open"Accessor (or data key) for each period's opening value. Defaults to
"open"; a row without one opens at its close. Rows that share a series and a period merge into one candle, taking the first row's open (in data order, so sort rows oldest first). Override with anaggsentry on the data key, or, for a function accessor, on"open".parentunknownParent config used by the wrapper.
renderfunctionDraws the visualization given the specified configuration.
rendererboolean|"svg"|"canvas"Selects which @d3plus/render backend paints the visible output.
"svg"= SvgRenderer (default),"canvas"= CanvasRenderer. Boolean arguments both normalize to"svg".selectstring|htmlelementThe SVG container element as a d3 selector or DOM element. Defaults to
undefined.shapeConfigd3plusconfigConfiguration object with key/value pairs applied as method calls on each shape.
skipGapsbooleanDefaulttruePlaces periods one slot apart in date order (default
true), so days without data (weekends, holidays) leave no gap;falseplaces each period at its date on a continuous time axis, wherexConfig.rangeBreakscan hide weekends, holidays, or off-hours.thresholdnumber|functionThe threshold value for bucketing small data points together, as a share of the total. On a stacked Plot, the series whose summed value across every position is under that share of the whole chart's total merge into one series, stacked on top. A bucket needs at least two items, and its tooltips list them. Off (
0) by default on Plot charts.thresholdKeystring|functionAccessor for the value used in the threshold algorithm. A stacked Plot defaults to its stacked value.
timestring|false|functionAccessor function or string key for the time dimension of each data point.
timelinebooleanDefaultfalseWhether to show the timeline component.
timelineDefaultstring|date|array.<string|date>The starting time or range for the timeline. Can be a single Date/String, or an Array of 2 values representing the min and max.
tooltipConfigtooltipconfigDefault{tbody: (d: DataPoint, i: number) => candleTooltipRows(viz, d, i)}Configuration for the tooltip component.
totalstring|boolean|functionAccessor function or string key for the total value displayed in the visualization.
translatefunctionDefines how informational text strings should be displayed. By default, this function will try to find the string in question (which is the first argument provided to this function) inside of an internally managed translation Object. If you'd like to override to use custom text, simply pass this method your own custom formatting function.
upColorstring|functionDefault"#2f9e44"The color of periods that closed at or above their open: a color string, or an accessor of the row. Defaults to green.
variant"candlestick"|"ohlc"Default"candlestick"How each period draws:
"candlestick"(default), a wick from the high to the low around a body from the open to the close; or"ohlc", a line from the high to the low with the open ticked to the left and the close ticked to the right.volumestring|false|functionAccessor (or data key) for each period's traded volume. Off by default; when set, a strip under the candles draws one bar per candle, as tall as its volume on the strip's own axis (ticks abbreviated, e.g. "1.2M"), in its candle's up or down color, and the tooltip adds a Volume row. Bars are always filled, hollow candles included, and take
shapeConfig.textureandshapeConfig.backgroundImagelike filled candles; they hover with their candle. The price axis shrinks to make room, and the x axis sits under the strip. Merged rows add their volumes; anaggsentry overrides it as it does foropen. Setfalseto turn it off.volumeConfigobjectDefaultVOLUME_DEFAULTSThe volume strip's layout and styling:
height, its height as a share of the plot's (default0.2; pixels when above 1; at most half the plot);gap, the pixels between the candles and the strip (default16);axisConfig, Axis config for the strip's value axis; andshapeConfig, Path config for the bars (default{fillOpacity: 0.5}).xplotaccessorargDefaultfunctiond => d["x"]Accessor function or string key for the x-axis value of each data point.
x2plotaccessorargDefaultfunctiond => d["x2"]Accessor function or string key for the secondary x-axis value of each data point.
x2ConfigrecordDefault{}A pass-through to the underlying Axis config used for the secondary x-axis. Includes additional functionality where passing "auto" as the value for the scale method will determine if the scale should be "linear" or "log" based on the provided data.
xConfigrecordDefaultfunction{gridConfig: {stroke: (d) => { if (this.schema.discrete?.charAt(0) === "x" || this._swarm?.cross === "x") return "transparent"; const range = this._xAxis.range(); const position = this._xAxis._getPosition.bind(this._xAxis)(d.id); if (range[0] === position) return "transparent"; return chartGridline(this); }}}A pass-through to the underlying Axis config used for the x-axis. Includes additional functionality where passing "auto" as the value for the scale method will determine if the scale should be "linear" or "log" based on the provided data.
yplotaccessorargDefaultfunctiond => d["y"]Accessor function or string key for the y-axis value of each data point.
y2plotaccessorargDefaultfunctiond => d["y2"]Accessor function or string key for the secondary y-axis value of each data point.
y2ConfigrecordDefault{}A pass-through to the underlying Axis config used for the secondary y-axis. Includes additional functionality where passing "auto" as the value for the scale method will determine if the scale should be "linear" or "log" based on the provided data.
yConfigrecordDefaultfunction{gridConfig: {stroke: (d) => { if (this.schema.discrete?.charAt(0) === "y" || this._swarm?.cross === "y") return "transparent"; const range = this._yAxis.range(); const position = this._yAxis._getPosition.bind(this._yAxis)(d.id); if (range[range.length - 1] === position) return "transparent"; return chartGridline(this); }}}A pass-through to the underlying Axis config used for the y-axis. Includes additional functionality where passing "auto" as the value for the scale method will determine if the scale should be "linear" or "log" based on the provided data.
Note: If a "domain" array is passed to the y-axis config, it will be reversed.