Charts/Base
Candlestick
<Candlestick /> · 12 examples
Open, high, low and close for each period, drawn as one candle, with volume underneath.
Overview
A line chart of a price throws away almost everything that happened in a day. It keeps one number, usually the close, and pretends the rest of the day was quiet. A candlestick keeps four: where the period opened, where it closed, and how far it strayed up and down on the way. That is a lot of story for a few pixels of width.
The form is usually traced to Japanese rice traders in the eighteenth century, with the merchant Munehisa Homma often named as the person who made it famous. The details of that tale are better told by people who have read the sources than by a documentation page, but the design has clearly survived for a reason. Western traders found it in the 1990s and have been drawing it on every screen since, usually in front of a green and red glow.
Do not let the finance flavour fool you. Anything that has a first, a last, a smallest and a largest value per bucket is a candlestick in waiting: the latency of each minute, the temperature of each day, the queue depth of each hour. A candle says where the bucket started, where it ended, and how wild it got in between. The only thing it will not do is predict next Tuesday, which is why the people who read tea leaves for a living still prefer it.
Props
API
<Candlestick> draws price bars: each period's open, high, low and close as a candle or an OHLC bar, with trading volume along the bottom. It is a port of Grafana's Candlestick panel; see Coming from Grafana.
use zopra_charts::*;
Not sure which option fits? See the guide.
<Candlestick>
<Candlestick data={bars} x={|b: &Bar| b.time}
open={|b: &Bar| b.open} high={|b: &Bar| b.high} low={|b: &Bar| b.low}
close={|b: &Bar| b.close} volume={|b: &Bar| b.volume}>
<TrendSeries name="SMA 20" y={|b: &Bar| b.sma} />
</Candlestick>| Prop | Type | Default |
|---|---|---|
data | Vec<T>, Signal<Vec<T>>, Frame<N>, Signal<Frame<N>>, or your own Dataset | required |
x | Fn(&T) -> f64: the start of each period, in milliseconds since the epoch | for a Frame: the x_field, or the first field |
x_field | field name, for a Frame | the first field |
open, high, low, close, volume | Fn(&T) -> f64 | for a Frame: found by name, see Fields |
| children | <TrendSeries> overlays, such as moving averages | none |
mode | CandleMode | CandlesVolume |
candle_style | CandleStyle | Candles |
color_strategy | ColorStrategy | OpenClose |
up, down, flat | colours | your theme's good, bad and neutral colours |
include_all_fields | bool: draw a Frame's other fields as lines | false |
x_axis | AxisConfig | a time axis |
y_axis | AxisConfig for the price axis | AxisConfig::new() |
legend | Legend | lists the overlays |
tooltip | Tooltip | Tooltip::multi(): open, high, low, close and volume |
annotations | Annotations | none |
orientation, timezones, keyboard, on_select | as on <TimeSeries> | |
class, key |
Fields
With a Frame and no field accessors, fields are matched by name, ignoring case:
| Part | Field names |
|---|---|
| open | open, o |
| high | high, h, max |
| low | low, l, min |
| close | close, c |
| volume | volume, v |
Missing parts are filled in as Grafana does:
- No open: each candle opens at the previous close.
- No close: each candle closes at the next open.
- No high or low: the wick ends at the body.
include_all_fields draws every other field of the frame as a line on the price axis. In Candles mode an unused volume field becomes one of those lines; in Volume mode, high and low do.
How candles are drawn
- Width. Bodies are 60% of the narrowest gap between periods. Wicks and OHLC ticks are 1 px wide when bodies are 12 px or narrower, otherwise 2 px.
- Colour. With
ColorStrategy::OpenClose, a candle is up when it closes above its open. WithCloseClose, it is up when it closes above the previous close; rising candles are then drawn hollow, outlined in their colour. Equal values count as up, except the first candle underCloseClose, which is flat. - Volume. In
CandlesVolumemode, volume bars sit in the bottom seventh of the chart on their own hidden scale (0 to 7 × the largest volume), coloured like their candle at half opacity. InVolumemode, they use the whole chart and the price axis. - Overlays.
<TrendSeries>children are drawn over the candles on the price axis and listed in the legend; the price parts themselves are not.
Enums
| Enum | Variants |
|---|---|
CandleMode | Candles, CandlesVolume (default), Volume |
CandleStyle | Candles (default), OhlcBars |
ColorStrategy | OpenClose (default), CloseClose |
Coming from Grafana
| Grafana option | Here |
|---|---|
| Mode | mode |
| Candle style | candle_style |
| Color strategy | color_strategy |
| Up color, Down color, Flat color | up, down, flat |
| Open, High, Low, Close, Volume fields | open, high, low, close, volume, or field names |
| Include all fields | include_all_fields, or <TrendSeries> children |
| Legend, Tooltip, Annotations | legend, tooltip, annotations |
Not available here: the volume field's own fill opacity (volume is drawn at 50%) and tick labels on the volume axis.
Run them
12 examples
Press Run to load an example into the live render at the top of the page. Open one to read its code.
How to read it
- 01Read the body first: the filled part runs from open to close, and its colour says whether it went up or down under the chosen strategy.
- 02Then the wicks. A long upper wick means the price went high and was pushed back. A long lower one means the opposite. Both are the range the line chart hid.
- 03Look at volume under the candle. A big move on small volume and a big move on large volume are different events.
- 04Hover a candle for open, high, low, close and volume.
When to use it, and when not to
Reach for it when
- Each x holds a range, not a single value: a trading day, a minute of latency, a day's temperature.
- You care about the spread within a period as well as where it ended.
- You want to overlay a moving average, a band or a target on the same axes.
- Volume or activity should be read alongside price, in one panel.
Skip it when
- You have one value per point. Candlestick with only a close draws bodies that are just the change since the last candle, which is a fine way to disguise a line chart as a lot of rectangles. Use Time Series.
- Your audience does not read candles. Explaining which end of the body is the open will take longer than reading the data.
- Periods are very uneven in size, such as one tick and then a whole week, so the candles are not comparable.
- You want to show that patterns predict the future. They do not, whatever the green glow suggests.
The math behind it
One bucket, four numbers
For each period you supply an open , a high , a low and a close (and optionally a volume ). The candle is a body between and and a thin wick from to . Both are placed on a shared linear y scale, the same one used by Trend, so the axis is rounded outwards to nice numbers in the usual way.
Parts you do not supply are not an error. If there is no open, the candle opens at the previous close, which is what happens in a market that never closes. If you give only a close, the whole chart still draws: each candle spans previous close to close.
Colour: which way did it go
Colour is a function of direction. With the default ColorStrategy::OpenClose a candle is up when its close is at or above its open, and down otherwise. With ColorStrategy::CloseClose the comparison is against the previous close, and the candle is up when . The two can disagree: a stock that opens far below yesterday's close and ends the day slightly higher is an up candle by one rule and a down candle by the other.
Equal values count as up, with one exception: the very first candle under CloseClose has no previous close and is drawn flat. Under CloseClose, rising candles are drawn hollow, outlined in their colour, which is the convention many trading tools use.
Volume and bar width
In the default CandlesVolume mode the plot is shared: candles use the price scale and volume bars use their own scale, drawn at half opacity so they stay behind the candles. The Candles and Volume modes give the whole height to one of them.
Moving averages and bands are ordinary <TrendSeries> children with the full Trend styling, drawn over the candles.
Real life usage
The five-minute outage that wasn't in the average
Ines was an SRE at a company that sold appointment reminders by text message. On the dashboard the checkout latency was a calm blue line sitting at about 180 milliseconds, and it had been that calm blue line for months, including during the incident the customer success team kept bringing up in meetings.
The incident was real. Customers had written in. Some had been charged twice. And the latency chart, which was an average per minute, showed a polite little bump to 260 ms and then went back to being calm, like a man who has been told to relax.
An average is a very efficient way to hide a minute in which 3 requests took 40 seconds and 9,000 took 180 milliseconds. Ines knew that. She needed a chart that would show the worst request in every minute along with the first and last, so that anyone looking could see the length of the tail without opening a query console.
She rebuilt the panel with <Candlestick> from zopra-charts: for each minute, the first latency as open, the last as close, the minimum as low and the maximum as high, with request count as volume. A moving average went on top as a <TrendSeries>, and she picked blue and orange for up and down so nobody would need a colour chart.
During the incident window the candles stopped looking like candles and started looking like flagpoles. Wicks ran up to 41 seconds, at the same minutes the double-charge tickets arrived, and the volume bars dipped just before, which is what a retry storm looks like from the outside.
Armed with that picture she got the retry policy changed in a single afternoon. The next month there were two wicks above 5 seconds instead of forty-three, and the customer success team found something else to bring up in meetings.
The calm blue line is still on the dashboard, in the corner, labelled average. It has been asked to reflect on that.
Pitfalls
- Colour rules differ between tools. Open-close and close-close colouring give different candles for the same data. Pick one and say which.
- Gaps in time. Weekends and holidays leave holes unless your x values are sequence numbers. Decide whether a gap is information.
- Red and green only. Pick
upanddowncolours that read for colour-blind viewers, such as blue and orange. - Treating a single close as OHLC. With close only, each candle opens at the previous close, which draws bodies but adds no information.
From around the web