Polygon:
- Added async methods to polygon. - The `requests` library is no longer required, with `urllib` being used instead. - Added the `get_bar_data` function, which returns a dataframe of aggregate data from polygon. - Opened up the `subscribe` and `unsubscribe` functions Enhancements: - Tables will now scroll when the rows exceed table height. Bugs: - Fixed a bug preventing async functions being used with horizontal line event. - Fixed a bug causing the legend to show duplicate lines if the line was created after the legend. - Fixed a bug causing the line hide icon to persist within the legend after deletion (#75) - Fixed a bug causing the search box to be unfocused when the chart is loaded.
This commit is contained in:
@ -14,6 +14,9 @@ if (!window.TopBar) {
|
||||
this.topBar.style.display = 'flex'
|
||||
this.topBar.style.alignItems = 'center'
|
||||
chart.wrapper.prepend(this.topBar)
|
||||
chart.topBar = this.topBar
|
||||
this.reSize = () => chart.reSize()
|
||||
this.reSize()
|
||||
}
|
||||
makeSwitcher(items, activeItem, callbackName) {
|
||||
let switcherElement = document.createElement('div');
|
||||
@ -45,6 +48,7 @@ if (!window.TopBar) {
|
||||
switcherElement.appendChild(itemEl);
|
||||
return itemEl;
|
||||
});
|
||||
widget.intervalElements = intervalElements
|
||||
|
||||
let onItemClicked = (item)=> {
|
||||
if (item === activeItem) return
|
||||
@ -59,6 +63,7 @@ if (!window.TopBar) {
|
||||
|
||||
this.topBar.appendChild(switcherElement)
|
||||
this.makeSeparator(this.topBar)
|
||||
this.reSize()
|
||||
return widget
|
||||
}
|
||||
makeTextBoxWidget(text) {
|
||||
@ -69,9 +74,10 @@ if (!window.TopBar) {
|
||||
textBox.innerText = text
|
||||
this.topBar.append(textBox)
|
||||
this.makeSeparator(this.topBar)
|
||||
this.reSize()
|
||||
return textBox
|
||||
}
|
||||
makeButton(defaultText, callbackName) {
|
||||
makeButton(defaultText, callbackName, separator) {
|
||||
let button = document.createElement('button')
|
||||
button.style.border = 'none'
|
||||
button.style.padding = '2px 5px'
|
||||
@ -103,7 +109,9 @@ if (!window.TopBar) {
|
||||
button.style.color = this.textColor
|
||||
button.style.fontWeight = 'normal'
|
||||
})
|
||||
if (separator) this.makeSeparator()
|
||||
this.topBar.appendChild(button)
|
||||
this.reSize()
|
||||
return widget
|
||||
}
|
||||
|
||||
@ -159,11 +167,10 @@ function makeSearchBox(chart) {
|
||||
chart.chart.subscribeCrosshairMove((param) => {
|
||||
if (param.point) yPrice = param.point.y;
|
||||
})
|
||||
let selectedChart = false
|
||||
chart.wrapper.addEventListener('mouseover', (event) => selectedChart = true)
|
||||
chart.wrapper.addEventListener('mouseout', (event) => selectedChart = false)
|
||||
window.selectedChart = chart
|
||||
chart.wrapper.addEventListener('mouseover', (event) => window.selectedChart = chart)
|
||||
chart.commandFunctions.push((event) => {
|
||||
if (!selectedChart) return false
|
||||
if (selectedChart !== chart) return false
|
||||
if (searchWindow.style.display === 'none') {
|
||||
if (/^[a-zA-Z0-9]$/.test(event.key)) {
|
||||
searchWindow.style.display = 'flex';
|
||||
|
||||
@ -1,103 +1,113 @@
|
||||
function makeChart(innerWidth, innerHeight, autoSize=true) {
|
||||
let chart = {
|
||||
markers: [],
|
||||
horizontal_lines: [],
|
||||
lines: [],
|
||||
wrapper: document.createElement('div'),
|
||||
div: document.createElement('div'),
|
||||
scale: {
|
||||
width: innerWidth,
|
||||
height: innerHeight,
|
||||
},
|
||||
candleData: [],
|
||||
commandFunctions: [],
|
||||
precision: 2,
|
||||
}
|
||||
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)'
|
||||
if (!window.Chart) {
|
||||
class Chart {
|
||||
constructor(chartId, innerWidth, innerHeight, position, autoSize) {
|
||||
this.makeCandlestickSeries = this.makeCandlestickSeries.bind(this)
|
||||
this.reSize = this.reSize.bind(this)
|
||||
this.id = chartId
|
||||
this.lines = []
|
||||
this.wrapper = document.createElement('div')
|
||||
this.div = document.createElement('div')
|
||||
this.scale = {
|
||||
width: innerWidth,
|
||||
height: innerHeight,
|
||||
}
|
||||
},
|
||||
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.wrapper.style.width = `${100*innerWidth}%`
|
||||
chart.wrapper.style.height = `${100*innerHeight}%`
|
||||
chart.wrapper.style.display = 'flex'
|
||||
chart.wrapper.style.flexDirection = 'column'
|
||||
chart.wrapper.style.position = 'relative'
|
||||
this.commandFunctions = []
|
||||
this.chart = LightweightCharts.createChart(this.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},
|
||||
})
|
||||
this.wrapper.style.width = `${100 * innerWidth}%`
|
||||
this.wrapper.style.height = `${100 * innerHeight}%`
|
||||
this.wrapper.style.display = 'flex'
|
||||
this.wrapper.style.flexDirection = 'column'
|
||||
this.wrapper.style.position = 'relative'
|
||||
this.wrapper.style.float = position
|
||||
|
||||
chart.div.style.position = 'relative'
|
||||
chart.div.style.display = 'flex'
|
||||
chart.wrapper.appendChild(chart.div)
|
||||
document.getElementById('wrapper').append(chart.wrapper)
|
||||
this.div.style.position = 'relative'
|
||||
this.div.style.display = 'flex'
|
||||
this.wrapper.appendChild(this.div)
|
||||
document.getElementById('wrapper').append(this.wrapper)
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
for (let i=0; i<chart.commandFunctions.length; i++) {
|
||||
if (chart.commandFunctions[i](event)) break
|
||||
document.addEventListener('keydown', (event) => {
|
||||
for (let i = 0; i < this.commandFunctions.length; i++) {
|
||||
if (this.commandFunctions[i](event)) break
|
||||
}
|
||||
})
|
||||
if (!autoSize) return
|
||||
window.addEventListener('resize', () => this.reSize())
|
||||
}
|
||||
})
|
||||
reSize() {
|
||||
let topBarOffset = 'topBar' in this ? this.topBar.offsetHeight : 0
|
||||
this.chart.resize(window.innerWidth * this.scale.width, (window.innerHeight * this.scale.height) - topBarOffset)
|
||||
}
|
||||
makeCandlestickSeries() {
|
||||
this.markers = []
|
||||
this.horizontal_lines = []
|
||||
this.candleData = []
|
||||
this.precision = 2
|
||||
let up = 'rgba(39, 157, 130, 100)'
|
||||
let down = 'rgba(200, 97, 100, 100)'
|
||||
this.series = this.chart.addCandlestickSeries({
|
||||
color: 'rgb(0, 120, 255)', upColor: up, borderUpColor: up, wickUpColor: up,
|
||||
downColor: down, borderDownColor: down, wickDownColor: down, lineWidth: 2,
|
||||
})
|
||||
this.volumeSeries = this.chart.addHistogramSeries({
|
||||
color: '#26a69a',
|
||||
priceFormat: {type: 'volume'},
|
||||
priceScaleId: '',
|
||||
})
|
||||
this.series.priceScale().applyOptions({
|
||||
scaleMargins: {top: 0.2, bottom: 0.2},
|
||||
});
|
||||
this.volumeSeries.priceScale().applyOptions({
|
||||
scaleMargins: {top: 0.8, bottom: 0},
|
||||
});
|
||||
}
|
||||
toJSON() {
|
||||
// Exclude the chart attribute from serialization
|
||||
const {chart, ...serialized} = this;
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
window.Chart = Chart
|
||||
|
||||
if (!autoSize) return chart
|
||||
window.addEventListener('resize', () => reSize(chart))
|
||||
return chart
|
||||
}
|
||||
|
||||
function reSize(chart) {
|
||||
let topBarOffset = 'topBar' in chart ? chart.topBar.offsetHeight : 0
|
||||
chart.chart.resize(window.innerWidth*chart.scale.width, (window.innerHeight*chart.scale.height)-topBarOffset)
|
||||
}
|
||||
|
||||
if (!window.HorizontalLine) {
|
||||
class HorizontalLine {
|
||||
constructor(chart, lineId, price, color, width, style, axisLabelVisible, text) {
|
||||
this.updatePrice = this.updatePrice.bind(this)
|
||||
this.deleteLine = this.deleteLine.bind(this)
|
||||
this.chart = chart
|
||||
this.price = price
|
||||
this.color = color
|
||||
this.id = lineId
|
||||
this.priceLine = {
|
||||
price: this.price,
|
||||
color: color,
|
||||
color: this.color,
|
||||
lineWidth: width,
|
||||
lineStyle: style,
|
||||
axisLabelVisible: axisLabelVisible,
|
||||
@ -128,7 +138,8 @@ if (!window.HorizontalLine) {
|
||||
|
||||
updateColor(color) {
|
||||
this.chart.series.removePriceLine(this.line)
|
||||
this.priceLine.color = color
|
||||
this.color = color
|
||||
this.priceLine.color = this.color
|
||||
this.line = this.chart.series.createPriceLine(this.priceLine)
|
||||
}
|
||||
|
||||
@ -210,11 +221,7 @@ if (!window.HorizontalLine) {
|
||||
|
||||
makeLines(chart) {
|
||||
this.lines = []
|
||||
if (this.linesEnabled) {
|
||||
chart.lines.forEach((line) => {
|
||||
this.lines.push(this.makeLineRow(line))
|
||||
})
|
||||
}
|
||||
if (this.linesEnabled) chart.lines.forEach(line => this.lines.push(this.makeLineRow(line)))
|
||||
}
|
||||
|
||||
makeLineRow(line) {
|
||||
@ -322,39 +329,29 @@ function syncCrosshairs(childChart, parentChart) {
|
||||
childChart.subscribeCrosshairMove(childCrosshairHandler)
|
||||
}
|
||||
|
||||
function chartTimeToDate(stampOrBusiness) {
|
||||
if (typeof stampOrBusiness === 'number') {
|
||||
stampOrBusiness = new Date(stampOrBusiness*1000)
|
||||
}
|
||||
else if (typeof stampOrBusiness === 'string') {
|
||||
let [year, month, day] = stampOrBusiness.split('-').map(Number)
|
||||
stampOrBusiness = new Date(Date.UTC(year, month-1, day))
|
||||
}
|
||||
else {
|
||||
stampOrBusiness = new Date(Date.UTC(stampOrBusiness.year, stampOrBusiness.month - 1, stampOrBusiness.day))
|
||||
}
|
||||
return stampOrBusiness
|
||||
function stampToDate(stampOrBusiness) {
|
||||
return new Date(stampOrBusiness*1000)
|
||||
}
|
||||
function dateToStamp(date) {
|
||||
return Math.floor(date.getTime()/1000)
|
||||
}
|
||||
|
||||
function dateToChartTime(date, interval) {
|
||||
if (interval >= 24*60*60*1000) {
|
||||
return {day: date.getUTCDate(), month: date.getUTCMonth()+1, year: date.getUTCFullYear()}
|
||||
}
|
||||
return Math.floor(date.getTime()/1000)
|
||||
function lastBar(obj) {
|
||||
return obj[obj.length-1]
|
||||
}
|
||||
|
||||
function calculateTrendLine(startDate, startValue, endDate, endValue, interval, chart, ray=false) {
|
||||
let reversed = false
|
||||
if (chartTimeToDate(endDate).getTime() < chartTimeToDate(startDate).getTime()) {
|
||||
if (stampToDate(endDate).getTime() < stampToDate(startDate).getTime()) {
|
||||
reversed = true;
|
||||
[startDate, endDate] = [endDate, startDate];
|
||||
}
|
||||
let startIndex
|
||||
if (chartTimeToDate(startDate).getTime() < chartTimeToDate(chart.candleData[0].time).getTime()) {
|
||||
if (stampToDate(startDate).getTime() < stampToDate(chart.candleData[0].time).getTime()) {
|
||||
startIndex = 0
|
||||
}
|
||||
else {
|
||||
startIndex = chart.candleData.findIndex(item => chartTimeToDate(item.time).getTime() === chartTimeToDate(startDate).getTime())
|
||||
startIndex = chart.candleData.findIndex(item => stampToDate(item.time).getTime() === stampToDate(startDate).getTime())
|
||||
}
|
||||
|
||||
if (startIndex === -1) {
|
||||
@ -366,9 +363,9 @@ function calculateTrendLine(startDate, startValue, endDate, endValue, interval,
|
||||
startValue = endValue
|
||||
}
|
||||
else {
|
||||
endIndex = chart.candleData.findIndex(item => chartTimeToDate(item.time).getTime() === chartTimeToDate(endDate).getTime())
|
||||
endIndex = chart.candleData.findIndex(item => stampToDate(item.time).getTime() === stampToDate(endDate).getTime())
|
||||
if (endIndex === -1) {
|
||||
let barsBetween = (chartTimeToDate(endDate)-chartTimeToDate(chart.candleData[chart.candleData.length-1].time))/interval
|
||||
let barsBetween = (stampToDate(endDate)-stampToDate(chart.candleData[chart.candleData.length-1].time))/interval
|
||||
endIndex = chart.candleData.length-1+barsBetween
|
||||
}
|
||||
}
|
||||
@ -384,8 +381,7 @@ function calculateTrendLine(startDate, startValue, endDate, endValue, interval,
|
||||
}
|
||||
else {
|
||||
iPastData ++
|
||||
currentDate = dateToChartTime(new Date(chartTimeToDate(chart.candleData[chart.candleData.length-1].time).getTime()+(iPastData*interval)), interval)
|
||||
|
||||
currentDate = dateToStamp(new Date(stampToDate(chart.candleData[chart.candleData.length-1].time).getTime()+(iPastData*interval)))
|
||||
}
|
||||
|
||||
const currentValue = reversed ? startValue + rate_of_change * (numBars - i) : startValue + rate_of_change * i;
|
||||
@ -431,22 +427,23 @@ if (!window.ContextMenu) {
|
||||
active ? document.addEventListener('contextmenu', this.onRightClick) : document.removeEventListener('contextmenu', this.onRightClick)
|
||||
}
|
||||
menuItem(text, action, hover=false) {
|
||||
let item = document.createElement('div')
|
||||
let item = document.createElement('span')
|
||||
item.style.display = 'flex'
|
||||
item.style.alignItems = 'center'
|
||||
item.style.justifyContent = 'space-between'
|
||||
item.style.padding = '0px 10px'
|
||||
item.style.margin = '3px 0px'
|
||||
item.style.padding = '2px 10px'
|
||||
item.style.margin = '1px 0px'
|
||||
item.style.borderRadius = '3px'
|
||||
this.menu.appendChild(item)
|
||||
|
||||
let elem = document.createElement('div')
|
||||
let elem = document.createElement('span')
|
||||
elem.innerText = text
|
||||
item.appendChild(elem)
|
||||
|
||||
if (hover) {
|
||||
let arrow = document.createElement('div')
|
||||
arrow.innerHTML = `<svg width="15px" height="10px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.82054 20.7313C8.21107 21.1218 8.84423 21.1218 9.23476 20.7313L15.8792 14.0868C17.0505 12.9155 17.0508 11.0167 15.88 9.84497L9.3097 3.26958C8.91918 2.87905 8.28601 2.87905 7.89549 3.26958C7.50497 3.6601 7.50497 4.29327 7.89549 4.68379L14.4675 11.2558C14.8581 11.6464 14.8581 12.2795 14.4675 12.67L7.82054 19.317C7.43002 19.7076 7.43002 20.3407 7.82054 20.7313Z" fill="#fff"/></svg>`
|
||||
let arrow = document.createElement('span')
|
||||
arrow.innerText = `►`
|
||||
arrow.style.fontSize = '8px'
|
||||
item.appendChild(arrow)
|
||||
}
|
||||
|
||||
@ -457,13 +454,17 @@ if (!window.ContextMenu) {
|
||||
})
|
||||
elem.addEventListener('mouseout', (event) => item.style.backgroundColor = 'transparent')
|
||||
if (!hover) elem.addEventListener('click', (event) => {action(event); this.menu.style.display = 'none'})
|
||||
else elem.addEventListener('mouseover', () => action(item.getBoundingClientRect()))
|
||||
else {
|
||||
let timeout
|
||||
elem.addEventListener('mouseover', () => timeout = setTimeout(() => action(item.getBoundingClientRect()), 100))
|
||||
elem.addEventListener('mouseout', () => clearTimeout(timeout))
|
||||
}
|
||||
}
|
||||
separator() {
|
||||
let separator = document.createElement('div')
|
||||
separator.style.width = '90%'
|
||||
separator.style.height = '1px'
|
||||
separator.style.margin = '4px 0px'
|
||||
separator.style.margin = '3px 0px'
|
||||
separator.style.backgroundColor = '#3C434C'
|
||||
this.menu.appendChild(separator)
|
||||
}
|
||||
@ -471,3 +472,5 @@ if (!window.ContextMenu) {
|
||||
}
|
||||
window.ContextMenu = ContextMenu
|
||||
}
|
||||
|
||||
window.callbackFunction = () => undefined;
|
||||
@ -1,9 +1,8 @@
|
||||
if (!window.Table) {
|
||||
class Table {
|
||||
constructor(width, height, headings, widths, alignments, position, draggable = false, chart) {
|
||||
constructor(width, height, headings, widths, alignments, position, draggable = false) {
|
||||
this.container = document.createElement('div')
|
||||
this.callbackName = null
|
||||
this.chart = chart
|
||||
|
||||
if (draggable) {
|
||||
this.container.style.position = 'absolute'
|
||||
@ -15,7 +14,7 @@ if (!window.Table) {
|
||||
|
||||
this.container.style.zIndex = '2000'
|
||||
this.container.style.width = width <= 1 ? width * 100 + '%' : width + 'px'
|
||||
this.container.style.minHeight = height <= 1 ? height * 100 + '%' : height + 'px'
|
||||
this.container.style.height = height <= 1 ? height * 100 + '%' : height + 'px'
|
||||
this.container.style.display = 'flex'
|
||||
this.container.style.flexDirection = 'column'
|
||||
this.container.style.justifyContent = 'space-between'
|
||||
@ -52,7 +51,10 @@ if (!window.Table) {
|
||||
th.style.border = '1px solid rgb(70, 70, 70)'
|
||||
}
|
||||
|
||||
this.container.appendChild(this.table)
|
||||
let overflowWrapper = document.createElement('div')
|
||||
overflowWrapper.style.overflow = 'auto'
|
||||
overflowWrapper.appendChild(this.table)
|
||||
this.container.appendChild(overflowWrapper)
|
||||
document.getElementById('wrapper').appendChild(this.container)
|
||||
|
||||
if (!draggable) return
|
||||
@ -137,11 +139,6 @@ if (!window.Table) {
|
||||
this.footer[i].style.textAlign = 'center'
|
||||
}
|
||||
}
|
||||
toJSON() {
|
||||
// Exclude the chart attribute from serialization
|
||||
const {chart, ...serialized} = this;
|
||||
return serialized;
|
||||
}
|
||||
}
|
||||
window.Table = Table
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ if (!window.ToolBox) {
|
||||
currentTime = this.chart.chart.timeScale().coordinateToTime(param.point.x)
|
||||
if (!currentTime) {
|
||||
let barsToMove = param.logical - this.chart.chart.timeScale().coordinateToLogical(this.chart.chart.timeScale().timeToCoordinate(lastCandleTime))
|
||||
currentTime = dateToChartTime(new Date(chartTimeToDate(this.chart.candleData[this.chart.candleData.length - 1].time).getTime() + (barsToMove * this.interval)), this.interval)
|
||||
currentTime = dateToStamp(new Date(stampToDate(this.chart.candleData[this.chart.candleData.length - 1].time).getTime() + (barsToMove * this.interval)))
|
||||
}
|
||||
let currentPrice = this.chart.series.coordinateToPrice(param.point.y)
|
||||
|
||||
@ -298,7 +298,6 @@ if (!window.ToolBox) {
|
||||
|
||||
if (boundaryConditional) {
|
||||
if (hoveringOver === drawing) return
|
||||
|
||||
if (!horizontal && !drawing.ray) drawing.line.setMarkers(drawing.markers)
|
||||
document.body.style.cursor = 'pointer'
|
||||
document.addEventListener('mousedown', checkForClick)
|
||||
@ -324,13 +323,17 @@ if (!window.ToolBox) {
|
||||
let originalPrice
|
||||
let mouseDown = false
|
||||
let clickedEnd = false
|
||||
let labelColor
|
||||
let checkForClick = (event) => {
|
||||
mouseDown = true
|
||||
document.body.style.cursor = 'grabbing'
|
||||
this.chart.chart.applyOptions({handleScroll: false})
|
||||
this.chart.chart.timeScale().applyOptions({shiftVisibleRangeOnNewBar: false})
|
||||
|
||||
this.chart.chart.unsubscribeCrosshairMove(hoverOver)
|
||||
|
||||
labelColor = this.chart.chart.options().crosshair.horzLine.labelBackgroundColor
|
||||
this.chart.chart.applyOptions({crosshair: {horzLine: {labelBackgroundColor: hoveringOver.color}}})
|
||||
if ('price' in hoveringOver) {
|
||||
originalPrice = hoveringOver.price
|
||||
this.chart.chart.subscribeCrosshairMove(crosshairHandlerHorz)
|
||||
@ -353,6 +356,8 @@ if (!window.ToolBox) {
|
||||
document.body.style.cursor = this.chart.cursor
|
||||
|
||||
this.chart.chart.applyOptions({handleScroll: true})
|
||||
this.chart.chart.timeScale().applyOptions({shiftVisibleRangeOnNewBar: true})
|
||||
this.chart.chart.applyOptions({crosshair: {horzLine: {labelBackgroundColor: labelColor}}})
|
||||
if (hoveringOver && 'price' in hoveringOver && hoveringOver.id !== 'toolBox') {
|
||||
window.callbackFunction(`${hoveringOver.id}_~_${hoveringOver.price.toFixed(8)}`);
|
||||
}
|
||||
@ -372,8 +377,8 @@ if (!window.ToolBox) {
|
||||
let priceDiff = priceAtCursor - originalPrice
|
||||
let barsToMove = param.logical - originalIndex
|
||||
|
||||
let startBarIndex = this.chart.candleData.findIndex(item => chartTimeToDate(item.time).getTime() === chartTimeToDate(hoveringOver.from[0]).getTime())
|
||||
let endBarIndex = this.chart.candleData.findIndex(item => chartTimeToDate(item.time).getTime() === chartTimeToDate(hoveringOver.to[0]).getTime())
|
||||
let startBarIndex = this.chart.candleData.findIndex(item => stampToDate(item.time).getTime() === stampToDate(hoveringOver.from[0]).getTime())
|
||||
let endBarIndex = this.chart.candleData.findIndex(item => stampToDate(item.time).getTime() === stampToDate(hoveringOver.to[0]).getTime())
|
||||
|
||||
let startDate
|
||||
let endBar
|
||||
@ -385,19 +390,18 @@ if (!window.ToolBox) {
|
||||
endBar = endBarIndex === -1 ? null : this.chart.candleData[endBarIndex + barsToMove]
|
||||
}
|
||||
|
||||
let endDate = endBar ? endBar.time : dateToChartTime(new Date(chartTimeToDate(hoveringOver.to[0]).getTime() + (barsToMove * this.interval)), this.interval)
|
||||
let endDate = endBar ? endBar.time : dateToStamp(new Date(stampToDate(hoveringOver.to[0]).getTime() + (barsToMove * this.interval)))
|
||||
let startValue = hoveringOver.from[1] + priceDiff
|
||||
let endValue = hoveringOver.to[1] + priceDiff
|
||||
let data = calculateTrendLine(startDate, startValue, endDate, endValue, this.interval, this.chart, hoveringOver.ray)
|
||||
|
||||
this.chart.chart.timeScale().applyOptions({shiftVisibleRangeOnNewBar: false})
|
||||
|
||||
let logical = this.chart.chart.timeScale().getVisibleLogicalRange()
|
||||
|
||||
hoveringOver.from = [data[0].time, data[0].value]
|
||||
hoveringOver.to = [data[data.length - 1].time, data[data.length - 1].value]
|
||||
hoveringOver.line.setData(data)
|
||||
|
||||
this.chart.chart.timeScale().applyOptions({shiftVisibleRangeOnNewBar: true})
|
||||
this.chart.chart.timeScale().setVisibleLogicalRange(logical)
|
||||
|
||||
if (!hoveringOver.ray) {
|
||||
@ -435,7 +439,7 @@ if (!window.ToolBox) {
|
||||
let lastCandleTime = this.chart.candleData[this.chart.candleData.length - 1].time
|
||||
if (!currentTime) {
|
||||
let barsToMove = param.logical - this.chart.chart.timeScale().coordinateToLogical(this.chart.chart.timeScale().timeToCoordinate(lastCandleTime))
|
||||
currentTime = dateToChartTime(new Date(chartTimeToDate(this.chart.candleData[this.chart.candleData.length - 1].time).getTime() + (barsToMove * this.interval)), this.interval)
|
||||
currentTime = dateToStamp(new Date(stampToDate(this.chart.candleData[this.chart.candleData.length - 1].time).getTime() + (barsToMove * this.interval)))
|
||||
}
|
||||
let data = calculateTrendLine(firstTime, firstPrice, currentTime, currentPrice, this.interval, this.chart)
|
||||
hoveringOver.line.setData(data)
|
||||
@ -472,8 +476,8 @@ if (!window.ToolBox) {
|
||||
renderDrawings() {
|
||||
this.drawings.forEach((item) => {
|
||||
if ('price' in item) return
|
||||
let startDate = dateToChartTime(new Date(Math.round(chartTimeToDate(item.from[0]).getTime() / this.interval) * this.interval), this.interval)
|
||||
let endDate = dateToChartTime(new Date(Math.round(chartTimeToDate(item.to[0]).getTime() / this.interval) * this.interval), this.interval)
|
||||
let startDate = dateToStamp(new Date(Math.round(stampToDate(item.from[0]).getTime() / this.interval) * this.interval))
|
||||
let endDate = dateToStamp(new Date(Math.round(stampToDate(item.to[0]).getTime() / this.interval) * this.interval))
|
||||
let data = calculateTrendLine(startDate, item.from[1], endDate, item.to[1], this.interval, this.chart, item.ray)
|
||||
item.from = [data[0].time, data[0].value]
|
||||
item.to = [data[data.length - 1].time, data[data.length-1].value]
|
||||
@ -537,8 +541,8 @@ if (!window.ToolBox) {
|
||||
},
|
||||
}),
|
||||
})
|
||||
let startDate = dateToChartTime(new Date(Math.round(chartTimeToDate(item.from[0]).getTime() / this.interval) * this.interval), this.interval)
|
||||
let endDate = dateToChartTime(new Date(Math.round(chartTimeToDate(item.to[0]).getTime() / this.interval) * this.interval), this.interval)
|
||||
let startDate = dateToStamp(new Date(Math.round(stampToDate(item.from[0]).getTime() / this.interval) * this.interval))
|
||||
let endDate = dateToStamp(new Date(Math.round(stampToDate(item.to[0]).getTime() / this.interval) * this.interval))
|
||||
let data = calculateTrendLine(startDate, item.from[1], endDate, item.to[1], this.interval, this.chart, item.ray)
|
||||
item.from = [data[0].time, data[0].value]
|
||||
item.to = [data[data.length - 1].time, data[data.length-1].value]
|
||||
@ -664,7 +668,7 @@ if (!window.ColorPicker) {
|
||||
}
|
||||
openMenu(rect, drawing) {
|
||||
this.drawing = drawing
|
||||
this.rgbValues = this.extractRGB('price' in drawing ? drawing.priceLine.color : drawing.color)
|
||||
this.rgbValues = this.extractRGB(drawing.color)
|
||||
this.opacity = parseFloat(this.rgbValues[3])
|
||||
this.container.style.top = (rect.top-30)+'px'
|
||||
this.container.style.left = rect.right+'px'
|
||||
|
||||
Reference in New Issue
Block a user