statusheader on gui

This commit is contained in:
David Brazda
2023-06-06 16:04:47 +02:00
parent 80e264eeaa
commit b32edf7d2b
9 changed files with 222 additions and 15 deletions

View File

@ -297,7 +297,7 @@ def next(data, state: StrategyState):
state.indicators.slope[-1]=slope state.indicators.slope[-1]=slope
#angle je ze slope #angle je ze slope
state.statinds.angle = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=state.bars.time[-slope_lookback], lookbackprice=lookbackprice, minimum_slope=minimum_slope) state.statinds.angle = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=state.bars.time[-slope_lookback], lookbackprice=lookbackprice, minimum_slope=minimum_slope, maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20))
#slope MA vyrovna vykyvy ve slope, dále pracujeme se slopeMA #slope MA vyrovna vykyvy ve slope, dále pracujeme se slopeMA
slope_MA_length = 5 slope_MA_length = 5
@ -333,6 +333,19 @@ def next(data, state: StrategyState):
state.ilog(e=f"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc()) state.ilog(e=f"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc())
#state.indicators.RSI14[-1]=0 #state.indicators.RSI14[-1]=0
def populate_cbar_rsi_indicator():
#CBAR RSI indicator
try:
crsi_length = int(safe_get(state.vars, "crsi_length",14))
source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap
crsi_res = rsi(source, crsi_length)
crsi_value = trunc(crsi_res[-1],3)
state.cbar_indicators.CRSI[-1]=crsi_value
#state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
except Exception as e:
state.ilog(e=f"CRSI {crsi_length=} necháváme 0", message=str(e)+format_exc())
#state.indicators.RSI14[-1]=0
def slope_too_low(): def slope_too_low():
return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope) return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope)
@ -368,7 +381,7 @@ def next(data, state: StrategyState):
state.vars.jevylozeno = 0 state.vars.jevylozeno = 0
state.ilog(e="PB prazdne nastavujeme: neni vylozeno", jevylozeno=state.vars.jevylozeno) state.ilog(e="PB prazdne nastavujeme: neni vylozeno", jevylozeno=state.vars.jevylozeno)
##kdy nenakupovat - tzn. neprojdou nakupy a kdyz uz jsou tak se zrusi ##kdy nesmí být žádné nákupní objednávky - zruší se
def buy_protection_enabled(): def buy_protection_enabled():
dont_buy_when = dict(AND=dict(), OR=dict()) dont_buy_when = dict(AND=dict(), OR=dict())
##add conditions here ##add conditions here
@ -402,12 +415,16 @@ def next(data, state: StrategyState):
def buy_conditions_met(): def buy_conditions_met():
#preconditions #preconditions
dont_buy_when = dict(AND=dict(), OR=dict()) dont_buy_when = dict(AND=dict(), OR=dict())
dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0)
if safe_get(state.vars, "buy_only_on_confirmed",True):
dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0)
#od posledniho vylozeni musi ubehnout N baru #od posledniho vylozeni musi ubehnout N baru
dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (state.vars.last_buysignal_index + safe_get(state.vars, "lastbuy_offset",3)) dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (state.vars.last_buysignal_index + safe_get(state.vars, "lastbuy_offset",3))
dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1) dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1)
dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1) dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1)
#dont_buy_when['buy_protection_enabled'] = buy_protection_enabled() dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
#dont_buy_when['slope_too_low'] = slope_too_low()
dont_buy_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0)) dont_buy_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0))
dont_buy_when['close_rush'] = is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "close_rush",0)) dont_buy_when['close_rush'] = is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "close_rush",0))
dont_buy_when['rsi_is_zero'] = (state.indicators.RSI14[-1] == 0) dont_buy_when['rsi_is_zero'] = (state.indicators.RSI14[-1] == 0)
@ -434,12 +451,23 @@ def next(data, state: StrategyState):
#buy_cond['AND']['rsi_is_rising'] = isrising(state.indicators.RSI14,2) #buy_cond['AND']['rsi_is_rising'] = isrising(state.indicators.RSI14,2)
#buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) #buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
#puvodni buy conditiony #puvodni buy conditiony RSI pod + EMA klesajici
#buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) #buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
#buy_cond["AND"]["ema_trend_is_falling"] = isfalling(state.indicators.ema,state.vars.Trend) #buy_cond["AND"]["ema_trend_is_falling"] = isfalling(state.indicators.ema,state.vars.Trend)
#pouze RSI pod 35 a zadny jiny #pouze RSI nizke a RSI klesa
buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
buy_cond["AND"]["rsi_is_falling"] = isfalling(state.indicators.RSI14,state.vars.Trend)
#buy_cond['crsi_below_crsi_buy_limit'] = state.cbar_indicators.CRSI[-1] < safe_get(state.vars, "crsi_buy_signal_below",30)
#slopME klesa a RSI začalo stoupat
# buy_cond["AND"]["rsi_is_rising2"] = isrising(state.indicators.RSI14,2)
# buy_cond['AND']['slopeMA_falling_Trend'] = isfalling(state.indicators.slopeMA,state.vars.Trend)
# buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
#zkusit jako doplnkovy BUY SIGNAL 3 klesavy cbar RSI pripadne TICK PRICE
result, conditions_met = eval_cond_dict(buy_cond) result, conditions_met = eval_cond_dict(buy_cond)
if result: if result:
@ -484,8 +512,10 @@ def next(data, state: StrategyState):
last_ind_vals[key] = state.cbar_indicators[key][-5:] last_ind_vals[key] = state.cbar_indicators[key][-5:]
return last_ind_vals return last_ind_vals
conf_bar = data['confirmed'] conf_bar = data['confirmed']
state.ilog(e=f"---{data['index']}-{conf_bar}--") last_update_delta = round((float(data['updated']) - state.vars.last_update_time),6) if state.vars.last_update_time != 0 else 0
state.vars.last_update_time = float(data['updated'])
state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}")
#kroky pro CONFIRMED BAR only #kroky pro CONFIRMED BAR only
if conf_bar == 1: if conf_bar == 1:
@ -501,8 +531,11 @@ def next(data, state: StrategyState):
else: else:
#CBAR INDICATOR pro tick price a deltu VOLUME #CBAR INDICATOR pro tick price a deltu VOLUME
populate_cbar_tick_price_indicator() populate_cbar_tick_price_indicator()
populate_cbar_rsi_indicator()
#SPOLECNA LOGIKA - bar indikatory muzeme populovat kazdy tick (dobre pro RT GUI), ale uklada se stejne az pri confirmu #SPOLECNA LOGIKA - bar indikatory muzeme populovat kazdy tick (dobre pro RT GUI), ale uklada se stejne az pri confirmu
populate_ema_indicator() populate_ema_indicator()
populate_slope_indicator() populate_slope_indicator()
populate_rsi_indicator() populate_rsi_indicator()
@ -526,9 +559,11 @@ def init(state: StrategyState):
state.vars.last_tick_volume = 0 state.vars.last_tick_volume = 0
state.vars.next_new = 0 state.vars.next_new = 0
state.vars.last_buysignal_index = 0 state.vars.last_buysignal_index = 0
state.vars.last_update_time = 0
#state.cbar_indicators['ivwap'] = [] #state.cbar_indicators['ivwap'] = []
state.cbar_indicators['tick_price'] = [] state.cbar_indicators['tick_price'] = []
state.cbar_indicators['tick_volume'] = [] state.cbar_indicators['tick_volume'] = []
state.cbar_indicators['CRSI'] = []
state.indicators['ema'] = [] state.indicators['ema'] = []
state.indicators['slope'] = [] state.indicators['slope'] = []
state.indicators['slopeMA'] = [] state.indicators['slopeMA'] = []

View File

@ -18,6 +18,7 @@ from tinydb import TinyDB, Query, where
from tinydb.operations import set from tinydb.operations import set
import json import json
from numpy import ndarray from numpy import ndarray
import pandas as pd
from traceback import format_exc from traceback import format_exc
from datetime import timedelta, time from datetime import timedelta, time
@ -415,8 +416,50 @@ def get_trade_history(symbol: str, timestamp_from: float, timestamp_to:float):
except Exception as e: except Exception as e:
return (-2, f"problem {e}") return (-2, f"problem {e}")
def populate_metrics_output_directory(strat: StrategyInstance):
"""
WIP
Spocte zakladni metriky pred ulozenim do archivu
"""
#open_orders to dataset
oo_dict = AttributeDict(orderid=[],submitted_at=[],symbol=[],side=[],order_type=[],qty=[],limit_price=[],status=[])
for t in strat.open_orders:
oo_dict.orderid.append(str(t.id))
oo_dict.submitted_at.append(t.submitted_at)
oo_dict.symbol.append(t.symbol)
oo_dict.side.append(t.side)
oo_dict.qty.append(t.qty)
oo_dict.order_type.append(t.order_type)
oo_dict.limit_price.append(t.limit_price)
oo_dict.status.append(t.status)
open_orders_df = pd.DataFrame(oo_dict)
open_orders_df = open_orders_df.set_index('submitted_at', drop=False)
#trades to dataset
trade_dict = AttributeDict(orderid=[],timestamp=[],symbol=[],side=[],order_type=[],qty=[],price=[],position_qty=[],value=[],cash=[],pos_avg_price=[])
for t in strat.trades:
trade_dict.orderid.append(str(t.order.id))
trade_dict.timestamp.append(t.timestamp)
trade_dict.symbol.append(t.order.symbol)
trade_dict.side.append(t.order.side)
trade_dict.qty.append(t.qty)
trade_dict.price.append(t.price)
trade_dict.position_qty.append(t.position_qty)
trade_dict.value.append(t.value)
trade_dict.cash.append(t.cash)
trade_dict.order_type.append(t.order.order_type)
trade_dict.pos_avg_price.append(t.pos_avg_price)
trade_df = pd.DataFrame(trade_dict)
trade_df = trade_df.set_index('timestamp',drop=False)
#archives runner and details #archives runner and details
def archive_runner(runner: Runner, strat: StrategyInstance): def archive_runner(runner: Runner, strat: StrategyInstance):
#results_metrics = dict()
print("inside archive_runner") print("inside archive_runner")
try: try:
if strat.bt is not None: if strat.bt is not None:
@ -434,6 +477,13 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT, BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT,
BT_FILL_CONDITION_SELL_LIMIT=BT_FILL_CONDITION_SELL_LIMIT)) BT_FILL_CONDITION_SELL_LIMIT=BT_FILL_CONDITION_SELL_LIMIT))
#WIP
#populate result metrics dictionary (max drawdown etc.)
#list of maximum positions (2000 2x, 1800 x 1, 900 x 1, 100 x 20)
#list of most profitable trades (pos,avgp + cena)
#nejspis prevedeni na dataset a report nad datasetem
#results_metrics = populate_metrics(strat)
runArchive: RunArchive = RunArchive(id = runner.id, runArchive: RunArchive = RunArchive(id = runner.id,
strat_id = runner.strat_id, strat_id = runner.strat_id,
name=runner.run_name, name=runner.run_name,

View File

@ -67,6 +67,7 @@
<pre id="statusSettings" class="headerItem"></pre> <pre id="statusSettings" class="headerItem"></pre>
</div> </div>
</div> </div>
<div id="statusHeaderTool"></div>
<div id="chart" style="display: None; float: left; "></div> <div id="chart" style="display: None; float: left; "></div>
<div class="legend" id="legend"></div> <div class="legend" id="legend"></div>
<div id="msgContainer"> <div id="msgContainer">
@ -236,15 +237,15 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="editnote" class="form-label">note</label> <label for="editnote" class="form-label">note</label>
<textarea class="form-control" rows="2" id="editnote" name="note"></textarea> <textarea class="form-control" rows="3" id="editnote" name="note"></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="stratvars" class="form-label">Stratvars</label> <label for="stratvars" class="form-label">Stratvars</label>
<textarea class="form-control" rows="4" id="editstratvars" name="stratvars"></textarea> <textarea class="form-control" rows="8" id="editstratvars" name="stratvars"></textarea>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="strat_json" class="form-label">Strat JSON</label> <label for="strat_json" class="form-label">Strat JSON</label>
<textarea class="form-control" rows="4" id="editstratjson" name="stratjson"></textarea> <textarea class="form-control" rows="6" id="editstratjson" name="stratjson"></textarea>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">

View File

@ -639,7 +639,7 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
toolTip.innerHTML += `<pre>${JSON.stringify(tradeDetails.get(param.time),null,2)}</pre><div>${price.toFixed(3)}</div>`; toolTip.innerHTML += `<pre>${JSON.stringify(tradeDetails.get(param.time),null,2)}</pre><div>${price.toFixed(3)}</div>`;
console.log("toolTip.innerHTML",toolTip.innerHTML) //console.log("toolTip.innerHTML",toolTip.innerHTML)
//inspirace //inspirace
// toolTip.innerHTML = `<div style="color: ${'#2962FF'}">Apple Inc.</div><div style="font-size: 24px; margin: 4px 0px; color: ${'black'}"> // toolTip.innerHTML = `<div style="color: ${'#2962FF'}">Apple Inc.</div><div style="font-size: 24px; margin: 4px 0px; color: ${'black'}">

View File

@ -251,6 +251,10 @@ var archiveRecords =
targets: [5,6], targets: [5,6],
render: function ( data, type, row ) { render: function ( data, type, row ) {
now = new Date(data) now = new Date(data)
if (type == "sort") {
return new Date(data).getTime();
}
if (isToday(now)) { if (isToday(now)) {
//return local time only //return local time only
return 'dnes ' + format_date(data,false,true) return 'dnes ' + format_date(data,false,true)
@ -267,8 +271,12 @@ var archiveRecords =
{ {
targets: [9,10], targets: [9,10],
render: function ( data, type, row ) { render: function ( data, type, row ) {
if (type == "sort") {
return new Date(data).getTime();
}
//console.log(data)
//market datetime //market datetime
return format_date(data, true) return data ? format_date(data, true) : data
}, },
}, },
{ {

View File

@ -118,6 +118,16 @@ function connect(event) {
//pre.appendChild(stLine) //pre.appendChild(stLine)
//line.appendChild(pre) //line.appendChild(pre)
lines.appendChild(line) lines.appendChild(line)
//addline to statusheader if set
for (const [key, value] of Object.entries(statusBarConfig)) {
if (logLine.event.includes(value)) {
console.log("found", value, key, logLine.event)
document.getElementById("status"+key).textContent = logLine.event + (logLine.message ? " - " + logLine.message : "")
document.getElementById("status"+key).title = JSON.stringify(logLine,null,2);
}
}
}); });
$('#messages').animate({ $('#messages').animate({
scrollTop: $('#lines')[0].scrollHeight}, 2000); scrollTop: $('#lines')[0].scrollHeight}, 2000);

View File

@ -6,6 +6,7 @@ function populate_real_time_chart() {
intitialize_candles() intitialize_candles()
initialize_vwap() initialize_vwap()
initialize_volume() initialize_volume()
initialize_statusheader()
chart.subscribeClick(param => { chart.subscribeClick(param => {
//display timestamp in trade-timestamp input field //display timestamp in trade-timestamp input field

View File

@ -8,6 +8,12 @@ var verticalSeries=null
var candlestickSeries = null var candlestickSeries = null
var volumeSeries = null var volumeSeries = null
var vwapSeries = null var vwapSeries = null
var statusBarConfig = JSON.parse(localStorage.getItem("statusBarConfig"));
if (statusBarConfig == null) {
statusBarConfig = {}
}
const sorter = (a, b) => a.time > b.time ? 1 : -1; const sorter = (a, b) => a.time > b.time ? 1 : -1;
@ -24,13 +30,89 @@ indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, pri
{name: "emaSlow", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false}, {name: "emaSlow", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
{name: "emaFast", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false}, {name: "emaFast", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
{name: "RSI14", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "RSI14", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
{name: "RSI5", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "CRSI", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
{name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
{name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
{name: "ppo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "ppo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
{name: "stoch2", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "stoch2", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
{name: "stoch1", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},] {name: "stoch1", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},]
function initialize_statusheader() {
var rows = 2;
var columns = 4;
console.log(JSON.stringify(statusBarConfig))
// Create the grid table
var gridTable = document.getElementById('statusHeaderTool');
var cntid = 0
for (var i = 0; i < rows; i++) {
var row = document.createElement('tr');
for (var j = 0; j < columns; j++) {
cntid++
var cell = document.createElement('td');
cell.className = "statustd";
var div = document.createElement('div');
var cellid = "status" + cntid
div.id = cellid;
var input = document.createElement('input');
input.id = cntid;
input.type = 'text';
input.style.display = "none";
if (statusBarConfig !== null && statusBarConfig[cntid]) {
//div.style.backgroundColor = 'red';
div.textContent = "set";
input.value = statusBarConfig[cntid];
}
cell.addEventListener('click', function() {
var inputValue = this.querySelector('input').value;
//this.querySelector('div').textContent = inputValue;
this.querySelector('div').style.display = 'none';
this.querySelector('input').style.display = 'block';
this.querySelector('input').focus();
});
input.addEventListener('blur', function() {
this.style.display = 'none';
//this.previousElementSibling.textContent = inputValue;
this.previousElementSibling.style.display = 'block';
if (this.value !== "") {
statusBarConfig[this.id] = this.value;
}
else {
delete statusBarConfig[this.id]
}
if (statusBarConfig[this.id]) {
this.previousElementSibling.textContent = "set"
//this.previousElementSibling.style.backgroundColor = 'red';
}
else {
this.previousElementSibling.style.backgroundColor = 'transparent';
}
console.log("potom", JSON.stringify(statusBarConfig))
localStorage.setItem("statusBarConfig", JSON.stringify(statusBarConfig));
});
cell.appendChild(div);
cell.appendChild(input);
row.appendChild(cell);
}
gridTable.appendChild(row);
}
}
function get_ind_config(indName) { function get_ind_config(indName) {
const i = indConfig.findIndex(e => e.name === indName); const i = indConfig.findIndex(e => e.name === indName);
if (i>-1) if (i>-1)

View File

@ -224,7 +224,7 @@ html {
position: absolute; position: absolute;
color: #050505; color: #050505;
left: 115px; left: 115px;
top: 115px; top: 195px;
z-index: 1; z-index: 1;
font-size: 12px; font-size: 12px;
line-height: 18px; line-height: 18px;
@ -315,6 +315,26 @@ pre {
width: max-content; width: max-content;
} }
.statustd {
width: 95px;
height: 25px;
border: 1px solid black;
text-align: center;
}
#statusHeaderTool {
margin-left: 0px;
font-size: normal;
/* font-weight: bold; */
display: flex;
/* background-color: #dfe4e6; */
/* color: white; */
padding: 1px;
padding-left: 5px;
width: max-content;
height: 95px;
}
.headerItem { .headerItem {
padding-right: 30px; padding-right: 30px;
} }