SL do grafu, pred zmenou signal podminek
This commit is contained in:
@ -7,6 +7,7 @@ from v2realbot.indicators.indicators import ema
|
|||||||
from v2realbot.indicators.oscillators import rsi
|
from v2realbot.indicators.oscillators import rsi
|
||||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
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, eval_cond_dict, Average, crossed_down, crossed_up, crossed, is_pivot, json_serial
|
from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, print, safe_get, round2five, is_open_rush, is_close_rush, eval_cond_dict, Average, crossed_down, crossed_up, crossed, is_pivot, json_serial
|
||||||
|
from v2realbot.common.model import SLHistory
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import json
|
import json
|
||||||
@ -498,20 +499,25 @@ def next(data, state: StrategyState):
|
|||||||
lookbacktime = state.bars.time[-slope_lookback]
|
lookbacktime = state.bars.time[-slope_lookback]
|
||||||
else:
|
else:
|
||||||
#kdyz neni dostatek hodnot, pouzivame jako levy bod open hodnotu close[0]
|
#kdyz neni dostatek hodnot, pouzivame jako levy bod open hodnotu close[0]
|
||||||
lookbackprice = state.bars.vwap[0]
|
|
||||||
|
|
||||||
#pokud neni dostatek, bereme vzdy petinu ze stávajících barů
|
|
||||||
# cnt = len(state.bars.close)
|
|
||||||
# if cnt>5:
|
|
||||||
# sliced_to = int(cnt/5)
|
|
||||||
# lookbackprice= Average(state.bars.vwap[:sliced_to])
|
|
||||||
|
|
||||||
# else:
|
|
||||||
#lookbackprice = state.bars.vwap[0]
|
#lookbackprice = state.bars.vwap[0]
|
||||||
#update -- lookback je pole z toho co mame
|
|
||||||
|
#dalsi vyarianta-- lookback je pole z toho všeho co mame
|
||||||
#lookbackprice = Average(state.bars.vwap)
|
#lookbackprice = Average(state.bars.vwap)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#pokud neni dostatek, bereme vzdy prvni petinu z dostupnych barů
|
||||||
|
# a z ní uděláme průměr
|
||||||
|
cnt = len(state.bars.close)
|
||||||
|
if cnt>5:
|
||||||
|
sliced_to = int(cnt/5)
|
||||||
|
lookbackprice= Average(state.bars.vwap[:sliced_to])
|
||||||
|
lookbacktime = state.bars.time[int(sliced_to/2)]
|
||||||
|
else:
|
||||||
|
lookbackprice = Average(state.bars.vwap)
|
||||||
lookbacktime = state.bars.time[0]
|
lookbacktime = state.bars.time[0]
|
||||||
state.ilog(e=f"IND {name} slope - not enough data bereme left bod open", slope_lookback=slope_lookback)
|
|
||||||
|
state.ilog(e=f"IND {name} slope - not enough data bereme left bod open", slope_lookback=slope_lookback, lookbackprice=lookbackprice)
|
||||||
|
|
||||||
#výpočet úhlu - a jeho normalizace
|
#výpočet úhlu - a jeho normalizace
|
||||||
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
|
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
|
||||||
@ -533,7 +539,7 @@ def next(data, state: StrategyState):
|
|||||||
state.indicators[name+"MA"][-1]=slopeMA
|
state.indicators[name+"MA"][-1]=slopeMA
|
||||||
last_slopesMA = state.indicators[name+"MA"][-10:]
|
last_slopesMA = state.indicators[name+"MA"][-10:]
|
||||||
|
|
||||||
state.ilog(e=f"{name=} {slope=} {slopeMA=}", msg=f"{lookbackprice=}", lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators[name][-10:], last_slopesMA=last_slopesMA)
|
state.ilog(e=f"{name=} {slope=} {slopeMA=}", msg=f"{lookbackprice=} {lookbacktime=}", slope_lookback=slope_lookback, lookbackoffset=lookback_offset, lookbacktime=lookbacktime, minimum_slope=minimum_slope, last_slopes=state.indicators[name][-10:], last_slopesMA=last_slopesMA)
|
||||||
#dale pracujeme s timto MAckovanym slope
|
#dale pracujeme s timto MAckovanym slope
|
||||||
#slope = slopeMA
|
#slope = slopeMA
|
||||||
|
|
||||||
@ -752,7 +758,11 @@ def next(data, state: StrategyState):
|
|||||||
# return result
|
# return result
|
||||||
|
|
||||||
|
|
||||||
def trail_SL_if_required(direction: TradeDirection):
|
def insert_SL_history():
|
||||||
|
#insert stoploss history as key sl_history into runner archive extended data
|
||||||
|
state.extData["sl_history"].append(SLHistory(id=state.vars.activeTrade.id, time=state.time, sl_val=state.vars.activeTrade.stoploss_value))
|
||||||
|
|
||||||
|
def trail_SL_management():
|
||||||
#pokud se cena posouva nasim smerem olespon o (0.05) nad (SL + 0.09val), posuneme SL o offset
|
#pokud se cena posouva nasim smerem olespon o (0.05) nad (SL + 0.09val), posuneme SL o offset
|
||||||
#+ varianta - skoncit breakeven
|
#+ varianta - skoncit breakeven
|
||||||
|
|
||||||
@ -768,10 +778,14 @@ def next(data, state: StrategyState):
|
|||||||
# #zda trailing zastavit na brakeeven
|
# #zda trailing zastavit na brakeeven
|
||||||
# SL_trailing_stop_at_breakeven_short = true
|
# SL_trailing_stop_at_breakeven_short = true
|
||||||
# SL_trailing_stop_at_breakeven_long = true
|
# SL_trailing_stop_at_breakeven_long = true
|
||||||
if direction == TradeDirection.LONG:
|
if int(state.positions) != 0 and float(state.avgp)>0 and state.vars.pending is None:
|
||||||
smer = "long"
|
|
||||||
else:
|
if int(state.positions) < 0:
|
||||||
|
direction = TradeDirection.SHORT
|
||||||
smer = "short"
|
smer = "short"
|
||||||
|
else:
|
||||||
|
direction = TradeDirection.LONG
|
||||||
|
smer = "long"
|
||||||
|
|
||||||
options = safe_get(state.vars, 'exit_conditions', None)
|
options = safe_get(state.vars, 'exit_conditions', None)
|
||||||
if options is None:
|
if options is None:
|
||||||
@ -785,7 +799,7 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
#pokud je pozadovan trail jen do breakeven a uz prekroceno
|
#pokud je pozadovan trail jen do breakeven a uz prekroceno
|
||||||
if (direction == TradeDirection.LONG and stop_breakeven and state.vars.activeTrade.stoploss_value >= float(state.avgp)) or (direction == TradeDirection.SHORT and stop_breakeven and state.vars.activeTrade.stoploss_value <= float(state.avgp)):
|
if (direction == TradeDirection.LONG and stop_breakeven and state.vars.activeTrade.stoploss_value >= float(state.avgp)) or (direction == TradeDirection.SHORT and stop_breakeven and state.vars.activeTrade.stoploss_value <= float(state.avgp)):
|
||||||
state.ilog(e=f"SL trail stop at breakeven {str(smer)} SL:{state.vars.activeTrade.stoploss_value} UNCHANGED", stop_breakeven=stop_breakeven)
|
state.ilog(e=f"SL trail STOP at breakeven {str(smer)} SL:{state.vars.activeTrade.stoploss_value} UNCHANGED", stop_breakeven=stop_breakeven)
|
||||||
return
|
return
|
||||||
|
|
||||||
#IDEA: Nyni posouvame SL o offset, mozna ji posunout jen o direktivu step ?
|
#IDEA: Nyni posouvame SL o offset, mozna ji posunout jen o direktivu step ?
|
||||||
@ -794,17 +808,38 @@ def next(data, state: StrategyState):
|
|||||||
def_SL_normalized = normalize_tick(def_SL)
|
def_SL_normalized = normalize_tick(def_SL)
|
||||||
if direction == TradeDirection.LONG:
|
if direction == TradeDirection.LONG:
|
||||||
move_SL_threshold = state.vars.activeTrade.stoploss_value + offset_normalized + def_SL_normalized
|
move_SL_threshold = state.vars.activeTrade.stoploss_value + offset_normalized + def_SL_normalized
|
||||||
state.ilog(e=f"SL trailing EVAL {smer} SL:{state.vars.activeTrade.stoploss_value} MOVETHRESHOLD:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
state.ilog(e=f"SL TRAIL EVAL {smer} SL:{round(state.vars.activeTrade.stoploss_value,3)} TRAILGOAL:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||||
if (move_SL_threshold) < data['close']:
|
if (move_SL_threshold) < data['close']:
|
||||||
state.vars.activeTrade.stoploss_value += offset_normalized
|
state.vars.activeTrade.stoploss_value += offset_normalized
|
||||||
|
insert_SL_history()
|
||||||
state.ilog(e=f"SL TRAIL TH {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
state.ilog(e=f"SL TRAIL TH {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||||
elif direction == TradeDirection.SHORT:
|
elif direction == TradeDirection.SHORT:
|
||||||
move_SL_threshold = state.vars.activeTrade.stoploss_value - offset_normalized - def_SL_normalized
|
move_SL_threshold = state.vars.activeTrade.stoploss_value - offset_normalized - def_SL_normalized
|
||||||
state.ilog(e=f"SL trailing EVAL {smer} SL:{state.vars.activeTrade.stoploss_value} MOVETHRESHOLD:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
state.ilog(e=f"SL TRAIL EVAL {smer} SL:{round(state.vars.activeTrade.stoploss_value,3)} TRAILGOAL:{move_SL_threshold}", def_SL=def_SL, offset=offset, offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||||
if (move_SL_threshold) > data['close']:
|
if (move_SL_threshold) > data['close']:
|
||||||
state.vars.activeTrade.stoploss_value -= offset_normalized
|
state.vars.activeTrade.stoploss_value -= offset_normalized
|
||||||
state.ilog(e=f"SL TRAIL TH {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
insert_SL_history()
|
||||||
|
state.ilog(e=f"SL TRAIL GOAL {smer} reached {move_SL_threshold} SL moved to {state.vars.activeTrade.stoploss_value}", offset_normalized=offset_normalized, def_SL_normalized=def_SL_normalized)
|
||||||
|
|
||||||
|
def close_position(direction: TradeDirection, reason: str):
|
||||||
|
state.ilog(e=f"CLOSING TRADE {reason} {str(direction)}", curr_price=data["close"], trade=state.vars.activeTrade)
|
||||||
|
if direction == TradeDirection.SHORT:
|
||||||
|
res = state.buy(size=abs(int(state.positions)))
|
||||||
|
if isinstance(res, int) and res < 0:
|
||||||
|
raise Exception(f"error in required operation {reason} {res}")
|
||||||
|
|
||||||
|
elif direction == TradeDirection.LONG:
|
||||||
|
res = state.sell(size=state.positions)
|
||||||
|
if isinstance(res, int) and res < 0:
|
||||||
|
raise Exception(f"error in required operation STOPLOSS SELL {res}")
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise Exception(f"unknow TradeDirection in close_position")
|
||||||
|
|
||||||
|
#pri uzavreni tradu zapisujeme SL history - lepsi zorbazeni v grafu
|
||||||
|
insert_SL_history()
|
||||||
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
|
state.vars.activeTrade = None
|
||||||
|
|
||||||
def eval_close_position():
|
def eval_close_position():
|
||||||
curr_price = float(data['close'])
|
curr_price = float(data['close'])
|
||||||
@ -817,32 +852,21 @@ def next(data, state: StrategyState):
|
|||||||
state.ilog(e=f"Goal price {goal_price} max price {max_price}")
|
state.ilog(e=f"Goal price {goal_price} max price {max_price}")
|
||||||
|
|
||||||
#close position handling
|
#close position handling
|
||||||
|
#TBD pridat OPTIMALIZACI POZICE - EXIT 1/2
|
||||||
|
|
||||||
#mame short pozice - (IDEA: rozlisovat na zaklade aktivniho tradu - umozni mi spoustet i long pozicemi)
|
#mame short pozice - (IDEA: rozlisovat na zaklade aktivniho tradu - umozni mi spoustet i pri soucasne long pozicemi)
|
||||||
if int(state.positions) < 0:
|
if int(state.positions) < 0:
|
||||||
#EOD EXIT - TBD
|
#EOD EXIT - TBD
|
||||||
|
#FORCED EXIT PRI KONCI DNE
|
||||||
#SL TRAILING
|
|
||||||
trail_SL_if_required(direction=TradeDirection.SHORT)
|
|
||||||
|
|
||||||
#SL - execution
|
#SL - execution
|
||||||
if curr_price > state.vars.activeTrade.stoploss_value:
|
if curr_price > state.vars.activeTrade.stoploss_value:
|
||||||
state.ilog(e=f"STOPLOSS reached on SHORT", curr_price=curr_price, trade=state.vars.activeTrade)
|
close_position(direction=TradeDirection.SHORT, reason="SL REACHED")
|
||||||
res = state.buy(size=abs(int(state.positions)))
|
|
||||||
if isinstance(res, int) and res < 0:
|
|
||||||
raise Exception(f"error in required operation STOPLOSS BUY {res}")
|
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
|
||||||
state.vars.activeTrade = None
|
|
||||||
return
|
return
|
||||||
|
|
||||||
#CLOSING BASED ON EXIT CONDITIONS
|
#CLOSING BASED ON EXIT CONDITIONS
|
||||||
if exit_conditions_met(TradeDirection.SHORT):
|
if exit_conditions_met(TradeDirection.SHORT):
|
||||||
res = state.buy(size=abs(int(state.positions)))
|
close_position(direction=TradeDirection.SHORT, reason="EXIT COND MET")
|
||||||
if isinstance(res, int) and res < 0:
|
|
||||||
raise Exception(f"error in required operation EXIT COND BUY {res}")
|
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
|
||||||
state.vars.activeTrade = None
|
|
||||||
state.ilog(e=f"EXIT COND MET. market BUY was sent {curr_price=}", positions=state.positions, avgp=state.avgp)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
#PROFIT
|
#PROFIT
|
||||||
@ -853,37 +877,19 @@ def next(data, state: StrategyState):
|
|||||||
max_price_signal = curr_price<=max_price
|
max_price_signal = curr_price<=max_price
|
||||||
#OPTIMALIZACE pri stoupajícím angle
|
#OPTIMALIZACE pri stoupajícím angle
|
||||||
if max_price_signal or sell_protection_enabled() is False:
|
if max_price_signal or sell_protection_enabled() is False:
|
||||||
res = state.buy(size=abs(int(state.positions)))
|
close_position(direction=TradeDirection.SHORT, reason=f"PROFIT or MAXPROFIT REACHED {max_price_signal=}")
|
||||||
if isinstance(res, int) and res < 0:
|
|
||||||
raise Exception(f"error in required operation PROFIT BUY {res}")
|
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
|
||||||
state.vars.activeTrade = None
|
|
||||||
state.ilog(e=f"PROFIT MET EXIT. market BUY was sent {curr_price=} {max_price_signal=}", positions=state.positions, avgp=state.avgp)
|
|
||||||
return
|
return
|
||||||
#mame long
|
#mame long
|
||||||
elif int(state.positions) > 0:
|
elif int(state.positions) > 0:
|
||||||
#EOD EXIT - TBD
|
#EOD EXIT - TBD
|
||||||
|
|
||||||
#SL - trailing
|
|
||||||
trail_SL_if_required(direction=TradeDirection.LONG)
|
|
||||||
|
|
||||||
#SL - execution
|
#SL - execution
|
||||||
if curr_price < state.vars.activeTrade.stoploss_value:
|
if curr_price < state.vars.activeTrade.stoploss_value:
|
||||||
state.ilog(e=f"STOPLOSS reached on LONG", curr_price=curr_price, trade=state.vars.activeTrade)
|
close_position(direction=TradeDirection.LONG, reason="SL REACHED")
|
||||||
res = state.sell(size=state.positions)
|
|
||||||
if isinstance(res, int) and res < 0:
|
|
||||||
raise Exception(f"error in required operation STOPLOSS SELL {res}")
|
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
|
||||||
state.vars.activeTrade = None
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if exit_conditions_met(TradeDirection.LONG):
|
if exit_conditions_met(TradeDirection.LONG):
|
||||||
res = state.sell(size=abs(int(state.positions)))
|
close_position(direction=TradeDirection.LONG, reason="EXIT CONDS MET")
|
||||||
if isinstance(res, int) and res < 0:
|
|
||||||
raise Exception(f"error in required operation EXIT COND SELL {res}")
|
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
|
||||||
state.vars.activeTrade = None
|
|
||||||
state.ilog(e=f"EXIT COND MET. market SELL was sent {curr_price=}", positions=state.positions, avgp=state.avgp)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
#PROFIT
|
#PROFIT
|
||||||
@ -894,12 +900,7 @@ def next(data, state: StrategyState):
|
|||||||
max_price_signal = curr_price>=max_price
|
max_price_signal = curr_price>=max_price
|
||||||
#OPTIMALIZACE pri stoupajícím angle
|
#OPTIMALIZACE pri stoupajícím angle
|
||||||
if max_price_signal or sell_protection_enabled() is False:
|
if max_price_signal or sell_protection_enabled() is False:
|
||||||
res = state.sell(size=state.positions)
|
close_position(direction=TradeDirection.LONG, reason=f"PROFIT or MAXPROFIT REACHED {max_price_signal=}")
|
||||||
if isinstance(res, int) and res < 0:
|
|
||||||
raise Exception(f"error in required operation PROFIT SELL {res}")
|
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
|
||||||
state.vars.activeTrade = None
|
|
||||||
state.ilog(e=f"PROFIT MET EXIT. market SELL was sent {curr_price=} {max_price_signal=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def execute_prescribed_trades():
|
def execute_prescribed_trades():
|
||||||
@ -939,6 +940,7 @@ def next(data, state: StrategyState):
|
|||||||
#normalizuji dle aktualni ceny
|
#normalizuji dle aktualni ceny
|
||||||
sl_defvalue_normalized = normalize_tick(sl_defvalue)
|
sl_defvalue_normalized = normalize_tick(sl_defvalue)
|
||||||
state.vars.activeTrade.stoploss_value = float(data['close']) - sl_defvalue_normalized
|
state.vars.activeTrade.stoploss_value = float(data['close']) - sl_defvalue_normalized
|
||||||
|
insert_SL_history()
|
||||||
state.ilog(e=f"Nastaveno SL na {sl_defvalue}, priced normalized: {sl_defvalue_normalized} price: {state.vars.activeTrade.stoploss_value }")
|
state.ilog(e=f"Nastaveno SL na {sl_defvalue}, priced normalized: {sl_defvalue_normalized} price: {state.vars.activeTrade.stoploss_value }")
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
elif state.vars.activeTrade.direction == TradeDirection.SHORT:
|
elif state.vars.activeTrade.direction == TradeDirection.SHORT:
|
||||||
@ -952,6 +954,7 @@ def next(data, state: StrategyState):
|
|||||||
#normalizuji dle aktualni ceny
|
#normalizuji dle aktualni ceny
|
||||||
sl_defvalue_normalized = normalize_tick(sl_defvalue)
|
sl_defvalue_normalized = normalize_tick(sl_defvalue)
|
||||||
state.vars.activeTrade.stoploss_value = float(data['close']) + sl_defvalue_normalized
|
state.vars.activeTrade.stoploss_value = float(data['close']) + sl_defvalue_normalized
|
||||||
|
insert_SL_history()
|
||||||
state.ilog(e=f"Nastaveno SL na {sl_defvalue}, priced normalized: {sl_defvalue_normalized} price: {state.vars.activeTrade.stoploss_value }")
|
state.ilog(e=f"Nastaveno SL na {sl_defvalue}, priced normalized: {sl_defvalue_normalized} price: {state.vars.activeTrade.stoploss_value }")
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
else:
|
else:
|
||||||
@ -966,7 +969,7 @@ def next(data, state: StrategyState):
|
|||||||
def execute_asr():
|
def execute_asr():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#preconditions and conditions of BUY SIGNAL
|
#preconditions and conditions of LONG/SHORT SIGNAL
|
||||||
def conditions_met(signalname: str, direction: TradeDirection):
|
def conditions_met(signalname: str, direction: TradeDirection):
|
||||||
if direction == TradeDirection.LONG:
|
if direction == TradeDirection.LONG:
|
||||||
smer = "long"
|
smer = "long"
|
||||||
@ -989,6 +992,8 @@ def next(data, state: StrategyState):
|
|||||||
# dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (int(state.vars.lastbuyindex) + int(safe_get(state.vars, "lastbuy_offset",3)))
|
# dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (int(state.vars.lastbuyindex) + int(safe_get(state.vars, "lastbuy_offset",3)))
|
||||||
# dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1)
|
# dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1)
|
||||||
# dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1)
|
# dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1)
|
||||||
|
|
||||||
|
#obecne open_rush platne pro vsechny
|
||||||
dont_do_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0))
|
dont_do_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0))
|
||||||
dont_do_when['close_rush'] = is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "close_rush",0))
|
dont_do_when['close_rush'] = is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "close_rush",0))
|
||||||
|
|
||||||
@ -1065,14 +1070,27 @@ def next(data, state: StrategyState):
|
|||||||
state.ilog(e="No options for {name} in stratvars")
|
state.ilog(e="No options for {name} in stratvars")
|
||||||
return
|
return
|
||||||
|
|
||||||
validfrom = safe_get(options, "validfrom", 0)
|
#check working windows
|
||||||
validto = safe_get(options, "validto", 0)
|
close_rush = safe_get(options, "close_rush",0)
|
||||||
|
open_rush = safe_get(options, "open_rush",0)
|
||||||
|
|
||||||
|
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="SINGAL {name} OUT of WORKING WINDOW", msg=f"{open_rush=} {close_rush=} ")
|
||||||
|
return
|
||||||
|
|
||||||
|
#natvrdo nebo na podminku
|
||||||
|
activated = safe_get(options, "activated", True)
|
||||||
|
|
||||||
recurring = safe_get(options, "reccurring", False)
|
recurring = safe_get(options, "reccurring", False)
|
||||||
on_confirmed_only = safe_get(options, 'on_confirmed_only', False)
|
on_confirmed_only = safe_get(options, 'on_confirmed_only', False)
|
||||||
plugin = safe_get(options, 'plugin', None)
|
plugin = safe_get(options, 'plugin', None)
|
||||||
short_enabled = safe_get(state.vars, "short_enabled",True)
|
short_enabled = safe_get(state.vars, "short_enabled",True)
|
||||||
long_enabled = safe_get(state.vars, "long_enabled",True)
|
long_enabled = safe_get(state.vars, "long_enabled",True)
|
||||||
|
|
||||||
|
if activated is False:
|
||||||
|
state.ilog(e="SIGNAL {name} NOT ACTIVATED")
|
||||||
|
return
|
||||||
|
|
||||||
#pokud je plugin True, spusti se kod
|
#pokud je plugin True, spusti se kod
|
||||||
if plugin:
|
if plugin:
|
||||||
execute_signal_generator_plugin(name)
|
execute_signal_generator_plugin(name)
|
||||||
@ -1122,6 +1140,9 @@ def next(data, state: StrategyState):
|
|||||||
if trade is None:
|
if trade is None:
|
||||||
return -1
|
return -1
|
||||||
|
|
||||||
|
#SL - trailing
|
||||||
|
trail_SL_management()
|
||||||
|
|
||||||
eval_close_position()
|
eval_close_position()
|
||||||
#SELL STOPLOSS
|
#SELL STOPLOSS
|
||||||
#SELL PROFIT
|
#SELL PROFIT
|
||||||
@ -1204,8 +1225,10 @@ def init(state: StrategyState):
|
|||||||
state.vars.work_dict_dont_do[signalname+"_"+ smer] = get_work_dict_with_directive(starts_with=signalname+"_dont_"+ smer +"_if")
|
state.vars.work_dict_dont_do[signalname+"_"+ smer] = get_work_dict_with_directive(starts_with=signalname+"_dont_"+ smer +"_if")
|
||||||
state.vars.work_dict_signal_if[signalname+"_"+ smer] = get_work_dict_with_directive(starts_with=signalname+"_"+smer+"_if")
|
state.vars.work_dict_signal_if[signalname+"_"+ smer] = get_work_dict_with_directive(starts_with=signalname+"_"+smer+"_if")
|
||||||
|
|
||||||
#nove atributy na rizeni tradu
|
#init klice v extData pro ulozeni historie SL
|
||||||
|
state.extData["sl_history"] = []
|
||||||
|
|
||||||
|
#nove atributy na rizeni tradu
|
||||||
#identifikuje provedenou změnu na Tradu (neděláme změny dokud nepřijde potvrzeni z notifikace)
|
#identifikuje provedenou změnu na Tradu (neděláme změny dokud nepřijde potvrzeni z notifikace)
|
||||||
state.vars.pending = None
|
state.vars.pending = None
|
||||||
#obsahuje aktivni Trade a jeho nastaveni
|
#obsahuje aktivni Trade a jeho nastaveni
|
||||||
|
|||||||
Binary file not shown.
@ -199,6 +199,12 @@ class RunArchive(BaseModel):
|
|||||||
end_positions_avgp: float = 0
|
end_positions_avgp: float = 0
|
||||||
open_orders: Union[dict, int] = None
|
open_orders: Union[dict, int] = None
|
||||||
|
|
||||||
|
#trida pro ukladani historie stoplossy do ext_data
|
||||||
|
class SLHistory(BaseModel):
|
||||||
|
id: Optional[UUID]
|
||||||
|
time: datetime
|
||||||
|
sl_val: float
|
||||||
|
|
||||||
#Contains archive of running strategies (runner) - detail data
|
#Contains archive of running strategies (runner) - detail data
|
||||||
class RunArchiveDetail(BaseModel):
|
class RunArchiveDetail(BaseModel):
|
||||||
id: UUID
|
id: UUID
|
||||||
@ -208,6 +214,7 @@ class RunArchiveDetail(BaseModel):
|
|||||||
indicators: List[dict]
|
indicators: List[dict]
|
||||||
statinds: dict
|
statinds: dict
|
||||||
trades: List[TradeUpdate]
|
trades: List[TradeUpdate]
|
||||||
|
ext_data: Optional[dict]
|
||||||
|
|
||||||
# class Trade(BaseModel):
|
# class Trade(BaseModel):
|
||||||
# order: Order
|
# order: Order
|
||||||
|
|||||||
@ -595,12 +595,14 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
|
|||||||
# flattened_indicators[key]= value
|
# flattened_indicators[key]= value
|
||||||
# flattened_indicators_list.append(flattened_indicators)
|
# flattened_indicators_list.append(flattened_indicators)
|
||||||
|
|
||||||
|
|
||||||
runArchiveDetail: RunArchiveDetail = RunArchiveDetail(id = runner.id,
|
runArchiveDetail: RunArchiveDetail = RunArchiveDetail(id = runner.id,
|
||||||
name=runner.run_name,
|
name=runner.run_name,
|
||||||
bars=strat.state.bars,
|
bars=strat.state.bars,
|
||||||
indicators=flattened_indicators_list,
|
indicators=flattened_indicators_list,
|
||||||
statinds=strat.state.statinds,
|
statinds=strat.state.statinds,
|
||||||
trades=strat.state.tradeList)
|
trades=strat.state.tradeList,
|
||||||
|
ext_data=strat.state.extData)
|
||||||
with lock:
|
with lock:
|
||||||
resh = db_arch_h.insert(runArchive.__dict__)
|
resh = db_arch_h.insert(runArchive.__dict__)
|
||||||
resd = insert_archive_detail(runArchiveDetail)
|
resd = insert_archive_detail(runArchiveDetail)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ var CHART_SHOW_TEXT = false
|
|||||||
// var volumeSeries = null
|
// var volumeSeries = null
|
||||||
var markersLine = null
|
var markersLine = null
|
||||||
var avgBuyLine = null
|
var avgBuyLine = null
|
||||||
|
var slLine = []
|
||||||
//TRANSFORM object returned from REST API get_arch_run_detail
|
//TRANSFORM object returned from REST API get_arch_run_detail
|
||||||
//to series and markers required by lightweigth chart
|
//to series and markers required by lightweigth chart
|
||||||
//input array object bars = { high: [1,2,3], time: [1,2,3], close: [2,2,2]...}
|
//input array object bars = { high: [1,2,3], time: [1,2,3], close: [2,2,2]...}
|
||||||
@ -15,6 +16,49 @@ function transform_data(data) {
|
|||||||
var bars = []
|
var bars = []
|
||||||
var volume = []
|
var volume = []
|
||||||
var vwap = []
|
var vwap = []
|
||||||
|
|
||||||
|
//pokud mame tak projedeme ext_data pro dane klice a s nimi pracujeme
|
||||||
|
var sl_line = []
|
||||||
|
var sl_line_markers = []
|
||||||
|
var sl_line_sada = []
|
||||||
|
var sl_line_markers_sada = []
|
||||||
|
//console.log(JSON.stringify(data.ext_data.sl_history, null, 2))
|
||||||
|
prev_id = 0
|
||||||
|
data.ext_data.sl_history.forEach((histRecord, index, array) => {
|
||||||
|
|
||||||
|
console.log("plnime")
|
||||||
|
|
||||||
|
//nova sada
|
||||||
|
if (prev_id !== histRecord.id) {
|
||||||
|
if (prev_id !== 0) {
|
||||||
|
//push sadu do pole
|
||||||
|
sl_line.push(sl_line_sada)
|
||||||
|
sl_line_markers.push(sl_line_markers_sada)
|
||||||
|
}
|
||||||
|
//init nova sada
|
||||||
|
sl_line_sada = []
|
||||||
|
sl_line_markers_sada = []
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_id = histRecord.id
|
||||||
|
//prevedeme iso data na timestampy
|
||||||
|
cas = histRecord.time
|
||||||
|
//line pro buy/sell markery
|
||||||
|
sline = {}
|
||||||
|
sline["time"] = cas
|
||||||
|
sline["value"] = histRecord.sl_val
|
||||||
|
sl_line_sada.push(sline)
|
||||||
|
|
||||||
|
sline_markers = {}
|
||||||
|
sline_markers["time"] = cas
|
||||||
|
sline_markers["position"] = "inBar"
|
||||||
|
sline_markers["color"] = "#f5aa42"
|
||||||
|
//sline_markers["shape"] = "circle"
|
||||||
|
sline_markers["text"] = histRecord.sl_val.toFixed(3)
|
||||||
|
sl_line_markers_sada.push(sline_markers)
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
data.bars.time.forEach((element, index, array) => {
|
data.bars.time.forEach((element, index, array) => {
|
||||||
sbars = {};
|
sbars = {};
|
||||||
svolume = {};
|
svolume = {};
|
||||||
@ -117,7 +161,7 @@ function transform_data(data) {
|
|||||||
marker["text"] += (trade.position_qty == 0) ? closed_trade_marker_and_profit : ""
|
marker["text"] += (trade.position_qty == 0) ? closed_trade_marker_and_profit : ""
|
||||||
} else {
|
} else {
|
||||||
closed_trade_marker_and_profit = (trade.profit) ? "c" + trade.profit.toFixed(1) + "/" + trade.profit_sum.toFixed(1) : "c"
|
closed_trade_marker_and_profit = (trade.profit) ? "c" + trade.profit.toFixed(1) + "/" + trade.profit_sum.toFixed(1) : "c"
|
||||||
marker["text"] = (trade.position_qty == 0) ? closed_trade_marker_and_profit : ""
|
marker["text"] = (trade.position_qty == 0) ? closed_trade_marker_and_profit : trade.price.toFixed(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
markers.push(marker)
|
markers.push(marker)
|
||||||
@ -153,7 +197,11 @@ function transform_data(data) {
|
|||||||
transformed["avgp_markers"] = avgp_markers
|
transformed["avgp_markers"] = avgp_markers
|
||||||
transformed["markers"] = markers
|
transformed["markers"] = markers
|
||||||
transformed["markers_line"] = markers_line
|
transformed["markers_line"] = markers_line
|
||||||
|
transformed["sl_line"] = sl_line
|
||||||
|
transformed["sl_line_markers"] = sl_line_markers
|
||||||
|
console.log("naplnene", sl_line, sl_line_markers)
|
||||||
|
//console_log(JSON.stringify(transformed["sl_line"],null,2))
|
||||||
|
//console_log(JSON.stringify(transformed["sl_line_markers"],null,2))
|
||||||
//get additional indicators
|
//get additional indicators
|
||||||
return transformed
|
return transformed
|
||||||
}
|
}
|
||||||
@ -541,9 +589,45 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
chart.removeSeries(markersLine)
|
chart.removeSeries(markersLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slLine.forEach((series, index, array) => {
|
||||||
|
chart.removeSeries(series)
|
||||||
|
})
|
||||||
|
// if (slLine) {
|
||||||
|
// chart.removeSeries(slLine)
|
||||||
|
// }
|
||||||
|
|
||||||
//console.log("avgp_buy_line",JSON.stringify(transformed_data["avgp_buy_line"],null,2))
|
//console.log("avgp_buy_line",JSON.stringify(transformed_data["avgp_buy_line"],null,2))
|
||||||
//console.log("avgp_markers",JSON.stringify(transformed_data["avgp_markers"],null,2))
|
//console.log("avgp_markers",JSON.stringify(transformed_data["avgp_markers"],null,2))
|
||||||
|
|
||||||
|
//if (transformed_data["sl_line"].length > 0) {
|
||||||
|
//console.log(JSON.stringify(transformed_data["sl_line"]), null,2)
|
||||||
|
//xx - ted bude slLine pole
|
||||||
|
transformed_data["sl_line"].forEach((slRecord, index, array) => {
|
||||||
|
|
||||||
|
console.log("uvnitr")
|
||||||
|
slLine_temp = chart.addLineSeries({
|
||||||
|
// title: "avgpbuyline",
|
||||||
|
color: '#e4c76d',
|
||||||
|
// color: 'transparent',
|
||||||
|
lineWidth: 1,
|
||||||
|
lastValueVisible: false
|
||||||
|
});
|
||||||
|
|
||||||
|
slLine_temp.applyOptions({
|
||||||
|
lastValueVisible: false,
|
||||||
|
priceLineVisible: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
slLine_temp.setData(slRecord);
|
||||||
|
//zatim nemame markery pro sl history
|
||||||
|
slLine_temp.setMarkers(transformed_data["sl_line_markers"][index]);
|
||||||
|
slLine.push(slLine_temp)
|
||||||
|
|
||||||
|
//xx
|
||||||
|
})
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
if (transformed_data["avgp_buy_line"].length > 0) {
|
if (transformed_data["avgp_buy_line"].length > 0) {
|
||||||
avgBuyLine = chart.addLineSeries({
|
avgBuyLine = chart.addLineSeries({
|
||||||
// title: "avgpbuyline",
|
// title: "avgpbuyline",
|
||||||
|
|||||||
@ -3,6 +3,7 @@ var pbiList = []
|
|||||||
var ws = null;
|
var ws = null;
|
||||||
var logcnt = 0
|
var logcnt = 0
|
||||||
var positionsPriceLine = null
|
var positionsPriceLine = null
|
||||||
|
var stoplossPriceLine = null
|
||||||
var limitkaPriceLine = null
|
var limitkaPriceLine = null
|
||||||
var angleSeries = {}
|
var angleSeries = {}
|
||||||
//var angleSeries_slow = 1
|
//var angleSeries_slow = 1
|
||||||
@ -200,6 +201,24 @@ function connect(event) {
|
|||||||
candlestickSeries.removePriceLine(positionsPriceLine)
|
candlestickSeries.removePriceLine(positionsPriceLine)
|
||||||
}
|
}
|
||||||
positionsPriceLine = candlestickSeries.createPriceLine(posLine);
|
positionsPriceLine = candlestickSeries.createPriceLine(posLine);
|
||||||
|
|
||||||
|
if (positions.sl_value !== null) {
|
||||||
|
if (stoplossPriceLine !== null) {
|
||||||
|
candlestickSeries.removePriceLine(stoplossPriceLine)
|
||||||
|
}
|
||||||
|
const stoplossLine = {
|
||||||
|
price: positions.sl_value,
|
||||||
|
color: '#f5aa42',
|
||||||
|
lineWidth: 1,
|
||||||
|
lineStyle: 1, // LineStyle.Dotted
|
||||||
|
axisLabelVisible: true,
|
||||||
|
title: "SL",
|
||||||
|
};
|
||||||
|
|
||||||
|
stoplossPriceLine = candlestickSeries.createPriceLine(stoplossLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed_data.hasOwnProperty("statinds")) {
|
if (parsed_data.hasOwnProperty("statinds")) {
|
||||||
|
|||||||
Binary file not shown.
@ -514,7 +514,14 @@ class Strategy:
|
|||||||
|
|
||||||
#vkladame average price and positions, pokud existuji
|
#vkladame average price and positions, pokud existuji
|
||||||
#self.state.avgp , self.state.positions
|
#self.state.avgp , self.state.positions
|
||||||
rt_out["positions"] = dict(time=self.state.time, positions=self.state.positions, avgp=self.state.avgp)
|
|
||||||
|
#pro typ strategie Classic, posilame i vysi stoploss
|
||||||
|
try:
|
||||||
|
sl_value = self.state.vars["activeTrade"].stoploss_value
|
||||||
|
except (KeyError, AttributeError):
|
||||||
|
sl_value = None
|
||||||
|
|
||||||
|
rt_out["positions"] = dict(time=self.state.time, positions=self.state.positions, avgp=self.state.avgp, sl_value=sl_value)
|
||||||
|
|
||||||
#vkladame limitku a pendingbuys
|
#vkladame limitku a pendingbuys
|
||||||
try:
|
try:
|
||||||
@ -652,6 +659,8 @@ class StrategyState:
|
|||||||
self.iter_log_list = []
|
self.iter_log_list = []
|
||||||
self.profit = 0
|
self.profit = 0
|
||||||
self.tradeList = []
|
self.tradeList = []
|
||||||
|
#nova promenna pro externi data do ArchiveDetaili, napr. pro zobrazeni v grafu, je zde např. SL history
|
||||||
|
self.extData = {}
|
||||||
self.mode = None
|
self.mode = None
|
||||||
|
|
||||||
def ilog(self, e: str = None, msg: str = None, **kwargs):
|
def ilog(self, e: str = None, msg: str = None, **kwargs):
|
||||||
|
|||||||
Binary file not shown.
@ -9,7 +9,7 @@ import decimal
|
|||||||
from v2realbot.enums.enums import RecordType, Mode, StartBarAlign
|
from v2realbot.enums.enums import RecordType, Mode, StartBarAlign
|
||||||
import pickle
|
import pickle
|
||||||
import os
|
import os
|
||||||
from v2realbot.common.model import StrategyInstance, Runner, RunArchive, RunArchiveDetail, Intervals
|
from v2realbot.common.model import StrategyInstance, Runner, RunArchive, RunArchiveDetail, Intervals, SLHistory
|
||||||
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||||
from typing import List
|
from typing import List
|
||||||
import tomli
|
import tomli
|
||||||
@ -208,6 +208,8 @@ def json_serial(obj):
|
|||||||
return obj.__dict__
|
return obj.__dict__
|
||||||
if type(obj) is Intervals:
|
if type(obj) is Intervals:
|
||||||
return obj.__dict__
|
return obj.__dict__
|
||||||
|
if type(obj) is SLHistory:
|
||||||
|
return obj.__dict__
|
||||||
|
|
||||||
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user