brighter-trading/static/Strategies.js

373 lines
16 KiB
JavaScript

//TODO this func is unused left over for reference.
//conditions_satisfied(signals){
// let result = true;
// for(let cond of this.conditions){
// if (cond.trig_val == 'true'){
// if (signals[cond.on] == true){
// result = result && true;
// }else{
// result = false;
// }
// }
// else if (cond.trig_val == 'false'){
// if (signals[cond.on] == false){
// result = result && true;
// }else{
// result = false;
// }
// }
// else if (cond.trig_val == 'changed'){
// // If no last result exists for this trigger, create one.
// if ( !this.last_results[cond.on] ){
// this.last_results[cond.on] = signals[cond.on];
// }
// if (signals[cond.on] != this.last_results[cond.on]){
// result = result && true;
// }else{
// result = false;
// }
// }
// }
// return result;
//}
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 an object representing the strategy.
- Record the strategy in the an instance list.
- Update the display output.
- Send the strategy object to the server.
*/
let strat = {};
strat.name = document.getElementById('stg_name').value;
if (strat.name == ''){
alert('Please provide a name.');
return;
}
strat.type = document.getElementById('strat_type').value;
strat.side = document.getElementById('trade_in_side').value;
strat.margin = document.getElementById('margin_select').value;
strat.trade_amount = document.getElementById('trade_amount').value;
strat.max_position = document.getElementById('strgy_total').value;
strat.trading_fee = document.getElementById('fee').value;
strat.max_loss = document.getElementById('max_loss').value;
strat.symbol = window.UI.data.trading_pair;
strat.net_profit = 0;
strat.gross_profit = 0;
strat.net_loss = 0;
strat.gross_loss = 0;
strat.current_position = 0;
strat.current_value = 0;
strat.active = false;
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;
}
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;
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.send_to_app( "new_strategy", strat);
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', 'take_profit');
}
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 += '<option>' + option + '</option>';
}
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 == 'take_profit'){
// 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.send_to_app('request', 'strategies');
}
del(name){
window.UI.data.comms.send_to_app('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 ="<button type='button' name='delete' class='e_btn' value='" + strat.name + "' onclick='" + on_click + "'>&#10008;</button>";
strats += "<li id='" + strat.name + "_item'>" + button + "<pre>" + JSON.stringify(strat) + "</pre></li>";
}
this.target.innerHTML = strats;
}
}