Trading Surface 3D - Editor
Example of creating a 3D-chart based on Technical Analysis Chart.
Several technical indicators are drawn on a 3D-chart, some as lines or points, others as surface colors.
The example loads data from a csv-file.
const lcjsTrader = require('@lightningchart/lcjs-trader')
const lcjs = require('@lightningchart/lcjs')
const { MovingAverageType, TechnicalAnalysisMethods } = lcjsTrader
const { AxisTickStrategies, ColorRGBA, emptyFill, emptyLine, LUT, PalettedFill, PointStyle3D, SolidFill, SolidLine } = 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 containerTAChart = document.createElement('div')
containerTAChart.style.width = '50%'
exampleContainer.append(containerTAChart)
const containerSurface = document.createElement('div')
containerSurface.style.width = '50%'
exampleContainer.append(containerSurface)
const taMethods = new TechnicalAnalysisMethods(taChart)
// Create a trading chart.
const taChart = trader.tradingChart({ parentElement: containerTAChart, loadFromStorage: false })
taChart.indicators().addVolume()
taChart.indicators().addSchaffTrendCycle()
taChart.indicators().addSimpleMovingAverage()
taChart.indicators().addParabolicSAR()
const surfaceChart = trader.lightningChart().Chart3D({
container: containerSurface,
legend: {
visible: false,
entries: { show: false }
}
})
surfaceChart.getDefaultAxisX().setTickStrategy(AxisTickStrategies.Empty)
surfaceChart.getDefaultAxisZ().setTickStrategy(AxisTickStrategies.Empty)
surfaceChart.setCameraLocation({ x: 0, y: 2, z: 3})
.setCursor((cursor) => {
cursor.setTickZ((tick) => tick.setTextFillStyle(emptyFill))
})
.setTitle('Surface Trading Chart')
// Add a default dataset.
await fetch(`${document.head.baseURI}examples/assets/1202/NVIDIA Corp (NVDA).csv`).then((res) => res.text()).then((text) => {
taChart.loadCsvString(text, 'NVIDIA Corp (NVDA)')
const dataset = taChart.getData(false)
const volumes = taChart.getVolumeData()
let count = 0
for (let i = 0; i < dataset[0].length; i++) {
if (count == 20 || i == 0) {
surfaceChart.getDefaultAxisX().addCustomTick()
.setValue(i)
.setTextRotation(90)
.setTextFormatter(() => dataset[0][i])
count = 0
} else {
count++
}
}
surfaceChart.getDefaultAxisZ().addCustomTick().setValue(0).setTextFormatter(() => '0')
surfaceChart.getDefaultAxisZ().addCustomTick().setValue(50).setTextFormatter(() => '328M')
surfaceChart.getDefaultAxisZ().addCustomTick().setValue(100).setTextFormatter(() => '655M')
surfaceChart.getDefaultAxisX().setInterval({ start: 0, end: dataset[0].length - 1 })
// Creating height data for the surface.
const heightData = []
for (let i = 0; i < dataset[0].length; i++) {
const rowData = [
dataset[4][i],
dataset[4][i],
]
heightData.push(rowData)
}
// Creating intensity data for the surface based on Schaff Trend Cycle indicator.
const stcData = taMethods.calculateSchaffTrendCycle(dataset[4], 23, 50, 10, 3, 3, 10, 3, 3,
MovingAverageType.ExponentialMovingAverage,
MovingAverageType.ExponentialMovingAverage,
MovingAverageType.ExponentialMovingAverage,
MovingAverageType.ExponentialMovingAverage,
MovingAverageType.ExponentialMovingAverage,
MovingAverageType.ExponentialMovingAverage
)
const diff = dataset[4].length - stcData.length
const colorData = []
for (let i = 0; i < dataset[0].length; i++) {
const rowData = []
if (i < diff) {
rowData[0] = 50
rowData[1] = 50
} else {
rowData[0] = stcData[i - diff]
rowData[1] = stcData[i - diff]
}
colorData.push(rowData)
}
// Creating the actual surface.
surfaceChart.addSurfaceGridSeries({
dataOrder: 'columns',
rows: 2,
columns: dataset[0].length
})
.setStep({ x: 1, z: 100 })
.setFillStyle(new PalettedFill({
lookUpProperty: 'value',
lut: new LUT({
steps: [
{ value: 0, color: ColorRGBA( 200, 0, 0, 200 ) },
{ value: 25, color: ColorRGBA( 200, 150, 200 ) },
{ value: 50, color: ColorRGBA( 200, 200, 200, 200 ) },
{ value: 75, color: ColorRGBA( 0, 150, 150, 200 ) },
{ value: 100, color: ColorRGBA( 0, 200, 0, 200 ) }
],
interpolate: true
})
}))
.setCursorFormattingOverride((hit, before) => {
return [
before[0],
before[1],
before[2],
before[4],
['Volume', '', volumes[hit.x].toString()]
]
})
.invalidateHeightMap(heightData)
.invalidateIntensityValues(colorData)
// Creating a secondary surface to show the Volume values.
const heightData2 = []
for (let i = 0; i < heightData.length; i++) {
const rowData = []
for (let j = 0; j < 101; j++) {
rowData.push(heightData[i][0] + 0.05)
}
heightData2.push(rowData)
}
const colorData2 = []
const highVolume = Math.max(...volumes)
for (let i = 0; i < heightData.length; i++) {
const rowData = []
const volumePoint = Math.round(volumes[i] / highVolume * 100)
for (let j = 0; j < 101; j++) {
if (j < volumePoint) {
rowData[j] = 50
} else if (j == volumePoint) {
rowData[j] = 100
} else {
rowData[j] = 0
}
}
colorData2.push(rowData)
}
surfaceChart.addSurfaceGridSeries({
dataOrder: 'columns',
rows: 101,
columns: dataset[0].length
})
.setStep({ x: 1, z: 1 })
.setWireframeStyle(emptyLine)
.setFillStyle(new PalettedFill({
lookUpProperty: 'value',
lut: new LUT({
steps: [
{ value: 0, color: ColorRGBA( 0, 0, 0, 220 ) },
{ value: 50, color: ColorRGBA( 0, 0, 0, 0 ) },
{ value: 100, color: ColorRGBA( 250, 250, 0, 250 ) }
],
interpolate: true
})
}))
.setPointerEvents(false)
.invalidateHeightMap(heightData2)
.invalidateIntensityValues(colorData2)
// Creating a 3D-line based on Simple Moving Average.
const smaValues = taMethods.calculateSimpleMovingAverage(dataset[4], 14)
const lineData = []
for (let i = 0; i < smaValues.length; i++) {
lineData.push({ x: i + 13, y: smaValues[i], z: 0 })
}
surfaceChart.addLineSeries()
.setName('SMA (14)')
.setStrokeStyle(new SolidLine({
thickness: 3,
fillStyle: new SolidFill({ color: ColorRGBA( 255, 255, 0 )})
}))
.add(lineData)
// Creating point series based on Parabolic SAR.
const psarValues = taMethods.calculateParabolicSAR(dataset[2], dataset[3], 0.02, 0.2)
const psarData = []
for (let i = 0; i < psarValues.length; i++) {
psarData.push({ x: i + 2, y: psarValues[i], z: 100 })
}
surfaceChart.addPointSeries()
.setName('Parabolic SAR')
.setPointStyle(new PointStyle3D.Triangulated({
size: 8,
fillStyle: new SolidFill({ color: ColorRGBA( 0, 255, 255 )})
}))
.add(psarData)
})
})Example of creating a 3D-chart based on Technical Analysis Chart.
Several technical indicators are drawn on a 3D-chart, some as lines or points, others as surface colors.
The example loads data from a csv-file.