Trend / Intermediate
Candlestick Chart
Compare opening, closing, high, and low values for ordered sessions.
Interactive Chart Preview
JAVASCRIPTEdit the column names and values to update your chart. Changes stay in this page until you reload.
| Row# | Calendar Date | Opening Price | Session High | Session Low | Closing Price | Remove row |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | ||||||
| 3 | ||||||
| 4 | ||||||
| 5 | ||||||
| 6 |
Use distinct calendar dates in increasing order. Low and High must contain both Open and Close. Equal values are valid. Dates have equal session spacing; skipped dates do not create extra width.
Chart.js Code Example
JAVASCRIPTimport Chart from 'chart.js/auto';
// Illustrative data used by the live preview.
const chartData = {
"ohlcHeaders": [
"Session Date",
"Open",
"High",
"Low",
"Close"
],
"ohlc": [
{
"date": "2025-01-06",
"open": 100,
"high": 106,
"low": 98,
"close": 104
},
{
"date": "2025-01-07",
"open": 105,
"high": 108,
"low": 101,
"close": 102
},
{
"date": "2025-01-08",
"open": 102,
"high": 107,
"low": 100,
"close": 106
},
{
"date": "2025-01-09",
"open": 107,
"high": 110,
"low": 104,
"close": 107
},
{
"date": "2025-01-10",
"open": 106,
"high": 109,
"low": 103,
"close": 108
},
{
"date": "2025-01-13",
"open": 110,
"high": 115,
"low": 108,
"close": 113
}
],
"datasets": []
};
function createConfig(chartData) {
const rows = chartData.ohlc, headers = chartData.ohlcHeaders;
const low = Math.min(...rows.map(row => row.low)), high = Math.max(...rows.map(row => row.high));
const padding = high > low ? (high - low) * 0.05 : Math.max(1, Math.abs(low) * 0.05);
const minimum = low - padding, maximum = high + padding;
const color = (row) => row.close > row.open ? '#2563eb' : row.close < row.open ? '#be123c' : '#475569';
return {
type: 'bar', data: { labels: rows.map(row => row.date), datasets: [{ label: 'Session', data: rows.map(row => [row.open, row.close]), backgroundColor: rows.map(color), borderColor: rows.map(color), borderWidth: 1, categoryPercentage: 0.6, barPercentage: 1, maxBarThickness: 40 }] },
plugins: [{ id: 'candle-wicks', beforeDatasetsDraw: chart => {
const ctx = chart.ctx, half = Math.min(20, chart.chartArea.width / rows.length * 0.3);
ctx.save();
ctx.lineWidth = 1.5;
rows.forEach((row, index) => {
const x = chart.scales.x.getPixelForValue(index);
ctx.strokeStyle = color(row);
ctx.beginPath();
ctx.moveTo(x, chart.scales.y.getPixelForValue(row.low));
ctx.lineTo(x, chart.scales.y.getPixelForValue(row.high));
ctx.stroke();
if (row.open === row.close) {
const y = chart.scales.y.getPixelForValue(row.open);
ctx.beginPath();
ctx.moveTo(x - half, y);
ctx.lineTo(x + half, y);
ctx.stroke();
}
});
ctx.restore();
} }],
options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false },
scales: { x: { title: { display: true, text: `${headers[0]} (Equal Spacing)` }, grid: { display: false }, ticks: { maxRotation: 45 } }, y: { min: minimum, max: maximum, title: { display: true, text: 'Price' } } },
plugins: { legend: { display: false }, title: { display: true, text: 'Body: Open to Close; Wick: Low to High' }, tooltip: { callbacks: { label: item => { const row = rows[item.dataIndex]; return [row.open, row.high, row.low, row.close].map((value, index) => `${headers[index + 1]}: ${value}`); } } } },
},
};
}
const chart = new Chart(document.getElementById('myChart'), createConfig(chartData));Preview and code follow the same library selection.
Run This Example
Install the package below in a browser project such as Vite. Put the copied code in a client JavaScript module and add this container to the page before the module runs.
npm install chart.js@4.5.1<div style="height:320px"><canvas id="myChart"></canvas></div>The example includes its sample data. When removing the chart, destroy or dispose of its instance and disconnect any resize observer.
Reading This Example
These illustrative prices cover six sessions from 6 to 13 January 2025. The first opens at 100 and closes at 104; the second opens at 105 and closes at 102. On 9 January, both Open and Close are 107, so the body is a horizontal mark. The overall low is 98 and high is 115. All sessions occupy equal horizontal spacing despite the missing weekend dates.
All library tabs use these illustrative values. Rendering styles and library APIs differ, so use the table to compare exact numbers.
About this example & sample data
| Session Date | Open | High | Low | Close |
|---|---|---|---|---|
| 2025-01-06 | 100 | 106 | 98 | 104 |
| 2025-01-07 | 105 | 108 | 101 | 102 |
| 2025-01-08 | 102 | 107 | 100 | 106 |
| 2025-01-09 | 107 | 110 | 104 | 107 |
| 2025-01-10 | 106 | 109 | 103 | 108 |
| 2025-01-13 | 110 | 115 | 108 | 113 |
READ THE CHART
Read Four Values in Each Session
A candlestick combines an opening value, closing value, high, and low for one interval. The body shows the difference between open and close; the thin wick reaches the interval extremes. It reveals variation that a line of closing values alone would hide.
Read the Body and Wick Together
The body spans Open to Close, while the wick spans Low to High. Blue means Close is above that session's Open, red means below, and gray means equal. A horizontal body mark, often called a doji, retains equal opening and closing values. A long wick shows a wide observed range; it does not tell you the order or duration of movements within the session.
Compare With the Correct Opening Value
A blue candle can still close below the previous session's close if it opened lower. Its color compares its own Open and Close only. A new session may open above or below the prior close. The editor allows those gaps and requires both Open and Close to lie between the supplied Low and High. Prices in this example must be nonnegative.
Keep Session Dates in Order
The date editor accepts real calendar dates, with one observation per date in increasing order. Dates are labels for equally spaced sessions in all six examples. Skipped dates, including the weekend in this sample, do not occupy extra horizontal space. This is not an elapsed-time axis. Date validation uses UTC calendar dates without accepting timestamps or applying a local timezone conversion.
Keep Interpretation Within the Data
These fictional values explain chart mechanics. Candle shapes do not establish a cause or predict a later price. The chart contains no volume, trades, or within-session path. Use a Line Chart for a simpler view of one recorded value per interval. The Seaborn example applies its theme to Matplotlib rectangles and lines; it is not a native Seaborn candlestick function.