statusheader on gui
This commit is contained in:
@ -297,7 +297,7 @@ def next(data, state: StrategyState):
|
||||
state.indicators.slope[-1]=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_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.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():
|
||||
return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope)
|
||||
|
||||
@ -368,7 +381,7 @@ def next(data, state: StrategyState):
|
||||
state.vars.jevylozeno = 0
|
||||
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():
|
||||
dont_buy_when = dict(AND=dict(), OR=dict())
|
||||
##add conditions here
|
||||
@ -402,12 +415,16 @@ def next(data, state: StrategyState):
|
||||
def buy_conditions_met():
|
||||
#preconditions
|
||||
dont_buy_when = dict(AND=dict(), OR=dict())
|
||||
|
||||
|
||||
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
|
||||
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['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['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)
|
||||
@ -434,12 +451,23 @@ def next(data, state: StrategyState):
|
||||
#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)
|
||||
|
||||
#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"]["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_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)
|
||||
if result:
|
||||
@ -485,7 +513,9 @@ def next(data, state: StrategyState):
|
||||
return last_ind_vals
|
||||
|
||||
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
|
||||
if conf_bar == 1:
|
||||
@ -501,8 +531,11 @@ def next(data, state: StrategyState):
|
||||
else:
|
||||
#CBAR INDICATOR pro tick price a deltu VOLUME
|
||||
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
|
||||
|
||||
|
||||
populate_ema_indicator()
|
||||
populate_slope_indicator()
|
||||
populate_rsi_indicator()
|
||||
@ -526,9 +559,11 @@ def init(state: StrategyState):
|
||||
state.vars.last_tick_volume = 0
|
||||
state.vars.next_new = 0
|
||||
state.vars.last_buysignal_index = 0
|
||||
state.vars.last_update_time = 0
|
||||
#state.cbar_indicators['ivwap'] = []
|
||||
state.cbar_indicators['tick_price'] = []
|
||||
state.cbar_indicators['tick_volume'] = []
|
||||
state.cbar_indicators['CRSI'] = []
|
||||
state.indicators['ema'] = []
|
||||
state.indicators['slope'] = []
|
||||
state.indicators['slopeMA'] = []
|
||||
|
||||
@ -18,6 +18,7 @@ from tinydb import TinyDB, Query, where
|
||||
from tinydb.operations import set
|
||||
import json
|
||||
from numpy import ndarray
|
||||
import pandas as pd
|
||||
from traceback import format_exc
|
||||
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:
|
||||
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
|
||||
def archive_runner(runner: Runner, strat: StrategyInstance):
|
||||
#results_metrics = dict()
|
||||
print("inside archive_runner")
|
||||
try:
|
||||
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_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,
|
||||
strat_id = runner.strat_id,
|
||||
name=runner.run_name,
|
||||
|
||||
@ -67,6 +67,7 @@
|
||||
<pre id="statusSettings" class="headerItem"></pre>
|
||||
</div>
|
||||
</div>
|
||||
<div id="statusHeaderTool"></div>
|
||||
<div id="chart" style="display: None; float: left; "></div>
|
||||
<div class="legend" id="legend"></div>
|
||||
<div id="msgContainer">
|
||||
@ -236,15 +237,15 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<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 class="form-group">
|
||||
<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 class="form-group">
|
||||
<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 class="modal-footer">
|
||||
|
||||
@ -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>`;
|
||||
|
||||
console.log("toolTip.innerHTML",toolTip.innerHTML)
|
||||
//console.log("toolTip.innerHTML",toolTip.innerHTML)
|
||||
|
||||
//inspirace
|
||||
// toolTip.innerHTML = `<div style="color: ${'#2962FF'}">Apple Inc.</div><div style="font-size: 24px; margin: 4px 0px; color: ${'black'}">
|
||||
|
||||
@ -251,6 +251,10 @@ var archiveRecords =
|
||||
targets: [5,6],
|
||||
render: function ( data, type, row ) {
|
||||
now = new Date(data)
|
||||
if (type == "sort") {
|
||||
return new Date(data).getTime();
|
||||
}
|
||||
|
||||
if (isToday(now)) {
|
||||
//return local time only
|
||||
return 'dnes ' + format_date(data,false,true)
|
||||
@ -267,8 +271,12 @@ var archiveRecords =
|
||||
{
|
||||
targets: [9,10],
|
||||
render: function ( data, type, row ) {
|
||||
if (type == "sort") {
|
||||
return new Date(data).getTime();
|
||||
}
|
||||
//console.log(data)
|
||||
//market datetime
|
||||
return format_date(data, true)
|
||||
return data ? format_date(data, true) : data
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -118,6 +118,16 @@ function connect(event) {
|
||||
//pre.appendChild(stLine)
|
||||
//line.appendChild(pre)
|
||||
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({
|
||||
scrollTop: $('#lines')[0].scrollHeight}, 2000);
|
||||
|
||||
@ -6,6 +6,7 @@ function populate_real_time_chart() {
|
||||
intitialize_candles()
|
||||
initialize_vwap()
|
||||
initialize_volume()
|
||||
initialize_statusheader()
|
||||
|
||||
chart.subscribeClick(param => {
|
||||
//display timestamp in trade-timestamp input field
|
||||
|
||||
@ -8,6 +8,12 @@ var verticalSeries=null
|
||||
var candlestickSeries = null
|
||||
var volumeSeries = 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;
|
||||
|
||||
@ -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: "emaFast", titlevisible: true, embed: true, display: true, priceScaleId: "right", 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: "apo", 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: "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) {
|
||||
const i = indConfig.findIndex(e => e.name === indName);
|
||||
if (i>-1)
|
||||
|
||||
@ -224,7 +224,7 @@ html {
|
||||
position: absolute;
|
||||
color: #050505;
|
||||
left: 115px;
|
||||
top: 115px;
|
||||
top: 195px;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
@ -315,6 +315,26 @@ pre {
|
||||
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 {
|
||||
padding-right: 30px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user