diff --git a/v2realbot/common/PrescribedTradeModel.py b/v2realbot/common/PrescribedTradeModel.py index a15ebb8..6bfa6a2 100644 --- a/v2realbot/common/PrescribedTradeModel.py +++ b/v2realbot/common/PrescribedTradeModel.py @@ -17,9 +17,13 @@ class TradeStoplossType(str, Enum): FIXED = "fixed" TRAILING = "trailing" +#Predpis obchodu vygenerovany signalem, je to zastresujici jednotka +#ke kteremu jsou pak navazany jednotlivy FILLy (reprezentovany model.TradeUpdate) - napr. castecne exity atp. class Trade(BaseModel): id: UUID last_update: datetime + entry_time: Optional[datetime] = None + exit_time: Optional[datetime] = None status: TradeStatus generated_by: Optional[str] = None direction: TradeDirection diff --git a/v2realbot/common/model.py b/v2realbot/common/model.py index 4274acb..fc23955 100644 --- a/v2realbot/common/model.py +++ b/v2realbot/common/model.py @@ -178,6 +178,7 @@ class Order(BaseModel): side: OrderSide limit_price: Optional[float] +#entita pro kazdy kompletni FILL, je navazana na prescribed_trade class TradeUpdate(BaseModel): event: Union[TradeEvent, str] execution_id: Optional[UUID] @@ -194,6 +195,7 @@ class TradeUpdate(BaseModel): rel_profit: Optional[float] rel_profit_cum: Optional[float] signal_name: Optional[str] + prescribed_trade_id: Optional[str] class RunArchiveChange(BaseModel): diff --git a/v2realbot/enums/enums.py b/v2realbot/enums/enums.py index 1043ff5..2ca465e 100644 --- a/v2realbot/enums/enums.py +++ b/v2realbot/enums/enums.py @@ -56,6 +56,7 @@ class RecordType(str, Enum): BAR = "bar" CBAR = "cbar" CBARVOLUME = "cbarvolume" + CBARRENKO = "cbarrenko" TRADE = "trade" class Mode(str, Enum): diff --git a/v2realbot/loader/aggregator.py b/v2realbot/loader/aggregator.py index ffb2f71..42eff1c 100644 --- a/v2realbot/loader/aggregator.py +++ b/v2realbot/loader/aggregator.py @@ -51,16 +51,21 @@ class TradeAggregator: self.lasttimestamp = 0 #inicalizace pro prvni agregaci self.newBar = dict(high=0, low=999999, volume = 0, trades = 0, confirmed = 0, vwap = 0, close=0, index = 1, updated = 0) - self.openedVolumeBar = None + self.openedBar = None self.lastConfirmedTime = 0 self.bar_start = 0 self.curr_bar_volume = None + self.current_bar_open = None + self.align = align self.tm: datetime = None self.firstpass = True self.vwaphelper = 0 self.returnBar = {} self.lastBarConfirmed = False + self.lastConfirmedBar = None + self.lasthigh = None + self.lastlow = None #min trade size self.minsize = minsize @@ -168,6 +173,9 @@ class TradeAggregator: if self.rectype == RecordType.CBARVOLUME: return await self.calculate_volume_bar(data, symbol) + + if self.rectype == RecordType.CBARRENKO: + return await self.calculate_renko_bar(data, symbol) async def calculate_time_bar(self, data, symbol): #print("barstart",datetime.fromtimestamp(self.bar_start)) @@ -372,7 +380,7 @@ class TradeAggregator: """" Agreguje VOLUME BARS - hlavni promenne - - self.openedVolumeBar (dict) = stavová obsahují aktivní nepotvrzený bar + - self.openedBar (dict) = stavová obsahují aktivní nepotvrzený bar - confirmedBars (list) = nestavová obsahuje confirmnute bary, které budou na konci funkceflushnuty """"" #volume_bucket = 10000 #daily MA volume z emackova na 30 deleno 50ti - dat do configu @@ -381,16 +389,16 @@ class TradeAggregator: confirmedBars = [] #potvrdi existujici a nastavi k vraceni def confirm_existing(): - self.openedVolumeBar['confirmed'] = 1 - self.openedVolumeBar['vwap'] = self.vwaphelper / self.openedVolumeBar['volume'] + self.openedBar['confirmed'] = 1 + self.openedBar['vwap'] = self.vwaphelper / self.openedBar['volume'] self.vwaphelper = 0 #ulozime zacatek potvrzeneho baru - self.lastBarConfirmed = self.openedVolumeBar['time'] + #self.lastBarConfirmed = self.openedBar['time'] - self.openedVolumeBar['updated'] = data['t'] - confirmedBars.append(deepcopy(self.openedVolumeBar)) - self.openedVolumeBar = None + self.openedBar['updated'] = data['t'] + confirmedBars.append(deepcopy(self.openedBar)) + self.openedBar = None #TBD po každém potvrzení zvýšíme čas o nanosekundu (pro zobrazení v gui) #data['t'] = data['t'] + 0.000001 @@ -399,7 +407,7 @@ class TradeAggregator: #inicializuji pro nový bar self.vwaphelper += (data['p'] * size) self.barindex +=1 - self.openedVolumeBar = { + self.openedBar = { "close": data['p'], "high": data['p'], "low": data['p'], @@ -418,20 +426,20 @@ class TradeAggregator: def update_unconfirmed(size): #spočteme vwap - potřebujeme předchozí hodnoty self.vwaphelper += (data['p'] * size) - self.openedVolumeBar['updated'] = data['t'] - self.openedVolumeBar['close'] = data['p'] - self.openedVolumeBar['high'] = max(self.openedVolumeBar['high'],data['p']) - self.openedVolumeBar['low'] = min(self.openedVolumeBar['low'],data['p']) - self.openedVolumeBar['volume'] = self.openedVolumeBar['volume'] + size - self.openedVolumeBar['trades'] = self.openedVolumeBar['trades'] + 1 - self.openedVolumeBar['vwap'] = self.vwaphelper / self.openedVolumeBar['volume'] + self.openedBar['updated'] = data['t'] + self.openedBar['close'] = data['p'] + self.openedBar['high'] = max(self.openedBar['high'],data['p']) + self.openedBar['low'] = min(self.openedBar['low'],data['p']) + self.openedBar['volume'] = self.openedBar['volume'] + size + self.openedBar['trades'] = self.openedBar['trades'] + 1 + self.openedBar['vwap'] = self.vwaphelper / self.openedBar['volume'] #pohrat si s timto round - self.openedVolumeBar['hlcc4'] = round((self.openedVolumeBar['high']+self.openedVolumeBar['low']+self.openedVolumeBar['close']+self.openedVolumeBar['close'])/4,3) + self.openedBar['hlcc4'] = round((self.openedBar['high']+self.openedBar['low']+self.openedBar['close']+self.openedBar['close'])/4,3) #init new - confirmed def initialize_confirmed(size): #ulozime zacatek potvrzeneho baru - self.lastBarConfirmed = datetime.fromtimestamp(data['t']) + #self.lastBarConfirmed = datetime.fromtimestamp(data['t']) self.barindex +=1 confirmedBars.append({ "close": data['p'], @@ -450,17 +458,17 @@ class TradeAggregator: }) #existuje stávající bar a vejdeme se do nej - if self.openedVolumeBar is not None and int(data['s']) + self.openedVolumeBar['volume'] < volume_bucket: + if self.openedBar is not None and int(data['s']) + self.openedBar['volume'] < volume_bucket: #vejdeme se do stávajícího baru (tzn. neprekracujeme bucket) update_unconfirmed(int(data['s'])) #updatujeme stávající nepotvrzeny bar #nevejdem se do nej nebo neexistuje predchozi bar else: #1)existuje predchozi bar - doplnime zbytkem do valikosti bucketu a nastavime confirmed - if self.openedVolumeBar is not None: + if self.openedBar is not None: #doplnime je zbytkem - bucket_left = volume_bucket - self.openedVolumeBar['volume'] + bucket_left = volume_bucket - self.openedBar['volume'] # - update and confirm bar update_unconfirmed(bucket_left) confirm_existing() @@ -468,7 +476,7 @@ class TradeAggregator: #zbytek mnozství jde do dalsiho zpracovani data['s'] = int(data['s']) - bucket_left #nastavime cas o nanosekundu vyssi - data['t'] = data['t'] + 0.000001 + data['t'] = round((data['t']) + 0.000001,6) #2 vytvarime novy bar (bary) a vejdeme se do nej if int(data['s']) < volume_bucket: @@ -483,10 +491,10 @@ class TradeAggregator: # 500 #vytvarime plne potvrzene buckety (kolik se jich plne vejde) - for size in range(0, int(data['s']), volume_bucket): + for size in range(volume_bucket, int(data['s']), volume_bucket): initialize_confirmed(volume_bucket) #nastavime cas o nanosekundu vyssi - data['t'] = data['t'] + 0.000001 + data['t'] = round((data['t']) + 0.000001,6) #create complete full bucket with same prices and size #naplnit do return pole @@ -517,17 +525,170 @@ class TradeAggregator: #pokud mame confirm bary, tak FLUSHNEME confirm a i případný open (zrejme se pak nejaky vytvoril) if len(confirmedBars) > 0: - return_set = confirmedBars + ([self.openedVolumeBar] if self.openedVolumeBar is not None else []) + return_set = confirmedBars + ([self.openedBar] if self.openedBar is not None else []) confirmedBars = [] return return_set #nemame confirm, FLUSHUJEME CBARVOLUME open - neresime zmenu ceny, ale neposilame kulomet (pokud nam nevytvari conf. bar) - if self.openedVolumeBar is not None and self.rectype == RecordType.CBARVOLUME: + if self.openedBar is not None and self.rectype == RecordType.CBARVOLUME: #zkousime pustit i stejnou cenu(potrebujeme kvuli MYSELLU), ale blokoval kulomet,tzn. trady mensi nez GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN (1ms) #if self.diff_price is True: if self.trades_too_close is False: - return [self.openedVolumeBar] + return [self.openedBar] + else: + return [] + else: + return [] + + async def calculate_renko_bar(self, data, symbol): + """" + Agreguje RENKO BARS - dle brick size + hlavni promenne + - self.openedBar (dict) = stavová obsahují aktivní nepotvrzený bar + - confirmedBars (list) = nestavová obsahuje confirmnute bary, které budou na konci funkceflushnuty + + Omezeni: vzhledek tomu, že strategie v CBARu potřebuje realný průběh tick by tick a skutečné Renko bary znamenají + vyřazování určitých průběhů cenu, tak je realizováno Renko bary s high and low a následným updatem open ceny před confirmací. + + open a close bude tedy v potvrzeném baru správně, high-low bude ukazovat na celkový pohyb cen v rámci baru. + + Ve strategii je třeba počítat s tím, že open v nepotvrzeném baru není finální. + """"" + + #pocet ticku např. 10ticků, případně pak na procenta + brick_size = self.resolution + #potvrzene pripravene k vraceni + confirmedBars = [] + #potvrdi existujici a nastavi k vraceni + def confirm_existing(): + self.openedBar['confirmed'] = 1 + self.openedBar['vwap'] = self.vwaphelper / self.openedBar['volume'] + self.vwaphelper = 0 + + self.openedBar['updated'] = data['t'] + obar_copy = deepcopy(self.openedBar) + confirmedBars.append(obar_copy) + self.lastConfirmedBar = obar_copy + self.openedBar = None + #TBD po každém potvrzení zvýšíme čas o nanosekundu (pro zobrazení v gui) + #data['t'] = data['t'] + 0.000001 + + #init unconfirmed - velikost bucketu kontrolovana predtim + def initialize_unconfirmed(): + #inicializuji pro nový bar + self.vwaphelper += (data['p'] * int(data['s'])) + self.barindex +=1 + self.openedBar = { + "close": data['p'], + "high": data['p'], + "low": data['p'], + "open": data['p'], + "volume": int(data['s']), + "trades": 1, + "hlcc4": data['p'], + "confirmed": 0, + "time": datetime.fromtimestamp(data['t']), + "updated": data['t'], + "vwap": data['p'], + "index": self.barindex, + "resolution":self.resolution + } + + def update_unconfirmed(open = None): + + if open is not None: + self.openedBar['open'] = open + #spočteme vwap - potřebujeme předchozí hodnoty + self.vwaphelper += (data['p'] * int(data['s'])) + self.openedBar['updated'] = data['t'] + self.openedBar['close'] = data['p'] + self.openedBar['high'] = max(self.openedBar['high'],data['p']) + self.openedBar['low'] = min(self.openedBar['low'],data['p']) + self.openedBar['volume'] = self.openedBar['volume'] + int(data['s']) + self.openedBar['trades'] = self.openedBar['trades'] + 1 + self.openedBar['vwap'] = self.vwaphelper / self.openedBar['volume'] + #pohrat si s timto round + self.openedBar['hlcc4'] = round((self.openedBar['high']+self.openedBar['low']+self.openedBar['close']+self.openedBar['close'])/4,3) + + #init new - confirmed + def initialize_confirmed(size): + self.barindex +=1 + cf_bar = { + "close": data['p'], + "high": data['p'], + "low": data['p'], + "open": data['p'], + "volume": size, + "trades": 1, + "hlcc4":data['p'], + "confirmed": 1, + "time": datetime.fromtimestamp(data['t']), + "updated": data['t'], + "vwap": data['p'], + "index": self.barindex, + "resolution":self.resolution + } + self.lastConfirmedBar = cf_bar + confirmedBars.append(cf_bar) + + #nastaveni top a low boundary comparatorů bud podle h/l predchoziho potvrzeneho baru + if self.lastConfirmedBar is not None: + top_boundary = max(self.lastConfirmedBar["open"], self.lastConfirmedBar["close"]) + low_boundary = min(self.lastConfirmedBar["open"], self.lastConfirmedBar["close"]) + #nebo openu, pokud mame jen nepotvrzeny + elif self.openedBar is not None: + top_boundary = self.openedBar["open"] + low_boundary = self.openedBar["open"] + + if self.openedBar is None: + initialize_unconfirmed() + #pct variant: brick_size = self.brick_percentage * self.open_price / 100.0 + elif data['p'] >= top_boundary + brick_size: # Check if the price has moved by the brick size + #confirm nese novou cenu, muzou tam byt skryte trady se stejnou cenou nebo kulomet o ktere bychom prisli + #jinymi slovy prekonací tick renkobaru patří do starého baru + #novy bar je vytvoren az dalsim tickem, snad to nebude vadit + + #updatujeme open, kam patri + update_unconfirmed(open=top_boundary) + confirm_existing() + elif data['p'] <= low_boundary - brick_size: + update_unconfirmed(open=low_boundary) + confirm_existing() + else: + #update stávající + update_unconfirmed() + + #je cena stejna od predchoziho tradu? pro nepotvrzeny cbar vracime jen pri zmene ceny + if self.last_price == data['p']: + self.diff_price = False + else: + self.diff_price = True + self.last_price = data['p'] + + if float(data['t']) - float(self.lasttimestamp) < GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN: + self.trades_too_close = True + else: + self.trades_too_close = False + + #uložíme do předchozí hodnoty (poznáme tak open a close) + self.lasttimestamp = data['t'] + self.iterace += 1 + # print(self.iterace, data) + + #pokud mame confirm bary, tak FLUSHNEME confirm a i případný open (zrejme se pak nejaky vytvoril) + if len(confirmedBars) > 0: + return_set = confirmedBars + ([self.openedBar] if self.openedBar is not None else []) + confirmedBars = [] + return return_set + + #nemame confirm, FLUSHUJEME CBARVOLUME open - neresime zmenu ceny, ale neposilame kulomet (pokud nam nevytvari conf. bar) + if self.openedBar is not None and self.rectype == RecordType.CBARRENKO: + + #zkousime pustit i stejnou cenu(potrebujeme kvuli MYSELLU), ale blokoval kulomet,tzn. trady mensi nez GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN (1ms) + #if self.diff_price is True: + if self.trades_too_close is False: + return [self.openedBar] else: return [] else: diff --git a/v2realbot/static/js/utils.js b/v2realbot/static/js/utils.js index 97b7913..69a82c3 100644 --- a/v2realbot/static/js/utils.js +++ b/v2realbot/static/js/utils.js @@ -672,6 +672,12 @@ function populate_indicator_buttons(def) { buttonElement.appendChild(itemEl); ; }); + + var funcButtonElement = document.createElement('div'); + funcButtonElement.id = "funcIndicatorsButtons" + funcButtonElement.classList.add('funcButtons'); + + //create toggle all button var itemEl = document.createElement('button'); itemEl.innerText = "all" @@ -682,7 +688,7 @@ function populate_indicator_buttons(def) { itemEl.addEventListener('click', function() { onResetClicked(); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); //button pro toggle profitu var itemEl = document.createElement('button'); @@ -693,7 +699,7 @@ function populate_indicator_buttons(def) { itemEl.addEventListener('click', function(e) { profitLineToggle(); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); //button pro toggle fullscreenu var itemEl = document.createElement('button'); @@ -704,7 +710,7 @@ function populate_indicator_buttons(def) { itemEl.addEventListener('click', function(e) { toggleWide(); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); //button pro toggle fullscreenu var itemEl = document.createElement('button'); @@ -716,7 +722,7 @@ function populate_indicator_buttons(def) { itemEl.addEventListener('click', function(e) { toggleVolume(); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); // //button pro toggle markeru nakupu/prodeju var itemEl = document.createElement('button'); @@ -745,7 +751,7 @@ function populate_indicator_buttons(def) { mrkLineToggle(); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); //create plus button to create new button var itemEl = document.createElement('button'); @@ -757,7 +763,7 @@ function populate_indicator_buttons(def) { index_ind++ onItemClickedEdit(e, index_ind); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); //save indicator buttons - will generate indicators to stratvars var itemEl = document.createElement('button'); @@ -769,7 +775,9 @@ function populate_indicator_buttons(def) { index_ind++ generateIndicators(e); }); - buttonElement.appendChild(itemEl); + funcButtonElement.appendChild(itemEl); + + buttonElement.appendChild(funcButtonElement) return buttonElement; } diff --git a/v2realbot/strategy/StrategyClassicSL.py b/v2realbot/strategy/StrategyClassicSL.py index dbf0aad..854e5ed 100644 --- a/v2realbot/strategy/StrategyClassicSL.py +++ b/v2realbot/strategy/StrategyClassicSL.py @@ -150,8 +150,11 @@ class StrategyClassicSL(Strategy): trade.rel_profit = rel_profit trade.rel_profit_cum = rel_profit_cum_calculated signal_name = trade.generated_by - if data.event == TradeEvent.FILL: - trade.status == TradeStatus.CLOSED + + #Pokud FILL uzaviral celou pozici - uzavreme prescribed trade + if data.event == TradeEvent.FILL and data.position_qty == 0: + trade.status = TradeStatus.CLOSED + trade.exit_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY) break if data.event == TradeEvent.FILL: @@ -164,6 +167,7 @@ class StrategyClassicSL(Strategy): setattr(tradeData, "profit", trade_profit) setattr(tradeData, "profit_sum", self.state.profit) setattr(tradeData, "signal_name", signal_name) + setattr(tradeData, "prescribed_trade_id", self.state.vars.pending) #self.state.ilog(f"updatnut tradeList o profit", tradeData=json.loads(json.dumps(tradeData, default=json_serial))) setattr(tradeData, "rel_profit", rel_profit) setattr(tradeData, "rel_profit_cum", rel_profit_cum_calculated) @@ -184,11 +188,15 @@ class StrategyClassicSL(Strategy): for trade in self.state.vars.prescribedTrades: if trade.id == self.state.vars.pending: signal_name = trade.generated_by + #zapiseme entry_time (jen pokud to neni partial add) - tzn. jen poprvé + if data.event == TradeEvent.FILL and trade.entry_time is None: + trade.entry_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY) #zapsat do tradeList for tradeData in self.state.tradeList: if tradeData.execution_id == data.execution_id: setattr(tradeData, "signal_name", signal_name) + setattr(tradeData, "prescribed_trade_id", self.state.vars.pending) self.state.ilog(e="BUY: Jde o LONG nakuú nepocitame profit zatim") @@ -271,8 +279,10 @@ class StrategyClassicSL(Strategy): trade.rel_profit = rel_profit trade.rel_profit_cum = rel_profit_cum_calculated signal_name = trade.generated_by - if data.event == TradeEvent.FILL: - trade.status == TradeStatus.CLOSED + #Pokud FILL uzaviral celou pozici - uzavreme prescribed trade + if data.event == TradeEvent.FILL and data.position_qty == 0: + trade.status = TradeStatus.CLOSED + trade.exit_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY) break if data.event == TradeEvent.FILL: @@ -285,6 +295,7 @@ class StrategyClassicSL(Strategy): setattr(tradeData, "profit", trade_profit) setattr(tradeData, "profit_sum", self.state.profit) setattr(tradeData, "signal_name", signal_name) + setattr(tradeData, "prescribed_trade_id", self.state.vars.pending) #self.state.ilog(f"updatnut tradeList o profi {str(tradeData)}") setattr(tradeData, "rel_profit", rel_profit) setattr(tradeData, "rel_profit_cum", rel_profit_cum_calculated) @@ -305,11 +316,15 @@ class StrategyClassicSL(Strategy): for trade in self.state.vars.prescribedTrades: if trade.id == self.state.vars.pending: signal_name = trade.generated_by + #zapiseme entry_time (jen pokud to neni partial add) - tzn. jen poprvé + if data.event == TradeEvent.FILL and trade.entry_time is None: + trade.entry_time = datetime.fromtimestamp(self.state.time).astimezone(zoneNY) #zapsat update profitu do tradeList for tradeData in self.state.tradeList: if tradeData.execution_id == data.execution_id: setattr(tradeData, "signal_name", signal_name) + setattr(tradeData, "prescribed_trade_id", self.state.vars.pending) self.state.ilog(e="SELL: Jde o SHORT nepocitame profit zatim") diff --git a/v2realbot/strategy/base.py b/v2realbot/strategy/base.py index bd7806e..ca9f317 100644 --- a/v2realbot/strategy/base.py +++ b/v2realbot/strategy/base.py @@ -65,6 +65,7 @@ class Strategy: self.ilog_save = ilog_save self.secondary_res_start_time = dict() self.secondary_res_start_index = dict() + self.last_index = -1 #TODO predelat na dynamické queues self.q1 = queue.Queue() @@ -156,9 +157,11 @@ class Strategy: #tzn. v NEXT dealame u indikatoru vzdy pouze UPDATE def save_item_history(self,item): + """" + Logika obsahujici ukladani baru a indikatoru(standardnich a cbar) do historie a inicializace novych zaznamu + """ if self.rectype == RecordType.BAR: #jako cas indikatorů pridavame cas baru a inicialni hodnoty vsech indikatoru - for key in self.state.indicators: if key == 'time': self.state.indicators['time'].append(item['updated']) @@ -170,7 +173,7 @@ class Strategy: #implementovat az podle skutecnych pozadavku #self.state.indicators['time'].append(datetime.fromtimestamp(self.state.last_trade_time)) #self.append_trade(self.state.trades,item) - elif self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME): + elif self.rectype in (RecordType.CBAR): if self.nextnew: #standardni identifikatory - populace hist zaznamu pouze v novem baru (dale se deji jen udpaty) for key in self.state.indicators: @@ -220,7 +223,40 @@ class Strategy: #zatim jedno, predelat pak na list # if safe_get(self.state.vars, "secondary_resolution",None): # self.process_secondary_indicators(item) + elif self.rectype in (RecordType.CBARVOLUME, RecordType.CBARRENKO): + #u cbarvolume muze prijit i samostatny confirm nesouci data, tzn. chytame se na INDEX (tzn. jestli prisel udpate nebo novy) + #NEW + if item['index'] != self.last_index: + #standardni identifikatory - populace hist zaznamu pouze v novem baru (dale se deji jen udpaty) + for key in self.state.indicators: + if key == 'time': + self.state.indicators['time'].append(item['time']) + else: + self.state.indicators[key].append(0) + + #populujeme i novy bar v historii + self.append_bar(self.state.bars,item) + #UPDATE + else: + #bary updatujeme, pridavame jen prvni + self.replace_prev_bar(self.state.bars,item) + + #UPD + #tady mozna u standardnich(barovych) identifikatoru updatnout cas na "updated" - aby nebyl + #stale zarovnan s casem baru + for key in self.state.indicators: + if key == 'time': + self.state.indicators['time'][-1] = item['updated'] + + #cbar indikatory populace v kazde iteraci + for key in self.state.cbar_indicators: + if key == 'time': + self.state.cbar_indicators['time'].append(item['updated']) + else: + self.state.cbar_indicators[key].append(0) + + self.last_index = item['index'] # #tady jsem skoncil # def process_secondary_indicators(self, item): @@ -275,14 +311,14 @@ class Strategy: a,p = self.interface.pos() if a != -1: self.state.avgp, self.state.positions = a,p - elif self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME) and item['confirmed'] == 1: + elif self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME, RecordType.CBARRENKO) and item['confirmed'] == 1: a,p = self.interface.pos() if a != -1: self.state.avgp, self.state.positions = a,p """update state.last_trade_time a time of iteration""" def update_times(self, item): - if self.rectype == RecordType.BAR or self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME): + if self.rectype == RecordType.BAR or self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME, RecordType.CBARRENKO): self.state.last_trade_time = item['updated'] elif self.rectype == RecordType.TRADE: self.state.last_trade_time = item['t'] @@ -524,7 +560,7 @@ class Strategy: if self.rtqueue is not None: rt_out = dict() - if self.rectype == RecordType.BAR or self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME): + if self.rectype == RecordType.BAR or self.rectype in (RecordType.CBAR, RecordType.CBARVOLUME, RecordType.CBARRENKO): rt_out["bars"] = item else: rt_out["trades"] = item diff --git a/v2realbot/strategyblocks/indicators/cbar_price.py b/v2realbot/strategyblocks/indicators/cbar_price.py index 1edf005..0d6968c 100644 --- a/v2realbot/strategyblocks/indicators/cbar_price.py +++ b/v2realbot/strategyblocks/indicators/cbar_price.py @@ -5,7 +5,7 @@ def populate_cbar_tick_price_indicator(data, state: StrategyState): conf_bar = data['confirmed'] #specifická sekce pro CBARVOLUME, kde vzdy máme nova data v confirmation baru (tzn. tickprice pocitame jak pri potvrzenem tak nepotvrzenem) - if state.rectype == RecordType.CBARVOLUME: + if state.rectype in (RecordType.CBARVOLUME, RecordType.CBARRENKO): try: tick_price = data['close'] tick_delta_volume = data['volume'] - state.vars.last_tick_volume diff --git a/v2realbot/strategyblocks/newtrade/prescribedtrades.py b/v2realbot/strategyblocks/newtrade/prescribedtrades.py index 443a17c..e6f05be 100644 --- a/v2realbot/strategyblocks/newtrade/prescribedtrades.py +++ b/v2realbot/strategyblocks/newtrade/prescribedtrades.py @@ -62,10 +62,10 @@ def execute_prescribed_trades(state: StrategyState, data): state.ilog(lvl=1,e=f"Nastaveno SL na {sl_defvalue}, priced normalized: {sl_defvalue_normalized} price: {state.vars.activeTrade.stoploss_value }") elif isinstance(sl_defvalue, str): #from indicator - ind = sl_defvalue_abs + ind = sl_defvalue sl_defvalue_abs = float(value_or_indicator(state, sl_defvalue)) if sl_defvalue_abs >= float(data['close']): - raise Exception(f"error in stoploss {sl_defvalue_abs} >= curr price") + raise Exception(f"error in stoploss {ind} {sl_defvalue_abs} >= curr price") state.vars.activeTrade.stoploss_value = sl_defvalue_abs state.ilog(lvl=1,e=f"Nastaveno SL na {sl_defvalue_abs} dle indikatoru {ind}") insert_SL_history(state) @@ -92,10 +92,10 @@ def execute_prescribed_trades(state: StrategyState, data): state.ilog(lvl=1,e=f"Nastaveno SL na {sl_defvalue}, priced normalized: {sl_defvalue_normalized} price: {state.vars.activeTrade.stoploss_value }") elif isinstance(sl_defvalue, str): #from indicator - ind = sl_defvalue_abs + ind = sl_defvalue sl_defvalue_abs = float(value_or_indicator(state, sl_defvalue)) if sl_defvalue_abs <= float(data['close']): - raise Exception(f"error in stoploss {sl_defvalue_abs} <= curr price") + raise Exception(f"error in stoploss {ind} {sl_defvalue_abs} <= curr price") state.vars.activeTrade.stoploss_value = sl_defvalue_abs state.ilog(lvl=1,e=f"Nastaveno SL na {sl_defvalue_abs} dle indikatoru {ind}") insert_SL_history(state)