From e08ae0f53785cd650a41b102deccc64e88fa5670 Mon Sep 17 00:00:00 2001 From: David Brazda Date: Wed, 6 Sep 2023 17:37:56 +0200 Subject: [PATCH] pridano indikator natr + vychytavky na frontendu --- v2realbot/ENTRY_ClassicSL_v01.py | 80 ++++++++++++++---- .../common/__pycache__/model.cpython-310.pyc | Bin 7551 -> 7633 bytes v2realbot/common/model.py | 2 + v2realbot/controller/services.py | 6 +- .../__pycache__/indicators.cpython-310.pyc | Bin 1010 -> 1236 bytes v2realbot/indicators/indicators.py | 8 ++ v2realbot/static/js/archivetables.js | 13 ++- 7 files changed, 88 insertions(+), 21 deletions(-) diff --git a/v2realbot/ENTRY_ClassicSL_v01.py b/v2realbot/ENTRY_ClassicSL_v01.py index 8807add..619b1e0 100644 --- a/v2realbot/ENTRY_ClassicSL_v01.py +++ b/v2realbot/ENTRY_ClassicSL_v01.py @@ -3,7 +3,7 @@ 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.indicators import ema, natr from v2realbot.indicators.oscillators import rsi from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, round2five, is_open_rush, is_close_rush, is_still, is_window_open, eval_cond_dict, Average, crossed_down, crossed_up, crossed, is_pivot, json_serial @@ -248,6 +248,8 @@ def next(data, state: StrategyState): populate_dynamic_RSI_indicator(name = name) elif type == "EMA": populate_dynamic_ema_indicator(name = name) + elif type == "NATR": + populate_dynamic_natr_indicator(name = name) else: return @@ -285,6 +287,34 @@ def next(data, state: StrategyState): except Exception as e: state.ilog(e=f"IND ERROR {name} EMA necháváme 0", message=str(e)+format_exc()) + #NATR INDICATOR + # type = NATR, ĺength = [14], on_confirmed_only = [true, false] + def populate_dynamic_natr_indicator(name): + ind_type = "NATR" + options = safe_get(state.vars.indicators, name, None) + if options is None: + state.ilog(e=f"No options for {name} in stratvars") + return + + #poustet kazdy tick nebo jenom na confirmed baru (on_confirmed_only = true) + on_confirmed_only = safe_get(options, 'on_confirmed_only', False) + natr_length = int(safe_get(options, "length",5)) + if on_confirmed_only is False or (on_confirmed_only is True and data['confirmed']==1): + try: + source_high = state.bars["high"][-natr_length:] + source_low = state.bars["low"][-natr_length:] + source_close = state.bars["close"][-natr_length:] + #if len(source) > ema_length: + natr_value = natr(source_high, source_low, source_close, natr_length) + val = round(natr_value[-1],4) + state.indicators[name][-1]= val + #state.indicators[name][-1]= round2five(val) + state.ilog(e=f"IND {name} NATR {val} {natr_length=}") + #else: + # state.ilog(e=f"IND {name} EMA necháváme 0", message="not enough source data", source=source, ema_length=ema_length) + except Exception as e: + state.ilog(e=f"IND ERROR {name} NATR necháváme 0", message=str(e)+format_exc()) + #RSI INDICATOR # type = RSI, source = [close, vwap, hlcc4], rsi_length = [14], MA_length = int (optional), on_confirmed_only = [true, false] # pokud existuje MA, vytvarime i stejnojnojmenny MAcko @@ -742,18 +772,32 @@ def next(data, state: StrategyState): else: smer = "short" - #get name of strategy - signal_originator = state.vars.activeTrade.generated_by - - if signal_originator is not None: - exit_cond_only_on_confirmed = safe_get(state.vars.signals[signal_originator], "exit_cond_only_on_confirmed", safe_get(state.vars, "exit_cond_only_on_confirmed", False)) - else: - exit_cond_only_on_confirmed = safe_get(state.vars, "exit_cond_only_on_confirmed", False) + directive_name = "exit_cond_only_on_confirmed" + exit_cond_only_on_confirmed = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, False)) if exit_cond_only_on_confirmed and data['confirmed'] == 0: state.ilog("EXIT COND ONLY ON CONFIRMED BAR") return False + #POKUD je nastaven MIN PROFIT, zkontrolujeme ho a az pripadne pustime CONDITIONY + directive_name = "exit_cond_min_profit" + exit_cond_min_profit = get_override_for_active_trade(directive_name=directive_name, default_value=safe_get(state.vars, directive_name, None)) + + #máme nastavený exit_cond_min_profit + # zjistíme, zda jsme v daném profit a případně nepustíme dál + # , zjistíme aktuální cenu a přičteme k avgp tento profit a podle toho pustime dal + + if exit_cond_min_profit is not None: + exit_cond_min_profit_normalized = normalize_tick(float(exit_cond_min_profit)) + exit_cond_goal_price = price2dec(float(state.avgp)+exit_cond_min_profit_normalized,3) if int(state.positions) > 0 else price2dec(float(state.avgp)-exit_cond_min_profit_normalized,3) + curr_price = float(data["close"]) + state.ilog(e=f"EXIT COND min profit {exit_cond_goal_price=} {exit_cond_min_profit=} {exit_cond_min_profit_normalized=} {curr_price=}") + if (int(state.positions) < 0 and curr_price<=exit_cond_goal_price) or (int(state.positions) > 0 and curr_price>=exit_cond_goal_price): + state.ilog(e=f"EXIT COND min profit PASS - POKRACUJEME") + else: + state.ilog(e=f"EXIT COND min profit NOT PASS") + return False + #TOTO ZATIM NEMA VYZNAM # options = safe_get(state.vars, 'exit_conditions', None) # if options is None: @@ -919,7 +963,8 @@ def next(data, state: StrategyState): #pri uzavreni tradu zapisujeme SL history - lepsi zorbazeni v grafu insert_SL_history() state.vars.pending = state.vars.activeTrade.id - state.vars.activeTrade = None + state.vars.activeTrade = None + state.vars.last_exit_index = data["index"] def eval_close_position(): curr_price = float(data['close']) @@ -1125,14 +1170,6 @@ def next(data, state: StrategyState): #ZAKLADNI KONTROLY ATRIBUTU s fallbackem na obecné #check working windows (open - close, in minutes from the start of marker) - next_signal_offset = safe_get(options, "next_signal_offset_from_last",safe_get(state.vars, "next_signal_offset_from_last",0)) - - if state.vars.last_buy_index is not None: - index_to_compare = int(state.vars.last_buy_index)+int(next_signal_offset) - if index_to_compare > int(data["index"]): - state.ilog(e=f"NEXT SIGNAL OFFSET {next_signal_offset} waiting - TOO SOON", currindex=data["index"], index_to_compare=index_to_compare) - return False - window_open = safe_get(options, "window_open",safe_get(state.vars, "window_open",0)) window_close = safe_get(options, "window_close",safe_get(state.vars, "window_close",390)) @@ -1140,6 +1177,14 @@ def next(data, state: StrategyState): state.ilog(e=f"SIGNAL {signalname} - WINDOW CLOSED", msg=f"{window_open=} {window_close=} ") return False + next_signal_offset = safe_get(options, "next_signal_offset_from_last_exit",safe_get(state.vars, "next_signal_offset_from_last_exit",0)) + + if state.vars.last_exit_index is not None: + index_to_compare = int(state.vars.last_exit_index)+int(next_signal_offset) + if index_to_compare > int(data["index"]): + state.ilog(e=f"NEXT SIGNAL OFFSET from EXIT {next_signal_offset} waiting - TOO SOON", currindex=data["index"], index_to_compare=index_to_compare, last_exit_index=state.vars.last_exit_index) + return False + # if is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), open_rush) or is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), close_rush): # state.ilog(e=f"SIGNAL {signalname} - WINDOW CLOSED", msg=f"{open_rush=} {close_rush=} ") # return False @@ -1415,6 +1460,7 @@ def init(state: StrategyState): state.vars.last_tick_volume = 0 state.vars.next_new = 0 state.vars.last_buy_index = None + state.vars.last_exit_index = None state.vars.last_update_time = 0 state.vars.reverse_position_waiting_amount = 0 #INIT promenne, ktere byly zbytecne ve stratvars diff --git a/v2realbot/common/__pycache__/model.cpython-310.pyc b/v2realbot/common/__pycache__/model.cpython-310.pyc index 6286240d1cc225efb4ddc190875a2bbdf1a26ef3..22c4329be12a0078e47cfca50ad19ea9688c4fbb 100644 GIT binary patch delta 567 zcmZ9IJxtqB5XXHbHmR{4*Kuvkm{%V>E7MF_x%6gzdL_#u9~K<(096f zSO5FR{BFR@?w(NuwoWVO|<%DB>6U0xc? zW5wz~39qann83cwcy}V>q(;kh^CybfBj`#B(wQ_oE(2_kWxRhHcDJ)NP$Qc9f!FQ` zL|nud&u^iDzSpGvp%_-1)c=XUy-{c;{eNED`9QUOidZA)N*WA&B?dv@o)O}Kf9sYC zQGcW+LIM(^l8_w!3Z%A92V@P0b8noU^`D-Q^awo5tJuzEsvmjMVPqLIj9JDMW0TNJ z)fN2~6-x-InMV0H-VR8SBdyNCsa1epufrHyBVQdx=T2 z?9!!^2wl4N4@jMiAc$_^t#i%z9`j+|ciy}=GySE%MecL11#o@5|9b5%Z|Q8j*U??3 z6arZjUU@s1wPDw^;WHA4ZgdMajkvaf3HxZ38JLabdfPFfs6{;2;mB}Vv1K~FM`Mqv z9%^?mmY8H7YEVcF*#WF3kC_KNJ)!y-et-4tp;bZ%Ef8iplU2-P8gz6A zzRV#NWx=;4L#KE}mS86}AIxU3K37bUq7!0-Gw7$B<#Tigig#E(kr$+{5Y`Bz2j<8t z5i*22;gWDgh(g}5v>Lk4XxMAP&M6j?HR|QwzA+mpzfmZR&;mLemE53kIsFp3Mpbfx z59@~GHqjlRRRn_iqpb%iNif-jqs)&>QHl HNX0|{=?`Oc diff --git a/v2realbot/common/model.py b/v2realbot/common/model.py index 4ce9b1c..e2987bb 100644 --- a/v2realbot/common/model.py +++ b/v2realbot/common/model.py @@ -121,6 +121,7 @@ class Runner(BaseModel): run_instance: Optional[object] = None run_pause_ev: Optional[object] = None run_stop_ev: Optional[object] = None + run_stratvars_toml: Optional[str] = None class Bar(BaseModel): @@ -207,6 +208,7 @@ class RunArchive(BaseModel): end_positions: int = 0 end_positions_avgp: float = 0 open_orders: Union[dict, int] = None + stratvars_toml: Optional[str] = None #trida pro ukladani historie stoplossy do ext_data class SLHistory(BaseModel): diff --git a/v2realbot/controller/services.py b/v2realbot/controller/services.py index 3c4ad67..859e495 100644 --- a/v2realbot/controller/services.py +++ b/v2realbot/controller/services.py @@ -490,7 +490,8 @@ def run_stratin(id: UUID, runReq: RunRequest, synchronous: bool = False, inter_b run_account = runReq.account, run_ilog_save = runReq.ilog_save, run_mode = runReq.mode, - run_instance = instance) + run_instance = instance, + run_stratvars_toml=i.stratvars_conf) db.runners.append(runner) print(db.runners) print(i) @@ -666,7 +667,8 @@ def archive_runner(runner: Runner, strat: StrategyInstance, inter_batch_params: trade_count=len(strat.state.tradeList), end_positions=strat.state.positions, end_positions_avgp=round(float(strat.state.avgp),3), - open_orders=results_metrics + open_orders=results_metrics, + stratvars_toml=runner.run_stratvars_toml ) #flatten indicators from numpy array diff --git a/v2realbot/indicators/__pycache__/indicators.cpython-310.pyc b/v2realbot/indicators/__pycache__/indicators.cpython-310.pyc index 0c9d5f06cce5b70330f74d286b2d032058a99212..ad5fd8c460662b1c6170ecbb3663f8e296f9d88b 100644 GIT binary patch delta 609 zcmZuu%SyvQ6wOQ~k3RCSzEE5VE`lIZa92c7>duXzkd4GnwbeEWlN2eWbfH_p(68v% zbkkM-z^yBn-a9Q_6erx*N$xpwZ+?t<$&M_mtiaiR{pI&8w+~31A77l=Tx(aKDA&31 zq4^efmUWp|pte_am0M6doZKp&n}5~E8gLbQ+!o!4w-_=n55CaBF2Rx$aH*0h?_`9L zKqL?;M4FNpngN#4Oy%U0jabHjo!(4|Kmtz{$Xn2~Td*)lg{S!?9;CrTr~7==@lBcc zqBp-RvsN!k+OkuWpl_;(@+2aUhghH`IKN5osS!rxN8fe8n)&Q*M;MTKx=es6uFZuCJ$qUN;`@%OMIa9Q5O1LBkmSSP=3c5zZu3udZ<| k^2+OyQXB^@%tk-rgI@cbK$YP2Ou57=OzaX@b&W0K4;m0^+yDRo delta 370 zcmcb@`H7t`pO=@50SGE?MyEJ2PvnzfOqi(cpvs-XmdcaHl)|3E(ZU+Vn*!r=rf>oI zd?}2<44OO>7Z~vx0rk4wVk<~3%FIuhe2__UvM`ga_)5kiHlTziTM;vmDq;Z=x0p&Y zC#NxKbAYT{$xy^Uxr{MM62##E;$kp^k%f_ik&jV`v50H(J|AObjFhv5g&W8%V7tQxPkWa?|9G zVk;@l$t