NEW FEATURE: Polygon.io Full integration
- Added `polygon` to the common methods, allowing for data to be pulled from polygon.io. (`chart.polygon.<method>`)
- Added the `PolygonChart` object, which allows for a plug and play solution with the Polygon API.
- Check the docs for more details and examples!

Enhancements:
- Added `clear_markers` and `clear_horizontal_lines` to the common methods.
- Added the `maximize` parameter to the `Chart` object, which maximizes the chart window when shown.
- The Legend will now show Line values, and can be disabled using the `lines` parameter.
- Added the `name` parameter to the `set` method of line, using the column within the dataframe as the value and using its name within the legend.
- Added the `scale_candles_only` parameter to all Chart objects, which prevents the autoscaling of Lines.

- new `screenshot` method, which returns a bytes object of the displayed chart.

Fixes:
- `chart.lines()` now returns a copy of the list rather than the original.
This commit is contained in:
louisnw
2023-06-28 18:36:32 +01:00
parent adfc58a8af
commit d9c8aa3bd8
16 changed files with 932 additions and 649 deletions

View File

@ -0,0 +1,167 @@
function makeChart(innerWidth, innerHeight, autoSize=true) {
let chart = {
markers: [],
horizontal_lines: [],
wrapper: document.createElement('div'),
div: document.createElement('div'),
legend: document.createElement('div'),
scale: {
width: innerWidth,
height: innerHeight
},
}
chart.chart = LightweightCharts.createChart(chart.div, {
width: window.innerWidth*innerWidth,
height: window.innerHeight*innerHeight,
layout: {
textColor: '#d1d4dc',
background: {
color:'#000000',
type: LightweightCharts.ColorType.Solid,
},
fontSize: 12
},
rightPriceScale: {
scaleMargins: {top: 0.3, bottom: 0.25},
},
timeScale: {timeVisible: true, secondsVisible: false},
crosshair: {
mode: LightweightCharts.CrosshairMode.Normal,
vertLine: {
labelBackgroundColor: 'rgb(46, 46, 46)'
},
horzLine: {
labelBackgroundColor: 'rgb(55, 55, 55)'
}
},
grid: {
vertLines: {color: 'rgba(29, 30, 38, 5)'},
horzLines: {color: 'rgba(29, 30, 58, 5)'},
},
handleScroll: {vertTouchDrag: true},
})
let up = 'rgba(39, 157, 130, 100)'
let down = 'rgba(200, 97, 100, 100)'
chart.series = chart.chart.addCandlestickSeries({
color: 'rgb(0, 120, 255)', upColor: up, borderUpColor: up, wickUpColor: up,
downColor: down, borderDownColor: down, wickDownColor: down, lineWidth: 2,
})
chart.volumeSeries = chart.chart.addHistogramSeries({
color: '#26a69a',
priceFormat: {type: 'volume'},
priceScaleId: '',
})
chart.series.priceScale().applyOptions({
scaleMargins: {top: 0.2, bottom: 0.2},
});
chart.volumeSeries.priceScale().applyOptions({
scaleMargins: {top: 0.8, bottom: 0},
});
chart.legend.style.position = 'absolute'
chart.legend.style.zIndex = 1000
chart.legend.style.width = `${(chart.scale.width*100)-8}vw`
chart.legend.style.top = '10px'
chart.legend.style.left = '10px'
chart.legend.style.fontFamily = 'Monaco'
chart.legend.style.fontSize = '11px'
chart.legend.style.color = 'rgb(191, 195, 203)'
chart.wrapper.style.width = `${100*innerWidth}%`
chart.wrapper.style.height = `${100*innerHeight}%`
chart.wrapper.style.display = 'flex'
chart.wrapper.style.flexDirection = 'column'
chart.div.style.position = 'relative'
chart.div.style.display = 'flex'
chart.div.appendChild(chart.legend)
chart.wrapper.appendChild(chart.div)
document.getElementById('wrapper').append(chart.wrapper)
if (!autoSize) {
return chart
}
let topBarOffset = 0
window.addEventListener('resize', function() {
if ('topBar' in chart) {
topBarOffset = chart.topBar.offsetHeight
}
chart.chart.resize(window.innerWidth*innerWidth, (window.innerHeight*innerHeight)-topBarOffset)
});
return chart
}
function makeHorizontalLine(chart, lineId, price, color, width, style, axisLabelVisible, text) {
let priceLine = {
price: price,
color: color,
lineWidth: width,
lineStyle: style,
axisLabelVisible: axisLabelVisible,
title: text,
};
let line = {
line: chart.series.createPriceLine(priceLine),
price: price,
id: lineId,
};
chart.horizontal_lines.push(line)
}
function legendItemFormat(num) {
return num.toFixed(2).toString().padStart(8, ' ')
}
function syncCrosshairs(childChart, parentChart) {
let parent = 0
let child = 0
let parentCrosshairHandler = (e) => {
parent ++
if (parent < 10) {
return
}
child = 0
parentChart.applyOptions({crosshair: { horzLine: {
visible: true,
labelVisible: true,
}}})
childChart.applyOptions({crosshair: { horzLine: {
visible: false,
labelVisible: false,
}}})
childChart.unsubscribeCrosshairMove(childCrosshairHandler)
if (e.time !== undefined) {
let xx = childChart.timeScale().timeToCoordinate(e.time);
childChart.setCrosshairXY(xx,300,true);
} else if (e.point !== undefined){
childChart.setCrosshairXY(e.point.x,300,false);
}
childChart.subscribeCrosshairMove(childCrosshairHandler)
}
let childCrosshairHandler = (e) => {
child ++
if (child < 10) {
return
}
parent = 0
childChart.applyOptions({crosshair: {horzLine: {
visible: true,
labelVisible: true,
}}})
parentChart.applyOptions({crosshair: {horzLine: {
visible: false,
labelVisible: false,
}}})
parentChart.unsubscribeCrosshairMove(parentCrosshairHandler)
if (e.time !== undefined) {
let xx = parentChart.timeScale().timeToCoordinate(e.time);
parentChart.setCrosshairXY(xx,300,true);
} else if (e.point !== undefined){
parentChart.setCrosshairXY(e.point.x,300,false);
}
parentChart.subscribeCrosshairMove(parentCrosshairHandler)
}
parentChart.subscribeCrosshairMove(parentCrosshairHandler)
childChart.subscribeCrosshairMove(childCrosshairHandler)
}