max profit a loss to quit incorporated
This commit is contained in:
@ -1121,6 +1121,7 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
#check activation
|
#check activation
|
||||||
if activated is False:
|
if activated is False:
|
||||||
|
state.ilog(e=f"{signalname} not ACTIVATED")
|
||||||
cond_dict = state.vars.conditions[KW.activate][signalname]
|
cond_dict = state.vars.conditions[KW.activate][signalname]
|
||||||
result, conditions_met = evaluate_directive_conditions(cond_dict, "OR")
|
result, conditions_met = evaluate_directive_conditions(cond_dict, "OR")
|
||||||
state.ilog(e=f"EVAL ACTIVATION CONDITION =OR= {result}", **conditions_met, cond_dict=cond_dict)
|
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")
|
state.ilog(e=f"not ACTIVATED")
|
||||||
return False
|
return False
|
||||||
else:
|
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
|
# OBECNE PRECONDITIONS - typu dont_do_when
|
||||||
precond_check = dict(AND=dict(), OR=dict())
|
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)
|
# dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1)
|
||||||
|
|
||||||
#obecne open_rush platne pro vsechny
|
#obecne open_rush platne pro vsechny
|
||||||
precond_check['on_confirmed_only'] = safe_get(options, 'on_confirmed_only', False)
|
#precond_check['on_confirmed_only'] = safe_get(options, 'on_confirmed_only', False) - chybi realizace podminky, pripadne dodelat na short_on_confirmed
|
||||||
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))
|
|
||||||
|
|
||||||
# #testing preconditions
|
# #testing preconditions
|
||||||
result, cond_met = eval_cond_dict(precond_check)
|
result, cond_met = eval_cond_dict(precond_check)
|
||||||
if result:
|
if result:
|
||||||
state.ilog(e=f"PRECOND GENERAL not met {cond_met}", message=cond_met, precond_check=precond_check)
|
state.ilog(e=f"PRECOND GENERAL not met {cond_met}", message=cond_met, precond_check=precond_check)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
state.ilog(e=f"{signalname} ALL PRECOND MET")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def execute_signal_generator(name):
|
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)
|
options = safe_get(state.vars.signals, name, None)
|
||||||
|
|
||||||
if options is None:
|
if options is None:
|
||||||
@ -1176,9 +1178,15 @@ def next(data, state: StrategyState):
|
|||||||
if plugin:
|
if plugin:
|
||||||
execute_signal_generator_plugin(name)
|
execute_signal_generator_plugin(name)
|
||||||
else:
|
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
|
#common signals based on 1) configured signals in stratvars
|
||||||
#toto umoznuje jednoduchy prescribed trade bez ceny
|
#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(
|
state.vars.prescribedTrades.append(Trade(
|
||||||
id=uuid4(),
|
id=uuid4(),
|
||||||
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
|
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
|
||||||
@ -1187,7 +1195,7 @@ def next(data, state: StrategyState):
|
|||||||
direction=TradeDirection.LONG,
|
direction=TradeDirection.LONG,
|
||||||
entry_price=None,
|
entry_price=None,
|
||||||
stoploss_value = 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(
|
state.vars.prescribedTrades.append(Trade(
|
||||||
id=uuid4(),
|
id=uuid4(),
|
||||||
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
|
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
|
||||||
@ -1196,6 +1204,8 @@ def next(data, state: StrategyState):
|
|||||||
direction=TradeDirection.SHORT,
|
direction=TradeDirection.SHORT,
|
||||||
entry_price=None,
|
entry_price=None,
|
||||||
stoploss_value = None))
|
stoploss_value = None))
|
||||||
|
else:
|
||||||
|
state.ilog(e=f"{name} NO SIGNAL")
|
||||||
|
|
||||||
def signal_search():
|
def signal_search():
|
||||||
# SIGNAL sekce ve stratvars obsahuje signaly: Ty se skladaji z obecnych parametru a podsekce podminek.
|
# 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
|
#MAIN LOOP
|
||||||
lp = data['close']
|
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)} 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)
|
||||||
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))
|
|
||||||
inds = get_last_ind_vals()
|
inds = get_last_ind_vals()
|
||||||
state.ilog(e="Indikatory", **inds)
|
state.ilog(e="Indikatory", **inds)
|
||||||
|
|
||||||
@ -1253,6 +1262,7 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
#pokud mame prazdne pozice a neceka se na nic
|
#pokud mame prazdne pozice a neceka se na nic
|
||||||
if state.positions == 0 and state.vars.pending is None:
|
if state.positions == 0 and state.vars.pending is None:
|
||||||
|
|
||||||
execute_prescribed_trades()
|
execute_prescribed_trades()
|
||||||
#pokud se neaktivoval nejaky trade, poustime signal search - ale jen jednou za bar?
|
#pokud se neaktivoval nejaky trade, poustime signal search - ale jen jednou za bar?
|
||||||
#if conf_bar == 1:
|
#if conf_bar == 1:
|
||||||
@ -1265,7 +1275,7 @@ def next(data, state: StrategyState):
|
|||||||
elif state.vars.activeTrade and state.vars.pending is None:
|
elif state.vars.activeTrade and state.vars.pending is None:
|
||||||
manage_active_trade() #optimalize, close
|
manage_active_trade() #optimalize, close
|
||||||
# - close means change status in prescribed Trends,update profit, delete from activeTrade
|
# - close means change status in prescribed Trends,update profit, delete from activeTrade
|
||||||
|
|
||||||
|
|
||||||
def init(state: StrategyState):
|
def init(state: StrategyState):
|
||||||
#place to declare new vars
|
#place to declare new vars
|
||||||
|
|||||||
Binary file not shown.
@ -168,6 +168,7 @@ class TradeUpdate(BaseModel):
|
|||||||
pos_avg_price: Optional[float]
|
pos_avg_price: Optional[float]
|
||||||
profit: Optional[float]
|
profit: Optional[float]
|
||||||
profit_sum: Optional[float]
|
profit_sum: Optional[float]
|
||||||
|
signal_name: Optional[str]
|
||||||
|
|
||||||
|
|
||||||
class RunArchiveChange(BaseModel):
|
class RunArchiveChange(BaseModel):
|
||||||
|
|||||||
@ -57,6 +57,12 @@ function transform_data(data) {
|
|||||||
sline_markers["text"] = histRecord.sl_val.toFixed(3)
|
sline_markers["text"] = histRecord.sl_val.toFixed(3)
|
||||||
sl_line_markers_sada.push(sline_markers)
|
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) => {
|
data.bars.time.forEach((element, index, array) => {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
from v2realbot.strategy.base import Strategy
|
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.utils.tlog import tlog, tlog_exception
|
||||||
from v2realbot.enums.enums import Mode, Order, Account, RecordType
|
from v2realbot.enums.enums import Mode, Order, Account, RecordType
|
||||||
#from alpaca.trading.models import TradeUpdate
|
#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:
|
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)
|
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):
|
async def orderUpdateBuy(self, data: TradeUpdate):
|
||||||
o: Order = data.order
|
o: Order = data.order
|
||||||
|
signal_name = None
|
||||||
##nejak to vymyslet, aby se dal poslat cely Trade a serializoval se
|
##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)))
|
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.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
|
||||||
trade.profit += trade_profit
|
trade.profit += trade_profit
|
||||||
trade.profit_sum = self.state.profit
|
trade.profit_sum = self.state.profit
|
||||||
|
signal_name = trade.generated_by
|
||||||
|
|
||||||
#zapsat update profitu do tradeList
|
#zapsat update profitu do tradeList
|
||||||
for tradeData in self.state.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
|
#pridat jako attribut, aby proslo i na LIVE a PAPPER, kde se bere TradeUpdate z Alpaca
|
||||||
setattr(tradeData, "profit", trade_profit)
|
setattr(tradeData, "profit", trade_profit)
|
||||||
setattr(tradeData, "profit_sum", self.state.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)))
|
#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:
|
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")
|
self.state.ilog(e="BUY: Jde o LONG nakuú nepocitame profit zatim")
|
||||||
|
|
||||||
#ic("vstupujeme do orderupdatebuy")
|
#ic("vstupujeme do orderupdatebuy")
|
||||||
@ -102,6 +135,7 @@ class StrategyClassicSL(Strategy):
|
|||||||
trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
|
trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
|
||||||
trade.profit += trade_profit
|
trade.profit += trade_profit
|
||||||
trade.profit_sum = self.state.profit
|
trade.profit_sum = self.state.profit
|
||||||
|
signal_name = trade.generated_by
|
||||||
|
|
||||||
#zapsat update profitu do tradeList
|
#zapsat update profitu do tradeList
|
||||||
for tradeData in self.state.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
|
#pridat jako attribut, aby proslo i na LIVE a PAPPER, kde se bere TradeUpdate z Alpaca
|
||||||
setattr(tradeData, "profit", trade_profit)
|
setattr(tradeData, "profit", trade_profit)
|
||||||
setattr(tradeData, "profit_sum", self.state.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:
|
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")
|
self.state.ilog(e="SELL: Jde o SHORT nepocitame profit zatim")
|
||||||
|
|
||||||
#update pozic, v trade update je i pocet zbylych pozic
|
#update pozic, v trade update je i pocet zbylych pozic
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user