Stock markets close at weekends, leaving holes on a calendar axis. This axis skips days with no data: 200 trading days of price and volume, one after another.
Data that exists only on working days, or during opening hours, looks broken on a calendar axis: the line jumps across every weekend and the columns leave holes. A gapless axis puts the days one after another, so the whole width shows data.
Built with amCharts 5, a JavaScript library. The JavaScript includes your theme and renderer (canvas or SVG); the JSON also follows the changes you make with the controls.
npm install @amcharts/amcharts5. See Getting started.
The same chart as a JSON config. Chart Maker reads and writes this format, the library's JSON parser turns it into a chart, and the <am5-chart> element puts it on a page with no code."type" is the class to create and "settings" what you would pass to its new() in code; "properties" fill in its parts, lists such as series and axes or templates such as columns.template; "refs" holds objects used in more than one place ("#series-0" stands for the one named series-0); a string starting with "@" takes a value from another object, such as "@series.get('fill')".
A complete page. Save it as an .html file and open it in a browser.
Paste this into an AI coding assistant to build the chart from scratch. More in amCharts & AI.
// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");
// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
// a drag zooms (the cursor's behavior below), so the chart itself doesn't pan
panX: false,
panY: false,
wheelX: "panX", // a horizontal wheel or trackpad swipe pans...
wheelY: "zoomX", // ...and the vertical wheel zooms in on the days
pinchZoomX: true, // pinch with two fingers to zoom on a touch screen
paddingLeft: 0 // the value labels sit at the chart's left edge
}));
// Add cursor
// https://www.amcharts.com/docs/v5/charts/xy-chart/cursor/
var cursor = chart.set("cursor", am5xy.XYCursor.new(root, {
// drag across the plot to zoom in on those days
behavior: "zoomX"
}));
cursor.lineY.set("visible", false); // only the vertical cursor line, no horizontal one
// Generate random data
var date = new Date();
date.setHours(0, 0, 0, 0);
var value = 1000; // the prices start near 1000
var volume = 100000; // the volumes start near 100,000
// the next weekday's price and volume, each a small random step from the day before
function generateData() {
value = Math.round((Math.random() * 10 - 5) + value); // the price moves by up to 5...
volume = Math.round((Math.random() * 1000 - 500) + volume); // ...the volume by up to 500
am5.time.add(date, "day", 1);
// add another if it's saturday
if (date.getDay() == 6) {
am5.time.add(date, "day", 1);
}
// add another if it's sunday
if (date.getDay() == 0) {
am5.time.add(date, "day", 1);
}
return {
date: date.getTime(),
value: value,
volume: volume
};
}
// an array of count weekdays
function generateDatas(count) {
var data = [];
for (var i = 0; i < count; ++i) {
data.push(generateData());
}
return data;
}
// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
// a date axis that skips dates with no data (the weekends here), so the line has no gaps
var xAxis = chart.xAxes.push(am5xy.GaplessDateAxis.new(root, {
maxDeviation: 0, // no panning past the first or last day
baseInterval: { // one point per day
timeUnit: "day",
count: 1
},
renderer: am5xy.AxisRendererX.new(root, {
minorGridEnabled: true // fainter grid lines between the labeled ones
}),
tooltip: am5.Tooltip.new(root, {}) // a date label follows the cursor along the axis
}));
var yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
// no panning or zooming out past the prices
maxDeviation: 0,
// 20% extra room below the line, where the volume columns stand
extraMin: 0.2,
renderer: am5xy.AxisRendererY.new(root, {})
}));
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.LineSeries.new(root, {
name: "Series",
xAxis: xAxis,
yAxis: yAxis,
valueYField: "value",
valueXField: "date",
tooltip: am5.Tooltip.new(root, {
labelText: "{valueY}" // the tooltip shows the price
})
}));
// y axis for volume
var volumeAxisRenderer = am5xy.AxisRendererY.new(root, {});
volumeAxisRenderer.grid.template.set("forceHidden", true); // no grid lines...
volumeAxisRenderer.labels.template.set("forceHidden", true); // ...and no labels for the volume axis
var volumeAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, {
// the bottom quarter of the plot area, under the price line
height: am5.percent(25),
y: am5.percent(100),
centerY: am5.percent(100),
panY: false, // the volume axis never pans up or down
renderer: volumeAxisRenderer
}));
// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var volumeSeries = chart.series.push(am5xy.ColumnSeries.new(root, {
name: "Volume Series",
xAxis: xAxis,
yAxis: volumeAxis,
valueYField: "volume",
valueXField: "date",
tooltip: am5.Tooltip.new(root, {
labelText: "{valueY}" // the tooltip shows the volume
})
}));
// slightly see-through, no outline, each column 40% of its day's width
volumeSeries.columns.template.setAll({ fillOpacity: 0.8, strokeOpacity: 0, width: am5.percent(40) })
// Add scrollbar
// https://www.amcharts.com/docs/v5/charts/xy-chart/scrollbars/
chart.set("scrollbarX", am5.Scrollbar.new(root, {
orientation: "horizontal" // a bar above the plot to zoom and scroll through the days
}));
// Set data
var data = generateDatas(200);
series.data.setAll(data);
volumeSeries.data.setAll(data);
// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear(1000);
chart.appear(1000, 100);
{
"type": "XYChart",
"settings": {
"panX": false,
"panY": false,
"wheelX": "panX",
"wheelY": "zoomX",
"pinchZoomX": true,
"paddingLeft": 0,
"cursor": {
"type": "XYCursor",
"settings": {
"behavior": "zoomX"
},
"properties": {
"lineY": {
"settings": {
"visible": false
}
}
}
},
"scrollbarX": {
"type": "Scrollbar",
"settings": {
"orientation": "horizontal"
}
}
},
"properties": {
"series": [
"#series-0",
"#series-1"
],
"xAxes": [
"#axis-0"
],
"yAxes": [
"#axis-1",
"#axis-2"
]
},
"refs": [
{
"data-0": [
{
"date": 1791406800000,
"value": 1005,
"volume": 99878
},
{
"date": 1791493200000,
"value": 1006,
"volume": 100101
},
{
"date": 1791752400000,
"value": 1008,
"volume": 100266
},
{
"date": 1791838800000,
"value": 1011,
"volume": 100517
},
{
"date": 1791925200000,
"value": 1016,
"volume": 100883
},
{
"date": 1792011600000,
"value": 1012,
"volume": 100743
},
{
"date": 1792098000000,
"value": 1012,
"volume": 100354
},
{
"date": 1792357200000,
"value": 1008,
"volume": 100066
},
{
"date": 1792443600000,
"value": 1010,
"volume": 100031
},
{
"date": 1792530000000,
"value": 1010,
"volume": 99844
},
{
"date": 1792616400000,
"value": 1011,
"volume": 99528
},
{
"date": 1792702800000,
"value": 1016,
"volume": 99752
},
{
"date": 1792965600000,
"value": 1016,
"volume": 99664
},
{
"date": 1793052000000,
"value": 1014,
"volume": 100023
},
{
"date": 1793138400000,
"value": 1010,
"volume": 99615
},
{
"date": 1793224800000,
"value": 1010,
"volume": 99187
},
{
"date": 1793311200000,
"value": 1010,
"volume": 99618
},
{
"date": 1793570400000,
"value": 1007,
"volume": 99549
},
{
"date": 1793656800000,
"value": 1008,
"volume": 100024
},
{
"date": 1793743200000,
"value": 1008,
"volume": 100340
},
{
"date": 1793829600000,
"value": 1012,
"volume": 99954
},
{
"date": 1793916000000,
"value": 1007,
"volume": 100156
},
{
"date": 1794175200000,
"value": 1008,
"volume": 100363
},
{
"date": 1794261600000,
"value": 1004,
"volume": 100074
},
{
"date": 1794348000000,
"value": 1003,
"volume": 100023
},
{
"date": 1794434400000,
"value": 999,
"volume": 99696
},
{
"date": 1794520800000,
"value": 1000,
"volume": 100012
},
{
"date": 1794780000000,
"value": 1005,
"volume": 100350
},
{
"date": 1794866400000,
"value": 1005,
"volume": 100731
},
{
"date": 1794952800000,
"value": 1010,
"volume": 100602
},
{
"date": 1795039200000,
"value": 1014,
"volume": 100139
},
{
"date": 1795125600000,
"value": 1013,
"volume": 100260
},
{
"date": 1795384800000,
"value": 1012,
"volume": 99987
},
{
"date": 1795471200000,
"value": 1011,
"volume": 99568
},
{
"date": 1795557600000,
"value": 1011,
"volume": 100049
},
{
"date": 1795644000000,
"value": 1012,
"volume": 99950
},
{
"date": 1795730400000,
"value": 1012,
"volume": 99760
},
{
"date": 1795989600000,
"value": 1010,
"volume": 99844
},
{
"date": 1796076000000,
"value": 1005,
"volume": 100034
},
{
"date": 1796162400000,
"value": 1004,
"volume": 99753
},
{
"date": 1796248800000,
"value": 1004,
"volume": 99774
},
{
"date": 1796335200000,
"value": 1006,
"volume": 99738
},
{
"date": 1796594400000,
"value": 1003,
"volume": 100238
},
{
"date": 1796680800000,
"value": 1004,
"volume": 99743
},
{
"date": 1796767200000,
"value": 1003,
"volume": 99961
},
{
"date": 1796853600000,
"value": 1005,
"volume": 99825
},
{
"date": 1796940000000,
"value": 1002,
"volume": 99864
},
{
"date": 1797199200000,
"value": 1002,
"volume": 99473
},
{
"date": 1797285600000,
"value": 1004,
"volume": 99185
},
{
"date": 1797372000000,
"value": 1006,
"volume": 98711
},
{
"date": 1797458400000,
"value": 1007,
"volume": 98969
},
{
"date": 1797544800000,
"value": 1007,
"volume": 98745
},
{
"date": 1797804000000,
"value": 1007,
"volume": 98369
},
{
"date": 1797890400000,
"value": 1005,
"volume": 98255
},
{
"date": 1797976800000,
"value": 1005,
"volume": 98192
},
{
"date": 1798063200000,
"value": 1009,
"volume": 98625
},
{
"date": 1798149600000,
"value": 1008,
"volume": 98707
},
{
"date": 1798408800000,
"value": 1007,
"volume": 98300
},
{
"date": 1798495200000,
"value": 1005,
"volume": 97928
},
{
"date": 1798581600000,
"value": 1005,
"volume": 97738
},
{
"date": 1798668000000,
"value": 1000,
"volume": 98155
},
{
"date": 1798754400000,
"value": 999,
"volume": 98489
},
{
"date": 1799013600000,
"value": 995,
"volume": 98489
},
{
"date": 1799100000000,
"value": 991,
"volume": 98595
},
{
"date": 1799186400000,
"value": 993,
"volume": 99022
},
{
"date": 1799272800000,
"value": 992,
"volume": 99007
},
{
"date": 1799359200000,
"value": 991,
"volume": 98797
},
{
"date": 1799618400000,
"value": 996,
"volume": 98522
},
{
"date": 1799704800000,
"value": 994,
"volume": 98767
},
{
"date": 1799791200000,
"value": 995,
"volume": 98797
},
{
"date": 1799877600000,
"value": 991,
"volume": 99292
},
{
"date": 1799964000000,
"value": 996,
"volume": 99331
},
{
"date": 1800223200000,
"value": 991,
"volume": 99011
},
{
"date": 1800309600000,
"value": 995,
"volume": 99069
},
{
"date": 1800396000000,
"value": 990,
"volume": 98579
},
{
"date": 1800482400000,
"value": 987,
"volume": 98082
},
{
"date": 1800568800000,
"value": 988,
"volume": 98547
},
{
"date": 1800828000000,
"value": 988,
"volume": 98233
},
{
"date": 1800914400000,
"value": 993,
"volume": 98350
},
{
"date": 1801000800000,
"value": 996,
"volume": 98316
},
{
"date": 1801087200000,
"value": 991,
"volume": 98526
},
{
"date": 1801173600000,
"value": 993,
"volume": 98444
},
{
"date": 1801432800000,
"value": 996,
"volume": 98801
},
{
"date": 1801519200000,
"value": 994,
"volume": 99042
},
{
"date": 1801605600000,
"value": 994,
"volume": 99306
},
{
"date": 1801692000000,
"value": 993,
"volume": 99445
},
{
"date": 1801778400000,
"value": 995,
"volume": 99119
},
{
"date": 1802037600000,
"value": 994,
"volume": 98778
},
{
"date": 1802124000000,
"value": 993,
"volume": 99163
},
{
"date": 1802210400000,
"value": 993,
"volume": 98758
},
{
"date": 1802296800000,
"value": 989,
"volume": 98491
},
{
"date": 1802383200000,
"value": 985,
"volume": 98135
},
{
"date": 1802642400000,
"value": 985,
"volume": 97956
},
{
"date": 1802728800000,
"value": 982,
"volume": 98304
},
{
"date": 1802815200000,
"value": 984,
"volume": 98649
},
{
"date": 1802901600000,
"value": 984,
"volume": 98856
},
{
"date": 1802988000000,
"value": 981,
"volume": 98665
},
{
"date": 1803247200000,
"value": 977,
"volume": 98436
},
{
"date": 1803333600000,
"value": 974,
"volume": 98516
},
{
"date": 1803420000000,
"value": 976,
"volume": 98477
},
{
"date": 1803506400000,
"value": 977,
"volume": 98943
},
{
"date": 1803592800000,
"value": 972,
"volume": 99017
},
{
"date": 1803852000000,
"value": 969,
"volume": 99213
},
{
"date": 1803938400000,
"value": 972,
"volume": 98865
},
{
"date": 1804024800000,
"value": 968,
"volume": 99297
},
{
"date": 1804111200000,
"value": 967,
"volume": 99569
},
{
"date": 1804197600000,
"value": 968,
"volume": 99270
},
{
"date": 1804456800000,
"value": 964,
"volume": 98930
},
{
"date": 1804543200000,
"value": 961,
"volume": 98651
},
{
"date": 1804629600000,
"value": 960,
"volume": 98763
},
{
"date": 1804716000000,
"value": 958,
"volume": 98462
},
{
"date": 1804802400000,
"value": 959,
"volume": 98658
},
{
"date": 1805061600000,
"value": 956,
"volume": 98869
},
{
"date": 1805148000000,
"value": 961,
"volume": 98510
},
{
"date": 1805234400000,
"value": 966,
"volume": 98282
},
{
"date": 1805320800000,
"value": 970,
"volume": 98506
},
{
"date": 1805407200000,
"value": 969,
"volume": 98123
},
{
"date": 1805666400000,
"value": 969,
"volume": 98083
},
{
"date": 1805752800000,
"value": 968,
"volume": 97796
},
{
"date": 1805839200000,
"value": 970,
"volume": 97807
},
{
"date": 1805925600000,
"value": 969,
"volume": 98301
},
{
"date": 1806012000000,
"value": 970,
"volume": 97963
},
{
"date": 1806267600000,
"value": 970,
"volume": 98368
},
{
"date": 1806354000000,
"value": 975,
"volume": 98173
},
{
"date": 1806440400000,
"value": 979,
"volume": 97751
},
{
"date": 1806526800000,
"value": 977,
"volume": 97524
},
{
"date": 1806613200000,
"value": 975,
"volume": 97959
},
{
"date": 1806872400000,
"value": 977,
"volume": 97947
},
{
"date": 1806958800000,
"value": 977,
"volume": 97595
},
{
"date": 1807045200000,
"value": 976,
"volume": 97584
},
{
"date": 1807131600000,
"value": 971,
"volume": 97631
},
{
"date": 1807218000000,
"value": 971,
"volume": 97654
},
{
"date": 1807477200000,
"value": 974,
"volume": 98060
},
{
"date": 1807563600000,
"value": 970,
"volume": 98273
},
{
"date": 1807650000000,
"value": 966,
"volume": 98414
},
{
"date": 1807736400000,
"value": 965,
"volume": 98873
},
{
"date": 1807822800000,
"value": 966,
"volume": 98748
},
{
"date": 1808082000000,
"value": 961,
"volume": 99069
},
{
"date": 1808168400000,
"value": 961,
"volume": 98689
},
{
"date": 1808254800000,
"value": 964,
"volume": 98295
},
{
"date": 1808341200000,
"value": 969,
"volume": 97874
},
{
"date": 1808427600000,
"value": 972,
"volume": 98037
},
{
"date": 1808686800000,
"value": 976,
"volume": 98037
},
{
"date": 1808773200000,
"value": 979,
"volume": 97813
},
{
"date": 1808859600000,
"value": 982,
"volume": 97782
},
{
"date": 1808946000000,
"value": 981,
"volume": 98037
},
{
"date": 1809032400000,
"value": 979,
"volume": 98068
},
{
"date": 1809291600000,
"value": 977,
"volume": 97926
},
{
"date": 1809378000000,
"value": 974,
"volume": 97823
},
{
"date": 1809464400000,
"value": 976,
"volume": 97476
},
{
"date": 1809550800000,
"value": 977,
"volume": 97179
},
{
"date": 1809637200000,
"value": 973,
"volume": 96919
},
{
"date": 1809896400000,
"value": 976,
"volume": 96665
},
{
"date": 1809982800000,
"value": 980,
"volume": 97105
},
{
"date": 1810069200000,
"value": 982,
"volume": 97073
},
{
"date": 1810155600000,
"value": 981,
"volume": 96596
},
{
"date": 1810242000000,
"value": 981,
"volume": 96141
},
{
"date": 1810501200000,
"value": 985,
"volume": 95801
},
{
"date": 1810587600000,
"value": 984,
"volume": 96184
},
{
"date": 1810674000000,
"value": 987,
"volume": 96151
},
{
"date": 1810760400000,
"value": 982,
"volume": 96618
},
{
"date": 1810846800000,
"value": 984,
"volume": 96896
},
{
"date": 1811106000000,
"value": 982,
"volume": 97104
},
{
"date": 1811192400000,
"value": 982,
"volume": 96650
},
{
"date": 1811278800000,
"value": 984,
"volume": 96242
},
{
"date": 1811365200000,
"value": 985,
"volume": 95913
},
{
"date": 1811451600000,
"value": 984,
"volume": 95636
},
{
"date": 1811710800000,
"value": 981,
"volume": 95902
},
{
"date": 1811797200000,
"value": 978,
"volume": 95433
},
{
"date": 1811883600000,
"value": 980,
"volume": 95026
},
{
"date": 1811970000000,
"value": 979,
"volume": 95365
},
{
"date": 1812056400000,
"value": 982,
"volume": 95590
},
{
"date": 1812315600000,
"value": 984,
"volume": 96053
},
{
"date": 1812402000000,
"value": 985,
"volume": 96539
},
{
"date": 1812488400000,
"value": 981,
"volume": 96082
},
{
"date": 1812574800000,
"value": 983,
"volume": 96178
},
{
"date": 1812661200000,
"value": 983,
"volume": 95807
},
{
"date": 1812920400000,
"value": 980,
"volume": 95389
},
{
"date": 1813006800000,
"value": 983,
"volume": 95583
},
{
"date": 1813093200000,
"value": 985,
"volume": 95478
},
{
"date": 1813179600000,
"value": 983,
"volume": 95640
},
{
"date": 1813266000000,
"value": 983,
"volume": 96011
},
{
"date": 1813525200000,
"value": 983,
"volume": 96350
},
{
"date": 1813611600000,
"value": 987,
"volume": 96176
},
{
"date": 1813698000000,
"value": 989,
"volume": 96088
},
{
"date": 1813784400000,
"value": 992,
"volume": 96146
},
{
"date": 1813870800000,
"value": 992,
"volume": 96568
},
{
"date": 1814130000000,
"value": 994,
"volume": 96944
},
{
"date": 1814216400000,
"value": 990,
"volume": 97227
},
{
"date": 1814302800000,
"value": 988,
"volume": 96792
},
{
"date": 1814389200000,
"value": 988,
"volume": 96382
},
{
"date": 1814475600000,
"value": 991,
"volume": 96329
},
{
"date": 1814734800000,
"value": 990,
"volume": 96455
},
{
"date": 1814821200000,
"value": 988,
"volume": 96101
},
{
"date": 1814907600000,
"value": 987,
"volume": 96128
},
{
"date": 1814994000000,
"value": 987,
"volume": 96090
},
{
"date": 1815080400000,
"value": 991,
"volume": 96103
},
{
"date": 1815339600000,
"value": 989,
"volume": 95706
},
{
"date": 1815426000000,
"value": 987,
"volume": 95282
},
{
"date": 1815512400000,
"value": 986,
"volume": 95058
}
]
},
{
"axis-0": {
"type": "GaplessDateAxis",
"settings": {
"maxDeviation": 0,
"baseInterval": {
"timeUnit": "day",
"count": 1
},
"renderer": {
"type": "AxisRendererX",
"settings": {
"minorGridEnabled": true
}
},
"tooltip": {
"type": "Tooltip"
}
}
}
},
{
"axis-1": {
"type": "ValueAxis",
"settings": {
"maxDeviation": 0,
"extraMin": 0.2,
"renderer": {
"type": "AxisRendererY"
}
}
}
},
{
"axis-2": {
"type": "ValueAxis",
"settings": {
"height": {
"type": "Percent",
"value": 25
},
"y": {
"type": "Percent",
"value": 100
},
"centerY": {
"type": "Percent",
"value": 100
},
"panY": false,
"renderer": {
"type": "AxisRendererY",
"properties": {
"labels": {
"properties": {
"template": {
"settings": {
"forceHidden": true
}
}
}
},
"grid": {
"properties": {
"template": {
"settings": {
"forceHidden": true
}
}
}
}
}
}
}
}
},
{
"series-0": {
"type": "LineSeries",
"settings": {
"name": "Series",
"xAxis": "#axis-0",
"yAxis": "#axis-1",
"valueYField": "value",
"valueXField": "date",
"tooltip": {
"type": "Tooltip",
"settings": {
"labelText": "{valueY}"
}
}
},
"properties": {
"data": "#data-0"
}
}
},
{
"series-1": {
"type": "ColumnSeries",
"settings": {
"name": "Volume Series",
"xAxis": "#axis-0",
"yAxis": "#axis-2",
"valueYField": "volume",
"valueXField": "date",
"tooltip": {
"type": "Tooltip",
"settings": {
"labelText": "{valueY}"
}
}
},
"properties": {
"data": "#data-0",
"columns": {
"properties": {
"template": {
"settings": {
"fillOpacity": 0.8,
"strokeOpacity": 0,
"width": {
"type": "Percent",
"value": 40
}
}
}
}
}
}
}
}
]
}