brighter-trading/static/charts.js

192 lines
7.2 KiB
JavaScript

class Charts {
constructor(idata) {
// Unpack the initialization data.
this.chart1_id = idata.chart1_id;
this.chart2_id = idata.chart2_id;
this.chart3_id = idata.chart3_id;
this.trading_pair = idata.trading_pair;
this.price_history = idata.price_history;
/* A list of bound charts this is necessary for maintaining a dynamic
number of charts with their position and zoom factors bound.*/
this.bound_charts=[];
// Only the main chart is created by default.
this.create_main_chart();
}
create_main_chart() {
// Pass the id of the element to create the main chart in.
// This function returns the main chart object.
this.chart_1 = this.create_chart(this.chart1_id);
// Display the trading pair as a watermark overlaying the chart.
this.addWatermark(this.chart_1, this.trading_pair);
// - Create the candle stick series for our chart
this.candleSeries = this.chart_1.addCandlestickSeries();
//Initialise the candlestick series
this.price_history.then((ph) => {
//Initialise the candle data
this.candleSeries.setData(ph);
})
this.bind_charts(this.chart_1);
}
update_main_chart(new_candle){
// Update candlestick series
this.candleSeries.update(new_candle);
}
create_RSI_chart(){
this.chart2 = this.create_chart(this.chart2_id, 100);
this.set_priceScale(this.chart2, 0.3, 0.0);
// Put the name of the chart in a watermark in the chart.
this.addWatermark(this.chart2, 'RSI');
// Todo: Not sure how to set this
//this.chart2.applyOptions({ priceRange: {minValue:0,maxValue:100} });
this.bind_charts(this.chart2);
}
create_MACD_chart(){
this.chart3 = this.create_chart(this.chart3_id, 100);
this.addWatermark(this.chart3, 'MACD');
this.bind_charts(this.chart3);
}
create_chart(target_id, height=500){
// Accepts a target element to place the chart in.
// Returns the chart object.
let container = document.getElementById(target_id);
//Create a lightweight chart object.
let chart = LightweightCharts.createChart(container, {
width: 1000,
height: height,
crosshair: {
mode: LightweightCharts.CrosshairMode.Normal,
},
priceScale: {
borderColor: 'rgba(197, 203, 206, 0.8)',
},
timeScale: {
borderColor: 'rgba(197, 203, 206, 0.8)',
timeVisible: true,
secondsVisible: false,
barSpacing: 6
},
handleScroll: true
});
return chart;
}
set_priceScale(chart, top, bottom){
chart.priceScale('right').applyOptions({
scaleMargins: {
top: top,
bottom: bottom,
},
});
}
addWatermark(chart,text){
chart.applyOptions({
watermark: {visible: true,
color: '#DBC29E',
text: text,
fontSize: 30,
fontFamily: 'Roboto',
fontStyle: 'bold',
vertAlign: 'center'
}
});
}
bind_charts(chart){
// keep a list of charts and bind all their position and spacing.
// Add (arg1) to bound_charts
this.add_to_list(chart);
// Get the number of objects in bound_charts
let bcl = Object.keys(this.bound_charts).length;
// if bound_charts has two element in it bind them
if (bcl == 2) { this.bind2charts(); }
// if bound_charts has two element in it bind them
if (bcl == 3) { this.bind3charts(); }
return;
}
add_to_list(chart){
// If the chart isn't already included in the list, add it.
if ( !this.bound_charts.includes(chart) ){
this.bound_charts.push(chart);
}
}
bind2charts(){
//On change in chart 1 change chart 2
let syncHandler1 = (e) => {
// Get the barSpacing(zoom) and position of 1st chart.
let barSpacing1 = this.bound_charts[0].timeScale().getBarSpacing();
let scrollPosition1 = this.bound_charts[0].timeScale().scrollPosition();
// Apply barSpacing(zoom) and position to 2nd chart.
this.bound_charts[1].timeScale().applyOptions({ rightOffset: scrollPosition1, barSpacing: barSpacing1 });
}
this.bound_charts[0].timeScale().subscribeVisibleTimeRangeChange(syncHandler1);
//On change in chart 2 change chart 1
let syncHandler2 = (e) => {
// Get the barSpacing(zoom) and position of chart 2
let barSpacing2 = this.bound_charts[1].timeScale().getBarSpacing();
let scrollPosition2 = this.bound_charts[1].timeScale().scrollPosition();
// Apply barSpacing(zoom) and position to chart 1
this.bound_charts[0].timeScale().applyOptions({ rightOffset: scrollPosition2, barSpacing: barSpacing2 });
}
this.bound_charts[1].timeScale().subscribeVisibleTimeRangeChange(syncHandler2);
}
bind3charts(){
//On change to chart 1 change chart 2 and 3
let syncHandler = (e) => {
// Get the barSpacing(zoom) and position of chart 1
let barSpacing1 = this.bound_charts[0].timeScale().getBarSpacing();
let scrollPosition1 = this.bound_charts[0].timeScale().scrollPosition();
// Apply barSpacing(zoom) and position to new chart
this.bound_charts[1].timeScale().applyOptions({ rightOffset: scrollPosition1, barSpacing: barSpacing1 });
this.bound_charts[2].timeScale().applyOptions({ rightOffset: scrollPosition1, barSpacing: barSpacing1 });
}
this.bound_charts[0].timeScale().subscribeVisibleTimeRangeChange(syncHandler);
//On change to chart 2 change chart 1 and 3
let syncHandler2 = (e) => {
// Get the barSpacing(zoom) and position of chart 2
let barSpacing2 = this.bound_charts[1].timeScale().getBarSpacing();
let scrollPosition2 = this.bound_charts[1].timeScale().scrollPosition();
// Apply barSpacing(zoom) and position to chart 1 and 3
this.bound_charts[0].timeScale().applyOptions({ rightOffset: scrollPosition2, barSpacing: barSpacing2 });
this.bound_charts[2].timeScale().applyOptions({ rightOffset: scrollPosition2, barSpacing: barSpacing2 });
}
this.bound_charts[1].timeScale().subscribeVisibleTimeRangeChange(syncHandler2);
//On change to chart 3 change chart 1 and 2
let syncHandler3 = (e) => {
// Get the barSpacing(zoom) and position of new chart
let barSpacing2 = this.bound_charts[2].timeScale().getBarSpacing();
let scrollPosition2 = this.bound_charts[2].timeScale().scrollPosition();
// Apply barSpacing(zoom) and position to parent chart
this.bound_charts[0].timeScale().applyOptions({ rightOffset: scrollPosition2, barSpacing: barSpacing2 });
this.bound_charts[1].timeScale().applyOptions({ rightOffset: scrollPosition2, barSpacing: barSpacing2 });
}
this.bound_charts[2].timeScale().subscribeVisibleTimeRangeChange(syncHandler3);
}
}