Introduction
Stock charts support comparing multiple securities by overlaying their price movements on the same chart. Comparisons automatically switch to percent scale mode to normalize different price ranges.
Adding Comparison Series
Add a comparison series using addComparingSeries():
import * as am5xy from "@amcharts/amcharts5/xy";
// Create comparison series
const comparingSeries = am5xy.LineSeries.new(root, {
name: "AAPL",
valueYField: "Close",
valueXField: "Date",
xAxis: dateAxis,
yAxis: valueAxis,
calculateAggregates: true,
legendValueText: "{valueY.formatNumber('#.00')}"
});
// Add to stock chart
const compSeries = stockChart.addComparingSeries(comparingSeries);
// Load data
compSeries.data.setAll(appleData);
Comparison series are typically line series for clearer visual distinction from the main candlestick series.
Percent Scale Mode
When comparison series are added, the chart automatically switches to percent scale mode:
const stockChart = root.container.children.push(
am5stock.StockChart.new(root, {
autoSetPercentScale: true // Default
})
);
Percent scale normalizes all series to show percentage change from a common starting point.
Manual Percent Scale
Manually control percent scale mode:
// Enable percent scale
stockChart.setPercentScale(true);
// Disable percent scale
stockChart.setPercentScale(false);
Percent Scale Settings
Customize how the main series appears in percent scale mode:
const stockChart = root.container.children.push(
am5stock.StockChart.new(root, {
percentScaleSeriesSettings: {
valueYShow: "valueYChangeSelectionPercent",
openValueYShow: "openValueYChangeSelectionPercent",
highValueYShow: "highValueYChangeSelectionPercent",
lowValueYShow: "lowValueYChangeSelectionPercent"
},
percentScaleValueAxisSettings: {
numberFormat: "#.00'%'",
extraMin: 0.1,
extraMax: 0.1
}
})
);
Comparison Control
Add a comparison control to the toolbar for user-friendly comparisons:
const comparisonControl = am5stock.ComparisonControl.new(root, {
stockChart: stockChart
});
Searchable Comparison Control
Implement search functionality:
const comparisonControl = am5stock.ComparisonControl.new(root, {
stockChart: stockChart,
searchable: true,
searchCallback: (query) => {
// Get already compared series
const compared = stockChart.getPrivate("comparedSeries", []);
const main = stockChart.get("stockSeries");
// Build list of available securities
const securities = [
{ label: "Apple", subLabel: "AAPL", id: "AAPL" },
{ label: "Microsoft", subLabel: "MSFT", id: "MSFT" },
{ label: "Alphabet", subLabel: "GOOG", id: "GOOG" },
{ label: "Amazon", subLabel: "AMZN", id: "AMZN" },
{ label: "Tesla", subLabel: "TSLA", id: "TSLA" },
{ label: "NVIDIA", subLabel: "NVDA", id: "NVDA" },
{ label: "Netflix", subLabel: "NFLX", id: "NFLX" }
];
// Filter by search query
const filtered = securities.filter(item =>
item.label.toLowerCase().includes(query.toLowerCase()) ||
item.subLabel.toLowerCase().includes(query.toLowerCase())
);
// Mark already-compared items as disabled
const comparedIds = compared.map(s => s.get("name"));
filtered.forEach(item => {
if (comparedIds.includes(item.id) || main.get("name") === item.id) {
item.disabled = true;
}
});
return filtered;
}
});
toolbar.controls.push(comparisonControl);
Handle Selection
Respond to comparison selection:
comparisonControl.events.on("selected", (ev) => {
addComparisonSeries(ev.item.id);
});
function addComparisonSeries(ticker) {
const series = am5xy.LineSeries.new(root, {
name: ticker,
valueYField: "Close",
valueXField: "Date",
xAxis: dateAxis,
yAxis: valueAxis,
calculateAggregates: true,
legendValueText: "{valueY.formatNumber('#.00')}"
});
const comparingSeries = stockChart.addComparingSeries(series);
// Load data for the ticker
fetch(`/api/data/${ticker}`)
.then(response => response.json())
.then(data => {
comparingSeries.data.setAll(data);
});
}
Removing Comparisons
Remove a comparison series:
stockChart.removeComparingSeries(comparingSeries);
When all comparisons are removed and autoSetPercentScale is enabled, the chart automatically exits percent scale mode.
Comparison Series Settings
Apply custom settings to all comparison series:
const stockChart = root.container.children.push(
am5stock.StockChart.new(root, {
comparingSeriesSettings: {
strokeWidth: 2,
valueYShow: "valueYChangeSelectionPercent"
}
})
);
Legend Integration
Comparison series automatically appear in the stock legend with close buttons:
const valueLegend = mainPanel.plotContainer.children.push(
am5stock.StockLegend.new(root, {
stockChart: stockChart
})
);
valueLegend.data.setAll([valueSeries, volumeSeries]);
When a comparison series is added, it appears in the legend with a close button that removes the comparison.
Complete Comparison Example
import * as am5 from "@amcharts/amcharts5";
import * as am5xy from "@amcharts/amcharts5/xy";
import * as am5stock from "@amcharts/amcharts5/stock";
// Create root and stock chart
const root = am5.Root.new("chartdiv");
const stockChart = root.container.children.push(
am5stock.StockChart.new(root, {
autoSetPercentScale: true
})
);
// Create main panel with axes and series
const mainPanel = stockChart.panels.push(
am5stock.StockPanel.new(root, {})
);
const valueAxis = mainPanel.yAxes.push(
am5xy.ValueAxis.new(root, {
renderer: am5xy.AxisRendererY.new(root, {})
})
);
const dateAxis = mainPanel.xAxes.push(
am5xy.GaplessDateAxis.new(root, {
baseInterval: { timeUnit: "day", count: 1 },
renderer: am5xy.AxisRendererX.new(root, {})
})
);
const valueSeries = mainPanel.series.push(
am5xy.CandlestickSeries.new(root, {
name: "MSFT",
valueXField: "Date",
valueYField: "Close",
highValueYField: "High",
lowValueYField: "Low",
openValueYField: "Open",
xAxis: dateAxis,
yAxis: valueAxis
})
);
stockChart.set("stockSeries", valueSeries);
// Add legend
const valueLegend = mainPanel.plotContainer.children.push(
am5stock.StockLegend.new(root, {
stockChart: stockChart
})
);
valueLegend.data.setAll([valueSeries]);
// Add comparison control
const comparisonControl = am5stock.ComparisonControl.new(root, {
stockChart: stockChart,
searchable: true,
searchCallback: (query) => {
const tickers = [
{ label: "Apple", subLabel: "AAPL", id: "AAPL" },
{ label: "Alphabet", subLabel: "GOOG", id: "GOOG" },
{ label: "Amazon", subLabel: "AMZN", id: "AMZN" }
];
return tickers.filter(item =>
item.label.toLowerCase().includes(query.toLowerCase())
);
}
});
comparisonControl.events.on("selected", (ev) => {
const series = am5xy.LineSeries.new(root, {
name: ev.item.id,
valueYField: "Close",
valueXField: "Date",
xAxis: dateAxis,
yAxis: valueAxis,
calculateAggregates: true
});
const comparingSeries = stockChart.addComparingSeries(series);
// Load data
fetch(`/api/data/${ev.item.id}`)
.then(response => response.json())
.then(data => comparingSeries.data.setAll(data));
});
const toolbar = am5stock.StockToolbar.new(root, {
container: document.getElementById("chartcontrols"),
stockChart: stockChart,
controls: [comparisonControl]
});
// Load main series data
valueSeries.data.setAll(msftData);
Accessing Compared Series
Get list of currently compared series:
const comparedSeries = stockChart.getPrivate("comparedSeries", []);
console.log("Comparing", comparedSeries.length, "securities");
comparedSeries.forEach(series => {
console.log(series.get("name"));
});
Comparison Limits
Limit the number of comparisons:
const comparisonControl = am5stock.ComparisonControl.new(root, {
stockChart: stockChart,
searchable: true,
searchCallback: (query) => {
const compared = stockChart.getPrivate("comparedSeries", []);
// Limit to 5 comparisons
if (compared.length >= 5) {
return [{
label: "Maximum 5 comparisons already selected",
id: "limit",
info: true
}];
}
return getSecurities(query);
}
});
Comparison Colors
Comparison series automatically get different colors from the chart’s color set. Customize individual series colors:
const series = am5xy.LineSeries.new(root, {
name: ticker,
valueYField: "Close",
valueXField: "Date",
xAxis: dateAxis,
yAxis: valueAxis,
stroke: am5.color(0xFF0000),
fill: am5.color(0xFF0000)
});
Events
Monitor comparison state:
stockChart.onPrivate("comparing", (comparing) => {
if (comparing) {
console.log("Chart is in comparison mode");
} else {
console.log("Chart is in normal mode");
}
});
Data Requirements
Comparison series must have:
- Same date field as main series
- At least a close value
- Data covering similar time range
const comparisonData = [
{ Date: 1617192000000, Close: 123.45 },
{ Date: 1617278400000, Close: 125.67 },
// ...
];