Close Editor Run Reset Auto Update CJS const lcjsTrader = require('@lightningchart/lcjs-trader')
const lcjs = require('@lightningchart/lcjs')
const { TechnicalAnalysisMethods } = lcjsTrader
const { BarChartSorting, ColorRGBA, emptyFill, LUT, PalettedFill } = lcjs
lcjsTrader.trader(TRADER_LICENSE).then(async (trader) => {
const exampleContainer = document.getElementById('chart') || document.body
if (exampleContainer === document.body) {
exampleContainer.style.width = '100vw'
exampleContainer.style.height = '100vh'
exampleContainer.style.margin = '0px'
}
exampleContainer.style.display = 'flex'
exampleContainer.style.flexDirection = 'row'
exampleContainer.style.flexWrap = 'wrap'
const containerSide = document.createElement('div')
containerSide.style.width = '33.33%'
containerSide.style.height = '66.66%'
exampleContainer.append(containerSide)
const containerTrader = document.createElement('div')
containerTrader.style.width = '66.66%'
containerTrader.style.height = '66.66%'
exampleContainer.append(containerTrader)
const containerLines = document.createElement('div')
containerLines.style.width = '100%'
containerLines.style.height = '50%'
containerSide.append(containerLines)
const containerBars = document.createElement('div')
containerBars.style.width = '100%'
containerBars.style.height = '50%'
containerSide.append(containerBars)
const containerHeatmap = document.createElement('div')
containerHeatmap.style.width = '33.33%'
containerHeatmap.style.height = '33.34%'
exampleContainer.append(containerHeatmap)
const containerPie = document.createElement('div')
containerPie.style.width = '33.33%'
containerPie.style.height = '33.34%'
exampleContainer.append(containerPie)
const containerGauge = document.createElement('div')
containerGauge.style.width = '33.33%'
containerGauge.style.height = '33.34%'
exampleContainer.append(containerGauge)
let currentDataset = []
const barData = []
let firstSet = true
// Creating the charts for the dashboard.
const taChart = trader.tradingChart({ parentElement: containerTrader, loadFromStorage: false })
const taMethods = new TechnicalAnalysisMethods(taChart)
const lineChart = trader.lightningChart().ChartXY({ container: containerLines })
.setTitle('Comparison')
.setCursorMode('show-nearest')
const barChart = trader.lightningChart().BarChart({ container: containerBars, legend: { visible: false } })
.setTitle('Price Change')
.setSorting(BarChartSorting.None)
let pieChart = trader.lightningChart().Pie({ container: containerPie, legend: { visible: false } })
.setTitle('Close - SMA')
.setMultipleSliceExplosion(true)
.setLabelFormatter((slice) => slice.getName() + ': ' + slice.getValue().toFixed(1))
.setCursorFormatting((_, hit, hits) => {
return [
hit.slice,
hit.value.toFixed(2)
]
})
const gaugeChart = trader.lightningChart().Gauge({ container: containerGauge })
.setTitle('Stochastic')
.setInterval(0, 100)
.setGapBetweenBarAndValueIndicators(2)
.setBarThickness(20)
.setTickFont((font) => font.setSize(20))
.setValueLabelFont((font) => font.setSize(34))
.setValueIndicators([
{ start: 0, end: 20, color: ColorRGBA( 255, 50, 50 ) },
{ start: 20, end: 50, color: lineChart.getTheme().examples.mainDataColor },
{ start: 50, end: 80, color: lineChart.getTheme().examples.mainDataColor },
{ start: 80, end: 100, color: ColorRGBA( 50, 255, 50 ) }
])
const heatmapChart = trader.lightningChart().ChartXY({ container: containerHeatmap, legend: { visible: false } })
.setTitle('Custom Volume at Price')
let heatmap = heatmapChart.addHeatmapGridSeries({})
let heatmapLine = heatmapChart.addPointLineAreaSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } })
.setAreaFillStyle(emptyFill)
.setPointFillStyle(emptyFill)
.setCursorEnabled(false)
.setDrawOrder({ seriesDrawOrderIndex: 10 })
await fetchDataSet('Bank of America Corporation (BAC)')
await fetchDataSet('Interactive Brokers Group, Inc. (IBKR)')
await fetchDataSet('JPMorgan Chase & Co. (JPM)')
await fetchDataSet('Morgan Stanley (MS)')
await fetchDataSet('Royal Bank of Canada (RY)')
await fetchDataSet('Wells Fargo & Company (WFC)')
taChart.setChartTitle('Wells Fargo & Company (WFC)')
updatePie()
updateHeatmap()
barChart.setData(barData)
barChart.getBars().forEach((bar) => {
bar.addEventListener('pointerdown', (_, hit) => {
let barName = ''
switch (hit.category) {
case 'BAC':
barName = 'Bank of America Corporation (BAC)'
break
case 'IBKR':
barName = 'Interactive Brokers Group, Inc. (IBKR)'
break
case 'JPM':
barName = 'JPMorgan Chase & Co. (JPM)'
break
case 'MS':
barName = 'Morgan Stanley (MS)'
break
case 'RY':
barName = 'Royal Bank of Canada (RY)'
break
case 'WFC':
barName = 'Wells Fargo & Company (WFC)'
break
default:
break
}
if (barName != '') {
replaceMainDataset(barName)
}
})
})
async function fetchDataSet(fileName) {
// Reading data from a file.
await fetch(`${document.head.baseURI}examples/assets/2101/` + fileName + `.csv`).then((res) => res.text()).then((text) => {
taChart.loadCsvString(text, '')
const dataSet = taChart.getData(false)
// Creating line series for the line chart based on each dataset.
const data = []
for (let i = 0; i < dataSet[0].length; i++) {
data[i] = i
}
const seriesName = fileName.substr(fileName.indexOf('(') + 1).slice(0, -1)
lineChart.addPointLineAreaSeries({ schema: { x: { pattern: 'progressive' }, y: { pattern: null } } })
.setName(seriesName)
.setAreaFillStyle(emptyFill)
.setPointFillStyle(emptyFill)
.appendSamples({ x: data, y: dataSet[4] })
.addEventListener('pointerdown', () => replaceMainDataset(fileName))
// Save data for the bar chart.
barData.push({ category: seriesName, value: dataSet[4][dataSet[4].length - 1] - dataSet[4][0] })
currentDataset = dataSet
updateGauge()
})
}
async function replaceMainDataset(fileName) {
await fetch(`${document.head.baseURI}examples/assets/2101/` + fileName + `.csv`).then((res) => res.text()).then((text) => {
taChart.loadCsvString(text, fileName)
currentDataset = taChart.getData(false)
updatePie()
updateGauge()
updateHeatmap()
})
}
function updatePie() {
const close = currentDataset[4][currentDataset[4].length - 1]
const sma5Values = taMethods.calculateSimpleMovingAverage(currentDataset[4], 5)
const sma10Values = taMethods.calculateSimpleMovingAverage(currentDataset[4], 10)
const sma15Values = taMethods.calculateSimpleMovingAverage(currentDataset[4], 15)
const sma20Values = taMethods.calculateSimpleMovingAverage(currentDataset[4], 20)
const sma25Values = taMethods.calculateSimpleMovingAverage(currentDataset[4], 25)
const sma30Values = taMethods.calculateSimpleMovingAverage(currentDataset[4], 30)
const pieData = [
{ name: 'SMA (5)', value: close - sma5Values[sma5Values.length - 1] },
{ name: 'SMA (10)', value: close - sma10Values[sma10Values.length - 1] },
{ name: 'SMA (15)', value: close - sma15Values[sma15Values.length - 1] },
{ name: 'SMA (20)', value: close - sma20Values[sma20Values.length - 1] },
{ name: 'SMA (25)', value: close - sma25Values[sma25Values.length - 1] },
{ name: 'SMA (30)', value: close - sma30Values[sma30Values.length - 1] }
]
if (firstSet) {
firstSet = false
pieData.forEach((item) => {
pieChart.addSlice(item.name, Math.abs(item.value))
})
} else {
for (let i = 0; i < pieChart.getSlices().length; i++) {
pieChart.getSlices()[i].setName(pieData[i].name).setValue(Math.abs(pieData[i].value))
}
}
}
function updateGauge() {
const stochasticValues = taMethods.calculateStochasticOscillator(currentDataset[4], currentDataset[2], currentDataset[3], 14, 3)
if (stochasticValues != null) {
gaugeChart.setValue(stochasticValues[0][stochasticValues[0].length - 1])
}
}
function updateHeatmap() {
heatmap.dispose()
heatmapLine.clear()
const highValues = currentDataset[2]
const lowValues = currentDataset[3]
const volumes = taChart.getVolumeData()
const max = Math.max(...highValues)
const min = Math.floor(Math.min(...lowValues))
const step = 1
const stepCount = Math.ceil((max - min) / step)
const nodeValues = []
for (let i = 0; i < stepCount; i++) {
nodeValues[i] = 0
}
for (let i = 0; i < highValues.length; i++) {
for (let j = 0; j < stepCount; j++) {
if (min + (j + 1) * step >= lowValues[i] && min + j * step <= highValues[i]) {
nodeValues[j]++
}
}
}
const heatmapData = []
let highest = 0
for (let i = 0; i < highValues.length; i++) {
const columnData = []
for (let j = 0; j < nodeValues.length; j++) {
columnData[j] = nodeValues[j] * volumes[i]
if (columnData[j] > highest) {
highest = columnData[j]
}
}
heatmapData.push(columnData)
}
heatmap = heatmapChart.addHeatmapGridSeries({
columns: heatmapData.length,
rows: nodeValues.length,
})
.setName('Volume at Price')
.setStart({ x: 0, y: min })
.setEnd({ x: currentDataset[0].length - 1, y: max })
.invalidateIntensityValues(heatmapData)
.setFillStyle(
new PalettedFill({
lookUpProperty: 'value',
lut: new LUT({
interpolate: true,
steps: [
{ value: 0, color: ColorRGBA(0, 0, 0, 0) },
{ value: highest * 0.25, color: ColorRGBA(0, 50, 255, 200) },
{ value: highest * 0.5, color: ColorRGBA(0, 255, 50, 200) },
{ value: highest * 0.75, color: ColorRGBA(255, 255, 50, 200) },
{ value: highest, color: ColorRGBA(255, 50, 50, 200) }
]
}),
}),
)
const data = []
for (let i = 0; i < currentDataset[0].length; i++) {
data[i] = i
}
heatmapLine.appendSamples({ x: data, y: currentDataset[4] })
heatmapChart.getDefaultAxisY().setInterval({ start: min, end: max })
}
})
Trading Dashboard - Editor
Example of a trading dashboard created by combining LightningChart Technical Analysis Chart with several LightningChart JS chart types. Clicking a line or a bar loads the respective dataset to the main chart.
The example loads data from a csv-file.