class Comms { constructor() { // List of callbacks callback function that will receive various updates. this.on_candle_update = []; this.on_candle_close = []; this.on_indctr_update = []; // Status of connection. this.connection_open = false; } register_callback(target, callback_func){ // Register any outside functions that need to receive updates. if (target=='candle_update'){ this.on_candle_update.push(callback_func) } else if (target=='candle_close'){ this.on_candle_close.push(callback_func) } else if (target=='indicator_update'){ this.on_indctr_update.push(callback_func) } else{console.log('Comms: Invalid target for callback');} } candle_update(new_candle){ // If no callback is registered do nothing. if (this.on_candle_update == null) {return}; // Call each registered callback passing the candle updates. for (i = 0; i < this.on_candle_update.length; i++) { this.on_candle_update[i](new_candle); } } candle_close(new_candle){ // Forward a copy of the new candle to the server. this.app_con.send( JSON.stringify({ message_type: "candle_data", data :new_candle })); // If no callback is registered do return. if (this.on_candle_close == null) {return}; // Call each registered callback passing the candle updates. for (i = 0; i < this.on_candle_close.length; i++) { this.on_candle_close[i](new_candle); } } indicator_update(data){ // If no callback is registered do return. if (this.on_indctr_update == null) {return}; // Call each registered callback passing the candle updates. for (i = 0; i < this.on_indctr_update.length; i++) { this.on_indctr_update[i](data); } } getPriceHistory(){ let ph = fetch('http://localhost:5000/history').then((r) => r.json()).then( (data) => { return data; } ); return ph; } getIndicatorData(){ let id = fetch('http://localhost:5000/indicator_init').then((r) => r.json()).then( (data) => { return data; } ); return id; } send_to_app(message_type, data){ console.log('window.UI.data.comms.send_to_app(): Sending->'); console.log( JSON.stringify({ message_type: message_type, data : data })); if (this.connection_open){ this.app_con.send( JSON.stringify({ message_type: message_type, data : data })); }else{ setTimeout(function(){ window.UI.data.comms.app_con.send( JSON.stringify({ message_type: message_type, data : data })) }, 1000); } } set_app_con(){ // Create a web socket connection to our app. this.app_con = new WebSocket('ws://localhost:5000/ws'); this.app_con.onopen = () => { this.app_con.send("Connection OK"); this.connection_open = true; } this.app_con.addEventListener('message', ev => { if(ev.data){ // Get the message received from server let msg = JSON.parse(ev.data) // Handle a request from the server if (msg.request) { //handle request console.log('Received a request from the server'); console.log(msg.request); } // Handle a reply from the server if (msg.reply) { // Handle updates from server. if (msg.reply == 'updates'){ if ('i_updates' in msg.data){ /* If the received message contains indicator updates. Forward them to the indicator instance. */ this.indicator_update(msg.data['i_updates']); // Forward the indicator updates to the signal instance. window.UI.signals.i_update(msg.data['i_updates']); } if ('s_updates' in msg.data){ /* If the received message contains signal updates. Forward them to the signals instance. These messages only arrive if a signal state changes. */ let updates = msg.data['s_updates']; window.UI.signals.update_signal_states(updates); window.UI.alerts.publish_alerts('signal_changes', updates); } if ('stg_updts' in msg.data){ /* If the received message contains signal updates. Forward them to the signals instance. These messages only arrive if a signal state changes. */ let stg_updts = msg.data['stg_updts']; window.UI.strats.update_received(stg_updts); } }else if (msg.reply == 'signals'){ /* On initialization the server will send a list of signals loaded from file. Forward this to the signals instance.*/ window.UI.signals.set_data(msg.data); }else if (msg.reply == 'strategies'){ /* On initialization the server will send a list of strategies loaded from file. Forward this to the strategies instance.*/ window.UI.strats.set_data(msg.data); } else if (msg.reply =='signal_created'){ /* After the server creates a new signal it will send the details here. Forward this to the signals instance. I re-used the init function. But wrapped the data in a list element.*/ let list_of_one = new Array(); list_of_one.push(msg.data); window.UI.signals.set_data(list_of_one); } else { console.log(msg.reply) console.log(msg.data) } } } }) } set_exchange_con(interval, tradingPair){ tradingPair = tradingPair.toLowerCase(); let ws = "wss://stream.binance.com:9443/ws/" + tradingPair + "@kline_" + interval; this.exchange_con = new WebSocket(ws); // Set the on-message call-back for the socket this.exchange_con.onmessage = (event) => { // Convert message to json obj let message = JSON.parse(event.data); // Isolate the candle data from message let candlestick = message.k; // Reformat data for lightweight charts let new_candle={ time: candlestick.t / 1000, open: candlestick.o, high: candlestick.h, low: candlestick.l, close: candlestick.c, vol: candlestick.v }; // Update frequently updated objects this.candle_update(new_candle); // Update less frequently updated objects. if (candlestick.x == true) { this.candle_close(new_candle); } } } }