Classes implemented in python and javascript. UML class diagram. Rough sequence uml. TODO: local file getting dirty from refresh. Signals implemented. Strategies implemented. Ready for implementation of Trades class.

This commit is contained in:
Rob 2022-06-06 13:40:14 -03:00
parent 5f5f34c945
commit 5d942a9c2c
11 changed files with 342 additions and 219 deletions

View File

@ -28,20 +28,28 @@ class Configuration:
# Call a static method from indicators that fills in a default list of indicators in config. # Call a static method from indicators that fills in a default list of indicators in config.
self.signals_list = Signals.get_signals_defaults() 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 . # The data that will be saved and loaded from file .
self.saved_data = None 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): def new_signal(self, data):
# Create a new signal. # Create a new signal.
self.saved_data['signals'].append(data) self.saved_data['signals'].append(data)
# Save it to file. # Save it to file.
self.config_and_states('save') self.config_and_states('save')
def remove_signal(self, data): def remove(self, what, name):
print(f'removing {data}') print(f'removing {what}:{name}')
for sig in self.saved_data['signals']: for obj in self.saved_data[what]:
if sig['name'] == data: if obj['name'] == name:
self.saved_data['signals'].remove(sig) self.saved_data[what].remove(obj)
break break
# Save it to file. # Save it to file.
self.config_and_states('save') self.config_and_states('save')
@ -53,7 +61,8 @@ class Configuration:
self.saved_data = { self.saved_data = {
'indicator_list': self.indicator_list, 'indicator_list': self.indicator_list,
'config': {'chart_interval': self.chart_interval, 'trading_pair': self.trading_pair}, '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(): def set_loaded_values():
@ -62,6 +71,7 @@ class Configuration:
self.chart_interval = self.saved_data['config']['chart_interval'] self.chart_interval = self.saved_data['config']['chart_interval']
self.trading_pair = self.saved_data['config']['trading_pair'] self.trading_pair = self.saved_data['config']['trading_pair']
self.signals_list = self.saved_data['signals'] self.signals_list = self.saved_data['signals']
self.strategies_list = self.saved_data['strategies']
def load_configuration(filepath): def load_configuration(filepath):
"""load file data""" """load file data"""

View File

@ -53,7 +53,7 @@ class Signal:
class Signals: class Signals:
def __init__(self): def __init__(self):
self.signals = [] self.signals = []
self.set_signals_defaults() # self.set_signals_defaults()
def set_signals_defaults(self): def set_signals_defaults(self):
"""These defaults are loaded if the config file is not found.""" """These defaults are loaded if the config file is not found."""
@ -91,7 +91,6 @@ class Signals:
prop1=sig['prop1'], operator=sig['operator'], prop1=sig['prop1'], operator=sig['operator'],
source2=sig['source2'], prop2=sig['prop2'], source2=sig['source2'], prop2=sig['prop2'],
state=sig['state'])) state=sig['state']))
print(self.signals)
def get_signals(self): def get_signals(self):
return self.signals return self.signals

15
Strategies.py Normal file
View File

@ -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

24
app.py
View File

@ -61,6 +61,15 @@ def ws(sock):
} }
resp = json.dumps(resp) resp = json.dumps(resp)
sock.send(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: else:
print('Warning: Unhandled request!') print('Warning: Unhandled request!')
print(msg_obj['data']) print(msg_obj['data'])
@ -68,6 +77,9 @@ def ws(sock):
if msg_obj['message_type'] == 'delete_signal': if msg_obj['message_type'] == 'delete_signal':
bt.app_data.delete_signal(msg_obj['data']) 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': if msg_obj['message_type'] == 'reply':
print(msg_obj['rep']) print(msg_obj['rep'])
print('Reply') print('Reply')
@ -83,6 +95,18 @@ def ws(sock):
} }
resp = json.dumps(resp) resp = json.dumps(resp)
sock.send(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 return
# The rendered page connects to the exchange and relays the candle data back here # The rendered page connects to the exchange and relays the candle data back here

32
data.py
View File

@ -1,6 +1,7 @@
from binance.client import Client from binance.client import Client
import config import config
from Strategies import Strategies
from candles import Candles from candles import Candles
from Configuration import Configuration from Configuration import Configuration
from exchange_info import ExchangeInfo from exchange_info import ExchangeInfo
@ -36,6 +37,9 @@ class BrighterData:
# Object that maintains exchange and account data # Object that maintains exchange and account data
self.exchange_info = ExchangeInfo(self.client) 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): def get_js_init_data(self):
"""Returns a JSON object of initialization data """Returns a JSON object of initialization data
for the javascript in the rendered HTML""" for the javascript in the rendered HTML"""
@ -90,8 +94,26 @@ class BrighterData:
self.signals.new_signal(data) self.signals.new_signal(data)
# Forward the new signal data to config. So it can save it to file. # Forward the new signal data to config. So it can save it to file.
self.config.new_signal(data) self.config.new_signal(data)
# Send the data back to where it came from.
return data 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): def get_signals(self):
""" Return a JSON object of all the signals in the signals instance.""" """ Return a JSON object of all the signals in the signals instance."""
sigs = self.signals.get_signals() sigs = self.signals.get_signals()
@ -100,11 +122,19 @@ class BrighterData:
json_str.append(json.dumps(sig.__dict__)) json_str.append(json.dumps(sig.__dict__))
return json_str 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): def delete_signal(self, signal_name):
# Delete the signal from the signals instance. # Delete the signal from the signals instance.
self.signals.delete_signal(signal_name) self.signals.delete_signal(signal_name)
# Delete the signal from the configuration file. # Delete the signal from the configuration file.
self.config.remove_signal(signal_name) self.config.remove('signals', signal_name)
app_data = BrighterData() app_data = BrighterData()

View File

@ -359,13 +359,17 @@ class Indicators:
"""Set the default settings for each indicator""" """Set the default settings for each indicator"""
indicator_list = { 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}, 'value': 0},
'EMA 50': {'type': 'EMA', 'period': 50, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}", 'EMA 50': {'type': 'EMA', 'period': 50, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0}, 'value': 0},
'EMA 100': {'type': 'EMA', 'period': 100, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}", 'EMA 100': {'type': 'EMA', 'period': 100, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0}, '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}, 'value': 0},
'RSI 14': {'type': 'RSI', 'period': 14, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}", 'RSI 14': {'type': 'RSI', 'period': 14, 'visible': True, 'color': f"#{random.randrange(0x1000000):06x}",
'value': 0}, 'value': 0},

View File

@ -1,86 +1,35 @@
class Strategy{ //TODO this func is unused left over for reference.
constructor(strat_type, name, side, take_profit, stop_loss, conditions) { //conditions_satisfied(signals){
// The type of alert. // let result = true;
this.type = strat_type; // for(let cond of this.conditions){
// The source of the alert. // if (cond.trig_val == 'true'){
this.name = name; // if (signals[cond.on] == true){
// buy|sell: string // result = result && true;
this.side = side; // }else{
// Conditions to exit trade in profit. {on: ('profit'|'condition'), trig_val: 999} // result = false;
this.take_profit = take_profit; // }
// Conditions to exit trade in loss. {on: ('loss'|'condition'), trig_val: 999} // }
this.stop_loss = stop_loss; // else if (cond.trig_val == 'false'){
// The conditions to evaluate. { on: (signal_name: str), trig_val: (true|false|changed) } // if (signals[cond.on] == false){
this.conditions = conditions; // result = result && true;
// html formatted representation. // }else{
this.display_output = this.format_html(); // result = false;
// any last results needed for comparison. // }
this.last_result = {}; // }
} // else if (cond.trig_val == 'changed'){
format_html(){ // // If no last result exists for this trigger, create one.
let html ='<li>' + '<span>' + this.name + '</span>'; // if ( !this.last_results[cond.on] ){
html +='<span>' + this.type + '</span>'; // this.last_results[cond.on] = signals[cond.on];
html +='<span>' + this.side + '</span>'; // }
if (this.take_profit.on == 'profit'){ // if (signals[cond.on] != this.last_results[cond.on]){
if(this.side == 'buy') {var then_do ='sell';} // result = result && true;
else if(this.side == 'sell') {var then_do ='buy';} // }else{
html += '<span>' + 'If profit exceeds' + ': ' + this.take_profit.trig_val + ' '+ then_do + '.</span>'; // result = false;
} // }
if (this.stop_loss.on == 'loss'){ // }
if(this.side == 'buy') {var then_do ='sell';} // }
else if(this.side == 'sell') {var then_do ='buy';} // return result;
html +='<span>' + 'If loss exceeds' + ': ' + this.stop_loss.trig_val + ' '+ then_do + '.</span>'; //}
}
for(let cond of this.conditions){
html += '<span>If ' + cond.on + ' is ' + cond.trig_val + '</span>';
}
html += '</li>';
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;
}
}
class Strategies { class Strategies {
constructor(target_id) { constructor(target_id) {
// The list of strategies. // The list of strategies.
@ -95,21 +44,123 @@ class Strategies {
open_form() { document.getElementById("new_strat_form").style.display = "grid"; } open_form() { document.getElementById("new_strat_form").style.display = "grid"; }
// Call to hide Create new signal dialog. // Call to hide Create new signal dialog.
close_form() { document.getElementById("new_strat_form").style.display = "none"; } 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(){ open_stg_form(){
this.open_form(); this.open_form();
this.fill_field('strat_opt', 'take_profit'); this.fill_field('strat_opt', 'take_profit');
// condition = { on: (signal_name: str), trig_val: (true|false|changed) } }
let cond1 = {on: 'signal1', trig_val:'changed'} clear_innerHTML(el){
// take_profit = {on: ('profit'|'condition'), trig_val: 999} el.innerHTML="";
let take_profit = {on: 'signal2', trig_val: false} }
// stop_loss = {on: ('loss'|'condition'), trig_val: 999} dropDown(name, label, parent, options){
let stop_loss = {on: 'loss', trig_val: '80%' } /* Create a html selection element and append it to a parent element.
let side='buy'; name: name and id of the element.
let conditions = []; //_str = side + condition + take_profit label: text displayed beside the selection list element.
conditions.push(cond1); parent: the html element to append to.
this.strategies.push( new Strategy('take_profit', 'strategy_#1', side, take_profit, stop_loss, conditions) ); options: An array of selection options.
this.update_html(); */
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){
/* 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){ fill_field(field, value){
if (field == 'strat_opt'){ if (field == 'strat_opt'){
@ -117,35 +168,17 @@ class Strategies {
if (value == 'take_profit'){ if (value == 'take_profit'){
// Clear previous content. // Clear previous content.
options.innerHTML=""; this.clear_innerHTML(options);
//Create a drop down for buy/sell option //Create a drop down for buy/sell option
let side_select_label = document.createElement("label"); this.dropDown('trade_in_side','Side:', options, ['buy','sell']);
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 = '<option>buy</option><option>sell</option>';
options.appendChild(side_select_label);
options.appendChild(side_select);
//Create an input for margin trading value. (1X-100X) //Create an input for margin trading value. (1-100)
let margin_label = document.createElement("label"); this.val_input('margin_select', 'Margin:', options, 1,100, 50);
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 a un ordered list to hold the conditions of trading in. // Create a un ordered list to hold the conditions of trading in.
let ul_in_cond = document.createElement('ul'); 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. // Create a submit button for the conditions.
let add_cond_btn = document.createElement('button'); let add_cond_btn = document.createElement('button');
@ -154,116 +187,108 @@ class Strategies {
add_cond_btn.innerHTML = "Add Condition"; add_cond_btn.innerHTML = "Add Condition";
add_cond_btn.onclick = function () { add_cond_btn.onclick = function () {
let li = document.createElement('li'); 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); ul_in_cond.appendChild(li);
}; };
// Add a horizontal rule. // Add a horizontal rule.
let element = document.createElement('hr'); options.appendChild(document.createElement('hr'));
options.appendChild(element);
//Create a drop down for trigger options //Create a drop down for trigger options
let trigger_label = document.createElement("label"); // Get the signal options from the signal instance.
trigger_label.for = 'trigger'; let ops = [];
trigger_label.innerHTML = 'Trigger Signal:'; for (let signal of window.UI.signals.signals) {ops.push(signal.name);}
let trigger = document.createElement("select"); this.dropDown('trigger','Trigger Signal:', options, ops);
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);
//Create a drop down for trigger value. //Create a drop down for trigger value.
let trigVal_label = document.createElement("label"); this.dropDown('trigVal','Trigger Value:', options, ['true', 'false', 'changed']);
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);
// Add the submit btn and the list to the dom. // Add the submit btn and the list to the dom.
options.appendChild(add_cond_btn); options.appendChild(add_cond_btn);
options.appendChild(ul_in_cond); options.appendChild(ul_in_cond);
// Add a horizontal rule. // Add a horizontal rule.
element = document.createElement('hr'); options.appendChild(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;
//Create a drop down for take profit type. //Create a drop down for take profit type.
let prof_typ_label = document.createElement("label"); this.dropDown('prof_typ','Profit type:', options, ['value', 'conditional']);
prof_typ_label.for = 'prof_typ'; // Add and onchange function to show and hide some options.
prof_typ_label.innerHTML = 'Profit type:'; let that = this;
let prof_typ = document.createElement("select"); document.getElementById('prof_typ').onchange= function(){
prof_typ.id = "prof_typ";
prof_typ.name = "prof_typ";
prof_typ.onchange= function(){
if (this.value == 'value'){ if (this.value == 'value'){
prof_value_lbl.style.display = 'inline-block'; that.hideShowTags(['prof_val_lbl','prof_val'], 'show');
profit_val.style.display = 'inline-block'; that.hideShowTags(['prof_trig_lbl', 'prof_trig', 'prof_trigVal_lbl', 'prof_trigVal'], 'hide');
//profit_trig.style.display = 'none';
} }
else if (this.value == 'conditional'){ else if (this.value == 'conditional'){
prof_value_lbl.style.display = 'none'; that.hideShowTags(['prof_val_lbl','prof_val'], 'hide');
profit_val.style.display = 'none'; that.hideShowTags(['prof_trig_lbl', 'prof_trig', 'prof_trigVal_lbl', 'prof_trigVal'], 'show');
//profit_trig.style.display = 'block';
} }
}; };
opt = document.createElement('option'); // Add a line break.
opt.value = 'value'; options.appendChild(document.createElement('br'));
opt.innerHTML = 'value';
prof_typ.appendChild(opt);
opt = document.createElement('option'); // Create an input for take profit value.
opt.value = 'conditional'; this.val_input('prof_val', 'Profit %:', options, 1,100, 50);
opt.innerHTML = 'conditional'; // Set display to visible.
prof_typ.appendChild(opt); this.hideShowTags(['prof_val_lbl','prof_val'], 'show');
// Add profit_type select element to the dom. // Create an input for take profit signal trigger.
options.appendChild(prof_typ_label); // Get the signal options from the signal instance.
options.appendChild(prof_typ); 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'); //Create a drop down for take profit trigger value.
options.appendChild(opt); 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. // Add a line break.
options.appendChild(prof_value_lbl); options.appendChild(document.createElement('br'));
options.appendChild(profit_val); // 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'){ if (value == 'incremental_profits'){
@ -274,14 +299,25 @@ class Strategies {
} }
} }
} }
set_target(){ initialize(){
// This is called after the html document has been parsed. // This is called after the html document has been parsed.
this.target = document.getElementById(this.target_id); 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(){ update_html(){
let strats =''; let strats ='';
let on_click = " window.UI.strats.del(this.value);";
for (let strat of this.strategies){ for (let strat of this.strategies){
strats += strat.print_html(); 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; this.target.innerHTML = strats;
} }

View File

@ -33,6 +33,7 @@ class Comms {
return id; return id;
} }
send_to_app(message_type, data){ 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 })); console.log( JSON.stringify({ message_type: message_type, data : data }));
if (this.connection_open){ if (this.connection_open){
this.app_con.send( JSON.stringify({ message_type: message_type, data : data })); 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. /* On initialization the server will send a list of signals loaded from file.
Forward this to the signals instance.*/ Forward this to the signals instance.*/
window.UI.signals.set_data(msg.data); 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'){ else if (msg.reply =='signal_created'){
/* After the server creates a new signal it will send the details here. /* After the server creates a new signal it will send the details here.

View File

@ -85,8 +85,8 @@ class User_Interface{
window.UI.signals.request_signals(); window.UI.signals.request_signals();
// initialize the alerts instance. // initialize the alerts instance.
window.UI.alerts.set_target(); window.UI.alerts.set_target();
// initialize the alerts instance. // initialize the strategies instance.
window.UI.strats.set_target(); window.UI.strats.initialize();
}); });
} }

View File

@ -58,9 +58,9 @@ class Signals {
// Keep a local record of the signals. // Keep a local record of the signals.
this.signals.push(obj); this.signals.push(obj);
// Define the function that is called when deleting an individual signal. // 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. // create a delete button for every individual signal.
let delete_btn = "<button onclick='" + click_func + "' style='color:red;'>&#10008;</button>"; let delete_btn = '<button onclick="' + click_func + '" style="color:red;">&#10008;</button>';
// Put all the attributes into html elements. // Put all the attributes into html elements.
let signal_name = " <span>" + obj.name + ": </span>"; let signal_name = " <span>" + obj.name + ": </span>";

View File

@ -46,7 +46,7 @@
<div id="strat_opt"></div> <div id="strat_opt"></div>
<div style="grid-column: 1 / span 2; grid-row: 5;"> <div style="grid-column: 1 / span 2; grid-row: 5;">
<button type="button" class="btn cancel" onclick="UI.strats.close_form()">Close</button> <button type="button" class="btn cancel" onclick="UI.strats.close_form()">Close</button>
<button type="button" class="btn next" onclick="UI.strats.next(1)">Next</button> <button type="button" class="btn next" onclick="UI.strats.submit()">Create Strategy</button>
</div> </div>
</div><!----End panel 1---------> </div><!----End panel 1--------->