diff --git a/Configuration.py b/Configuration.py
index a88ec8f..5b6a78a 100644
--- a/Configuration.py
+++ b/Configuration.py
@@ -28,20 +28,28 @@ class Configuration:
# Call a static method from indicators that fills in a default list of indicators in config.
self.signals_list = Signals.get_signals_defaults()
+ # list of strategies in config.
+ self.strategies_list = []
+
# The data that will be saved and loaded from file .
self.saved_data = None
+ def new_strategy(self, data):
+ # The strategies_list is modified by reference in strategies the loaded in config_and_states('save').
+ # Save it to file.
+ self.config_and_states('save')
+
def new_signal(self, data):
# Create a new signal.
self.saved_data['signals'].append(data)
# Save it to file.
self.config_and_states('save')
- def remove_signal(self, data):
- print(f'removing {data}')
- for sig in self.saved_data['signals']:
- if sig['name'] == data:
- self.saved_data['signals'].remove(sig)
+ def remove(self, what, name):
+ print(f'removing {what}:{name}')
+ for obj in self.saved_data[what]:
+ if obj['name'] == name:
+ self.saved_data[what].remove(obj)
break
# Save it to file.
self.config_and_states('save')
@@ -53,7 +61,8 @@ class Configuration:
self.saved_data = {
'indicator_list': self.indicator_list,
'config': {'chart_interval': self.chart_interval, 'trading_pair': self.trading_pair},
- 'signals': self.signals_list
+ 'signals': self.signals_list,
+ 'strategies': self.strategies_list
}
def set_loaded_values():
@@ -62,6 +71,7 @@ class Configuration:
self.chart_interval = self.saved_data['config']['chart_interval']
self.trading_pair = self.saved_data['config']['trading_pair']
self.signals_list = self.saved_data['signals']
+ self.strategies_list = self.saved_data['strategies']
def load_configuration(filepath):
"""load file data"""
diff --git a/Signals.py b/Signals.py
index b236fb9..086fdbd 100644
--- a/Signals.py
+++ b/Signals.py
@@ -53,7 +53,7 @@ class Signal:
class Signals:
def __init__(self):
self.signals = []
- self.set_signals_defaults()
+ # self.set_signals_defaults()
def set_signals_defaults(self):
"""These defaults are loaded if the config file is not found."""
@@ -91,7 +91,6 @@ class Signals:
prop1=sig['prop1'], operator=sig['operator'],
source2=sig['source2'], prop2=sig['prop2'],
state=sig['state']))
- print(self.signals)
def get_signals(self):
return self.signals
diff --git a/Strategies.py b/Strategies.py
new file mode 100644
index 0000000..d67d6d3
--- /dev/null
+++ b/Strategies.py
@@ -0,0 +1,15 @@
+class Strategies:
+ def __init__(self, loaded_strats):
+ self.strat_list = loaded_strats
+
+ def new_strategy(self, data):
+ self.strat_list.append(data)
+
+ def delete_strategy(self, name):
+ for obj in self.strat_list:
+ if obj['name'] == name:
+ self.strat_list.remove(obj)
+ break
+
+ def get_strategies(self):
+ return self.strat_list
diff --git a/app.py b/app.py
index 006d5ad..f00aceb 100644
--- a/app.py
+++ b/app.py
@@ -61,6 +61,15 @@ def ws(sock):
}
resp = json.dumps(resp)
sock.send(resp)
+ elif msg_obj['data'] == 'strategies':
+ strategies = bt.app_data.get_strategies()
+ if strategies:
+ resp = {
+ "reply": "strategies",
+ "data": strategies
+ }
+ resp = json.dumps(resp)
+ sock.send(resp)
else:
print('Warning: Unhandled request!')
print(msg_obj['data'])
@@ -68,6 +77,9 @@ def ws(sock):
if msg_obj['message_type'] == 'delete_signal':
bt.app_data.delete_signal(msg_obj['data'])
+ if msg_obj['message_type'] == 'delete_strategy':
+ bt.app_data.delete_strategy(msg_obj['data'])
+
if msg_obj['message_type'] == 'reply':
print(msg_obj['rep'])
print('Reply')
@@ -83,6 +95,18 @@ def ws(sock):
}
resp = json.dumps(resp)
sock.send(resp)
+
+ if msg_obj['message_type'] == 'new_strategy':
+ # Send the data to the BrighterData_obj
+ # and forward any returned data to the client.
+ r_data = bt.app_data.received_new_strategy(msg_obj['data'])
+ if r_data:
+ resp = {
+ "reply": "strategy_created",
+ "data": r_data
+ }
+ resp = json.dumps(resp)
+ sock.send(resp)
return
# The rendered page connects to the exchange and relays the candle data back here
diff --git a/data.py b/data.py
index 506cddd..4fdbcc6 100644
--- a/data.py
+++ b/data.py
@@ -1,6 +1,7 @@
from binance.client import Client
import config
+from Strategies import Strategies
from candles import Candles
from Configuration import Configuration
from exchange_info import ExchangeInfo
@@ -36,6 +37,9 @@ class BrighterData:
# Object that maintains exchange and account data
self.exchange_info = ExchangeInfo(self.client)
+ # Object that maintains the strategies data
+ self.strategies = Strategies(self.config.strategies_list)
+
def get_js_init_data(self):
"""Returns a JSON object of initialization data
for the javascript in the rendered HTML"""
@@ -90,8 +94,26 @@ class BrighterData:
self.signals.new_signal(data)
# Forward the new signal data to config. So it can save it to file.
self.config.new_signal(data)
+ # Send the data back to where it came from.
return data
+ def received_new_strategy(self, data):
+ # Check the data.
+ if 'name' not in data:
+ return 'data.py:received_new_strategy() - The new strategy has no name. '
+ # Forward the new strategy data to the strategy's instance. So it can create a new strategy.
+ self.strategies.new_strategy(data)
+ # Forward the new signal data to config. So it can save it to file.
+ self.config.new_strategy(data)
+ # Send the data back to where it came from.
+ return data
+
+ def delete_strategy(self, strategy_name):
+ # Delete the signal from the signals instance.
+ self.strategies.delete_strategy(strategy_name)
+ # Delete the signal from the configuration file.
+ self.config.remove('strategies', strategy_name)
+
def get_signals(self):
""" Return a JSON object of all the signals in the signals instance."""
sigs = self.signals.get_signals()
@@ -100,11 +122,19 @@ class BrighterData:
json_str.append(json.dumps(sig.__dict__))
return json_str
+ def get_strategies(self):
+ """ Return a JSON object of all the signals in the signals instance."""
+ strats = self.strategies.get_strategies()
+ json_str = []
+ for strat in strats:
+ json_str.append(json.dumps(strat))
+ return json_str
+
def delete_signal(self, signal_name):
# Delete the signal from the signals instance.
self.signals.delete_signal(signal_name)
# Delete the signal from the configuration file.
- self.config.remove_signal(signal_name)
+ self.config.remove('signals', signal_name)
app_data = BrighterData()
diff --git a/indicators.py b/indicators.py
index 1200a74..53c6fa2 100644
--- a/indicators.py
+++ b/indicators.py
@@ -359,13 +359,17 @@ class Indicators:
"""Set the default settings for each indicator"""
indicator_list = {
- 'SMA 21': {'type': 'SMA', 'period': 21, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
+ 'EMA 5': {'type': 'EMA', 'period': 5, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
+ 'value': 0},
+ 'EMA 15': {'type': 'EMA', 'period': 15, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
+ 'value': 0},
+ 'EMA 20': {'type': 'EMA', 'period': 20, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0},
'EMA 50': {'type': 'EMA', 'period': 50, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0},
'EMA 100': {'type': 'EMA', 'period': 100, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0},
- 'SMA 200': {'type': 'SMA', 'period': 200, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
+ 'EMA 200': {'type': 'EMA', 'period': 200, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0},
'RSI 14': {'type': 'RSI', 'period': 14, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0},
diff --git a/static/Strategies.js b/static/Strategies.js
index 2c5e9ff..2e1401c 100644
--- a/static/Strategies.js
+++ b/static/Strategies.js
@@ -1,86 +1,35 @@
-class Strategy{
- constructor(strat_type, name, side, take_profit, stop_loss, conditions) {
- // The type of alert.
- this.type = strat_type;
- // The source of the alert.
- this.name = name;
- // buy|sell: string
- this.side = side;
- // Conditions to exit trade in profit. {on: ('profit'|'condition'), trig_val: 999}
- this.take_profit = take_profit;
- // Conditions to exit trade in loss. {on: ('loss'|'condition'), trig_val: 999}
- this.stop_loss = stop_loss;
- // The conditions to evaluate. { on: (signal_name: str), trig_val: (true|false|changed) }
- this.conditions = conditions;
- // html formatted representation.
- this.display_output = this.format_html();
- // any last results needed for comparison.
- this.last_result = {};
- }
- format_html(){
- let html ='
';
- return html;
- }
- 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;
- }
- name(){
- return this.name;
- }
- type(){
- return this.type;
- }
- strategy(){
- return this.strategy;
- }
- print_html(){
- return this.display_output;
- }
-}
+//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.
@@ -95,21 +44,123 @@ class Strategies {
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.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();
+ }
+ 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');
- // condition = { on: (signal_name: str), trig_val: (true|false|changed) }
- let cond1 = {on: 'signal1', trig_val:'changed'}
- // take_profit = {on: ('profit'|'condition'), trig_val: 999}
- let take_profit = {on: 'signal2', trig_val: false}
- // stop_loss = {on: ('loss'|'condition'), trig_val: 999}
- let stop_loss = {on: 'loss', trig_val: '80%' }
- let side='buy';
- let conditions = []; //_str = side + condition + take_profit
- conditions.push(cond1);
- this.strategies.push( new Strategy('take_profit', 'strategy_#1', side, take_profit, stop_loss, conditions) );
- this.update_html();
+ }
+ 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){
+ /* 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;
+ input.max = max;
+ input.value = i_val;
+ 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'){
@@ -117,35 +168,17 @@ class Strategies {
if (value == 'take_profit'){
// Clear previous content.
- options.innerHTML="";
+ this.clear_innerHTML(options);
//Create a drop down for buy/sell option
- let side_select_label = document.createElement("label");
- side_select_label.for = 'trade_in_side';
- side_select_label.innerHTML = 'Side:';
- let side_select = document.createElement("select");
- side_select.id = "trade_in_side";
- side_select.name = "trade_in_side";
- side_select.innerHTML = '';
- options.appendChild(side_select_label);
- options.appendChild(side_select);
+ this.dropDown('trade_in_side','Side:', options, ['buy','sell']);
- //Create an input for margin trading value. (1X-100X)
- let margin_label = document.createElement("label");
- margin_label.for = 'margin';
- margin_label.innerHTML = 'Margin:';
- let margin_select = document.createElement("input");
- margin_select.name = 'margin';
- margin_select.type = 'number';
- margin_select.min = 1;
- margin_select.max = 100;
- margin_select.value = 1;
- options.appendChild(margin_label);
- options.appendChild(margin_select);
+ //Create an input for margin trading value. (1-100)
+ this.val_input('margin_select', 'Margin:', options, 1,100, 50);
// 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_conditions';
+ ul_in_cond.id ='trade_in_cond';
// Create a submit button for the conditions.
let add_cond_btn = document.createElement('button');
@@ -154,116 +187,108 @@ class Strategies {
add_cond_btn.innerHTML = "Add Condition";
add_cond_btn.onclick = function () {
let li = document.createElement('li');
- li.innerHTML = 'Trigger:'+ trigger.value+' Value:' + trigVal.value;
+ li.innerHTML = JSON.stringify({ Trigger: trigger.value, Value: trigVal.value });
ul_in_cond.appendChild(li);
};
// Add a horizontal rule.
- let element = document.createElement('hr');
- options.appendChild(element);
+ options.appendChild(document.createElement('hr'));
//Create a drop down for trigger options
- let trigger_label = document.createElement("label");
- trigger_label.for = 'trigger';
- trigger_label.innerHTML = 'Trigger Signal:';
- let trigger = document.createElement("select");
- trigger.id = "trigger";
- trigger.name = "trigger";
- // Populate the signal selector.
- for (let signal in window.UI.signals.signals){
- let opt = document.createElement('option');
- opt.value = window.UI.signals.signals[signal].name;
- opt.innerHTML = window.UI.signals.signals[signal].name;
- trigger.appendChild(opt);
- }
- // Add it to the dom.
- options.appendChild(trigger_label);
- options.appendChild(trigger);
+ // 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.
- let trigVal_label = document.createElement("label");
- trigVal_label.for = 'trigVal';
- trigVal_label.innerHTML = 'Trigger Value:';
- let trigVal = document.createElement("select");
- trigVal.id = "trigVal";
- trigVal.name = "trigVal";
-
- let opt = document.createElement('option');
- opt.value = true;
- opt.innerHTML = 'true';
- trigVal.appendChild(opt);
-
- opt = document.createElement('option');
- opt.value = false;
- opt.innerHTML = 'false';
- trigVal.appendChild(opt);
-
- opt = document.createElement('option');
- opt.value = 'changed';
- opt.innerHTML = 'changed';
- trigVal.appendChild(opt);
-
- // Add trigger Value select element to the dom.
- options.appendChild(trigVal_label);
- options.appendChild(trigVal);
+ 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.
- element = document.createElement('hr');
- options.appendChild(element);
-
- //Create an input for take profit value.
- let prof_value_lbl = document.createElement("label");
- prof_value_lbl.for = 'profit_val';
- prof_value_lbl.innerHTML = 'Profit %:';
- let profit_val = document.createElement("input");
- profit_val.type='number';
- profit_val.min=0; profit_val.max=100; profit_val.value = 50;
+ options.appendChild(document.createElement('hr'));
//Create a drop down for take profit type.
- let prof_typ_label = document.createElement("label");
- prof_typ_label.for = 'prof_typ';
- prof_typ_label.innerHTML = 'Profit type:';
- let prof_typ = document.createElement("select");
- prof_typ.id = "prof_typ";
- prof_typ.name = "prof_typ";
- prof_typ.onchange= function(){
+ 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'){
- prof_value_lbl.style.display = 'inline-block';
- profit_val.style.display = 'inline-block';
- //profit_trig.style.display = 'none';
+ 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'){
- prof_value_lbl.style.display = 'none';
- profit_val.style.display = 'none';
- //profit_trig.style.display = 'block';
+ that.hideShowTags(['prof_val_lbl','prof_val'], 'hide');
+ that.hideShowTags(['prof_trig_lbl', 'prof_trig', 'prof_trigVal_lbl', 'prof_trigVal'], 'show');
}
};
- opt = document.createElement('option');
- opt.value = 'value';
- opt.innerHTML = 'value';
- prof_typ.appendChild(opt);
+ // Add a line break.
+ options.appendChild(document.createElement('br'));
- opt = document.createElement('option');
- opt.value = 'conditional';
- opt.innerHTML = 'conditional';
- prof_typ.appendChild(opt);
+ // 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');
- // Add profit_type select element to the dom.
- options.appendChild(prof_typ_label);
- options.appendChild(prof_typ);
+ // 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');
- opt = document.createElement('br');
- options.appendChild(opt);
+ //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 value input to the dom.
- options.appendChild(prof_value_lbl);
- options.appendChild(profit_val);
+ // Add a line break.
+ options.appendChild(document.createElement('br'));
+ // Add a horizontal rule.
+ options.appendChild(document.createElement('hr'));
+ //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 take profit 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'){
@@ -274,14 +299,25 @@ class Strategies {
}
}
}
- set_target(){
+ 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){
- strats += strat.print_html();
+ let button ="";
+ strats += "
" + button + "
" + JSON.stringify(strat) + "
";
}
this.target.innerHTML = strats;
}
diff --git a/static/communication.js b/static/communication.js
index 31f8e64..6d42a4f 100644
--- a/static/communication.js
+++ b/static/communication.js
@@ -33,6 +33,7 @@ class Comms {
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 }));
@@ -83,6 +84,10 @@ class Comms {
/* 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.
diff --git a/static/general.js b/static/general.js
index 8c0dbc8..0cc64da 100644
--- a/static/general.js
+++ b/static/general.js
@@ -85,8 +85,8 @@ class User_Interface{
window.UI.signals.request_signals();
// initialize the alerts instance.
window.UI.alerts.set_target();
- // initialize the alerts instance.
- window.UI.strats.set_target();
+ // initialize the strategies instance.
+ window.UI.strats.initialize();
});
}
diff --git a/static/signals.js b/static/signals.js
index 841098f..d745fef 100644
--- a/static/signals.js
+++ b/static/signals.js
@@ -58,9 +58,9 @@ class Signals {
// Keep a local record of the signals.
this.signals.push(obj);
// Define the function that is called when deleting an individual signal.
- let click_func = "window.UI.signals.delete_signal('" + obj.name+ "')";
+ let click_func = "window.UI.signals.delete_signal('" + obj.name + "')";
// create a delete button for every individual signal.
- let delete_btn = "";
+ let delete_btn = '';
// Put all the attributes into html elements.
let signal_name = " " + obj.name + ": ";
diff --git a/templates/index.html b/templates/index.html
index 262be3e..c219be2 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -46,7 +46,7 @@