From 6524b228c4f5ce5e85ce2537f1438fd0a9afc496 Mon Sep 17 00:00:00 2001 From: David Brazda Date: Wed, 19 Apr 2023 08:40:02 +0200 Subject: [PATCH] rozpracovane zmeny --- testy/asyncioRun.py | 7 ++ v2realbot/ENTRY_backtest_strategyVykladaci.py | 39 +++++- v2realbot/main.py | 2 +- v2realbot/static/index.html | 35 +++++- v2realbot/static/js/mychart.js | 12 +- v2realbot/static/js/mywebsocket.js | 114 ++++++++++++++++-- v2realbot/static/main.css | 33 +++++ .../strategy/StrategyOrderLimitVykladaci.py | 22 +++- ...trategyOrderLimitVykladaci.cpython-310.pyc | Bin 5099 -> 6499 bytes .../strategy/__pycache__/base.cpython-310.pyc | Bin 11768 -> 12355 bytes v2realbot/strategy/base.py | 35 +++++- 11 files changed, 277 insertions(+), 22 deletions(-) create mode 100644 testy/asyncioRun.py diff --git a/testy/asyncioRun.py b/testy/asyncioRun.py new file mode 100644 index 0000000..88b9235 --- /dev/null +++ b/testy/asyncioRun.py @@ -0,0 +1,7 @@ +import asyncio + +async def vysledek(): + return 100 + +a = asyncio.run(vysledek()) +print(a) \ No newline at end of file diff --git a/v2realbot/ENTRY_backtest_strategyVykladaci.py b/v2realbot/ENTRY_backtest_strategyVykladaci.py index 3311267..a8fd019 100644 --- a/v2realbot/ENTRY_backtest_strategyVykladaci.py +++ b/v2realbot/ENTRY_backtest_strategyVykladaci.py @@ -40,6 +40,7 @@ stratvars = AttributeDict(maxpozic = 250, lastbuyindex=-6, pendingbuys={}, limitka = None, + limitka_price = None, jevylozeno=0, vykladka=5, curve = [0.01, 0.01, 0.01, 0, 0.02, 0.02, 0.01,0.01, 0.01,0.03, 0.01, 0.01, 0.01,0.04, 0.01,0.01, 0.01,0.05, 0.01,0.01, 0.01,0.01, 0.06,0.01, 0.01,0.01, 0.01], @@ -155,10 +156,10 @@ def next(data, state: StrategyState): slope_lookback = int(state.vars.slope_lookback) minimum_slope = float(state.vars.minimum_slope) - if len(state.indicators.ema) > slope_lookback: + if len(state.bars.close) > slope_lookback: #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 = ((state.bars.close[-1] - state.indicators.ema[-slope_lookback])/state.indicators.ema[-slope_lookback])*100 + slope = ((state.bars.close[-1] - state.bars.close[-slope_lookback])/state.bars.close[-slope_lookback])*100 #roc = ((state.indicators.ema[-1] - state.indicators.ema[-roc_lookback])/state.indicators.ema[-roc_lookback])*100 state.indicators.slope.append(slope) #state.indicators.roc.append(roc) @@ -166,6 +167,7 @@ def next(data, state: StrategyState): #ic(state.indicators.roc[-5:]) except Exception as e: print("Exception in NEXT Indicator section", str(e)) + state.ilog(e="EXCEPTION", msg="Exception in NEXT Indicator section" + str(e)) print("is falling",isfalling(state.indicators.ema,state.vars.Trend)) print("is rising",isrising(state.indicators.ema,state.vars.Trend)) @@ -175,34 +177,54 @@ def next(data, state: StrategyState): ##CONSOLIDATION PART kazdy Nty bar dle nastaveni if int(data["index"])%int(state.vars.consolidation_bar_count) == 0: print("***Consolidation ENTRY***") + state.ilog(e="Konzolidujeme") orderlist = state.interface.get_open_orders(symbol=state.symbol, side=None) #print(orderlist) pendingbuys_new = {} limitka_old = state.vars.limitka print("Puvodni LIMITKA", limitka_old) + #zaciname s cistym stitem state.vars.limitka = None + state.vars.limitka_price = None + limitka_found = False for o in orderlist: if o.side == OrderSide.SELL: print("Nalezena LIMITKA") + limitka_found = True state.vars.limitka = o.id + state.vars.limitka_price = o.limit_price + ##TODO sem pridat upravu ceny if o.side == OrderSide.BUY: pendingbuys_new[str(o.id)]=float(o.limit_price) - print("Nová LIMITKA", state.vars.limitka) + state.ilog(e="Konzolidace", 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 + if state.positions > 0 and state.vars.limitka is None: + state.ilog(e="Neni limitka, ale mela by být.") + 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_price = price + state.ilog(e="Vytvořena nová limitka", limitka=str(state.vars.limitka), limtka_price=state.vars.limitka_price) + + if pendingbuys_new != state.vars.pendingbuys: + state.ilog(e="Rozdilna PB prepsana", pb_new=pendingbuys_new, pb_old = state.vars.pendingbuys) print("ROZDILNA PENDINGBUYS přepsána") print("OLD",state.vars.pendingbuys) state.vars.pendingbuys = unpackb(packb(pendingbuys_new)) print("NEW", state.vars.pendingbuys) else: print("PENDINGBUYS sedí - necháváme", state.vars.pendingbuys) + state.ilog(e="PB sedi nechavame", pb_new=pendingbuys_new, pb_old = state.vars.pendingbuys) print("OLD jevylozeno", state.vars.jevylozeno) if len(state.vars.pendingbuys) > 0: state.vars.jevylozeno = 1 else: state.vars.jevylozeno = 0 print("NEW jevylozeno", state.vars.jevylozeno) + state.ilog(e="Nove jevyloze", jevylozeno=state.vars.jevylozeno) #print(limitka) #print(pendingbuys_new) @@ -215,14 +237,21 @@ def next(data, state: StrategyState): else: print("no time for consolidation", data["index"]) + #HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru + lp = state.interface.get_last_price(symbol=state.symbol) + state.ilog(e="ITER_ENTRY", last_price=lp, stratvars=state.vars) + #SLOPE ANGLE PROTECTION + state.ilog(e="SLOPE", curr_slope=slope, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-5:]) if slope < minimum_slope: print("OCHRANA SLOPE TOO HIGH") + state.ilog(e="SLOPE_EXCEEDED") if len(state.vars.pendingbuys)>0: print("CANCEL PENDINGBUYS") ic(state.vars.pendingbuys) res = asyncio.run(state.cancel_pending_buys()) ic(state.vars.pendingbuys) + state.ilog(e="Rusime pendingbuyes", pb=state.vars.pendingbuys) print("slope", slope) print("min slope", minimum_slope) @@ -235,6 +264,7 @@ def next(data, state: StrategyState): ic(state.time) #zatim vykladame full #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() ## testuje aktualni cenu od nejvyssi visici limitky @@ -252,6 +282,7 @@ def next(data, state: StrategyState): print("max cena v orderbuys", maxprice) 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? res = asyncio.run(state.cancel_pending_buys()) @@ -268,6 +299,7 @@ def next(data, state: StrategyState): if len(state.vars.pendingbuys) == 0: state.vars.blockbuy = 0 state.vars.jevylozeno = 0 + state.ilog(e="PB se vyklepaly nastavujeme: neni vylozeno", jevylozeno=state.vars.jevylozeno) #TODO toto dodelat konzolidaci a mozna lock na limitku a pendingbuys a jevylozeno ?? @@ -305,6 +337,7 @@ def init(state: StrategyState): state.indicators['ema'] = [] state.indicators['slope'] = [] #state.indicators['roc'] = [] + #state.ilog(e="INIT", stratvars=state.vars) def main(): diff --git a/v2realbot/main.py b/v2realbot/main.py index a22ffa3..91b2edd 100644 --- a/v2realbot/main.py +++ b/v2realbot/main.py @@ -113,7 +113,7 @@ async def websocket_endpoint( if data=="break": break await ws.send_text(data) - print("WSTX thread received data", data) + print("WSTX thread received data") #,data) except Empty: print("WSTX thread Heartbeat. No data received from queue.") continue diff --git a/v2realbot/static/index.html b/v2realbot/static/index.html index f16ddc8..0facb64 100644 --- a/v2realbot/static/index.html +++ b/v2realbot/static/index.html @@ -16,6 +16,30 @@
+ + +
+
12233 Event
+
+ 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. +
+
+ +
+
12233 Event
+
+ 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. +
+
+ + +

Status: Not connected

@@ -26,11 +50,16 @@
-
    -
- +
+
+
+
+
+
+
+
diff --git a/v2realbot/static/js/mychart.js b/v2realbot/static/js/mychart.js index db8616c..15ca211 100644 --- a/v2realbot/static/js/mychart.js +++ b/v2realbot/static/js/mychart.js @@ -1,16 +1,18 @@ //const chartOptions = { layout: { textColor: 'black', background: { type: 'solid', color: 'white' } } }; -const chartOptions = { width: 1200, height: 600, leftPriceScale: {visible: true}} +const chartOptions = { width: 1045, height: 600, leftPriceScale: {visible: true}} const chart = LightweightCharts.createChart(document.getElementById('chart'), chartOptions); chart.applyOptions({ timeScale: { visible: true, timeVisible: true, secondsVisible: true }, crosshair: { mode: LightweightCharts.CrosshairMode.Normal, labelVisible: true }}) -const candlestickSeries = chart.addCandlestickSeries(); +const candlestickSeries = chart.addCandlestickSeries({ lastValueVisible: true, priceLineWidth:2, priceLineColor: "red", priceFormat: { type: 'price', precision: 2, minMove: 0.01 }}); candlestickSeries.priceScale().applyOptions({ scaleMargins: { top: 0.1, // highest point of the series will be 10% away from the top bottom: 0.4, // lowest point will be 40% away from the bottom }, }); + + const volumeSeries = chart.addHistogramSeries({title: "Volume", color: '#26a69a', priceFormat: {type: 'volume'}, priceScaleId: ''}); volumeSeries.priceScale().applyOptions({ // set the positioning of the volume series @@ -21,11 +23,13 @@ volumeSeries.priceScale().applyOptions({ }); const vwapSeries = chart.addLineSeries({ - title: "vwap", +// title: "vwap", color: '#2962FF', lineWidth: 1, + lastValueVisible: false }) +chart.timeScale().fitContent(); //TBD dynamicky zobrazovat vsechny indikatory //document.getElementById('chart').style.display = 'inline-block'; @@ -54,7 +58,7 @@ chart.subscribeCrosshairMove((param) => { firstRow.innerText += item.name + " " + ind.value + " "; }); - firstRow.innerText += 'vwap' + ' ' + vwap.toFixed(2) + " o" + bars.open + " h" + bars.high + " l" + bars.low + " c" + bars.close + " v" + volumes.value; + firstRow.innerText += ' vwap' + ' ' + vwap.toFixed(2) + " O" + bars.open + " H" + bars.high + " L" + bars.low + " C" + bars.close + " V" + volumes.value + ""; } else { firstRow.innerText = '-'; diff --git a/v2realbot/static/js/mywebsocket.js b/v2realbot/static/js/mywebsocket.js index b45073f..1977473 100644 --- a/v2realbot/static/js/mywebsocket.js +++ b/v2realbot/static/js/mywebsocket.js @@ -1,6 +1,9 @@ const momentumIndicatorNames = ["roc", "slope"] var indList = [] +var pbiList = [] var ws = null; +var positionsPriceLine = null +var limitkaPriceLine = null function connect(event) { var runnerId = document.getElementById("runnerId") try { @@ -16,12 +19,6 @@ function connect(event) { document.getElementById("chart").style.display = "block" } ws.onmessage = function(event) { - //var messages = document.getElementById('messages') - //var message = document.createElement('li') - //var content = document.createTextNode(event.data) - //message.appendChild(content) - //messages.appendChild(message) - var parsed_data = JSON.parse(event.data) console.log(JSON.stringify(parsed_data)) @@ -53,6 +50,107 @@ function connect(event) { }); } + //loglist + if (parsed_data.hasOwnProperty("iter_log")) { + iterLogList = parsed_data.iter_log + console.log("Incoming logline object") + + var lines = document.getElementById('lines') + var line = document.createElement('div') + line.classList.add("line") + const newLine = document.createTextNode("-----------------NEXT ITER------------------") + line.appendChild(newLine) + lines.appendChild(line) + + iterLogList.forEach((logLine) => { + console.log("logline item") + console.log(JSON.stringify(logLine,null,2)) + row = logLine.time + " " + logLine.event + ":" + logLine.message; + str_row = JSON.stringify(logLine.details, null, 2) + var lines = document.getElementById('lines') + var line = document.createElement('div') + line.classList.add("line") + //const newLine = document.createTextNode(row) + line.insertAdjacentHTML( 'beforeend', row ); + //line.appendChild(newLine) + var pre = document.createElement("span") + pre.classList.add("pidi") + const stLine = document.createTextNode(str_row) + pre.appendChild(stLine) + line.appendChild(pre) + lines.appendChild(line) + }); + $('#messages').animate({ + scrollTop: $('#lines')[0].scrollHeight}, 2000); + } + + //limitka + if (parsed_data.hasOwnProperty("limitka")) { + limitka = parsed_data.limitka + const limitkaLine = { + price: limitka.price, + color: '#1ed473', + lineWidth: 1, + lineStyle: 1, // LineStyle.Dotted + axisLabelVisible: true, + title: "SELL:XX", + }; + + if (limitkaPriceLine !== null) { + candlestickSeries.removePriceLine(limitkaPriceLine) + } + limitkaPriceLine = candlestickSeries.createPriceLine(limitkaLine); + } + + + if (parsed_data.hasOwnProperty("pendingbuys")) { + pendingbuys = parsed_data.pendingbuys + + //vymazeme vsechny predchozi instance pendingbuys + if (pbiList.length) { + console.log(pbiList) + pbiList.forEach((line) => { + candlestickSeries.removePriceLine(line) + }); + pbiList = [] + } + + //zobrazime pendingbuys a ulozime instance do pole + console.log("pred loopem") + for (const [orderid, price] of Object.entries(pendingbuys)) { + console.log("v loopu", price) + const pbLine = { + price: parseFloat(price), + color: "#e3a059", + lineWidth: 1, + lineStyle: 1, // LineStyle.Dotted + axisLabelVisible: true, + title: "BUY:", + }; + + pbLineInstance = candlestickSeries.createPriceLine(pbLine); + pbiList.push(pbLineInstance) + } + + } + + if (parsed_data.hasOwnProperty("positions")) { + positions = parsed_data.positions + const posLine = { + price: positions.avgp, + color: 'black', + lineWidth: 1, + lineStyle: 1, // LineStyle.Dotted + axisLabelVisible: true, + title: "POS:"+positions.positions, + }; + + if (positionsPriceLine !== null) { + candlestickSeries.removePriceLine(positionsPriceLine) + } + positionsPriceLine = candlestickSeries.createPriceLine(posLine); + } + if (parsed_data.hasOwnProperty("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) @@ -73,8 +171,9 @@ function connect(event) { } else { obj.series = chart.addLineSeries({ - title: key, + //title: key, lineWidth: 1, + lastValueVisible: false }) } obj.series.update({ @@ -95,6 +194,7 @@ function connect(event) { console.log(`${key}: ${value}`); } } + //chart.timeScale().fitContent(); } } ws.onclose = function(event) { diff --git a/v2realbot/static/main.css b/v2realbot/static/main.css index 7958b55..0f61487 100644 --- a/v2realbot/static/main.css +++ b/v2realbot/static/main.css @@ -15,6 +15,7 @@ align-self: auto; order: 0; margin-inline-start: 50px; + padding-bottom: 10px; } .chartContainer { @@ -30,4 +31,36 @@ font-size: 16px; line-height: 18px; font-weight: 300; +} + +#msgContainer { + display: grid; + overflow: auto; + height: 568px; +} + +.msgContainerInner { + display: flex; + overflow: auto; + height: 568px; + flex-direction: column-reverse; +} + +pre { + display: block; + /* padding: 9.5px; */ + /* margin: 0 0 10px; */ + font-size: 10px; + /* line-height: 2.428571; */ + color: #333; + word-break: break-all; + word-wrap: break-word; + /* background-color: #f5f5f5; */ + /* border: 1px solid #ccc; */ + border-radius: 4px; +} + +.pidi { + display: block; + font-size: smaller; } \ No newline at end of file diff --git a/v2realbot/strategy/StrategyOrderLimitVykladaci.py b/v2realbot/strategy/StrategyOrderLimitVykladaci.py index af19a66..e8b6613 100644 --- a/v2realbot/strategy/StrategyOrderLimitVykladaci.py +++ b/v2realbot/strategy/StrategyOrderLimitVykladaci.py @@ -17,11 +17,13 @@ class StrategyOrderLimitVykladaci(Strategy): super().__init__(name, symbol, next, init, account, mode, stratvars, open_rush, close_rush, pe, se) async def orderUpdateBuy(self, data: TradeUpdate): - o: Order = data.order + self.state.ilog(e="NOT:BUY_NOT_INCOMING", status=o.status, orderid=str(o.id)) if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED: + #pokud existuje objednavka v pendingbuys - vyhodime ji 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) print("limit buy filled or cancelled. Vyhazujeme z pendingbuys.") ic(self.state.vars.pendingbuys) @@ -34,13 +36,20 @@ class StrategyOrderLimitVykladaci(Strategy): self.state.avgp = float(data.price) 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_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) else: #avgp, pos self.state.avgp, self.state.positions = self.state.interface.pos() cena = price2dec(float(self.state.avgp) + float(self.state.vars.profit)) try: + 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_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)) 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)) + #stejne parametry - stava se pri rychle obratce, nevadi if e.code == 42210000: return 0,0 else: @@ -49,6 +58,7 @@ class StrategyOrderLimitVykladaci(Strategy): async def orderUpdateSell(self, data: TradeUpdate): if data.event == TradeEvent.PARTIAL_FILL: + self.state.ilog(e="NOT:SELL_PARTIAL_FILL", msg="pouze update pozic", orderid=str(data.order.id)) ic("partial fill jen udpatujeme pozice") self.state.avgp, self.state.positions = self.interface.pos() elif data.event == TradeEvent.FILL or data.event == TradeEvent.CANCELED: @@ -60,9 +70,11 @@ class StrategyOrderLimitVykladaci(Strategy): self.state.avgp, self.state.positions = self.interface.pos() ic(self.state.avgp, self.state.positions) self.state.vars.limitka = None + self.state.vars.limitka_price = None self.state.vars.lastbuyindex = -5 self.state.vars.jevylozeno = 0 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) #this parent method is called by strategy just once before waiting for first data def strat_init(self): @@ -77,6 +89,7 @@ class StrategyOrderLimitVykladaci(Strategy): def buy(self, size = None, repeat: bool = False): print("overriden method to size&check maximum ") 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) print("max mnostvi naplneno") return 0 if size is None: @@ -92,12 +105,13 @@ class StrategyOrderLimitVykladaci(Strategy): def buy_l(self, price: float = None, size = None, repeat: bool = False): print("entering overriden BUY") if int(self.state.positions) >= self.state.vars.maxpozic: - print("max mnostvi naplneno") + self.state.ilog(e="BUY_REQ_MAX_POS_REACHED", msg="Pozadavek na buy, max pozic", price=price, size=size, curr_positions=self.state.positions) return 0 if size is None: size=self.state.vars.chunk if price is None: price=price2dec((self.state.interface.get_last_price(self.symbol))) ic(price) 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) order = self.state.interface.buy_l(price=price, size=size) print("ukladame pendingbuys") self.state.vars.pendingbuys[str(order)]=price @@ -105,9 +119,11 @@ class StrategyOrderLimitVykladaci(Strategy): self.state.vars.lastbuyindex = self.state.bars['index'][-1] ic(self.state.blockbuy) 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) async def cancel_pending_buys(self): print("cancel pending buys called.") + self.state.ilog(e="CANCEL_ALL_PB_REQUESTED", pb=self.state.vars.pendingbuys) ##proto v pendingbuys pridano str(), protoze UUIN nejde serializovat ##padalo na variable changed during iteration, pridano if len(self.state.vars.pendingbuys)>0: @@ -117,7 +133,9 @@ class StrategyOrderLimitVykladaci(Strategy): #nejprve vyhodime z pendingbuys self.state.vars.pendingbuys.pop(key, False) res = self.interface.cancel(key) + self.state.ilog(e="PB_CANCELLED", orderid=key, res=str(res)) print("CANCEL PENDING BUYS RETURN", res) self.state.vars.pendingbuys={} self.state.vars.jevylozeno = 0 print("cancel pending buys end") + self.state.ilog(e="CANCEL_ALL_PB_FINISHED", pb=self.state.vars.pendingbuys) diff --git a/v2realbot/strategy/__pycache__/StrategyOrderLimitVykladaci.cpython-310.pyc b/v2realbot/strategy/__pycache__/StrategyOrderLimitVykladaci.cpython-310.pyc index 36e1869f6f6edd302c7af9038876580ca8aa0e79..70bd52c5278ffbc4fa840a940444ada331c4af36 100644 GIT binary patch literal 6499 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 delta 2209 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 0: + rt_out["iter_log"] = self.state.iter_log_list + + #print(rt_out) print("RTQUEUE INSERT") #send current values to Realtime display on frontend @@ -347,6 +366,10 @@ class Strategy: self.rtqueue.put(json.dumps(rt_out, default=json_serial)) print("RTQUEUE", self.rtqueue) + #cleaning iterlog lsit + #TODO pridat cistku i mimo RT blok + self.state.iter_log_list = [] + # inicializace poplatna typu strategie (např. u LIMITu dotažení existující limitky) def strat_init(self): @@ -448,4 +471,12 @@ class StrategyState: self.buy_l = self.interface.buy_l self.sell = self.interface.sell self.sell_l = self.interface.sell_l - self.cancel_pending_buys = None \ No newline at end of file + self.cancel_pending_buys = None + self.iter_log_list = [] + + def ilog(self, e: str = None, msg: str = None, **kwargs): + if e is None: + row = dict(time=self.time, message=msg, details=kwargs) + else: + row = dict(time=self.time, event=e, message=msg, details=kwargs) + self.iter_log_list.append(row) \ No newline at end of file