diff --git a/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py b/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py index eca1f9f..4cc2973 100644 --- a/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py +++ b/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py @@ -396,17 +396,30 @@ 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 + # 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 populate_secondary_rsi_indicator(): + #SBAR 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 + srsi_length = int(safe_get(state.vars, "srsi_length",14)) + source = state.secondary_indicators.sec_price #[-rsi_length:] #state.bars.vwap + srsi_res = rsi(source, srsi_length) + srsi_value = trunc(srsi_res[-1],3) + state.secondary_indicators.SRSI[-1]=srsi_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.ilog(e=f"SRSI {srsi_length=} necháváme 0", message=str(e)+format_exc()) #state.indicators.RSI14[-1]=0 def slope_too_low(): @@ -573,7 +586,12 @@ def next(data, state: StrategyState): for key in state.cbar_indicators: if key != 'time': - last_ind_vals[key] = state.cbar_indicators[key][-5:] + last_ind_vals[key] = state.cbar_indicators[key][-5:] + + for key in state.secondary_indicators: + if key != 'time': + last_ind_vals[key] = state.secondary_indicators[key][-5:] + return last_ind_vals conf_bar = data['confirmed'] @@ -591,11 +609,14 @@ def next(data, state: StrategyState): state.vars.last_tick_volume = 0 state.vars.next_new = 1 + #SRSI + populate_secondary_rsi_indicator() + #kroky pro CONTINOUS TICKS only 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 @@ -628,7 +649,7 @@ def init(state: StrategyState): #state.cbar_indicators['ivwap'] = [] state.cbar_indicators['tick_price'] = [] state.cbar_indicators['tick_volume'] = [] - state.cbar_indicators['CRSI'] = [] + state.secondary_indicators['SRSI'] = [] state.indicators['ema'] = [] state.indicators['slope'] = [] state.indicators['slopeMA'] = [] diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index c99ca90..af1f360 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -527,6 +527,16 @@ def archive_runner(runner: Runner, strat: StrategyInstance): #print("is not numpy", key, value) flattened_indicators[key]= value flattened_indicators_list.append(flattened_indicators) + flattened_indicators = {} + for key, value in strat.state.secondary_indicators.items(): + if isinstance(value, ndarray): + #print("is numpy", key,value) + flattened_indicators[key]= value.tolist() + #print("changed numpy:",value.tolist()) + else: + #print("is not numpy", key, value) + flattened_indicators[key]= value + flattened_indicators_list.append(flattened_indicators) runArchiveDetail: RunArchiveDetail = RunArchiveDetail(id = runner.id, name=runner.run_name, diff --git a/v2realbot/static/js/utils.js b/v2realbot/static/js/utils.js index 020c5ae..5e91300 100644 --- a/v2realbot/static/js/utils.js +++ b/v2realbot/static/js/utils.js @@ -30,12 +30,12 @@ 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: "CRSI", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, + {name: "SRSI", 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},] + {name: "sec_price", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},] function initialize_statusheader() { diff --git a/v2realbot/strategy/__pycache__/base.cpython-310.pyc b/v2realbot/strategy/__pycache__/base.cpython-310.pyc index d06bc37..a087840 100644 Binary files a/v2realbot/strategy/__pycache__/base.cpython-310.pyc and b/v2realbot/strategy/__pycache__/base.cpython-310.pyc differ diff --git a/v2realbot/strategy/base.py b/v2realbot/strategy/base.py index f05c2e4..16955e9 100644 --- a/v2realbot/strategy/base.py +++ b/v2realbot/strategy/base.py @@ -2,7 +2,7 @@ Strategy base class """ from datetime import datetime -from v2realbot.utils.utils import AttributeDict, zoneNY, is_open_rush, is_close_rush, json_serial, print +from v2realbot.utils.utils import AttributeDict, zoneNY, is_open_rush, is_close_rush, json_serial, print, safe_get, Average from v2realbot.utils.tlog import tlog from v2realbot.utils.ilog import insert_log, insert_log_multiple from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Order, Account @@ -55,7 +55,8 @@ class Strategy: self.rtqueue = None self.runner_id = runner_id self.ilog_save = ilog_save - + self.secondary_res_start_time = dict() + self.secondary_res_start_index = dict() #TODO predelat na dynamické queues self.q1 = queue.Queue() @@ -189,11 +190,57 @@ class Strategy: #pokud je potvrzeny, pak nenese nikdy zmenu ceny, nepridavame zaznam nic self.nextnew = 1 - #TODO potvrzeny CBAR by mohl triggerovat populaci indikatoru se sekundarnim rozlisenim (tbd co BAR?) - #zatim to udelat tak, ze secondary bude jen priceline nikoli ohlcv (pro RSI, MA a slope bude snad dostatecne) - #prvni iterace nastavi 0 (inicializace) - #kazdy potvrzeny bar updatne hodnotu, DOMYSLET tento algoritmus (co bude zde a co v NEXT) - #self.state.secondary_indicators + #pokud jsou nastaveny secondary - zatím skrz stratvars - pripadne do do API + #zatim jedno, predelat pak na list + if safe_get(self.state.vars, "secondary_timeframe",None): + self.process_secondary_indicators(item) + + + #tady jsem skoncil + def process_secondary_indicators(self, item): + #toto je voláno každý potvrzený CBAR + resolution = int(safe_get(self.state.vars, "secondary_timeframe",10)) + if int(item['resolution']) >= int(resolution) or int(resolution) % int(item['resolution']) != 0: + self.state.ilog(e=f"Secondary res {resolution} must be higher than main resolution {item['resolution']} a jejim delitelem") + + #prvni vytvori pocatecni + if safe_get(self.secondary_res_start_time, resolution, None) is None: + self.secondary_res_start_time[resolution] = item['time'] + self.secondary_res_start_index[resolution] = int(item['index']) + self.state.ilog(e=f"INIT SECINDS {self.secondary_res_start_time[resolution]=} {self.secondary_res_start_index[resolution]=}") + + start_timestamp = datetime.timestamp(self.secondary_res_start_time[resolution]) + self.state.ilog(e=f"SECINDS EVAL", start_time=start_timestamp,start_time_plus=start_timestamp + resolution, aktual=datetime.timestamp(item['time'])) + #pokud uz jsme prekrocili okno, ukladame hodnotu + if start_timestamp + resolution <= datetime.timestamp(item['time']): + self.state.ilog(e=f"SECINDS okno prekroceno") + + index_from = self.secondary_res_start_index[resolution] - int(item['index']) -1 + + #vytvorime cas a vyplnime data + for key in self.state.secondary_indicators: + if key == 'time': + #nastavujeme aktualni cas + self.state.secondary_indicators['time'].append(item['time']) + #self.state.secondary_indicators['time'].append(self.secondary_res_start_time[resolution] ) + + #pro cenu vyplnime aktualni cenou, pro ostatni 0 + elif key == 'sec_price': + #do ceny dame ceny v tomto okne + + source = self.state.bars['vwap'] + #source = self.state.bars['close'] + + self.state.ilog(e=f"SECINDS pocitame z hodnot", hodnty=source[index_from:]) + self.state.secondary_indicators[key].append(Average(self.state.bars['close'][index_from:])) + else: + self.state.secondary_indicators[key].append(0) + + self.state.ilog(e="SECIND populated", sec_price=self.state.secondary_indicators['sec_price'][-5:]) + + #priprava start hodnot pro dalsi iteraci + self.secondary_res_start_time[resolution] = item['time'] + self.secondary_res_start_index[resolution] = int(item['index']) """"refresh positions and avgp - for CBAR once per confirmed, for BARS each time""" @@ -445,6 +492,13 @@ class Strategy: rt_out["indicators"][key]= value[-1] except IndexError: pass + #secondaries + if len(self.state.secondary_indicators) > 0 and item['confirmed'] == 1: + for key, value in self.state.secondary_indicators.items(): + try: + rt_out["indicators"][key]= value[-1] + except IndexError: + pass #same for static indicators if len(self.state.statinds) > 0: @@ -580,6 +634,8 @@ class StrategyState: self.trades = AttributeDict(trades) self.indicators = AttributeDict(time=[]) self.cbar_indicators = AttributeDict(time=[]) + #secondary timeframe indicators + self.secondary_indicators = AttributeDict(time=[], sec_price=[]) self.statinds = AttributeDict() #these methods can be overrided by StrategyType (to add or alter its functionality) self.buy = self.interface.buy diff --git a/v2realbot/utils/__pycache__/utils.cpython-310.pyc b/v2realbot/utils/__pycache__/utils.cpython-310.pyc index b762a46..a899d3f 100644 Binary files a/v2realbot/utils/__pycache__/utils.cpython-310.pyc and b/v2realbot/utils/__pycache__/utils.cpython-310.pyc differ diff --git a/v2realbot/utils/utils.py b/v2realbot/utils/utils.py index 6045c33..557eed1 100644 --- a/v2realbot/utils/utils.py +++ b/v2realbot/utils/utils.py @@ -79,6 +79,9 @@ def eval_cond_dict(cond: dict) -> tuple[bool, str]: return False, None +def Average(lst): + return sum(lst) / len(lst) + def safe_get(collection, key, default=None): """Get values from a collection without raising errors"""