max profit a loss to quit incorporated
This commit is contained in:
@ -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:
|
||||
|
||||
Binary file not shown.
@ -168,6 +168,7 @@ class TradeUpdate(BaseModel):
|
||||
pos_avg_price: Optional[float]
|
||||
profit: Optional[float]
|
||||
profit_sum: Optional[float]
|
||||
signal_name: Optional[str]
|
||||
|
||||
|
||||
class RunArchiveChange(BaseModel):
|
||||
|
||||
@ -57,6 +57,12 @@ function transform_data(data) {
|
||||
sline_markers["text"] = histRecord.sl_val.toFixed(3)
|
||||
sl_line_markers_sada.push(sline_markers)
|
||||
|
||||
if (index === array.length - 1) {
|
||||
//pro posledni zaznam push sadu do pole
|
||||
sl_line.push(sl_line_sada)
|
||||
sl_line_markers.push(sl_line_markers_sada)
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
data.bars.time.forEach((element, index, array) => {
|
||||
|
||||
@ -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
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user