angle scope implemented

This commit is contained in:
David Brazda
2023-04-19 20:47:03 +02:00
parent 6524b228c4
commit bf98a4925b
12 changed files with 185 additions and 101 deletions

View File

@ -32,10 +32,10 @@ Více nakupuje oproti Dokupovaci. Tady vylozime a nakupujeme 5 pozic hned. Pri d
Do budoucna vice ridit nakupy pri klesani - napr. vyložení jen 2-3 pozic a další dokupy až po triggeru. Do budoucna vice ridit nakupy pri klesani - napr. vyložení jen 2-3 pozic a další dokupy až po triggeru.
# #
""" """
stratvars = AttributeDict(maxpozic = 250, stratvars = AttributeDict(maxpozic = 400,
chunk = 10, chunk = 10,
MA = 3, MA = 2,
Trend = 3, Trend = 2,
profit = 0.02, profit = 0.02,
lastbuyindex=-6, lastbuyindex=-6,
pendingbuys={}, pendingbuys={},
@ -47,8 +47,9 @@ stratvars = AttributeDict(maxpozic = 250,
blockbuy = 0, blockbuy = 0,
ticks2reset = 0.04, ticks2reset = 0.04,
consolidation_bar_count = 10, consolidation_bar_count = 10,
slope_lookback = 20, slope_lookback = 300,
minimum_slope = -0.23 lookback_offset = 20,
minimum_slope = -0.05,
) )
##toto rozparsovat a strategii spustit stejne jako v main ##toto rozparsovat a strategii spustit stejne jako v main
toml_string = """ toml_string = """
@ -108,6 +109,7 @@ def next(data, state: StrategyState):
last_price = price2dec(state.interface.get_last_price(state.symbol)) last_price = price2dec(state.interface.get_last_price(state.symbol))
#profit = float(state.vars.profit) #profit = float(state.vars.profit)
price = last_price price = last_price
state.ilog(e="BUY Vykladame", msg="first price"+str(price) + "pozic:"+str(vykladka), curve=curve, ema=state.indicators.ema[-1], trend=state.vars.Trend, price=price, vykladka=vykladka)
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci ##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
state.buy_l(price=price, size=qty) state.buy_l(price=price, size=qty)
print("prvni limitka na aktuální cenu. Další podle křivky", price, qty) print("prvni limitka na aktuální cenu. Další podle křivky", price, qty)
@ -140,7 +142,6 @@ def next(data, state: StrategyState):
## slope vyresi rychlé sesupy - jeste je treba podchytit pomalejsi sesupy ## slope vyresi rychlé sesupy - jeste je treba podchytit pomalejsi sesupy
slope = 99 slope = 99
#minimum slope disabled if -1 #minimum slope disabled if -1
@ -156,15 +157,30 @@ def next(data, state: StrategyState):
slope_lookback = int(state.vars.slope_lookback) slope_lookback = int(state.vars.slope_lookback)
minimum_slope = float(state.vars.minimum_slope) minimum_slope = float(state.vars.minimum_slope)
if len(state.bars.close) > slope_lookback: if len(state.bars.close) > slope_lookback + state.vars.lookback_offset:
#slope = ((state.indicators.ema[-1] - state.indicators.ema[-slope_lookback])/slope_lookback)*100
#PUVODNI slope = ((state.bars.close[-1] - state.bars.close[-slope_lookback])/slope_lookback)*100 #SLOPE INDICATOR POPULATION
slope = ((state.bars.close[-1] - state.bars.close[-slope_lookback])/state.bars.close[-slope_lookback])*100 #úhel stoupání a klesání vyjádřený mezi -1 až 1
#roc = ((state.indicators.ema[-1] - state.indicators.ema[-roc_lookback])/state.indicators.ema[-roc_lookback])*100 #pravý bod přímky je aktuální cena, levý je průměr X(lookback offset) starších hodnot od slope_lookback.
#obsahuje statický indikátor pro vizualizaci
array_od = slope_lookback + state.vars.lookback_offset
array_do = slope_lookback
lookbackprice_array = state.bars.vwap[-array_od:-array_do]
#obycejný prumer hodnot
lookbackprice = sum(lookbackprice_array)/state.vars.lookback_offset
#výpočet úhlu
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
state.indicators.slope.append(slope) state.indicators.slope.append(slope)
state.statinds.angle = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=state.bars.time[-slope_lookback], lookbackprice=lookbackprice)
#state.indicators.roc.append(roc) #state.indicators.roc.append(roc)
print("slope", state.indicators.slope[-5:]) print("slope", state.indicators.slope[-5:])
#ic(state.indicators.roc[-5:]) state.ilog(e="Slope "+str(slope), msg="lookback price:"+str(lookbackprice), lookbackoffset=state.vars.lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-5:])
else:
state.ilog(e="Slope - not enough data", slope_lookback=slope_lookback)
except Exception as e: except Exception as e:
print("Exception in NEXT Indicator section", str(e)) print("Exception in NEXT Indicator section", str(e))
state.ilog(e="EXCEPTION", msg="Exception in NEXT Indicator section" + str(e)) state.ilog(e="EXCEPTION", msg="Exception in NEXT Indicator section" + str(e))
@ -177,7 +193,7 @@ def next(data, state: StrategyState):
##CONSOLIDATION PART kazdy Nty bar dle nastaveni ##CONSOLIDATION PART kazdy Nty bar dle nastaveni
if int(data["index"])%int(state.vars.consolidation_bar_count) == 0: if int(data["index"])%int(state.vars.consolidation_bar_count) == 0:
print("***Consolidation ENTRY***") print("***Consolidation ENTRY***")
state.ilog(e="Konzolidujeme") state.ilog(e="***Konzolidujeme")
orderlist = state.interface.get_open_orders(symbol=state.symbol, side=None) orderlist = state.interface.get_open_orders(symbol=state.symbol, side=None)
#print(orderlist) #print(orderlist)
@ -198,11 +214,11 @@ def next(data, state: StrategyState):
if o.side == OrderSide.BUY: if o.side == OrderSide.BUY:
pendingbuys_new[str(o.id)]=float(o.limit_price) pendingbuys_new[str(o.id)]=float(o.limit_price)
state.ilog(e="Konzolidace", limitka_old=str(limitka_old), limitka_new=str(state.vars.limitka), limitka_new_price=state.vars.limitka_price) state.ilog(e="Konzolidace limitky", msg="limitka stejna?:"+str((str(limitka_old)==str(state.vars.limitka))), limitka_old=str(limitka_old), limitka_new=str(state.vars.limitka), limitka_new_price=state.vars.limitka_price)
#neni limitka, ale mela by byt - vytváříme ji #neni limitka, ale mela by byt - vytváříme ji
if state.positions > 0 and state.vars.limitka is None: if state.positions > 0 and state.vars.limitka is None:
state.ilog(e="Neni limitka, ale mela by být.") state.ilog(e="Limitka neni, ale mela by být.")
price=price2dec(float(state.avgp)+state.vars.profit) price=price2dec(float(state.avgp)+state.vars.profit)
state.vars.limitka = asyncio.run(state.interface.sell_l(price=price, size=state.positions)) state.vars.limitka = asyncio.run(state.interface.sell_l(price=price, size=state.positions))
state.vars.limitka_price = price state.vars.limitka_price = price
@ -224,7 +240,7 @@ def next(data, state: StrategyState):
else: else:
state.vars.jevylozeno = 0 state.vars.jevylozeno = 0
print("NEW jevylozeno", state.vars.jevylozeno) print("NEW jevylozeno", state.vars.jevylozeno)
state.ilog(e="Nove jevyloze", jevylozeno=state.vars.jevylozeno) state.ilog(e="Nove jevylozeno", msg=state.vars.jevylozeno)
#print(limitka) #print(limitka)
#print(pendingbuys_new) #print(pendingbuys_new)
@ -233,25 +249,25 @@ def next(data, state: StrategyState):
#print(len(pendingbuys_new)) #print(len(pendingbuys_new))
#print(jevylozeno) #print(jevylozeno)
print("***CONSOLIDATION EXIT***") print("***CONSOLIDATION EXIT***")
state.ilog(e="***Konzolidace konec")
else: else:
state.ilog(e="No time for consolidation", msg=data["index"])
print("no time for consolidation", data["index"]) print("no time for consolidation", data["index"])
#HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru #HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru
lp = state.interface.get_last_price(symbol=state.symbol) lp = state.interface.get_last_price(symbol=state.symbol)
state.ilog(e="ITER_ENTRY", last_price=lp, stratvars=state.vars) state.ilog(e="ENTRY", msg="AVGP:"+str(state.avgp)+ "POS:" +str(state.positions), last_price=lp, stratvars=state.vars)
#SLOPE ANGLE PROTECTION #SLOPE ANGLE PROTECTION
state.ilog(e="SLOPE", curr_slope=slope, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-5:])
if slope < minimum_slope: if slope < minimum_slope:
print("OCHRANA SLOPE TOO HIGH") print("OCHRANA SLOPE TOO HIGH")
state.ilog(e="SLOPE_EXCEEDED") state.ilog(e="Slope too high "+str(slope))
if len(state.vars.pendingbuys)>0: if len(state.vars.pendingbuys)>0:
print("CANCEL PENDINGBUYS") print("CANCEL PENDINGBUYS")
ic(state.vars.pendingbuys) ic(state.vars.pendingbuys)
res = asyncio.run(state.cancel_pending_buys()) res = asyncio.run(state.cancel_pending_buys())
ic(state.vars.pendingbuys) ic(state.vars.pendingbuys)
state.ilog(e="Rusime pendingbuyes", pb=state.vars.pendingbuys) state.ilog(e="Rusime pendingbuyes", pb=state.vars.pendingbuys, res=res)
print("slope", slope) print("slope", slope)
print("min slope", minimum_slope) print("min slope", minimum_slope)
@ -264,7 +280,6 @@ def next(data, state: StrategyState):
ic(state.time) ic(state.time)
#zatim vykladame full #zatim vykladame full
#positions = int(int(state.vars.maxpozic)/int(state.vars.chunk)) #positions = int(int(state.vars.maxpozic)/int(state.vars.chunk))
state.ilog(e="BUY SIGNAL", ema=state.indicators.ema[-1], trend=state.vars.Trend)
vyloz() vyloz()
## testuje aktualni cenu od nejvyssi visici limitky ## testuje aktualni cenu od nejvyssi visici limitky
@ -281,10 +296,9 @@ def next(data, state: StrategyState):
maxprice = max(state.vars.pendingbuys.values()) maxprice = max(state.vars.pendingbuys.values())
print("max cena v orderbuys", maxprice) print("max cena v orderbuys", maxprice)
if state.interface.get_last_price(state.symbol) > float(maxprice) + state.vars.ticks2reset: if state.interface.get_last_price(state.symbol) > float(maxprice) + state.vars.ticks2reset:
print("ujelo to vice nez o " + str(state.vars.ticks2reset) + ", rusime limit buye")
state.ilog(e="Ujelo to o více " + str(state.vars.ticks2reset), msg="rusime PB buye")
##TODO toto nejak vymyslet - duplikovat? ##TODO toto nejak vymyslet - duplikovat?
res = asyncio.run(state.cancel_pending_buys()) res = asyncio.run(state.cancel_pending_buys())
state.ilog(e="UJELO to o více " + str(state.vars.ticks2reset), msg="zrusene pb buye", pb=state.vars.pendingbuys)
#PENDING BUYS SPENT - PART #PENDING BUYS SPENT - PART
@ -336,6 +350,9 @@ def init(state: StrategyState):
print("INIT v main",state.name) print("INIT v main",state.name)
state.indicators['ema'] = [] state.indicators['ema'] = []
state.indicators['slope'] = [] state.indicators['slope'] = []
#static indicators - those not series based
state.statinds['angle'] = {}
#state.indicators['roc'] = [] #state.indicators['roc'] = []
#state.ilog(e="INIT", stratvars=state.vars) #state.ilog(e="INIT", stratvars=state.vars)
@ -351,15 +368,15 @@ def main():
name = os.path.basename(__file__) name = os.path.basename(__file__)
se = Event() se = Event()
pe = Event() pe = Event()
s = StrategyOrderLimitVykladaci(name = name, symbol = "BAC", account=Account.ACCOUNT2, next=next, init=init, stratvars=stratvars, open_rush=10, close_rush=0, pe=pe, se=se) s = StrategyOrderLimitVykladaci(name = name, symbol = "BAC", account=Account.ACCOUNT1, next=next, init=init, stratvars=stratvars, open_rush=10, close_rush=0, pe=pe, se=se)
s.set_mode(mode = Mode.BT, s.set_mode(mode = Mode.BT,
debug = False, debug = False,
start = datetime(2023, 4, 10, 9, 30, 0, 0, tzinfo=zoneNY), start = datetime(2023, 4, 14, 10, 42, 0, 0, tzinfo=zoneNY),
end = datetime(2023, 4, 10, 9, 35, 0, 0, tzinfo=zoneNY), end = datetime(2023, 4, 14, 14, 35, 0, 0, tzinfo=zoneNY),
cash=100000) cash=100000)
#na sekundovem baru nezaokrouhlovat MAcko #na sekundovem baru nezaokrouhlovat MAcko
s.add_data(symbol="BAC",rectype=RecordType.BAR,timeframe=5,minsize=100,update_ltp=True,align=StartBarAlign.ROUND,mintick=0, exthours=True) s.add_data(symbol="BAC",rectype=RecordType.BAR,timeframe=2,minsize=100,update_ltp=True,align=StartBarAlign.ROUND,mintick=0, exthours=False)
#s.add_data(symbol="C",rectype=RecordType.BAR,timeframe=1,filters=None,update_ltp=True,align=StartBarAlign.ROUND,mintick=0) #s.add_data(symbol="C",rectype=RecordType.BAR,timeframe=1,filters=None,update_ltp=True,align=StartBarAlign.ROUND,mintick=0)
s.start() s.start()

View File

@ -16,30 +16,6 @@
<body> <body>
<div id="main" class="mainConteiner flex-container"> <div id="main" class="mainConteiner flex-container">
<div id="chartContainer" class="flex-items"> <div id="chartContainer" class="flex-items">
<div class="line">
<div data-toggle="collapse" data-target="#rec1">12233 <strong>Event</strong></div>
<div id="rec1" class="collapse">
Detaila mozna structured
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
</div>
<div class="line">
<div data-toggle="collapse" data-target="#rec2">12233 <strong>Event</strong></div>
<div id="rec2" class="collapse">
Detaila mozna structured
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
</div>
<h4>Status: <span id="status">Not connected</span></h4> <h4>Status: <span id="status">Not connected</span></h4>
<div id="formular"> <div id="formular">
<form action=""> <form action="">
@ -287,6 +263,10 @@
<label for="cash" class="control-label">cash</label> <label for="cash" class="control-label">cash</label>
<input type="number" class="form-control" id="cash" name="cash" placeholder="cash" value="100000"> <input type="number" class="form-control" id="cash" name="cash" placeholder="cash" value="100000">
</div> </div>
<div class="form-group">
<label for="cash" class="control-label">Subscribe for RT</label>
<input type="checkbox" class="form-control" id="subscribe" name="subscribe">
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<!--<input type="hidden" name="id" id="id" />--> <!--<input type="hidden" name="id" id="id" />-->

View File

@ -29,7 +29,7 @@ const vwapSeries = chart.addLineSeries({
lastValueVisible: false lastValueVisible: false
}) })
chart.timeScale().fitContent(); //chart.timeScale().fitContent();
//TBD dynamicky zobrazovat vsechny indikatory //TBD dynamicky zobrazovat vsechny indikatory
//document.getElementById('chart').style.display = 'inline-block'; //document.getElementById('chart').style.display = 'inline-block';

View File

@ -399,6 +399,7 @@ $("#runModal").on('submit','#runForm', function(event){
localStorage.setItem("debug", $('#debug').val()); localStorage.setItem("debug", $('#debug').val());
event.preventDefault(); event.preventDefault();
$('#run').attr('disabled','disabled'); $('#run').attr('disabled','disabled');
var formData = $(this).serializeJSON(); var formData = $(this).serializeJSON();
//rename runid to id //rename runid to id
Object.defineProperty(formData, "id", Object.getOwnPropertyDescriptor(formData, "runid")); Object.defineProperty(formData, "id", Object.getOwnPropertyDescriptor(formData, "runid"));
@ -416,6 +417,12 @@ $("#runModal").on('submit','#runForm', function(event){
contentType: "application/json", contentType: "application/json",
data: jsonString, data: jsonString,
success:function(data){ success:function(data){
//pokud mame subscribnuto na RT
if ($('#subscribe').prop('checked')) {
//subscribe input value gets id of current runner
$('#runnerId').val($('#runid').val());
$( "#bt-conn" ).trigger( "click" );
}
$('#runForm')[0].reset(); $('#runForm')[0].reset();
window.$('#runModal').modal('hide'); window.$('#runModal').modal('hide');
$('#run').attr('disabled', false); $('#run').attr('disabled', false);

View File

@ -2,8 +2,11 @@ const momentumIndicatorNames = ["roc", "slope"]
var indList = [] var indList = []
var pbiList = [] var pbiList = []
var ws = null; var ws = null;
var logcnt = 0
var positionsPriceLine = null var positionsPriceLine = null
var limitkaPriceLine = null var limitkaPriceLine = null
var angleSeries = 1
function connect(event) { function connect(event) {
var runnerId = document.getElementById("runnerId") var runnerId = document.getElementById("runnerId")
try { try {
@ -21,7 +24,7 @@ function connect(event) {
ws.onmessage = function(event) { ws.onmessage = function(event) {
var parsed_data = JSON.parse(event.data) var parsed_data = JSON.parse(event.data)
console.log(JSON.stringify(parsed_data)) //console.log(JSON.stringify(parsed_data))
//check received data and display lines //check received data and display lines
if (parsed_data.hasOwnProperty("bars")) { if (parsed_data.hasOwnProperty("bars")) {
@ -38,6 +41,7 @@ function connect(event) {
} }
if (parsed_data.hasOwnProperty("bars")) { if (parsed_data.hasOwnProperty("bars")) {
console.log("mame bary")
var bar = parsed_data.bars var bar = parsed_data.bars
candlestickSeries.update(bar); candlestickSeries.update(bar);
volumeSeries.update({ volumeSeries.update({
@ -53,7 +57,7 @@ function connect(event) {
//loglist //loglist
if (parsed_data.hasOwnProperty("iter_log")) { if (parsed_data.hasOwnProperty("iter_log")) {
iterLogList = parsed_data.iter_log iterLogList = parsed_data.iter_log
console.log("Incoming logline object") //console.log("Incoming logline object")
var lines = document.getElementById('lines') var lines = document.getElementById('lines')
var line = document.createElement('div') var line = document.createElement('div')
@ -63,21 +67,38 @@ function connect(event) {
lines.appendChild(line) lines.appendChild(line)
iterLogList.forEach((logLine) => { iterLogList.forEach((logLine) => {
console.log("logline item") //console.log("logline item")
console.log(JSON.stringify(logLine,null,2)) //console.log(JSON.stringify(logLine,null,2))
row = logLine.time + " <strong>" + logLine.event + "</strong>:" + logLine.message;
// <div class="line">
// <div data-toggle="collapse" data-target="#rec1">12233 <strong>Event</strong></div>
// <div id="rec1" class="collapse">
// Detaila mozna structured
// Lorem ipsum dolor sit amet, consectetur adipisicing elit,
// sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
// quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
// </div>
// </div>
logcnt++;
row = '<div data-toggle="collapse" data-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ logLine.message+'</div>'
str_row = JSON.stringify(logLine.details, null, 2) str_row = JSON.stringify(logLine.details, null, 2)
row_detail = '<div id="rec'+logcnt+'" class="collapse pidi"><pre>' + str_row + '</pre></div>'
var lines = document.getElementById('lines') var lines = document.getElementById('lines')
var line = document.createElement('div') var line = document.createElement('div')
line.classList.add("line") line.classList.add("line")
//const newLine = document.createTextNode(row)
line.insertAdjacentHTML( 'beforeend', row ); line.insertAdjacentHTML( 'beforeend', row );
line.insertAdjacentHTML( 'beforeend', row_detail );
//line.appendChild(newLine) //line.appendChild(newLine)
var pre = document.createElement("span") //var pre = document.createElement("span")
pre.classList.add("pidi") //pre.classList.add("pidi")
const stLine = document.createTextNode(str_row) //const stLine = document.createTextNode(str_row)
pre.appendChild(stLine) //pre.appendChild(stLine)
line.appendChild(pre) //line.appendChild(pre)
lines.appendChild(line) lines.appendChild(line)
}); });
$('#messages').animate({ $('#messages').animate({
@ -108,7 +129,7 @@ function connect(event) {
//vymazeme vsechny predchozi instance pendingbuys //vymazeme vsechny predchozi instance pendingbuys
if (pbiList.length) { if (pbiList.length) {
console.log(pbiList) //console.log(pbiList)
pbiList.forEach((line) => { pbiList.forEach((line) => {
candlestickSeries.removePriceLine(line) candlestickSeries.removePriceLine(line)
}); });
@ -116,9 +137,9 @@ function connect(event) {
} }
//zobrazime pendingbuys a ulozime instance do pole //zobrazime pendingbuys a ulozime instance do pole
console.log("pred loopem") //console.log("pred loopem")
for (const [orderid, price] of Object.entries(pendingbuys)) { for (const [orderid, price] of Object.entries(pendingbuys)) {
console.log("v loopu", price) //console.log("v loopu", price)
const pbLine = { const pbLine = {
price: parseFloat(price), price: parseFloat(price),
color: "#e3a059", color: "#e3a059",
@ -151,50 +172,97 @@ function connect(event) {
positionsPriceLine = candlestickSeries.createPriceLine(posLine); positionsPriceLine = candlestickSeries.createPriceLine(posLine);
} }
if (parsed_data.hasOwnProperty("statinds")) {
console.log("got static indicators")
var statinds = parsed_data.statinds
if (Object.keys(statinds).length > 0) {
console.log("got static indicators")
console.log(JSON.stringify(statinds))
for (const [klic, hodnota] of Object.entries(statinds)) {
console.log(JSON.stringify(klic))
console.log(JSON.stringify(hodnota))
if (klic === "angle") {
//nejsou vsechny hodnoty
if (Object.keys(hodnota).length > 0) {
console.log("angle nalezen");
console.log(JSON.stringify(hodnota));
if (angleSeries !== 1) {
console.log("angle neni jedna" + toString(angleSeries))
chart.removeSeries(angleSeries)
}
angleSeries = chart.addLineSeries({
//title: key,
lineWidth: 2,
lineStyle: 2,
color: "#d432e6",
lastValueVisible: false,
priceLineVisible: false
})
dataPoints = [{time: hodnota.lookbacktime, value: hodnota.lookbackprice},{ time: hodnota.time, value: hodnota.price}]
console.log("pridano")
console.log(toString(dataPoints))
angleSeries.setData(dataPoints)
}
}
}
}
}
if (parsed_data.hasOwnProperty("indicators")) { if (parsed_data.hasOwnProperty("indicators")) {
console.log("jsme uvnitr indikatoru")
var indicators = parsed_data.indicators var indicators = parsed_data.indicators
//if there are indicators it means there must be at least two keys (except time which is always present) //if there are indicators it means there must be at least two keys (except time which is always present)
if (Object.keys(indicators).length > 1) { if (Object.keys(indicators).length > 1) {
for (const [key, value] of Object.entries(indicators)) { for (const [key, value] of Object.entries(indicators)) {
if (key !== "time") { if (key !== "time") {
//if indicator exists in array, initialize it and store reference to array //if indicator doesnt exists in array, initialize it and store reference to array
const searchObject= indList.find((obj) => obj.name==key); const searchObject= indList.find((obj) => obj.name==key);
if (searchObject == undefined) { if (searchObject == undefined) {
console.log("object new - init and add") //console.log("object new - init and add")
var obj = {name: key, series: null} var obj = {name: key, series: null}
if (momentumIndicatorNames.includes(key)) { if (momentumIndicatorNames.includes(key)) {
obj.series = chart.addLineSeries({ obj.series = chart.addLineSeries({
priceScaleId: 'left', priceScaleId: 'left',
title: key, title: key,
lineWidth: 1, lineWidth: 1
}) });
} }
else { else {
obj.series = chart.addLineSeries({ obj.series = chart.addLineSeries({
//title: key, //title: key,
lineWidth: 1, lineWidth: 1,
lastValueVisible: false lastValueVisible: false
}) });
} }
obj.series.update({ obj.series.update({
time: indicators.time, time: indicators.time,
value: value}); value: value});
indList.push(obj) indList.push(obj);
} }
//indicator exists in an array, let update it //indicator exists in an array, lets update it
else { else {
console.log("object found - update") //console.log("object found - update")
searchObject.series.update({ searchObject.series.update({
time: indicators.time, time: indicators.time,
value: value value: value
}); });
} }
} }
console.log(`${key}: ${value}`);
} }
} }
//chart.timeScale().fitContent();
} }
} }
ws.onclose = function(event) { ws.onclose = function(event) {

View File

@ -61,6 +61,6 @@ pre {
} }
.pidi { .pidi {
display: block; /* display: block; */
font-size: smaller; font-size: smaller;
} }

View File

@ -18,12 +18,12 @@ class StrategyOrderLimitVykladaci(Strategy):
async def orderUpdateBuy(self, data: TradeUpdate): async def orderUpdateBuy(self, data: TradeUpdate):
o: Order = data.order o: Order = data.order
self.state.ilog(e="NOT:BUY_NOT_INCOMING", status=o.status, orderid=str(o.id)) self.state.ilog(e="Příchozí BUY notifikace", msg="order status:"+o.status, status=o.status, orderid=str(o.id))
if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED: if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED:
#pokud existuje objednavka v pendingbuys - vyhodime ji #pokud existuje objednavka v pendingbuys - vyhodime ji
if self.state.vars.pendingbuys.pop(str(o.id), False): if self.state.vars.pendingbuys.pop(str(o.id), False):
self.state.ilog(e="NOT:BUY_NOT_DELETE_PB", msg="mazeme z pendingu", orderid=str(o.id), pb=self.state.vars.pendingbuys) self.state.ilog(e="Příchozí BUY notifikace - mazeme ji z pb", msg="order status:"+o.status, orderid=str(o.id), pb=self.state.vars.pendingbuys)
print("limit buy filled or cancelled. Vyhazujeme z pendingbuys.") print("limit buy filled or cancelled. Vyhazujeme z pendingbuys.")
ic(self.state.vars.pendingbuys) ic(self.state.vars.pendingbuys)
@ -37,7 +37,7 @@ class StrategyOrderLimitVykladaci(Strategy):
price=price2dec(float(o.filled_avg_price)+self.state.vars.profit) price=price2dec(float(o.filled_avg_price)+self.state.vars.profit)
self.state.vars.limitka = await self.interface.sell_l(price=price, size=o.filled_qty) self.state.vars.limitka = await self.interface.sell_l(price=price, size=o.filled_qty)
self.state.vars.limitka_price = price self.state.vars.limitka_price = price
self.state.ilog(e="NOT:BUY_NOT_LIMITKA_CREATE", msg="limitka neni vytvarime", orderid=str(o.id), limitka=str(self.state.vars.limitka), limtka_price=self.state.vars.limitka_price) self.state.ilog(e="Příchozí BUY notif - vytvarime limitku", msg="order status:"+o.status, orderid=str(o.id), limitka=str(self.state.vars.limitka), limtka_price=self.state.vars.limitka_price)
else: else:
#avgp, pos #avgp, pos
self.state.avgp, self.state.positions = self.state.interface.pos() self.state.avgp, self.state.positions = self.state.interface.pos()
@ -46,9 +46,9 @@ class StrategyOrderLimitVykladaci(Strategy):
puvodni = self.state.vars.limitka puvodni = self.state.vars.limitka
self.state.vars.limitka = await self.interface.repl(price=cena,orderid=self.state.vars.limitka,size=int(self.state.positions)) self.state.vars.limitka = await self.interface.repl(price=cena,orderid=self.state.vars.limitka,size=int(self.state.positions))
self.state.vars.limitka_price = cena self.state.vars.limitka_price = cena
self.state.ilog(e="NOT:BUY_NOT_LIMITKA_REPLACE", msg="limitka existuje-replace", orderid=str(o.id), limitka=str(self.state.vars.limitka), limtka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni)) self.state.ilog(e="Příchozí BUY notif - menime limitku", msg="order status:"+o.status, orderid=str(o.id), limitka=str(self.state.vars.limitka), limtka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni))
except APIError as e: except APIError as e:
self.state.ilog(e="NOT:BUY_NOT_LIMITKA_REPLACE_ERROR", msg=str(e), orderid=str(o.id), limitka=str(self.state.vars.limitka), limitka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni)) self.state.ilog(e="API ERROR pri zmene limitky", msg=str(e), orderid=str(o.id), limitka=str(self.state.vars.limitka), limitka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni))
#stejne parametry - stava se pri rychle obratce, nevadi #stejne parametry - stava se pri rychle obratce, nevadi
if e.code == 42210000: return 0,0 if e.code == 42210000: return 0,0
@ -58,7 +58,7 @@ class StrategyOrderLimitVykladaci(Strategy):
async def orderUpdateSell(self, data: TradeUpdate): async def orderUpdateSell(self, data: TradeUpdate):
if data.event == TradeEvent.PARTIAL_FILL: if data.event == TradeEvent.PARTIAL_FILL:
self.state.ilog(e="NOT:SELL_PARTIAL_FILL", msg="pouze update pozic", orderid=str(data.order.id)) self.state.ilog(e="SELL notifikace - Partial fill", msg="pouze update pozic", orderid=str(data.order.id))
ic("partial fill jen udpatujeme pozice") ic("partial fill jen udpatujeme pozice")
self.state.avgp, self.state.positions = self.interface.pos() self.state.avgp, self.state.positions = self.interface.pos()
elif data.event == TradeEvent.FILL or data.event == TradeEvent.CANCELED: elif data.event == TradeEvent.FILL or data.event == TradeEvent.CANCELED:
@ -74,7 +74,7 @@ class StrategyOrderLimitVykladaci(Strategy):
self.state.vars.lastbuyindex = -5 self.state.vars.lastbuyindex = -5
self.state.vars.jevylozeno = 0 self.state.vars.jevylozeno = 0
await self.state.cancel_pending_buys() await self.state.cancel_pending_buys()
self.state.ilog(e="NOT:SELL_FILL_OR_CANCEL", msg="mazeme limitku a pb", orderid=str(data.order.id), pb=self.state.vars.pendingbuys) self.state.ilog(e="Příchozí SELL - FILL nebo CANCEL - mazeme limitku a pb", msg="order status:"+ data.order.status, orderid=str(data.order.id), pb=self.state.vars.pendingbuys)
#this parent method is called by strategy just once before waiting for first data #this parent method is called by strategy just once before waiting for first data
def strat_init(self): def strat_init(self):
@ -89,7 +89,7 @@ class StrategyOrderLimitVykladaci(Strategy):
def buy(self, size = None, repeat: bool = False): def buy(self, size = None, repeat: bool = False):
print("overriden method to size&check maximum ") print("overriden method to size&check maximum ")
if int(self.state.positions) >= self.state.vars.maxpozic: if int(self.state.positions) >= self.state.vars.maxpozic:
self.state.ilog(e="BUY_REQ_MAX_POS_REACHED", msg="Pozadavek na buy, max pozic", curr_positions=self.state.positions) self.state.ilog(e="buy Maxim mnozstvi naplneno", curr_positions=self.state.positions)
print("max mnostvi naplneno") print("max mnostvi naplneno")
return 0 return 0
if size is None: if size is None:
@ -105,13 +105,13 @@ class StrategyOrderLimitVykladaci(Strategy):
def buy_l(self, price: float = None, size = None, repeat: bool = False): def buy_l(self, price: float = None, size = None, repeat: bool = False):
print("entering overriden BUY") print("entering overriden BUY")
if int(self.state.positions) >= self.state.vars.maxpozic: if int(self.state.positions) >= self.state.vars.maxpozic:
self.state.ilog(e="BUY_REQ_MAX_POS_REACHED", msg="Pozadavek na buy, max pozic", price=price, size=size, curr_positions=self.state.positions) self.state.ilog(e="buyl Maxim mnozstvi naplneno", price=price, size=size, curr_positions=self.state.positions)
return 0 return 0
if size is None: size=self.state.vars.chunk if size is None: size=self.state.vars.chunk
if price is None: price=price2dec((self.state.interface.get_last_price(self.symbol))) if price is None: price=price2dec((self.state.interface.get_last_price(self.symbol)))
ic(price) ic(price)
print("odesilame LIMIT s cenou/qty", price, size) print("odesilame LIMIT s cenou/qty", price, size)
self.state.ilog(e="BUY_REQ_ORDER_SENDING", msg="Pozadavek na buy, odesilame do if", price=price, size=size) self.state.ilog(e="odesilame buy_l do if", price=price, size=size)
order = self.state.interface.buy_l(price=price, size=size) order = self.state.interface.buy_l(price=price, size=size)
print("ukladame pendingbuys") print("ukladame pendingbuys")
self.state.vars.pendingbuys[str(order)]=price self.state.vars.pendingbuys[str(order)]=price
@ -119,11 +119,11 @@ class StrategyOrderLimitVykladaci(Strategy):
self.state.vars.lastbuyindex = self.state.bars['index'][-1] self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy) ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex) ic(self.state.vars.lastbuyindex)
self.state.ilog(e="BUY_REQ_ORDER_SENT", msg="Uloženo do pb", order=str(order), pb=self.state.vars.pendingbuys) self.state.ilog(e="Odslano a ulozeno do pb", order=str(order), pb=self.state.vars.pendingbuys)
async def cancel_pending_buys(self): async def cancel_pending_buys(self):
print("cancel pending buys called.") print("cancel pending buys called.")
self.state.ilog(e="CANCEL_ALL_PB_REQUESTED", pb=self.state.vars.pendingbuys) self.state.ilog(e="Rusime pendingy", pb=self.state.vars.pendingbuys)
##proto v pendingbuys pridano str(), protoze UUIN nejde serializovat ##proto v pendingbuys pridano str(), protoze UUIN nejde serializovat
##padalo na variable changed during iteration, pridano ##padalo na variable changed during iteration, pridano
if len(self.state.vars.pendingbuys)>0: if len(self.state.vars.pendingbuys)>0:
@ -133,9 +133,9 @@ class StrategyOrderLimitVykladaci(Strategy):
#nejprve vyhodime z pendingbuys #nejprve vyhodime z pendingbuys
self.state.vars.pendingbuys.pop(key, False) self.state.vars.pendingbuys.pop(key, False)
res = self.interface.cancel(key) res = self.interface.cancel(key)
self.state.ilog(e="PB_CANCELLED", orderid=key, res=str(res)) self.state.ilog(e="Pendingy zrusen pro"+str(key), orderid=str(key), res=str(res))
print("CANCEL PENDING BUYS RETURN", res) print("CANCEL PENDING BUYS RETURN", res)
self.state.vars.pendingbuys={} self.state.vars.pendingbuys={}
self.state.vars.jevylozeno = 0 self.state.vars.jevylozeno = 0
print("cancel pending buys end") print("cancel pending buys end")
self.state.ilog(e="CANCEL_ALL_PB_FINISHED", pb=self.state.vars.pendingbuys) self.state.ilog(e="Dokončeno zruseni vsech pb", pb=self.state.vars.pendingbuys)

View File

@ -338,9 +338,16 @@ class Strategy:
#odchyceny pripad, kdy indikatory jsou inicializovane, ale jeste v nich nejsou data, pak do WS nic neposilame #odchyceny pripad, kdy indikatory jsou inicializovane, ale jeste v nich nejsou data, pak do WS nic neposilame
try: try:
rt_out["indicators"][key]= value[-1] rt_out["indicators"][key]= value[-1]
#zatim takto odchycene identifikatory, ktere nemaji list, ale dict - do budoucna predelat na samostatny typ "indicators_static"
except IndexError: except IndexError:
pass pass
#same for static indicators
if len(self.state.statinds) > 0:
rt_out["statinds"] = dict()
for key, value in self.state.statinds.items():
rt_out["statinds"][key] = value
#vkladame average price and positions, pokud existuji #vkladame average price and positions, pokud existuji
#self.state.avgp , self.state.positions #self.state.avgp , self.state.positions
rt_out["positions"] = dict(time=self.state.time, positions=self.state.positions, avgp=self.state.avgp) rt_out["positions"] = dict(time=self.state.time, positions=self.state.positions, avgp=self.state.avgp)
@ -363,6 +370,7 @@ class Strategy:
print("RTQUEUE INSERT") print("RTQUEUE INSERT")
#send current values to Realtime display on frontend #send current values to Realtime display on frontend
#all datetime values are converted to timestamp #all datetime values are converted to timestamp
if self.rtqueue is not None:
self.rtqueue.put(json.dumps(rt_out, default=json_serial)) self.rtqueue.put(json.dumps(rt_out, default=json_serial))
print("RTQUEUE", self.rtqueue) print("RTQUEUE", self.rtqueue)
@ -466,6 +474,7 @@ class StrategyState:
self.bars = AttributeDict(bars) self.bars = AttributeDict(bars)
self.trades = AttributeDict(trades) self.trades = AttributeDict(trades)
self.indicators = AttributeDict(time=[]) self.indicators = AttributeDict(time=[])
self.statinds = AttributeDict()
#these methods can be overrided by StrategyType (to add or alter its functionality) #these methods can be overrided by StrategyType (to add or alter its functionality)
self.buy = self.interface.buy self.buy = self.interface.buy
self.buy_l = self.interface.buy_l self.buy_l = self.interface.buy_l

View File

@ -15,6 +15,7 @@ from typing import List
import tomli import tomli
from v2realbot.config import DATA_DIR from v2realbot.config import DATA_DIR
import requests import requests
from uuid import UUID
def send_to_telegram(message): def send_to_telegram(message):
apiToken = '5836666362:AAGPuzwp03tczMQTwTBiHW6VsZZ-1RCMAEE' apiToken = '5836666362:AAGPuzwp03tczMQTwTBiHW6VsZZ-1RCMAEE'
@ -35,7 +36,9 @@ def json_serial(obj):
if isinstance(obj, (datetime, date)): if isinstance(obj, (datetime, date)):
return obj.timestamp() return obj.timestamp()
raise TypeError ("Type %s not serializable" % type(obj)) if isinstance(obj, UUID):
return str(obj)
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
def parse_toml_string(tomlst: str): def parse_toml_string(tomlst: str):
try: try: