From 8004dc4b4c89c2049310877b7af7f3219bb16f25 Mon Sep 17 00:00:00 2001 From: David Brazda Date: Tue, 20 Jun 2023 15:21:21 +0200 Subject: [PATCH] mintrade delta pro kulomet,slowscope,strvrs enhncm --- testy/output_metriky_tradeList.py | 4 +- v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py | 226 +++++-- v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py | 599 ++++++++++++++++++ v2realbot/__pycache__/config.cpython-310.pyc | Bin 2847 -> 2934 bytes .../__pycache__/backtester.cpython-310.pyc | Bin 19082 -> 19107 bytes v2realbot/backtesting/backtester.py | 4 +- v2realbot/config.py | 4 + v2realbot/controller/services.py | 33 +- .../__pycache__/aggregator.cpython-310.pyc | Bin 6953 -> 7067 bytes v2realbot/loader/aggregator.py | 19 +- v2realbot/static/js/archivechart.js | 55 +- v2realbot/static/js/archivetables.js | 17 +- v2realbot/static/js/livewebsocket.js | 31 +- v2realbot/static/js/mytables.js | 12 +- v2realbot/static/js/utils.js | 100 +-- .../strategy/__pycache__/base.cpython-310.pyc | Bin 15792 -> 14325 bytes v2realbot/strategy/base.py | 90 +-- 17 files changed, 1007 insertions(+), 187 deletions(-) create mode 100644 v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py diff --git a/testy/output_metriky_tradeList.py b/testy/output_metriky_tradeList.py index 46d4233..99b18dd 100644 --- a/testy/output_metriky_tradeList.py +++ b/testy/output_metriky_tradeList.py @@ -1018,9 +1018,9 @@ for t in tradeList: trade_dict.timestamp.append(t.timestamp) trade_dict.symbol.append(t.order.symbol) trade_dict.side.append(t.order.side) - trade_dict.qty.append(t.qty) + trade_dict.qty.append(int(t.qty)) trade_dict.price.append(t.price) - trade_dict.position_qty.append(t.position_qty) + trade_dict.position_qty.append(int(t.position_qty)) trade_dict.value.append(t.value) trade_dict.cash.append(t.cash) trade_dict.order_type.append(t.order.order_type) diff --git a/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py b/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py index 4cc2973..cab78ca 100644 --- a/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py +++ b/v2realbot/ENTRY_Vykladaci_RSI_MYSELL.py @@ -5,7 +5,7 @@ from v2realbot.strategy.StrategyOrderLimitVykladaciNormalizedMYSELL import Strat from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType from v2realbot.indicators.indicators import ema from v2realbot.indicators.oscillators import rsi -from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, get_tick, round2five, is_open_rush, is_close_rush, eval_cond_dict +from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, get_tick, round2five, is_open_rush, is_close_rush, eval_cond_dict, Average from datetime import datetime #from icecream import install, ic #from rich import print @@ -33,6 +33,7 @@ potvrzený CBAR """ + stratvars = AttributeDict(maxpozic = 400, def_mode_from = 200, chunk = 10, @@ -108,7 +109,7 @@ def next(data, state: StrategyState): #state.ilog(e=f"STANDARD mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions) return False - def get_limitka_price(): + def get_profit_price(): def_profit = safe_get(state.vars, "def_profit",state.vars.profit) cena = float(state.avgp) #v MYSELL hrajeme i na 3 desetinna cisla - TBD mozna hrat jen na 5ky (0.125, 0.130, 0.135 atp.) @@ -117,6 +118,11 @@ def next(data, state: StrategyState): else: return price2dec(cena+get_tick(cena,float(state.vars.profit)),3) + def get_max_profit_price(): + max_profit = float(safe_get(state.vars, "max_profit",0.03)) + cena = float(state.avgp) + return price2dec(cena+get_tick(cena,max_profit),3) + def optimize_qty_multiplier(): akt_pozic = int(state.positions)/int(state.vars.chunk) multiplier = 1 @@ -124,7 +130,7 @@ def next(data, state: StrategyState): #zatim jednoduse pokud je akt. pozice 1 nebo 3 chunky (<4) tak zdvojnásubuju #aneb druhy a treti nakup if akt_pozic > 0 and akt_pozic < 4: - multiplier = safe_get(state.vars, "market_buy_multiplier", 2) + multiplier = safe_get(state.vars, "market_buy_multiplier", 1) state.ilog(e=f"BUY MULTIPLIER: {multiplier}") return multiplier @@ -252,8 +258,9 @@ def next(data, state: StrategyState): curr_price = float(data['close']) state.ilog(e="Eval SELL", price=curr_price, pos=state.positions, avgp=state.avgp, sell_in_progress=state.vars.sell_in_progress) if int(state.positions) > 0 and float(state.avgp)>0 and state.vars.sell_in_progress is False: - goal_price = get_limitka_price() - state.ilog(e=f"Goal price {goal_price}") + goal_price = get_profit_price() + max_price = get_max_profit_price() + state.ilog(e=f"Goal price {goal_price} max price {max_price}") #pokud je cena vyssi if curr_price>=goal_price: @@ -261,12 +268,12 @@ def next(data, state: StrategyState): #TODO cekat az slope prestane intenzivn erust, necekat az na klesani #TODO mozna cekat na nejaky signal RSI #TODO pripadne pokud dosahne TGTBB prodat ihned - + max_price_signal = curr_price>=max_price #OPTIMALIZACE pri stoupajícím angle - if sell_protection_enabled() is False: + if max_price_signal or sell_protection_enabled() is False: state.interface.sell(size=state.positions) state.vars.sell_in_progress = True - state.ilog(e=f"market SELL was sent {curr_price=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress) + state.ilog(e=f"market SELL was sent {curr_price=} {max_price_signal=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress) #pokud je cena nizsi, testujeme REVERSE POZITION PROTECTION else: pass @@ -312,9 +319,39 @@ def next(data, state: StrategyState): - - + # None - standard, defaults mode - attributes are read from general stratvars section + # other modes - attributtes are read from mode specific stratvars section, defaults to general section + #WIP + def set_mode(): + state.vars.mode = None + #dotahne hodnotu z prislusne sekce + #pouziva se namisto safe_get + # stratvars + # buysignal = 1 + # stratvars.mode1 + # buysignal = 2 + # PARAMS: + # - section: napr. stratvars.buysignal + # - var name: MA_length + # - default: defaultní hodnota, kdyz nenalezeno + # Kroky: 1) + # vrati danou hodnotu nastaveni podle aktualniho modu state.vars.mode + # pokud je None, vrati pro standardni mod, pokud neni nalezeno vrati default + # EXAMPLE: + # get_modded_vars("state") + #get_modded_vars(state.vars, 'buysignal', 1) - namista safe_get + + #WIP + def get_modded_vars(section, name: str, default = None): + if state.vars.mode is None: + return safe_get(section, name, default) + else: + try: + modded_section = section[state.vars.mode] + except KeyError: + modded_section = section + return safe_get(modded_section, name, safe_get(section, name, default)) def populate_ema_indicator(): #BAR EMA INDICATOR - @@ -336,6 +373,63 @@ def next(data, state: StrategyState): #evaluate buy signal #consolidation + # [stratvars.indicators.slope] + # lookback + # lookback_offset + def populate_slow_slope_indicator(): + options = safe_get(state.vars.indicators, 'slow_slope', None) + if options is None: + state.ilog(e="No options for slow slope in stratvars") + return + + + #SLOW SLOPE INDICATOR + #úhel stoupání a klesání vyjádřený mezi -1 až 1 + #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 (angle) pro vizualizaci + try: + slow_slope = 99 + slope_lookback = safe_get(options, 'slope_lookback', 100) + minimum_slope = safe_get(options, 'minimum_slope', 25) + maximum_slope = safe_get(options, "maximum_slope",0.9) + lookback_offset = safe_get(options, 'lookback_offset', 25) + + if len(state.bars.close) > (slope_lookback + lookback_offset): + array_od = slope_lookback + lookback_offset + array_do = slope_lookback + lookbackprice_array = state.bars.vwap[-array_od:-array_do] + #obycejný prumer hodnot + lookbackprice = round(sum(lookbackprice_array)/lookback_offset,3) + lookbacktime = state.bars.time[-slope_lookback] + else: + #kdyz neni dostatek hodnot, pouzivame jako levy bod open hodnotu close[0] + lookbackprice = state.bars.close[0] + lookbacktime = state.bars.time[0] + state.ilog(e="Slow Slope - not enough data bereme left bod open", slope_lookback=slope_lookback, slope=state.indicators.slope, slopeMA=state.indicators.slopeMA) + + #výpočet úhlu - a jeho normalizace + slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100 + slope = round(slope, 4) + state.indicators.slow_slope[-1]=slope + + #angle je ze slope + state.statinds.angle_slow = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=lookbacktime, lookbackprice=lookbackprice, minimum_slope=minimum_slope, maximum_slope=maximum_slope) + + #slope MA vyrovna vykyvy ve slope, dále pracujeme se slopeMA + slope_MA_length = safe_get(options, 'MA_length', 5) + source = state.indicators.slow_slope[-slope_MA_length:] + slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap + slopeMA = slopeMAseries[-1] + state.indicators.slow_slopeMA[-1]=slopeMA + + state.ilog(e=f"SLOW {slope=} {slopeMA=}", msg=f"{lookbackprice=}", lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-10:], last_slopesMA=state.indicators.slopeMA[-10:]) + #dale pracujeme s timto MAckovanym slope + #slope = slopeMA + + except Exception as e: + print("Exception in NEXT Slow Slope Indicator section", str(e)) + state.ilog(e="EXCEPTION", msg="Exception in Slow Slope Indicator section" + str(e) + format_exc()) + def populate_slope_indicator(): #SLOPE INDICATOR #úhel stoupání a klesání vyjádřený mezi -1 až 1 @@ -396,32 +490,37 @@ def next(data, state: StrategyState): state.ilog(e=f"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc()) #state.indicators.RSI14[-1]=0 - # def populate_cbar_rsi_indicator(): - # #CBAR RSI indicator - # try: - # crsi_length = int(safe_get(state.vars, "crsi_length",14)) - # source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap - # crsi_res = rsi(source, crsi_length) - # crsi_value = trunc(crsi_res[-1],3) - # state.cbar_indicators.CRSI[-1]=crsi_value - # #state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:]) - # except Exception as e: - # state.ilog(e=f"CRSI {crsi_length=} necháváme 0", message=str(e)+format_exc()) - # #state.indicators.RSI14[-1]=0 + def populate_cbar_rsi_indicator(): + #CBAR RSI indicator + options = safe_get(state.vars.indicators, 'crsi', None) + if options is None: + state.ilog(e="No options for crsi in stratvars") + return - def populate_secondary_rsi_indicator(): - #SBAR RSI indicator try: - 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 + crsi_length = int(safe_get(options, 'crsi_length', 14)) + source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap + crsi_res = rsi(source, crsi_length) + crsi_value = crsi_res[-1] + 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"SRSI {srsi_length=} necháváme 0", message=str(e)+format_exc()) + 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: + # 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"SRSI {srsi_length=} necháváme 0", message=str(e)+format_exc()) + # #state.indicators.RSI14[-1]=0 + def slope_too_low(): return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope) @@ -470,6 +569,25 @@ def next(data, state: StrategyState): return result def sell_protection_enabled(): + options = safe_get(state.vars, 'sell_protection', None) + if options is None: + state.ilog(e="No options for sell protection in stratvars") + return False + + disable_sell_proteciton_when = dict(AND=dict(), OR=dict()) + + #preconditions + disable_sell_proteciton_when['disabled_in_config'] = safe_get(options, 'enabled', False) is False + #too good to be true (maximum profit) + #disable_sell_proteciton_when['tgtbt_reached'] = safe_get(options, 'tgtbt', False) is False + + + #testing preconditions + result, conditions_met = eval_cond_dict(disable_sell_proteciton_when) + if result: + state.ilog(e=f"SELL_PROTECTION DISABLED by precondition {conditions_met}") + return False + dont_sell_when = dict(AND=dict(), OR=dict()) ##add conditions here @@ -477,9 +595,13 @@ def next(data, state: StrategyState): #pokud je slope too high, pak prodavame jakmile slopeMA zacne klesat, napr. 4MA (TODO 3) + #TODO zkusit pro pevny profit, jednoduse pozdrzet prodej - dokud tick_price roste nebo se drzi tak neprodavat, pokud klesne prodat + #mozna mit dva mody - pri vetsi volatilite pouzivat momentum, pri mensi nebo kdyz potrebuju pryc, tak prodat hned + + #toto docasne pryc dont_sell_when['slope_too_high'] = slope_too_high() and not isfalling(state.indicators.slopeMA,4) - dont_sell_when['AND']['slopeMA_rising'] = isrising(state.indicators.slopeMA,2) - dont_sell_when['AND']['rsi_not_falling'] = not isfalling(state.indicators.RSI14,3) + dont_sell_when['AND']['slopeMA_rising'] = isrising(state.indicators.slopeMA,safe_get(options, 'slopeMA_rising', 2)) + dont_sell_when['AND']['rsi_not_falling'] = not isfalling(state.indicators.RSI14,safe_get(options, 'rsi_not_falling',3)) #dont_sell_when['rsi_dont_buy'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50) result, conditions_met = eval_cond_dict(dont_sell_when) @@ -492,7 +614,6 @@ def next(data, state: StrategyState): #preconditions dont_buy_when = dict(AND=dict(), OR=dict()) - if safe_get(state.vars, "buy_only_on_confirmed",True): dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0) #od posledniho vylozeni musi ubehnout N baru @@ -563,7 +684,8 @@ def next(data, state: StrategyState): # state.indicators.tick_volume[-1] = state.indicators.tick_volume[-2] # else: - tick_price = round2five(data['close']) + #tick_price = round2five(data['close']) + tick_price = data['close'] tick_delta_volume = data['volume'] - state.vars.last_tick_volume #docasne dame pryc volume deltu a davame absolutni cislo @@ -588,16 +710,24 @@ def next(data, state: StrategyState): if key != 'time': 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:] + # 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'] + + #PROCES DELTAS - to function last_update_delta = round((float(data['updated']) - state.vars.last_update_time),6) if state.vars.last_update_time != 0 else 0 state.vars.last_update_time = float(data['updated']) - state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}") + + if len(state.vars.last_50_deltas) >=50: + state.vars.last_50_deltas.pop(0) + state.vars.last_50_deltas.append(last_update_delta) + avg_delta = Average(state.vars.last_50_deltas) + + state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}---AVGdelta:{avg_delta}") #kroky pro CONFIRMED BAR only if conf_bar == 1: @@ -609,13 +739,17 @@ def next(data, state: StrategyState): state.vars.last_tick_volume = 0 state.vars.next_new = 1 + #zatim takto na confirm + populate_slow_slope_indicator() + #SRSI - populate_secondary_rsi_indicator() + #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 +762,8 @@ def next(data, state: StrategyState): consolidation() #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) + lp = data['close'] state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, data=data, stratvars=state.vars) state.ilog(e="Indikatory", msg=str(get_last_ind_vals())) @@ -640,7 +775,9 @@ def init(state: StrategyState): print("INIT v main",state.name) state.vars['sell_in_progress'] = False + state.vars.mode = None state.vars.last_tick_price = 0 + state.vars.last_50_deltas = [] state.vars.last_tick_volume = 0 state.vars.next_new = 0 state.vars.last_buysignal_index = 0 @@ -649,13 +786,20 @@ def init(state: StrategyState): #state.cbar_indicators['ivwap'] = [] state.cbar_indicators['tick_price'] = [] state.cbar_indicators['tick_volume'] = [] - state.secondary_indicators['SRSI'] = [] + state.cbar_indicators['CRSI'] = [] + #state.secondary_indicators['SRSI'] = [] state.indicators['ema'] = [] state.indicators['slope'] = [] state.indicators['slopeMA'] = [] + state.indicators['slow_slope'] = [] + state.indicators['slow_slopeMA'] = [] state.indicators['RSI14'] = [] #static indicators - those not series based state.statinds['angle'] = dict(minimum_slope=state.vars["minimum_slope"], maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20)) + #state.statinds['angle_slow'] = dict(minimum_slope=safe_get(state.vars.indicators.slow_slope, "minimum_slope",-2), maximum_slope=safe_get(state.vars.indicators.slow_slope, "maximum_slope",2)) + state.statinds['angle_slow'] = dict(minimum_slope=state.vars['indicators']['slow_slope']["minimum_slope"], maximum_slope=state.vars['indicators']['slow_slope']["maximum_slope"]) + + state.vars["ticks2reset_backup"] = state.vars.ticks2reset def main(): diff --git a/v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py b/v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py new file mode 100644 index 0000000..eb6a0a9 --- /dev/null +++ b/v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py @@ -0,0 +1,599 @@ +import os,sys +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +from v2realbot.strategy.base import StrategyState +from v2realbot.strategy.StrategyOrderLimitVykladaciNormalizedMYSELL import StrategyOrderLimitVykladaciNormalizedMYSELL +from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType +from v2realbot.indicators.indicators import ema +from v2realbot.indicators.oscillators import rsi +from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, get_tick, round2five, is_open_rush, is_close_rush, eval_cond_dict +from datetime import datetime +#from icecream import install, ic +#from rich import print +from threading import Event +from msgpack import packb, unpackb +import asyncio +import os +from traceback import format_exc +import inspect + +print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +"""" +Využívá: StrategyOrderLimitVykladaciNormalizedMYSELL + +Kopie RSI Normalizovane Vykladaci navíc s řízením prodeje. +Nepoužíváme LIMITKU. + +Required CBAR. (pouze se změnou ceny) + +nepotvrzený CBAR bez minticku (pouze se změnou ceny) +- se používá pro žízení prodeje + +potvrzený CBAR +- se používá pro BUY + + +""" +stratvars = AttributeDict(maxpozic = 400, + def_mode_from = 200, + chunk = 10, + MA = 2, + Trend = 2, + profit = 0.02, + def_profit = 0.01, + 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], + curve_def = [0.02, 0.02, 0.02, 0, 0, 0.02, 0, 0, 0, 0.02], + blockbuy = 0, + ticks2reset = 0.04, + consolidation_bar_count = 10, + slope_lookback = 300, + lookback_offset = 20, + minimum_slope = -0.05, + first_buy_market = False + ) +##toto rozparsovat a strategii spustit stejne jako v main +toml_string = """ +[[strategies]] +name = "V1 na BAC" +symbol = "BAC" +script = "ENTRY_backtest_strategyVykladaci" +class = "StrategyOrderLimitVykladaci" +open_rush = 0 +close_rush = 0 +[strategies.stratvars] +maxpozic = 200 +chunk = 10 +MA = 6 +Trend = 5 +profit = 0.02 +lastbuyindex=-6 +pendingbuys={} +limitka = "None" +jevylozeno=0 +vykladka=5 +curve = [0.01, 0.01, 0.01,0.01, 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] +blockbuy = 0 +ticks2reset = 0.04 +[[strategies.add_data]] +symbol="BAC" +rectype="bar" +timeframe=5 +update_ltp=true +align="round" +mintick=0 +minsize=100 +exthours=false +""" + +def next(data, state: StrategyState): + print(10*"*","NEXT START",10*"*") + #ic(state.avgp, state.positions) + #ic(state.vars) + #ic(data) + + # + def is_defensive_mode(): + akt_pozic = int(state.positions) + max_pozic = int(state.vars.maxpozic) + def_mode_from = safe_get(state.vars, "def_mode_from",max_pozic/2) + if akt_pozic >= int(def_mode_from): + #state.ilog(e=f"DEFENSIVE mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions) + return True + else: + #state.ilog(e=f"STANDARD mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions) + return False + + def get_limitka_price(): + def_profit = safe_get(state.vars, "def_profit",state.vars.profit) + cena = float(state.avgp) + #v MYSELL hrajeme i na 3 desetinna cisla - TBD mozna hrat jen na 5ky (0.125, 0.130, 0.135 atp.) + if is_defensive_mode(): + return price2dec(cena+get_tick(cena,float(def_profit)),3) + else: + return price2dec(cena+get_tick(cena,float(state.vars.profit)),3) + + def consolidation(): + ##CONSOLIDATION PART - moved here, musí být před nákupem, jinak to dělalo nepořádek v pendingbuys + #docasne zkusime konzolidovat i kdyz neni vylozeno (aby se srovnala limitka ve vsech situacich) + if state.vars.jevylozeno == 1 or 1==1: + ##CONSOLIDATION PART kazdy Nty bar dle nastaveni + if int(data["index"])%int(state.vars.consolidation_bar_count) == 0: + print("***CONSOLIDATION ENTRY***") + state.ilog(e="CONSOLIDATION ENTRY ***") + + orderlist = state.interface.get_open_orders(symbol=state.symbol, side=None) + #pro jistotu jeste dotahneme aktualni pozice + state.avgp, state.positions = state.interface.pos() + + #print(orderlist) + pendingbuys_new = {} + #zaciname s cistym stitem + state.vars.limitka = None + state.vars.limitka_price = None + for o in orderlist: + if o.side == OrderSide.BUY and o.order_type == OrderType.LIMIT: + pendingbuys_new[str(o.id)]=float(o.limit_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 jevylozeno", msg=state.vars.jevylozeno) + + print("***CONSOLIDATION EXIT***") + state.ilog(e="CONSOLIDATION EXIT ***") + else: + state.ilog(e="No time for consolidation", msg=data["index"]) + print("no time for consolidation", data["index"]) + #mozna presunout o level vys + def vyloz(): + ##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci + #curve = [0.01, 0.01, 0, 0, 0.01, 0, 0, 0, 0.02, 0, 0, 0, 0.03, 0,0,0,0,0, 0.02, 0,0,0,0,0,0, 0.02] + curve = state.vars.curve + ##defenzivni krivka pro + curve_def = state.vars.curve_def + #vykladani po 5ti kusech, když zbývají 2 a méně, tak děláme nový výklad + vykladka = state.vars.vykladka + #kolik muzu max vylozit + kolikmuzu = int((int(state.vars.maxpozic) - int(state.positions))/int(state.vars.chunk)) + akt_pozic = int(state.positions) + max_pozic = int(state.vars.maxpozic) + + if akt_pozic >= max_pozic: + state.ilog(e="MAX pozic reached, cannot vyklad") + return + + #mame polovinu a vic vylozeno, pouzivame defenzicni krivku + if is_defensive_mode(): + state.ilog(e="DEF: Pouzivame defenzivni krivku", akt_pozic=akt_pozic, max_pozic=max_pozic, curve_def=curve_def) + curve = curve_def + #zaroven docasne menime ticks2reset na defenzivni 0.06 + state.vars.ticks2reset = 0.06 + state.ilog(e="DEF: Menime tick2reset na 0.06", ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup) + else: + #vracime zpet, pokud bylo zmeneno + if state.vars.ticks2reset != state.vars.ticks2reset_backup: + state.vars.ticks2reset = state.vars.ticks2reset_backup + state.ilog(e="DEF: Menime tick2reset zpet na"+str(state.vars.ticks2reset), ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup) + + if kolikmuzu < vykladka: vykladka = kolikmuzu + + if len(curve) < vykladka: + vykladka = len(curve) + qty = int(state.vars.chunk) + last_price = price2dec(state.interface.get_last_price(state.symbol)) + #profit = float(state.vars.profit) + price = last_price + state.ilog(e="BUY Vykladame", msg=f"first price {price=} {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 + + ##VAR - na zaklade conf. muzeme jako prvni posilat MARKET order + if safe_get(state.vars, "first_buy_market") == True: + #pri defenzivnim rezimu pouzivame vzdy LIMIT order + if is_defensive_mode(): + state.ilog(e="DEF mode on, odesilame jako prvni limitku") + state.buy_l(price=price, size=qty) + else: + state.ilog(e="Posilame jako prvni MARKET order") + state.buy(size=qty) + else: + state.buy_l(price=price, size=qty) + print("prvni limitka na aktuální cenu. Další podle křivky", price, qty) + for i in range(0,vykladka-1): + price = price2dec(float(price - get_tick(price, curve[i]))) + if price == last_price: + qty = qty + int(state.vars.chunk) + else: + state.buy_l(price=price, size=qty) + #print(i,"BUY limitka - delta",curve[i]," cena:", price, "mnozstvi:", qty) + qty = int(state.vars.chunk) + last_price = price + state.vars.blockbuy = 1 + state.vars.jevylozeno = 1 + state.vars.last_buysignal_index = data['index'] + + def eval_sell(): + """" + TBD + Když je RSI nahoře tak neprodávat, dokud 1) RSI neprestane stoupat 2)nedosahne to nad im not greedy limit + """ + ##mame pozice + ##aktualni cena je vetsi nebo rovna cene limitky + #muzeme zde jet i na pulcenty + curr_price = float(data['close']) + state.ilog(e="Eval SELL", price=curr_price, pos=state.positions, avgp=state.avgp, sell_in_progress=state.vars.sell_in_progress) + if int(state.positions) > 0 and float(state.avgp)>0 and state.vars.sell_in_progress is False: + goal_price = get_limitka_price() + state.ilog(e=f"Goal price {goal_price}") + if curr_price>=goal_price: + + #TODO cekat az slope prestane intenzivn erust, necekat az na klesani + #TODO mozna cekat na nejaky signal RSI + #TODO pripadne pokud dosahne TGTBB prodat ihned + + #OPTIMALIZACE pri stoupajícím angle + if sell_protection_enabled() is False: + state.interface.sell(size=state.positions) + state.vars.sell_in_progress = True + state.ilog(e=f"market SELL was sent {curr_price=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress) + + def populate_ema_indicator(): + #BAR EMA INDICATOR - + #plnime MAcko - nyni posilame jen N poslednich hodnot + #zaroven osetrujeme pripady, kdy je malo dat a ukladame nulu + try: + ma = int(state.vars.MA) + #poslednich ma hodnot + source = state.bars.close[-ma:] #state.bars.vwap + ema_value = ema(source, ma) + + ##pokus MACKO zakrouhlit na tri desetina a petku + state.indicators.ema[-1]=round2five(ema_value[-1]) + ##state.indicators.ema[-1]=trunc(ema_value[-1],3) + #state.ilog(e=f"EMA {state.indicators.ema[-1]}", ema_last=state.indicators.ema[-6:]) + except Exception as e: + state.ilog(e="EMA nechavame 0", message=str(e)+format_exc()) + #state.indicators.ema[-1]=(0) + #evaluate buy signal + #consolidation + + def populate_slope_indicator(): + #SLOPE INDICATOR + #úhel stoupání a klesání vyjádřený mezi -1 až 1 + #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 (angle) pro vizualizaci + try: + slope = 99 + slope_lookback = int(state.vars.slope_lookback) + minimum_slope = float(state.vars.minimum_slope) + lookback_offset = int(state.vars.lookback_offset) + + if len(state.bars.close) > (slope_lookback + lookback_offset): + array_od = slope_lookback + lookback_offset + array_do = slope_lookback + lookbackprice_array = state.bars.vwap[-array_od:-array_do] + #obycejný prumer hodnot + lookbackprice = round(sum(lookbackprice_array)/lookback_offset,3) + + #výpočet úhlu - a jeho normalizace + slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100 + slope = round(slope, 4) + state.indicators.slope[-1]=slope + + #angle je ze slope + state.statinds.angle = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=state.bars.time[-slope_lookback], lookbackprice=lookbackprice, minimum_slope=minimum_slope, maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20)) + + #slope MA vyrovna vykyvy ve slope, dále pracujeme se slopeMA + slope_MA_length = 5 + source = state.indicators.slope[-slope_MA_length:] + slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap + slopeMA = slopeMAseries[-1] + state.indicators.slopeMA[-1]=slopeMA + + state.ilog(e=f"{slope=} {slopeMA=}", msg=f"{lookbackprice=}", lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-10:], last_slopesMA=state.indicators.slopeMA[-10:]) + + #dale pracujeme s timto MAckovanym slope + slope = slopeMA + else: + #pokud plnime historii musime ji plnit od zacatku, vsehcny idenitifkatory maji spolecny time + #kvuli spravnemu zobrazovani na gui + #state.indicators.slopeMA[-1]=0 + #state.indicators.slopeMA.append(0) + state.ilog(e="Slope - not enough data", slope_lookback=slope_lookback, slope=state.indicators.slope, slopeMA=state.indicators.slopeMA) + except Exception as e: + print("Exception in NEXT Slope Indicator section", str(e)) + state.ilog(e="EXCEPTION", msg="Exception in Slope Indicator section" + str(e) + format_exc()) + + def populate_rsi_indicator(): + #RSI14 INDICATOR + try: + rsi_length = int(safe_get(state.vars, "rsi_length",14)) + source = state.bars.close #[-rsi_length:] #state.bars.vwap + rsi_res = rsi(source, rsi_length) + rsi_value = trunc(rsi_res[-1],3) + state.indicators.RSI14[-1]=rsi_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"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc()) + #state.indicators.RSI14[-1]=0 + + def populate_cbar_rsi_indicator(): + #CBAR RSI indicator + try: + crsi_length = int(safe_get(state.vars, "crsi_length",14)) + source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap + crsi_res = rsi(source, crsi_length) + crsi_value = trunc(crsi_res[-1],3) + state.cbar_indicators.CRSI[-1]=crsi_value + #state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:]) + except Exception as e: + state.ilog(e=f"CRSI {crsi_length=} necháváme 0", message=str(e)+format_exc()) + #state.indicators.RSI14[-1]=0 + + def slope_too_low(): + return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope) + + def slope_too_high(): + return state.indicators.slopeMA[-1] > float(safe_get(state.vars, "bigwave_slope_above",0.20)) + + #resetujeme, kdyz 1) je aktivni buy protection 2) kdyz to ujede + #TODO mozna tick2reset spoustet jednou za X opakovani + def pendingbuys_optimalization(): + if len(state.vars.pendingbuys)>0: + if buy_protection_enabled(): + #state.ilog(e="PENDINGBUYS reset", message=inspect.currentframe().f_code.co_name) + res = asyncio.run(state.cancel_pending_buys()) + state.ilog(e="CANCEL pendingbuyes", pb=state.vars.pendingbuys, res=res) + else: + #pokud mame vylozeno a cena je vetsi nez tick2reset + maxprice = max(state.vars.pendingbuys.values()) + if state.interface.get_last_price(state.symbol) > float(maxprice) + get_tick(maxprice, float(state.vars.ticks2reset)): + res = asyncio.run(state.cancel_pending_buys()) + state.ilog(e=f"UJELO to. Rusime PB", msg=f"{state.vars.ticks2reset=}", pb=state.vars.pendingbuys) + + #PENDING BUYS SPENT - PART + #pokud mame vylozeno a pendingbuys se vyklepou a + # 1 vykladame idned znovu + # vyloz() + # 2 nebo - počkat zase na signál a pokračovat dál + # state.vars.blockbuy = 0 + # state.vars.jevylozeno = 0 + # 3 nebo - počkat na signál s enablovaným lastbuy indexem (tzn. počká nutně ještě pár barů) + #podle BT vyhodnejsi vylozit ihned + if len(state.vars.pendingbuys) == 0: + state.vars.blockbuy = 0 + state.vars.jevylozeno = 0 + state.ilog(e="PB prazdne nastavujeme: neni vylozeno", jevylozeno=state.vars.jevylozeno) + + ##kdy nesmí být žádné nákupní objednávky - zruší se + def buy_protection_enabled(): + dont_buy_when = dict(AND=dict(), OR=dict()) + ##add conditions here + dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50) + dont_buy_when['slope_too_low'] = slope_too_low() + + result, cond_met = eval_cond_dict(dont_buy_when) + if result: + state.ilog(e=f"BUY_PROTECTION {cond_met}") + return result + + def sell_protection_enabled(): + dont_sell_when = dict(AND=dict(), OR=dict()) + ##add conditions here + + #IDENTIFIKOVAce rustoveho MOMENTA - pokud je momentum, tak prodávat později + + #pokud je slope too high, pak prodavame jakmile slopeMA zacne klesat, napr. 4MA (TODO 3) + + #toto docasne pryc dont_sell_when['slope_too_high'] = slope_too_high() and not isfalling(state.indicators.slopeMA,4) + dont_sell_when['AND']['slopeMA_rising'] = isrising(state.indicators.slopeMA,2) + dont_sell_when['AND']['rsi_not_falling'] = not isfalling(state.indicators.RSI14,3) + #dont_sell_when['rsi_dont_buy'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50) + + result, conditions_met = eval_cond_dict(dont_sell_when) + if result: + state.ilog(e=f"SELL_PROTECTION {conditions_met} enabled") + return result + + #preconditions and conditions of BUY SIGNAL + def buy_conditions_met(): + #preconditions + dont_buy_when = dict(AND=dict(), OR=dict()) + + + if safe_get(state.vars, "buy_only_on_confirmed",True): + dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0) + #od posledniho vylozeni musi ubehnout N baru + dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (state.vars.last_buysignal_index + safe_get(state.vars, "lastbuy_offset",3)) + dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1) + dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1) + dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50) + dont_buy_when['slope_too_low'] = slope_too_low() + dont_buy_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0)) + dont_buy_when['close_rush'] = is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "close_rush",0)) + dont_buy_when['rsi_is_zero'] = (state.indicators.RSI14[-1] == 0) + + #testing preconditions + result, cond_met = eval_cond_dict(dont_buy_when) + if result: + state.ilog(e=f"BUY precondition not met {cond_met}") + return False + + #conditions - bud samostatne nebo v groupe - ty musi platit dohromady + buy_cond = dict(AND=dict(), OR=dict()) + ##add buy conditions here + #cond groups ["AND"] + #cond groups ["OR"] + #no cond group - takes first + #TEST BUY SIGNALu z cbartick_price - 3klesave za sebou + #buy_cond['tick_price_falling_trend'] = isfalling(state.cbar_indicators.tick_price,state.vars.Trend) + + #slopeMA jde dolu, rsi jde nahoru + #buy mame kazdy potvrzeny, tzn. rsi falling muze byt jen 2 + + #buy_cond['AND']['slopeMA_falling'] = isfalling(state.indicators.slopeMA,3) + #buy_cond['AND']['rsi_is_rising'] = isrising(state.indicators.RSI14,2) + #buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) + + #puvodni buy conditiony RSI pod + EMA klesajici + #buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) + #buy_cond["AND"]["ema_trend_is_falling"] = isfalling(state.indicators.ema,state.vars.Trend) + + #pouze RSI nizke a RSI klesa + buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) + buy_cond["AND"]["rsi_is_falling"] = isfalling(state.indicators.RSI14,state.vars.Trend) + + #buy_cond['crsi_below_crsi_buy_limit'] = state.cbar_indicators.CRSI[-1] < safe_get(state.vars, "crsi_buy_signal_below",30) + + #slopME klesa a RSI začalo stoupat + # buy_cond["AND"]["rsi_is_rising2"] = isrising(state.indicators.RSI14,2) + # buy_cond['AND']['slopeMA_falling_Trend'] = isfalling(state.indicators.slopeMA,state.vars.Trend) + # buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) + + + #zkusit jako doplnkovy BUY SIGNAL 3 klesavy cbar RSI pripadne TICK PRICE + + result, conditions_met = eval_cond_dict(buy_cond) + if result: + state.ilog(e=f"BUY SIGNAL {conditions_met}") + return result + + def eval_buy(): + if buy_conditions_met(): + vyloz() + + def populate_cbar_tick_price_indicator(): + try: + #pokud v potvrzovacím baru nebyly zmeny, nechavam puvodni hodnoty + # if tick_delta_volume == 0: + # state.indicators.tick_price[-1] = state.indicators.tick_price[-2] + # state.indicators.tick_volume[-1] = state.indicators.tick_volume[-2] + # else: + + tick_price = round2five(data['close']) + tick_delta_volume = data['volume'] - state.vars.last_tick_volume + + #docasne dame pryc volume deltu a davame absolutni cislo + state.cbar_indicators.tick_price[-1] = tick_price + state.cbar_indicators.tick_volume[-1] = tick_delta_volume + except: + pass + + state.ilog(e=f"TICK PRICE {tick_price} VOLUME {tick_delta_volume} {conf_bar=}", prev_price=state.vars.last_tick_price, prev_volume=state.vars.last_tick_volume) + + state.vars.last_tick_price = tick_price + state.vars.last_tick_volume = data['volume'] + + def get_last_ind_vals(): + last_ind_vals = {} + #print(state.indicators.items()) + for key in state.indicators: + if key != 'time': + last_ind_vals[key] = state.indicators[key][-5:] + + for key in state.cbar_indicators: + if key != 'time': + last_ind_vals[key] = state.cbar_indicators[key][-5:] + return last_ind_vals + + conf_bar = data['confirmed'] + last_update_delta = round((float(data['updated']) - state.vars.last_update_time),6) if state.vars.last_update_time != 0 else 0 + state.vars.last_update_time = float(data['updated']) + state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}") + + #kroky pro CONFIRMED BAR only + if conf_bar == 1: + #logika pouze pro potvrzeny bar + state.ilog(e="BAR potvrzeny") + + + #pri potvrzem CBARu nulujeme counter volume pro tick based indicator + state.vars.last_tick_volume = 0 + state.vars.next_new = 1 + + #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 + + + populate_ema_indicator() + populate_slope_indicator() + populate_rsi_indicator() + eval_sell() + consolidation() + + #HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru + lp = state.interface.get_last_price(symbol=state.symbol) + state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, data=data, stratvars=state.vars) + state.ilog(e="Indikatory", msg=str(get_last_ind_vals())) + + eval_buy() + pendingbuys_optimalization() + +def init(state: StrategyState): + #place to declare new vars + print("INIT v main",state.name) + + state.vars['sell_in_progress'] = False + state.vars.last_tick_price = 0 + state.vars.last_tick_volume = 0 + state.vars.next_new = 0 + state.vars.last_buysignal_index = 0 + state.vars.last_update_time = 0 + #state.cbar_indicators['ivwap'] = [] + state.cbar_indicators['tick_price'] = [] + state.cbar_indicators['tick_volume'] = [] + state.cbar_indicators['CRSI'] = [] + state.indicators['ema'] = [] + state.indicators['slope'] = [] + state.indicators['slopeMA'] = [] + state.indicators['RSI14'] = [] + #static indicators - those not series based + state.statinds['angle'] = dict(minimum_slope=state.vars["minimum_slope"], maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20)) + state.vars["ticks2reset_backup"] = state.vars.ticks2reset + +def main(): + name = os.path.basename(__file__) + se = Event() + pe = Event() + s = StrategyOrderLimitVykladaciNormalizedMYSELL(name = name, symbol = "BAC", account=Account.ACCOUNT1, next=next, init=init, stratvars=stratvars, open_rush=10, close_rush=0, pe=pe, se=se, ilog_save=True) + s.set_mode(mode = Mode.BT, + debug = False, + start = datetime(2023, 4, 14, 10, 42, 0, 0, tzinfo=zoneNY), + end = datetime(2023, 4, 14, 14, 35, 0, 0, tzinfo=zoneNY), + cash=100000) + + #na sekundovem baru nezaokrouhlovat MAcko + 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.start() + print("zastavujeme") + +if __name__ == "__main__": + main() + + + + + \ No newline at end of file diff --git a/v2realbot/__pycache__/config.cpython-310.pyc b/v2realbot/__pycache__/config.cpython-310.pyc index 3aec37775dd021fcc66fbaa753812cb3856b8cc5..8ebf095ba3b000e9fcf2c741a61c4ea672573538 100644 GIT binary patch delta 360 zcmW-dJx{`55XXDvp}Yv?t(3PS0=^-OiB3d=6)F;`l8O$ubh(OQabeO#6Jc{AbvN+? zxG?HRFflQH0T)*{2jk!qF1gG7e)%Vt+=Kd~$`|2qP~f#wyrWxrB5Uw9sWxsXfMLfw zkTEiwQ3_&=B#ie3ntKFHI6exE0F{8y5-3daSRi>MVv^yD?Gf)Z3Wk8 z{#d9KTp1ev-|NB4&^@oaT}TG{SISfC^Kw|9I`9Edoz^@ez^1#+PGMtu&uSuUxo^@R zRNYsfsU-AP%QoAGcF)qAhTSweJ>5U hPt57N-z#eS{Cy!ofeYh4PD8pYW_zNu!O94Vlp`{3w%t1BdTSg7_B})?xi4jQ)O-T?-8!hR; zm2O7URC-8c9c|gLcGIr)v;LpnLPxgIl^v^hZFykJL)k-mp+-Fu)5P3Rl+Wp%XqaC* znrLjU`HBwmXFk$&XujMZ8kx`Hxj9>V$p;?m$&a;c>nJ?q>RXOC}h03$~-+t@+!p&^)jr%FKQ#|Rp#>RzFb)3b; z^{P>}D4M+E-E)<{bUdLvz?kFYjyY$K1_g|&*SKL2{($i4%O(YvGJyADJnjh`wqh~OITmmk}iGSYmz z_{w*!e}`Q2Rxm4*$F%fOBNumB8Qn<5J!V=r?n@YHo$rR+mEpR(abPGGi$;Qsw~3EdH-z?5EXFA# zZP_b~`;6qYWoFU|Q|G;qtjK0^CUH($v$iYC&7{F2qQ&2`ut~~;TX>)RkS<4K_#QwQ zP$|K7#fJ6{9pL?7s9-qz?>cCEjP&%B!8Oa^QAkz*0uZYMePah~bu6}Tf@;f$z^zG{ zQ>K-miX}3WlR3lU;sbwGMHdXa#lQR;Swz&-PWrcju>o*9U@KryEY{vyO`U1O8tvh` z#T&I@wokYN-5W+E!**F*lMN~B1k{ElT$lg3%i=`fwCZLm6Q2k6RKy|NBs%M+>JTC2 zZhI%qR4QR*60*)x_*&h%TWHs!vQ)F3+{i88;&{Qi=5=EgY_}C2D=6oUJoC) zg03jqY!WXtZ19%Zhz}e3Z^rhvnltl8vBeXGEo-kh*{JwW;}O;&_OJhAum_%KCa4QE z36tPa=oD}g%c$7ak0W>^gpeRY4obq0Zo0}hJ zJ%!87k1$!0t__D5I-xc=GmIHu?i;G$OOXMafH1kTSKA$~_3zuA-k(o3pT49#6rw={C5DXaU}O0i`yV?5MKiklqcTX*vk17l88Qz2jPH+GsR5 z&v^Ii9(8ewi>S zKLqI+3GvEIR!f@JEa}SD{I8gw6^pHbiXu~7YF+1pOIiM(z`;53ert5=X-Vd*!dmWF z<0(WNbn>4=T2zsgtw!XvD~*b5G2GU|o)EKbd+X7C+nr7%Q)co+&X%#}v{QyIUy7c> z$8G;)tVg`r9&e^0!NxRuONyZ;}ZL^_;1I((q^Rd51XHZ`qB*>e(8IP z#wCR1ixOJoq2-sw_O1);Ve$8_rjC~+Gbnd3C;7{gl$*KlFlM8&0o<;b%&TBUVB;xeQ9pX1G>wA~jyW*YR`i2ZVgDdr%S~knyy}{riq4b?u zpi6-U5|htMXL8wG(@2M*f=hv8u5Bf&+aB3OZGdZ2hV7A$VS;{J6kj{KmU^N6|3=zY zg}1+F#|b!7bu($nA26BZvdcH_4QpvVW#lY54Yqn}M$7UmV!oeysrR>GgTIKc`v^P*_jjmJJ$6|bN-2$p8JE)~n+L4rDt0^;Q z6>t9`nC}AY2Y3L(05{+`;3$9|5*5@8pb{_($OGm8^MD@$z66w}X{QV8koaow@rr+g jOp9Oad5OI*_6`Nv2V!Q3vrolmL$R`l_`A6o7>;}k7!!az delta 2614 zcmZuzZETZO6yELU)~y?3bRTSNWnc0#HU?~C8~bhx+ZbaE=&-1zYu{}hUEk)m8&Wrh znkdW+2uFx9L;(#50TQecV??6{_(23ze!a$oKPD2RF(xKP6XQLnKnt>D&(6K)-1GU| z`|iDCZ0;B{D`vAPMf|wV@ATcgZ2mo!x!~W_ci9?vC+#{L0NFIohTx8A3!8(|bSLaf zFJ$xZw!ky7kJB?X%?;wPYTBdl-EQs)j>`9$*oZFZ-@MK0*x|5k-{!DeU-Hb{*NAPY zfLqX98<2y175rnqZdfhWya8@xmXtQ4O0RIA%vI)5nV+vgB|#nPil9kT1m#()SSmQP zn%G)6lC^~K*rlvX8ny%Eh4ncL=h=*T+U(QpPC3H(zDSub2QDrgk`~RIW-_N!##fxI zp3XeQSc;HqrZXei)4Erg&oZxJDL(Di6e$;~bI!1)*xj53Y^lWfS`jz8XfovUL}a(e z>s2O$5vyZxaPy#K;(d^9DPZkTCC~;AOHFl^Fqc;H4)KS#BVcd&281pIqX1Rk*R!c- z8}EdZ;+!2mwUn@KP%Wi~7Bp!EO>U)dC*_VTuEmWCgyje;5!MS(OQ5x&BuC2P)ILm- z;~aP+{E%y7{ZNwER=TGE! zqlmey=_CF?z#UQCK_w!TYJPD!#f%%Hg_g_VCjG7(lzD}{hbqG5VYzSTitXb7<~ zF3I;S`sEyfh(YZc!=)A>4Iv+a7^N4In%ZfzIR?aKBmzkp4;p|*@Z=?P5A zR+)1pjra3r)HcDb`m-zyQw_arKYZD6aQ1cF281^ejv*XJm=mDt1OA{KcIli$odcp^ zGCqLXg92PeCFJq?BYVkKjOKAQ?M97d@<{!f`dXL4sRSk`!{r?#Hh*U36EK)urf)@-$HHNL`bU6E*^I=-}p9o z8*A7JING?0wZXl{0>SOS8-HTBXm*tmd9X&J;5m(|si{?&H<^&|{JQh(HAroFL7W+F zxl(-=%|Cc}hM#*R5sm6_c|kypxV!u!Y-~Nn-hf|QOEWHuO-V%XkMI~2wk@_?MN`T< ziGa}C7H#<)HD4fng>Vfa$p)9#1-LN84I!wh-Z6i`$Hiy(^wIY3*!%E(dpR3}zuHT! zr_snT!hz!6ds9lHl8mucbsdyg--N7d3bWvl`$EX-CPbR_@xow%%IRwba7hi z357Ts$J42U!p^xydK-wScq4e?u6E!u!CRs_kv`6M__4FNoIZl|3K7en%4jI*vKNjE zXX0A;y%F*MhT=_rW?^4f9{UWAcky(Z4y+77VQaMxC8 zcA4mlDw^YsxWH&HGaN>{lTd57h&Habe^ZH_=C={BVS;bpqD)PoCj=+1=E459yx4%F zSi|mtvY}Ws|Imhl@oqG&N7#%&FL@72sR(|A5d?bsbtp|C7!h7X*o*KI!ZgAR!XF3; pIy@L-cJ~RxFQ}P-SoeqQE{ybucLa{~aP~83d;1pr?}WS8{vW~YKEVJ0 diff --git a/v2realbot/backtesting/backtester.py b/v2realbot/backtesting/backtester.py index 04d4fef..aa373d5 100644 --- a/v2realbot/backtesting/backtester.py +++ b/v2realbot/backtesting/backtester.py @@ -181,7 +181,7 @@ class Backtester: todel.append(order) changes = 1 else: - print("NOT EXECUTED {a}") + print(f"NOT EXECUTED {a}") #ic("NOT EXECUTED",a) ##ic("istodel",todel) #vymazu z pending orderu vschny zprocesovane nebo ty na výmaz @@ -317,7 +317,7 @@ class Backtester: return -1 if not fill_time: - #ic("not FILLED") + print("not FILLED") return 0 else: diff --git a/v2realbot/config.py b/v2realbot/config.py index 2baf679..c1bc713 100644 --- a/v2realbot/config.py +++ b/v2realbot/config.py @@ -2,6 +2,8 @@ from alpaca.data.enums import DataFeed from v2realbot.enums.enums import Mode, Account, FillCondition from appdirs import user_data_dir +#minimalni vzdalenost mezi trady, kterou agregator pousti pro CBAR(0.001 - blokuje mensi nez 1ms) +AGG_MIN_TRADE_DELTA = 0.003 #normalized price for tick 0.01 NORMALIZED_TICK_BASE_PRICE = 30.00 LOG_RUNNER_EVENTS = False @@ -20,6 +22,8 @@ BT_FILL_LOG_SURROUNDING_TRADES = 10 # slow - price has to be bigger < BT_FILL_CONDITION_BUY_LIMIT = FillCondition.SLOW BT_FILL_CONDITION_SELL_LIMIT = FillCondition.SLOW +#TBD TODO not implemented yet +BT_FILL_PRICE_MARKET_ORDER_PREMIUM = 0.005 #backend counter of api requests COUNT_API_REQUESTS = False #stratvars that cannot be changed in gui diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index af1f360..84d84ca 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -11,7 +11,7 @@ from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Sto from v2realbot.utils.ilog import delete_logs from datetime import datetime from threading import Thread, current_thread, Event, enumerate -from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT +from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT, AGG_MIN_TRADE_DELTA import importlib from queue import Queue from tinydb import TinyDB, Query, where @@ -436,10 +436,14 @@ def populate_metrics_output_directory(strat: StrategyInstance): trade_dict.qty.append(t.qty) trade_dict.price.append(t.price) trade_dict.position_qty.append(t.position_qty) - trade_dict.value.append(t.value) - trade_dict.cash.append(t.cash) trade_dict.order_type.append(t.order.order_type) - trade_dict.pos_avg_price.append(t.pos_avg_price) + #backtest related additional attributtes, not present on LIVE + try: + trade_dict.value.append(t.value) + trade_dict.cash.append(t.cash) + trade_dict.pos_avg_price.append(t.pos_avg_price) + except Exception: + pass trade_df = pd.DataFrame(trade_dict) trade_df = trade_df.set_index('timestamp',drop=False) @@ -470,6 +474,7 @@ def archive_runner(runner: Runner, strat: StrategyInstance): settings = dict(resolution=strat.state.timeframe, rectype=strat.state.rectype, configs=dict( + AGG_MIN_TRADE_DELTA=AGG_MIN_TRADE_DELTA, BT_FILL_CONS_TRADES_REQUIRED=BT_FILL_CONS_TRADES_REQUIRED, BT_FILL_LOG_SURROUNDING_TRADES=BT_FILL_LOG_SURROUNDING_TRADES, BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT, @@ -527,16 +532,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) + # 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/loader/__pycache__/aggregator.cpython-310.pyc b/v2realbot/loader/__pycache__/aggregator.cpython-310.pyc index fe66ce9d987b2666fa5b41e07139bcae078dc480..941e5083b275f33a455ce71769d85fc8583b1b0c 100644 GIT binary patch delta 1777 zcmZuw+fN)-7@spUyUbqMga`Q{skHp`|H|%%u zE03}xXo;hbrJzibY&afoNy9d10KoO-Hj75pDOnYoV&6B6L4j8(rQL`_3%X%zj%8^@ z)3Oa!ab?>u?*PBuN3p?UfsV1y6_bpxfNz*x^<5$5Bir|**ynh6B;B79_6S%)IkrcV zg44Yw>=XKq9)!(Ys7QJMSN2M9f?QWtHQeqkEM@eZ|o?C{ZN&DM2Jv=URoL> z?4MB2EsV!8zN0MSltw2~POOR0=?J_5=qiEz8Q7gq*SOx15}XXrc6~?^g5y67)KB|} z@I5?a+u`%R3wod?0Otw&BK)n|407eA{QOOqIMYj%p!}@}oe1p+T?pOmpmA{V9GV$~ zHUysT0L%5L3ln;wp2-R*q7Ox>Bj) z&=xiqxq6d7iv$vGAjA+vtoHC{Mf)%iN9aLN5e5KUdGh7#0v$#_gfN1TWIsgI*&#Fs z5iTLTfDl2r4B$%Zg-w7`#r06DR?+E29yN`M>n&8P21HU2QGIljU5gH1o(3oHr-oCb z70osrItGC{j3YBxs;nBeqw&{^=e2)ghtc=E8Brl#k##lAkq}#NTIqWYtK}8TGU)`i zC?K3P;}&+LQTA8Ui_$o(Ly64MVzWqEn=p=7I$giXWiVaOM$M=h_;-jj&GuujvypgP zKmSow+4b19szK|c%1B3!>Zha6Y+7bR@vd|AAB(s?4gR`)RnFx9Lws4o*t%XnC7zs@riskSGfd? zRRY(AO%y>U(;hkIp(PN#jofAPiOI~Fs(V))z2Fp1WX}xIHJok&s50e3@ttgA^na>v zqv{=8_0viq>wVY~t+HFmuS-{ukI#?h092*k`uGm$2BuK_x~zQMZLEA=dl|GJrnTd$ zGsNF#X6mI=;?uW~afa~pZAiGXSpxmfP@Zlgk4t?@?=48&|Bv2MOraQ6Gcb+yr5#kZ48Q|Lv_I`rzS)V8viMn7iO zqhBxl%r}2CR?B>CYGPr+n0jfRr{zD{1Aa<*u=}l2tM(W&0M{70?C2Kf2lAa{bJ?8V(LgFnms zi|`nGmOl=sSr>mAo@S@{g~)g^yQ!EpX=zhhO_;6c>6^XH;2+K-?@e}_(J@JujBf7? z@*UgEjI61*Ww^d9y`u>(bHH8P)b8t;mHCV@sfc}y3^Dv_wEF__3F0@kD>R|bi>)Tt zWbE`QdOg@xLHm8Q+xNZ+vn?%o%@pMiqe*s){}SyCrp$0f!i-P2Qun>yfO}a~7GJsS zGjC=A80{)U&_>Wg&`!|F|ElZ1(m`gHpqW5~Tha0ZE2TnVxLVXnp>~322#(cI`X4HR zLeW`n$6A}G(bRh(iXUH_vo@vy9PpK*?LmTn9ee(=&`_v3M^!>*nX&^5^Al6kpc5-} zKTXydf?kTNlNTrEVSxMy!5~4B57z7B{bcqLJV$UA!B^hMts@j|KLAd}Hla(fCCm0t z<;rCXnG`a55YF+>>j#IX&{+(DmEoejY`LD{LC&;hka2(FH4QiU z2Mu#f<$goH=Mtr5iD%QbU{xES#rFGG}KC7#Kz^#-msLooUdMeUGaBklQ!S0u|>@YuQ7==>Kbq(Y2 zW}?A0{#)X{u|}2R*kXRD=oW3)%h?4Bx-sOd1*g0ry824F;^~3vtZNigz;b=X$*)40 zx|9eGuS`wz{MV-Ot=B1#BgiB8HHKk21w0SE0VoiN*JM&qaXkQyINB{(1P812BYT%A zSf$ebg~UWLTWoq6D_+Haf=f*_No6wuH6DOvTzm^#;@>4FJ5JpEsk~?Ayxfu1r$?bk z<5v-M6~v~*QPzq5-{u9oxB0f#W6Pkr4LlXtXxwPwkCJizd+MXDQEEl+5GE0HtvcmE z4{#_%LR42QW?ZGrqdKUl!yvc^S;uBmx0|#PdTjE$O|mA3bU7S#zcjw$js1}gtiM2Txate(Yb{BGttTj5VLZLG|b+5QYED8fg& XiI&5>knIbHSyYy`q^;P?@s@u96MAvv diff --git a/v2realbot/loader/aggregator.py b/v2realbot/loader/aggregator.py index b1ed749..549502e 100644 --- a/v2realbot/loader/aggregator.py +++ b/v2realbot/loader/aggregator.py @@ -11,7 +11,7 @@ import threading from copy import deepcopy from msgpack import unpackb import os -from config import DATA_DIR +from config import DATA_DIR, AGG_MIN_TRADE_DELTA class TradeAggregator: def __init__(self, @@ -66,6 +66,7 @@ class TradeAggregator: self.barindex = 1 self.diff_price = True self.preconfBar = {} + self.trades_too_close = False async def ingest_trade(self, indata, symbol): """ @@ -244,6 +245,11 @@ class TradeAggregator: self.diff_price = True self.last_price = data['p'] + if float(data['t']) - float(self.lasttimestamp) < AGG_MIN_TRADE_DELTA: + self.trades_too_close = True + else: + self.trades_too_close = False + #spočteme vwap - potřebujeme předchozí hodnoty self.vwaphelper += (data['p'] * data['s']) self.newBar['updated'] = data['t'] @@ -333,7 +339,16 @@ class TradeAggregator: #print(self.newBar) #pro (nepotvrzeny) cbar vracime jen pri zmene ceny - if self.diff_price is True: + + #nevracime pokud predchozi timestamp a novy od sebe nema alespon 1 ms (vyhneme se kulometum) + #127788.123000 127788.124000 (rozdil 0.001) + + + #zkousime pustit i stejnou cenu(potrebujeme kvuli MYSELLU), ale blokoval kulomet,tzn. trady mensi nez AGG_MIN_TRADE_DELTA (1ms) + #if self.diff_price is True: + + #pripadne jeste vratit jako subpodminkiu + if self.trades_too_close is False: return [self.newBar] else: return [] diff --git a/v2realbot/static/js/archivechart.js b/v2realbot/static/js/archivechart.js index bf03846..3a050c1 100644 --- a/v2realbot/static/js/archivechart.js +++ b/v2realbot/static/js/archivechart.js @@ -259,19 +259,24 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { intitialize_candles() candlestickSeries.setData(AllCandleSeriesesData.get(interval)); + remove_indicators(); + btnElement = document.getElementById("indicatorsButtons") + if (btnElement) { + container1.removeChild(btnElement); + } + if (interval == native_resolution) { //indicators are in native resolution only - display_indicators(data); - var indbuttonElement = populate_indicator_buttons(); - container1.append(indbuttonElement); + display_indicators(data, true); + var indbuttonElement = populate_indicator_buttons(true); } else { - remove_indicators(); - btnElement = document.getElementById("indicatorsButtons") - if (btnElement) { - container1.removeChild(btnElement); - } + //na nepuvodnim grafu zobrazit jako offset a zobrazit jako neviditelne + display_indicators(data,false,30) + //buttonky jako vypnute + var indbuttonElement = populate_indicator_buttons(false); } + container1.append(indbuttonElement); display_buy_markers(); @@ -284,7 +289,8 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { //pro kazdy identifikator zobrazime button na vypnuti zapnuti //vybereme barvu pro kazdy identifikator //zjistime typ idenitfikatoru - zatim right vs left - function display_indicators(data) { + // input: data, offset(zobrazovat pouze hodnoty kazdych N sekund, visible) + function display_indicators(data, visible, offset) { //console.log("indikatory", JSON.stringify(data.indicators,null,2)) //podobne v livewebsokcets.js - dat do jedne funkce if (data.hasOwnProperty("indicators")) { @@ -331,6 +337,16 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { //if (indicators.time[index] !== undefined) { //{console.log("problem",key,last)} time = indicators.time[index] + + //pokud je nastaveny offset (zobrazujeme pouze bod vzdaleny N sekund od posledniho) + //vynechavame prvni iteraci, aby se nam naplnil last_time + if (offset && last_time !==0) { + if (last_time + offset > time) { + return; + } + } + + if (last_time>=time) { console.log(key, "problem v case - zarovnano",time, last_time, element) @@ -437,6 +453,7 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { //add options obj.series.applyOptions({ + visible: visible, lastValueVisible: false, priceLineVisible: false, }); @@ -456,19 +473,21 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { } }) } + //vwap a volume zatim jen v detailnim zobrazeni + if (!offset) { + //display vwap and volume + initialize_vwap() + vwapSeries.setData(transformed_data["vwap"]) - //display vwap and volume - initialize_vwap() - vwapSeries.setData(transformed_data["vwap"]) - - initialize_volume() - volumeSeries.setData(transformed_data["volume"]) - console.log("volume") + initialize_volume() + volumeSeries.setData(transformed_data["volume"]) + console.log("volume") + } } function remove_indicators() { //reset COLORS - colors = reset_colors + colors = reset_colors.slice() //remove CUSTOMS indicators if exists indList.forEach((element, index, array) => { @@ -479,9 +498,11 @@ function chart_archived_run(archRecord, data, oneMinuteBars) { //remove BASIC indicators if (vwapSeries) { chart.removeSeries(vwapSeries) + vwapSeries = null; } if (volumeSeries) { chart.removeSeries(volumeSeries) + volumeSeries = null; } } diff --git a/v2realbot/static/js/archivetables.js b/v2realbot/static/js/archivetables.js index 30f7478..10bd6bc 100644 --- a/v2realbot/static/js/archivetables.js +++ b/v2realbot/static/js/archivetables.js @@ -71,16 +71,15 @@ $(document).ready(function () { // record2.history = ""; //jsonString2 = JSON.stringify(record2, null, 2); - - document.getElementById('first').innerHTML = '
'+JSON.stringify(record1, null, 2)+'
' - $('#diff_first').text(record1.name); - $('#diff_second').text(record2.name); - - //mozna parse? - + $('#diff_first').text(record1.name); + $('#diff_second').text(record2.name); + var delta = compareObjects(record1, record2) - const htmlMarkup1 = `
{\n${generateHTML(record2, delta)}}\n
`; - document.getElementById('second').innerHTML = htmlMarkup1; + const htmlMarkup2 = `
{\n${generateHTML(record2, delta)}}\n
`; + document.getElementById('second').innerHTML = htmlMarkup2; + + const htmlMarkup1 = `
{\n${generateHTML(record1, delta)}}\n
`; + document.getElementById('first').innerHTML = htmlMarkup1; event.preventDefault(); //$('#button_compare').attr('disabled','disabled'); diff --git a/v2realbot/static/js/livewebsocket.js b/v2realbot/static/js/livewebsocket.js index 0a4a3df..23559d8 100644 --- a/v2realbot/static/js/livewebsocket.js +++ b/v2realbot/static/js/livewebsocket.js @@ -5,6 +5,7 @@ var logcnt = 0 var positionsPriceLine = null var limitkaPriceLine = null var angleSeries = 1 +var angleSeries_slow = 1 var cbar = false //get details of runner to populate chart status @@ -54,7 +55,7 @@ function connect(event) { ws.onmessage = function(event) { 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 // if (parsed_data.hasOwnProperty("bars")) { @@ -238,6 +239,34 @@ function connect(event) { angleSeries.setData(dataPoints) } } + + if (klic === "angle_slow") { + + //nejsou vsechny hodnoty + if (Object.keys(hodnota).length > 2) { + // console.log("angle nalezen"); + // console.log(JSON.stringify(hodnota)); + if (angleSeries_slow !== 1) { + // console.log("angle neni jedna" + toString(angleSeries)) + chart.removeSeries(angleSeries_slow) + } + + angleSeries_slow = chart.addLineSeries({ + //title: key, + lineWidth: 2, + lineStyle: 2, + color: "#8c52c7", + lastValueVisible: false, + priceLineVisible: false, + priceLineWidth: 0, + priceLineStyle: 3 + }) + dataPoints = [{time: hodnota.lookbacktime, value: hodnota.lookbackprice},{ time: hodnota.time, value: hodnota.price}] + // console.log("pridano") + // console.log(toString(dataPoints)) + angleSeries_slow.setData(dataPoints) + } + } } diff --git a/v2realbot/static/js/mytables.js b/v2realbot/static/js/mytables.js index ea448dc..8895fa1 100644 --- a/v2realbot/static/js/mytables.js +++ b/v2realbot/static/js/mytables.js @@ -312,13 +312,17 @@ $(document).ready(function () { //jsonString2 = JSON.stringify(rec2, null, 2); - document.getElementById('first').innerHTML = '
'+JSON.stringify(rec1, null, 2)+'
' + //document.getElementById('first').innerHTML = '
'+JSON.stringify(rec1, null, 2)+'
' $('#diff_first').text(rec1.name); $('#diff_second').text(rec2.name); - var delta = compareObjects(rec1, rec2) - const htmlMarkup = `
{\n${generateHTML(rec2, delta)}}\n
`; - document.getElementById('second').innerHTML = htmlMarkup; + var delta = compareObjects(rec1, rec2) + const htmlMarkup2 = `
{\n${generateHTML(rec2, delta)}}\n
`; + document.getElementById('second').innerHTML = htmlMarkup2; + + //var delta1 = compareObjects(rec2, rec1) + const htmlMarkup1 = `
{\n${generateHTML(rec1, delta)}}\n
`; + document.getElementById('first').innerHTML = htmlMarkup1; event.preventDefault(); //$('#button_compare').attr('disabled','disabled'); diff --git a/v2realbot/static/js/utils.js b/v2realbot/static/js/utils.js index 5e91300..1cf006c 100644 --- a/v2realbot/static/js/utils.js +++ b/v2realbot/static/js/utils.js @@ -1,8 +1,8 @@ API_KEY = localStorage.getItem("api-key") var chart = null -var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"] -var reset_colors = colors +var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"] +var reset_colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"] var indList = [] var verticalSeries=null var candlestickSeries = null @@ -27,10 +27,12 @@ indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, pri {name: "ivwap", titlevisible: true, embed: true, display: false, priceScaleId: "right", lastValueVisible: false}, {name: "slope", titlevisible: true, embed: true, display: false, priceScaleId: "middle", lastValueVisible: false}, {name: "slopeMA", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false}, + {name: "slow_slope", titlevisible: true, embed: true, display: false, priceScaleId: "middle", lastValueVisible: false}, + {name: "slow_slopeMA", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false}, {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: "SRSI", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, + {name: "CRSI", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, {name: "ppo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false}, @@ -294,7 +296,7 @@ function initialize_vwap() { } -function populate_indicator_buttons() { +function populate_indicator_buttons(def) { var buttonElement = document.createElement('div'); buttonElement.id = "indicatorsButtons" buttonElement.classList.add('switcher'); @@ -305,7 +307,9 @@ function populate_indicator_buttons() { itemEl.id = "IND"+index; itemEl.style.color = item.series.options().color; itemEl.classList.add('switcher-item'); + if (def) { itemEl.classList.add('switcher-active-item'); + } itemEl.addEventListener('click', function() { onItemClicked1(index); }); @@ -464,9 +468,15 @@ Mousetrap.bind('x', function() { // for (let key in obj1) { // if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') { -// const nestedDiff = compareObjects(obj1[key], obj2[key]); -// if (Object.keys(nestedDiff).length > 0) { -// diff[key] = nestedDiff; +// if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) { +// if (!arraysAreEqual(obj1[key], obj2[key])) { +// diff[key] = obj2[key]; +// } +// } else { +// const nestedDiff = compareObjects(obj1[key], obj2[key]); +// if (Object.keys(nestedDiff).length > 0) { +// diff[key] = nestedDiff; +// } // } // } else if (obj1[key] !== obj2[key]) { // diff[key] = obj2[key]; @@ -476,52 +486,42 @@ Mousetrap.bind('x', function() { // return diff; // } -// function generateHTML(obj, diff, indent = '') { -// let html = ''; - -// for (let key in obj) { -// const value = obj[key]; - -// if (typeof value === 'object' && value !== null) { -// const nestedDiff = diff[key] || {}; -// const nestedIndent = indent + ' '; -// html += `${indent}"${key}": {\n${generateHTML(value, nestedDiff, nestedIndent)}${indent}},\n`; -// } else { -// if (key in diff) { -// html += `${indent}"${key}": ${JSON.stringify(value)},\n`; -// } else { -// html += `${indent}"${key}": ${JSON.stringify(value)},\n`; -// } -// } -// } - -// return html; -// } - - function compareObjects(obj1, obj2) { - const diff = {}; - - for (let key in obj1) { - if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') { - if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) { - if (!arraysAreEqual(obj1[key], obj2[key])) { - diff[key] = obj2[key]; - } - } else { - const nestedDiff = compareObjects(obj1[key], obj2[key]); - if (Object.keys(nestedDiff).length > 0) { - diff[key] = nestedDiff; - } - } - } else if (obj1[key] !== obj2[key]) { - diff[key] = obj2[key]; - } + const diff = {}; + + for (let key in obj1) { + if (!(key in obj2)) { + diff[key] = obj1[key]; + continue; + } + + if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') { + if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) { + if (!arraysAreEqual(obj1[key], obj2[key])) { + diff[key] = obj2[key]; + } + } else { + const nestedDiff = compareObjects(obj1[key], obj2[key]); + if (Object.keys(nestedDiff).length > 0) { + diff[key] = nestedDiff; + } + } + } else if (obj1[key] !== obj2[key]) { + diff[key] = obj2[key]; } - - return diff; } - + + for (let key in obj2) { + if (!(key in obj1)) { + diff[key] = obj2[key]; + } + } + + return diff; +} + + + function arraysAreEqual(arr1, arr2) { if (arr1.length !== arr2.length) { return false; diff --git a/v2realbot/strategy/__pycache__/base.cpython-310.pyc b/v2realbot/strategy/__pycache__/base.cpython-310.pyc index a087840d17a9fb011b1d0117f1cc1fd919532b44..595d2104feb94e8024c98ea0fafec9d5b254c150 100644 GIT binary patch delta 3268 zcma);YiwM_702(~eR#e0+Uq#RyS9_XZ(nar{J;)L91#+yA#re=goMV4ST>$(XV>=b zGJ6-tiBm%zAfk$(8QxTFh-ga+Eu^cW0)js18=68NQgu-qq)M&S_EV*PpinC*H%lpo_#~S#}y#I_QYdpP!W((hD zwvuT(A3Eb+WMgfl*`YL_;X9S4ec9)BzDsF3I6I&j!}%|GES-&=_l5Pbuw=f~a=mYX z?aja9dx+h-o2D(c0Cxh1fV+Ut0*8Tv1f$e(x(y2D8G^J&TK?$P5s2%6l|blpy=b;K zYY8(xBlf~UVKjf$A9k@L^5ekS;iFK8feM1{xpV(*Lpww_$%a>`fgp<*a1U?{*bWp# zMDq^$UWLgXk-e3lWAEfIS9+PBYX>y^8D4oc*rFQ&Sy$B<8Y6GpAJ1gW6ptN?3)@Y| ziYa-Zs%Nd?Qlr}Lgk{c%okiowcdP2zCi$1Djc$L5`$O5e%8-%TTVkRa|5jVd>ZVC+Gs~!U_S5MLPa!M9b-^i!Y8Qf#OnFPVb^Qdy zNkAvqu2g!~F0~RfX4Z<&WW-5W3I}>9{3vuyvN_;k+PAw*h;2jE^f zM6ABYdmogiX!x_va?%xv^&LSk-*UVtB$Yii`ITuO zhXHdJ3-XD``rsZCZP%n}i5e((%il(tsvdz@28%mur8Bhlk{cs6#fyVeEWi225GyN) zFYj*bphNa>V+bmHyW%QBxw;LOn$6z)y<<+M4jVryKiNWc9U>h(9pdjdQOs6Mp z7oBXiQoCASZmpL4n%A;1nQ0zsQQP$t+!uha00qfFGbw-He5!86vB-Q;&a`ar`YJrX z27DcO5h!wefpl*&(qEE)Xqg^{Go8VeRQ}H;smjKZE-~k976pDzKHhqyQN?58IgI=b zpvdb%8EiY$<#^eZSyYs;Vz~^DTW0oCrw{?oO4&9XK@TU^^`bs1|J}A_U5Jt}uO+F1 zb4+|}u|@5)PHo+CCEZhccJ-3%nbJjA9&e8ZM&=p!gf;FZ&4|3vZZr?LHOoJD2h;F- zSi5&%RcBAj8^2;v!9bNV-U-CPT@#l5!8^oMSlI8M3M}7QZ zi>X#Xu|lzum!5Nxr+-j8S*tX`WEHi`2DK&cU~<)xzM7Yx)5#VX)b7$!A)3YNx%ZiN z+QYPyoHCI1SFRl_S687tT!vT7GXRybKVuUqvzcus$w?BrJk z%c8D)8y;iAYpqd{);jTEnN+Ka)vDWa)rh#4@?(1~5$9%hK%|i^I%JwyzUV|89zMEl ztVD`u>DpA~F$bp;z?}S-agasiXlKp76co4zZP&D!QZ=Mv(p5yaY}WSgN^$dqa}{Ob z`%U1J0d4nvxTU`Z%VqgSXLHT72pFIUB1YvHn@&(YJ|X|n+3r%2qta-kx=J3lH$}h}pdOBw% z(kYtEY&@fO1J@}{Uf>d^Qo`eMNw=$x(`?dWE+)(gQ<$l7Q@ll%;+bS5@A_;1JfgD` zHp|#7YqN3jq*9y|Kc%msi=U(CFMxuDalrNez7~W@OjwUfDQt^pXv0p*oSrn zpwe9li)a7dgCj%YZfL2R>5&GUhXv9DfV$+>6Cu%T29m%<02iEd|2zokEMZtY3K40v z%hd@SpE0fDX)bm_p8?(nEMR5NR@P;ZVGaFdC*+BqTXlU(zS;8{OXNlGA>E6!FJ6{c zZXRG>>FIyHoC;ryRa3FBi@U_NZWu7fD3R|3@HsbB`C``^!2??ZQGj>>4}6Tz6@hG!6Tu>S$m&szg;B^>`cJUS~1truZW{*xsqxxR}hU@okq#&la!d8Trx19Sa{I z*sp=#pjSyO#?#}mSV0ZohH`dzEhH3+Xaar*U{Ay|!1a!3f($#cV?Gjmnwt&zLYoD& q#uo7>`p6eHeaLp_@8A4g*7*jtZFer0;Lad8-^%w>q2;kHBmV{Hv*@e< delta 4724 zcma)9Yj9h|6~24#)x)+VOO7A1?5|TP0E~c2IiqKx$k|kYb z?^O~D8!;$AGOYuhWrit_Y1}Cjl5~J#pit<8nRX_fX;T8_(c6~NnGQ41CqLRhosyoj zSGE-MnA)RHXU{o%cK7U_hyGQ4RTheig(pkSsPVj*G9kP#qU+vgNSJSSO z(nw>KL^awCR1;7=v=^u_T|@ieyP2+~{qWsF*U|Oxy_9ayTSsNOk#0Jv@&?!X0eU^% z0fG*_lMd*sK(v#7>7-gDBddY4OK^76J%ZDxb@Lz4F8xuVOGm)c=dj~f{p zW0O&)n^Dt>F)L~%(z?y-ybq8Y=gxWWA=mAL)+B?WAbLVT_q|5S8Nl7Icpl&J^753_sbhdVi%n~9| zX=vf2dH4&#jwX9a*;DABQ5H+xxObUb0goXM|)mbneUM|_Hxgh{Km%Ye;U#X9+=>T54y#4%aUYC7J;M7Nre(B7nLHJ zmMv+DP^DQa5}@QFnQ)mAhbl`NC8|y+tY6GkscTApSfXxc9#Eb~UDP`R?i1EQif*M+ zAt$jzpj6c?!9-whfepa88W#hO8#yJDHI7EJ^sr2QjtuEX)skV)S?|2YESXkHv;0#E z{L4*}g>tddETMrJl}NxZED}tR`w4T-uhLq_@cdHcjfEu|3`^6hSfXk`I=pk*HRYmJ z6EeH#@bExqtLK*^($Q~$JOuLBg}jE=HA~a(DX9RCR_T%{_moPdyX9ty*3ZbWGrWMR zDHj^C@T_vOhBknYN?Jwn62WMN9#!#mmUt>{bYwIHHk(Se!@_o@w+kQR?)e9ZwG*(o=f+Jh6$+w%{@@2m<{?e)FEeJzt3o?cA|va9}86>Z#Gb za-3Y7jBYJkKfE>H`^n0}^0nH&!u%3Dhqv$3R8|m2EoZus+ARsq6&5!&9X#Xhj2e0%jTQs)w4!CVL^I`pn9z^THgc5NzVLfK<6s*B>s(kK$8C5Y4*m+L#VaU>H6!re;7IL=Pt z@C-uby2JHP5slpgY<%q5oMl%J$5J_cCu0U<51@Lb@wJWX+_xk1K0eww)^-3%ycAoB zXRHwg-o-W6|JwMjO!EA-=IDmQsEWDWvDbr?D28I&n&@8gFxEKm~OEK zWbWhNZD|iZf@BR!RH!ytIQ5$?Z4HYLhf1-znx$bR?wRS;qzPYt6jN7+KqH@bP z=drmnt*ykx?tlS*a@p$M@@!{gsB{Y9dIZcA&V#=fD6TBu3T1Zt@_`QFo%1N=2u~tZ z_#THTet!AwEoH?;;-~o++jgvZ7B!zk_yNN62#XY-0p5#{2-yq#iMG^URE8F(A2ovr zpLhZhsCa_&#Ce&E3}57WJ)DICBX+6mQ6d7LQXxX)BdI9;)~O&m(t`Z%kz{PK#eeaFD(P(7f_$zeI{vPe;yma(2#N>ZJW&4v=~f`Zn< zH@Elr_d}_JYDL|^+0Tu3ZRKWFvZ^NsiG=^RNJlpxmnL$6sz=SvW0bo?V!EdSRx&H1j98b7(cZqKEJ#{b#FYB`DX` zhvaDm%D0L#sH(~q>F6_}G4Uh=Vuf0PL0UBfy#uY@BITO|CzPy%aSe1S1Uns1GL&3W z`mU$G85xBBEz-?WCJdWvnEWr1rd>qJ`>aN*iSw16g|M?Va4R;Lo@5wi1i)M)tt~?N z2Ht|(kv`jOwIr8L$yO^3&d6BcK{JGsqSGcU152B%<-%5*z%WY2(2^$_##*k`4T`*O zyDj#4$YLgA_#WWxO3XmOipAmpwihzH1!)}{P!VJ^DEbD%3{Q95)DvO5aj*wLwCdMp zOj}9m87DFs|650sb_^9yBm4+qkxeXD?8gW%bFFh_!v!F1KQy&03MDL>g2tAeC1ksSE&w?IHYy z`hJO8i$c}pS608j>3)#d-J*hB;2(B}3s|ApDugZo zTfNONQfvsvD@G-~vJ3ZH_-mP*U zU(x#ewJoHcPpo|*I0oTET@cJtbcq!xO1!_ny#Vn` zjyDkBM0g9~w+Q%zm<^y2@dDr(35$0jYdI6)wGDNgFyOyDobcsC>o#n-1Y_F`eb{KiVo#v3A3&>d3Yq9IdXc*hq3qk1imMT~g3ssx zycKhl|6|>d8h~G?d|-VKDa>WptEBKg8ZBj@@1ZHdP@TgG#$V>S3>VdE|DVDuTr-9f z#i92gg$HsvU$J>F8gu)c2PwF(}@X0I~ghdFRHRD}Rr3|A6o|fbEG!sS%Gx zE5hRfpV=7R{tl{$z`<^%!WCtM6Cl`y{=f}*C6x?#!(U*?)wZ&~^LIDCP4>= 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") + # #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]=}") + # #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") + # 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 + # 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] ) + # #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 + # #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'] + # 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=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:]) + # 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']) + # #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""" @@ -493,12 +493,12 @@ class Strategy: 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 + # 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: @@ -635,7 +635,7 @@ class StrategyState: self.indicators = AttributeDict(time=[]) self.cbar_indicators = AttributeDict(time=[]) #secondary timeframe indicators - self.secondary_indicators = AttributeDict(time=[], sec_price=[]) + #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