class Strategies { constructor(target_id) { // The list of strategies. this.strategies = []; // The html element id that displays the strategies. this.target_id = target_id; // The html element that displays the the strategies. this.target = null; } // Call to display Create new signal dialog. open_form() { document.getElementById("new_strat_form").style.display = "grid"; } // Call to hide Create new signal dialog. close_form() { document.getElementById("new_strat_form").style.display = "none"; } submit(){ /* - Collect the data from the form fields and create a json object representing a strategy. - Append the strategy to a local list of strategies. - Update the display output. - Send the strategy info to the server. */ let strat = {}; strat.name = document.getElementById('stg_name').value; if (strat.name == ''){ alert('Please provide a name.'); return; } // The type of strategy will determine underlying feature of its execution. strat.type = document.getElementById('strat_type').value; // Whether the strategy is bullish or bearish. strat.side = document.getElementById('trade_in_side').value; // Position size for each trade the strategy executes. strat.trade_amount = document.getElementById('trade_amount').value; // The maximum combined position allowed. strat.max_position = document.getElementById('strgy_total').value; // The fee the exchange charges per trade. strat.trading_fee = document.getElementById('fee').value; // The maximum allowable loss the strategy can endure in combined trades. // Before trading out and terminating execution. strat.max_loss = document.getElementById('max_loss').value; // The trading pair being exchanged. strat.symbol = window.UI.data.trading_pair; // The combined profit or loss including trading fees. strat.net_pl = 0; // The combined profit or loss. strat.gross_pl = 0; // The quantity of the traded assets being held. strat.combined_position = 0; // Opening value of the asset. strat.opening_value = 0; // The current value of the asset. strat.current_value = 0; // Whether or not the strategy has begun trading. strat.active = false; // The conditions that must be met before trading in. strat.trd_in_conds = {}; let conds = Array.from(document.querySelectorAll('#trade_in_cond>li')); for (let cond of conds){ let json_obj = JSON.parse(cond.innerHTML); strat.trd_in_conds[json_obj.Trigger] = json_obj.Value; } // The conditions that must be met before taking profit. let take_profit = {}; take_profit.typ = document.getElementById('prof_typ').value; if (take_profit.typ == 'conditional'){ take_profit.trig = document.getElementById('prof_trig').value; take_profit.val = document.getElementById('prof_trigVal').value; }else{ take_profit.val = document.getElementById('prof_val').value; } strat.take_profit = take_profit; // The conditions that must be met before taking a loss. let stop_loss = {}; stop_loss.typ = document.getElementById('loss_typ').value; if ( stop_loss.typ == 'conditional' ){ stop_loss.trig = document.getElementById('loss_trig').value; stop_loss.val = document.getElementById('loss_trigVal').value; }else{ stop_loss.val = document.getElementById('loss_val').value; } strat.stop_loss = stop_loss; // Add the strategy to the instance list. this.strategies.push(strat); // Add the strategy to display. this.update_html(); // Send the new strategy to the server. window.UI.data.comms.sendToApp( "new_strategy", strat); // Close the html form. this.close_form(); } update_received(stg_updts){ if ( 'cmd' in stg_updts) { let alert = window.UI.alerts.publish_alerts('strategy', stg_updts); this.executeCmd(stg_updts.cmd); } console.log('recieved stategy update.'); console.log(stg_updts); } set_data(strats){ for (let strat of strats){ // Add the strategy to the instance list. this.strategies.push(JSON.parse(strat)); } // Add the strategy to display. this.update_html(); } open_stg_form(){ this.open_form(); this.fill_field('strat_opt', 'in-out'); } clear_innerHTML(el){ el.innerHTML=""; } dropDown(name, label, parent, options){ /* Create a html selection element and append it to a parent element. name: name and id of the element. label: text displayed beside the selection list element. parent: the html element to append to. options: An array of selection options. */ let lbl = document.createElement("label"); lbl.for = name; lbl.id = name + '_lbl'; lbl.innerHTML = label; let select = document.createElement("select"); select.id = name; select.name = name; for(let option of options){ select.innerHTML += ''; } parent.appendChild(lbl); parent.appendChild(select); } val_input(name, label, parent, min, max, i_val, style = null){ /* Create an input element. name: name and id of the element. label: text displayed beside the element. parent: the html element to append to. min, max, i_val: Range and initialization values. */ let lbl = document.createElement("label"); lbl.for = name; lbl.id = name + '_lbl'; lbl.innerHTML = label; let input = document.createElement("input"); input.name = name; input.id = name; input.type = 'number'; input.min = min; if (max) {input.max = max;} input.value = i_val; if (style){ input.style = style; } parent.appendChild(lbl); parent.appendChild(input); } hideShowTags(elements, cmd){ /* Hides or shows 1 or many elements. Receives either string or array of string. */ if (typeof(elements) == 'string'){ elements = [elements]; } for(let el of elements){ if(cmd== 'hide'){document.getElementById(el).style.display = 'none';} if(cmd== 'show'){document.getElementById(el).style.display = 'inline-block';} } } fill_field(field, value){ if (field == 'strat_opt'){ let options = document.getElementById('strat_opt'); if (value == 'in-out'){ // Clear previous content. this.clear_innerHTML(options); // Add a horizontal rule. options.appendChild(document.createElement('hr')); //Create a drop down for buy/sell option this.dropDown('trade_in_side','Side:', options, ['buy','sell']); //Create an input for the margin. (1-100) this.val_input('margin_select', 'Margin:', options, 1,100, 50); // Add a line break. options.appendChild( document.createElement('br') ); //Create an input for the amount. (1-*) this.val_input('trade_amount', 'Trade amount:', options, 1, 0, 1,'width: 54px;'); //Create an input for the amount. (1-*) this.val_input('strgy_total', 'Strategy total:', options, 1, 0, 10, 'width: 54px;'); // Add a line break. options.appendChild( document.createElement('br') ); //Create an input for the fee. (0.01-1) this.val_input('fee', 'Trading Fee:', options, 0.001, 1, 0.025); // Create a un ordered list to hold the conditions of trading in. let ul_in_cond = document.createElement('ul'); ul_in_cond.id ='trade_in_cond'; // Create a submit button for the conditions. let add_cond_btn = document.createElement('button'); add_cond_btn.setAttribute('id','add_cond_btn'); add_cond_btn.setAttribute('type','button'); add_cond_btn.innerHTML = "Add Condition"; add_cond_btn.onclick = function () { let li = document.createElement('li'); li.innerHTML = JSON.stringify({ Trigger: trigger.value, Value: trigVal.value }); ul_in_cond.appendChild(li); }; // Add a horizontal rule. options.appendChild(document.createElement('hr')); //Create a drop down for trigger options // Get the signal options from the signal instance. let ops = []; for (let signal of window.UI.signals.signals) {ops.push(signal.name);} this.dropDown('trigger','Trigger Signal:', options, ops); //Create a drop down for trigger value. this.dropDown('trigVal','Trigger Value:', options, ['true', 'false', 'changed']); // Add the submit btn and the list to the dom. options.appendChild(add_cond_btn); options.appendChild(ul_in_cond); // Add a horizontal rule. options.appendChild(document.createElement('hr')); //Create a drop down for take profit type. this.dropDown('prof_typ','Profit type:', options, ['value', 'conditional']); // Add and onchange function to show and hide some options. let that = this; document.getElementById('prof_typ').onchange= function(){ if (this.value == 'value'){ that.hideShowTags(['prof_val_lbl','prof_val'], 'show'); that.hideShowTags(['prof_trig_lbl', 'prof_trig', 'prof_trigVal_lbl', 'prof_trigVal'], 'hide'); } else if (this.value == 'conditional'){ that.hideShowTags(['prof_val_lbl','prof_val'], 'hide'); that.hideShowTags(['prof_trig_lbl', 'prof_trig', 'prof_trigVal_lbl', 'prof_trigVal'], 'show'); } }; // Add a line break. options.appendChild(document.createElement('br')); // Create an input for take profit value. this.val_input('prof_val', 'Profit %:', options, 1,100, 50); // Set display to visible. this.hideShowTags(['prof_val_lbl','prof_val'], 'show'); // Create an input for take profit signal trigger. // Get the signal options from the signal instance. ops = []; for (let signal of window.UI.signals.signals) {ops.push(signal.name);} this.dropDown('prof_trig','Profit trigger:', options, ops); // Set display to hidden. this.hideShowTags(['prof_trig_lbl','prof_trig'], 'hide'); //Create a drop down for take profit trigger value. this.dropDown('prof_trigVal','Trigger Value:', options, ['true', 'false', 'changed']); // Set display to hidden. this.hideShowTags(['prof_trigVal_lbl','prof_trigVal'], 'hide'); // Add a line break. options.appendChild(document.createElement('br')); // Add a horizontal rule. options.appendChild(document.createElement('hr')); // Create an input for tolerable loss. this.val_input('max_loss', 'Max loss :', options, 1,100, 50); // Add a line break. options.appendChild(document.createElement('br')); //Create a drop down for Stop Loss type. this.dropDown('loss_typ','Stop-Loss type:', options, ['value', 'conditional']); // Add and onchange function to show and hide some options. document.getElementById('loss_typ').onchange= function(){ if (this.value == 'value'){ that.hideShowTags(['loss_val_lbl','loss_val'], 'show'); that.hideShowTags(['loss_trig_lbl', 'loss_trig', 'loss_trigVal_lbl', 'loss_trigVal'], 'hide'); } else if (this.value == 'conditional'){ that.hideShowTags(['loss_val_lbl','loss_val'], 'hide'); that.hideShowTags(['loss_trig_lbl', 'loss_trig', 'loss_trigVal_lbl', 'loss_trigVal'], 'show'); } }; // Add a line break. options.appendChild( document.createElement('br') ); // Create an input for stop loss value. this.val_input('loss_val', 'Loss %:', options, 1,100, 50); // Set display to visible. this.hideShowTags(['loss_val_lbl','loss_val'], 'show'); // Create an input for take profit signal trigger. // Get the signal options from the signal instance. ops = []; for (let signal of window.UI.signals.signals) {ops.push(signal.name);} this.dropDown('loss_trig','Stop-Loss trigger:', options, ops); // Set display to hidden. this.hideShowTags(['loss_trig_lbl','loss_trig'], 'hide'); //Create a drop down for take profit trigger value. this.dropDown('loss_trigVal','Loss Value:', options, ['true', 'false', 'changed']); // Set display to hidden. this.hideShowTags(['loss_trigVal_lbl','loss_trigVal'], 'hide'); // Add a line break. options.appendChild(document.createElement('br')); // Add a horizontal rule. options.appendChild(document.createElement('hr')); } if (value == 'incremental_profits'){ options.innerHTML="Incremental_profits -> not done."; } if (value == 'swing'){ options.innerHTML="swing -> not done."; } } } initialize(){ // This is called after the html document has been parsed. this.target = document.getElementById(this.target_id); // Send a request to the server for any loaded data. window.UI.data.comms.sendToApp('request', 'strategies'); } del(name){ window.UI.data.comms.sendToApp('delete_strategy', name); // Get the child element node let child = document.getElementById(name + '_item'); // Remove the child element from the document child.parentNode.removeChild(child); } update_html(){ let strats =''; let on_click = " window.UI.strats.del(this.value);"; for (let strat of this.strategies){ let button =""; strats += "
  • " + button + "
    " + JSON.stringify(strat) + "
  • "; } this.target.innerHTML = strats; } }