From e067a43ddadd6f9d62ff79cce5fe3b69f9f245f8 Mon Sep 17 00:00:00 2001 From: David Brazda Date: Fri, 1 Sep 2023 12:07:11 +0200 Subject: [PATCH] max profit a loss to quit incorporated --- v2realbot/ENTRY_ClassicSL_v01.py | 30 ++++++---- .../common/__pycache__/model.cpython-310.pyc | Bin 7217 -> 7244 bytes v2realbot/common/model.py | 1 + v2realbot/static/js/archivechart.js | 6 ++ v2realbot/strategy/StrategyClassicSL.py | 55 ++++++++++++++++-- .../strategy/__pycache__/base.cpython-310.pyc | Bin 14554 -> 14554 bytes 6 files changed, 78 insertions(+), 14 deletions(-) diff --git a/v2realbot/ENTRY_ClassicSL_v01.py b/v2realbot/ENTRY_ClassicSL_v01.py index e6da3e7..3a3ba5f 100644 --- a/v2realbot/ENTRY_ClassicSL_v01.py +++ b/v2realbot/ENTRY_ClassicSL_v01.py @@ -1121,6 +1121,7 @@ def next(data, state: StrategyState): #check activation if activated is False: + state.ilog(e=f"{signalname} not ACTIVATED") cond_dict = state.vars.conditions[KW.activate][signalname] result, conditions_met = evaluate_directive_conditions(cond_dict, "OR") state.ilog(e=f"EVAL ACTIVATION CONDITION =OR= {result}", **conditions_met, cond_dict=cond_dict) @@ -1134,7 +1135,8 @@ def next(data, state: StrategyState): state.ilog(e=f"not ACTIVATED") return False else: - state.vars.signals[signalname].activated = True + state.ilog(e=f"{signalname} JUST ACTIVATED") + state.vars.signals[signalname]["activated"] = True # OBECNE PRECONDITIONS - typu dont_do_when precond_check = dict(AND=dict(), OR=dict()) @@ -1148,19 +1150,19 @@ def next(data, state: StrategyState): # dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1) #obecne open_rush platne pro vsechny - precond_check['on_confirmed_only'] = safe_get(options, 'on_confirmed_only', False) - precond_check['short_enabled'] = safe_get(options, "short_enabled",safe_get(state.vars, "short_enabled",True)) - precond_check['long_enabled'] = safe_get(options, "long_enabled",safe_get(state.vars, "long_enabled",True)) + #precond_check['on_confirmed_only'] = safe_get(options, 'on_confirmed_only', False) - chybi realizace podminky, pripadne dodelat na short_on_confirmed # #testing preconditions result, cond_met = eval_cond_dict(precond_check) if result: state.ilog(e=f"PRECOND GENERAL not met {cond_met}", message=cond_met, precond_check=precond_check) return False + + state.ilog(e=f"{signalname} ALL PRECOND MET") return True def execute_signal_generator(name): - state.ilog(e=f"SIGNAL SEARCH for {name}") + state.ilog(e=f"SIGNAL SEARCH for {name}", cond_go=state.vars.conditions[KW.go][name], cond_dontgo=state.vars.conditions[KW.dont_go][name], cond_activate=state.vars.conditions[KW.activate][name] ) options = safe_get(state.vars.signals, name, None) if options is None: @@ -1176,9 +1178,15 @@ def next(data, state: StrategyState): if plugin: execute_signal_generator_plugin(name) else: + short_enabled = safe_get(options, "short_enabled",safe_get(state.vars, "short_enabled",True)) + long_enabled = safe_get(options, "long_enabled",safe_get(state.vars, "long_enabled",True)) #common signals based on 1) configured signals in stratvars #toto umoznuje jednoduchy prescribed trade bez ceny - if go_conditions_met(signalname=name, direction=TradeDirection.LONG): + if short_enabled is False: + state.ilog(e=f"{name} SHORT DISABLED") + if long_enabled is False: + state.ilog(e=f"{name} LONG DISABLED") + if long_enabled and go_conditions_met(signalname=name, direction=TradeDirection.LONG): state.vars.prescribedTrades.append(Trade( id=uuid4(), last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY), @@ -1187,7 +1195,7 @@ def next(data, state: StrategyState): direction=TradeDirection.LONG, entry_price=None, stoploss_value = None)) - elif go_conditions_met(signalname=name, direction=TradeDirection.SHORT): + elif short_enabled and go_conditions_met(signalname=name, direction=TradeDirection.SHORT): state.vars.prescribedTrades.append(Trade( id=uuid4(), last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY), @@ -1196,6 +1204,8 @@ def next(data, state: StrategyState): direction=TradeDirection.SHORT, entry_price=None, stoploss_value = None)) + else: + state.ilog(e=f"{name} NO SIGNAL") def signal_search(): # SIGNAL sekce ve stratvars obsahuje signaly: Ty se skladaji z obecnych parametru a podsekce podminek. @@ -1244,8 +1254,7 @@ def next(data, state: StrategyState): #MAIN LOOP lp = data['close'] - ispending = "N" if state.vars.pending is None else "Y" - state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} SL:{state.vars.activeTrade.stoploss_value if state.vars.activeTrade is not None else None} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} pending:{ispending}", activeTrade=json.loads(json.dumps(state.vars.activeTrade, default=json_serial)), prescribedTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)), pending=str(state.vars.pending), conditions=state.vars.conditions, last_price=lp, data=data, stratvars=str(state.vars)) + state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} SL:{state.vars.activeTrade.stoploss_value if state.vars.activeTrade is not None else None} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} pend:{state.vars.pending}", activeTrade=json.loads(json.dumps(state.vars.activeTrade, default=json_serial)), prescribedTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)), pending=str(state.vars.pending), last_price=lp, data=data, stratvars=state.vars) inds = get_last_ind_vals() state.ilog(e="Indikatory", **inds) @@ -1253,6 +1262,7 @@ def next(data, state: StrategyState): #pokud mame prazdne pozice a neceka se na nic if state.positions == 0 and state.vars.pending is None: + execute_prescribed_trades() #pokud se neaktivoval nejaky trade, poustime signal search - ale jen jednou za bar? #if conf_bar == 1: @@ -1265,7 +1275,7 @@ def next(data, state: StrategyState): elif state.vars.activeTrade and state.vars.pending is None: manage_active_trade() #optimalize, close # - close means change status in prescribed Trends,update profit, delete from activeTrade - + def init(state: StrategyState): #place to declare new vars diff --git a/v2realbot/common/__pycache__/model.cpython-310.pyc b/v2realbot/common/__pycache__/model.cpython-310.pyc index 5c72e14d440f89ff622add187150a6553f56bd7b..62fc75bd6981ec9abec5607b1038af4d8d5c8c13 100644 GIT binary patch delta 124 zcmdmJamIo-pO=@50SMe@e@r>Kk@u@GJtRvRN#JG9#c8SM~ aXEx84lxJkTw0XBwJ|nw;0IPtc2pa%OHz64S delta 88 zcmV-e0H^=VII%blZw(C!00000bMWqDs<93A69Jl&0~DDCWDQdQDGrma6m^p@6 { diff --git a/v2realbot/strategy/StrategyClassicSL.py b/v2realbot/strategy/StrategyClassicSL.py index cc2559b..b407ea1 100644 --- a/v2realbot/strategy/StrategyClassicSL.py +++ b/v2realbot/strategy/StrategyClassicSL.py @@ -1,5 +1,5 @@ from v2realbot.strategy.base import Strategy -from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print, json_serial, safe_get, get_tick +from v2realbot.utils.utils import parse_alpaca_timestamp, ltp, AttributeDict,trunc,price2dec, zoneNY, print, json_serial, safe_get, get_tick, send_to_telegram from v2realbot.utils.tlog import tlog, tlog_exception from v2realbot.enums.enums import Mode, Order, Account, RecordType #from alpaca.trading.models import TradeUpdate @@ -23,10 +23,28 @@ class StrategyClassicSL(Strategy): def __init__(self, name: str, symbol: str, next: callable, init: callable, account: Account, mode: Mode = Mode.PAPER, stratvars: AttributeDict = None, open_rush: int = 30, close_rush: int = 30, pe: Event = None, se: Event = None, runner_id: UUID = None, ilog_save: bool = False) -> None: super().__init__(name, symbol, next, init, account, mode, stratvars, open_rush, close_rush, pe, se, runner_id, ilog_save) - #todo dodelat profit, podle toho jestli jde o short nebo buy + #zkontroluje zda aktualni profit/loss - nedosahnul limit a pokud ano tak vypne strategii + async def check_max_profit_loss(self): + self.state.ilog(e="CHECK MAX PROFIT") + max_sum_profit_to_quit = safe_get(self.state.vars, "max_sum_profit_to_quit", None) + max_sum_loss_to_quit = safe_get(self.state.vars, "max_sum_loss_to_quit", None) + + if max_sum_profit_to_quit is not None: + if float(self.state.profit) >= float(max_sum_profit_to_quit): + self.state.ilog(e=f"QUITTING MAX SUM PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=}") + self.state.vars.pending = "max_sum_profit_to_quit" + send_to_telegram(f"QUITTING MAX SUM PROFIT REACHED {max_sum_profit_to_quit=} {self.state.profit=}") + self.se.set() + if max_sum_loss_to_quit is not None: + if float(self.state.profit) < 0 and float(self.state.profit) <= float(max_sum_loss_to_quit): + self.state.ilog(e=f"QUITTING MAX SUM LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=}") + self.state.vars.pending = "max_sum_loss_to_quit" + send_to_telegram(f"QUITTING MAX SUM LOSS REACHED {max_sum_loss_to_quit=} {self.state.profit=}") + self.se.set() async def orderUpdateBuy(self, data: TradeUpdate): o: Order = data.order + signal_name = None ##nejak to vymyslet, aby se dal poslat cely Trade a serializoval se self.state.ilog(e="Příchozí BUY notif", msg=o.status, trade=json.loads(json.dumps(data, default=json_serial))) @@ -54,6 +72,7 @@ class StrategyClassicSL(Strategy): trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY) trade.profit += trade_profit trade.profit_sum = self.state.profit + signal_name = trade.generated_by #zapsat update profitu do tradeList for tradeData in self.state.tradeList: @@ -61,9 +80,23 @@ class StrategyClassicSL(Strategy): #pridat jako attribut, aby proslo i na LIVE a PAPPER, kde se bere TradeUpdate z Alpaca setattr(tradeData, "profit", trade_profit) setattr(tradeData, "profit_sum", self.state.profit) + setattr(tradeData, "signal_name", signal_name) #self.state.ilog(f"updatnut tradeList o profit", tradeData=json.loads(json.dumps(tradeData, default=json_serial))) - + + #test na maximalni profit/loss + await self.check_max_profit_loss() + else: + #zjistime nazev signalu a updatneme do tradeListu - abychom meli svazano + for trade in self.state.vars.prescribedTrades: + if trade.id == self.state.vars.pending: + signal_name = trade.generated_by + + #zapsat update profitu do tradeList + for tradeData in self.state.tradeList: + if tradeData.execution_id == data.execution_id: + setattr(tradeData, "signal_name", signal_name) + self.state.ilog(e="BUY: Jde o LONG nakuú nepocitame profit zatim") #ic("vstupujeme do orderupdatebuy") @@ -102,6 +135,7 @@ class StrategyClassicSL(Strategy): trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY) trade.profit += trade_profit trade.profit_sum = self.state.profit + signal_name = trade.generated_by #zapsat update profitu do tradeList for tradeData in self.state.tradeList: @@ -109,9 +143,22 @@ class StrategyClassicSL(Strategy): #pridat jako attribut, aby proslo i na LIVE a PAPPER, kde se bere TradeUpdate z Alpaca setattr(tradeData, "profit", trade_profit) setattr(tradeData, "profit_sum", self.state.profit) - self.state.ilog(f"updatnut tradeList o profi {str(tradeData)}") + setattr(tradeData, "signal_name", signal_name) + #self.state.ilog(f"updatnut tradeList o profi {str(tradeData)}") + + await self.check_max_profit_loss() else: + #zjistime nazev signalu a updatneme do tradeListu - abychom meli svazano + for trade in self.state.vars.prescribedTrades: + if trade.id == self.state.vars.pending: + signal_name = trade.generated_by + + #zapsat update profitu do tradeList + for tradeData in self.state.tradeList: + if tradeData.execution_id == data.execution_id: + setattr(tradeData, "signal_name", signal_name) + self.state.ilog(e="SELL: Jde o SHORT nepocitame profit zatim") #update pozic, v trade update je i pocet zbylych pozic diff --git a/v2realbot/strategy/__pycache__/base.cpython-310.pyc b/v2realbot/strategy/__pycache__/base.cpython-310.pyc index e9a96f179207ced1daada31cfe2afbc9db576802..2db3dfcb67179c29ddf25189f2f2643a51840c96 100644 GIT binary patch delta 20 acmcarc&m^*pO=@50SFFm`?!(&yafPER|jAK delta 20 acmcarc&m^*pO=@50SImhzTe1w-U0wg9tP3?