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.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.common.model import SLHistory
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
import json
|
||||
@ -498,20 +499,25 @@ def next(data, state: StrategyState):
|
||||
lookbacktime = state.bars.time[-slope_lookback]
|
||||
else:
|
||||
#kdyz neni dostatek hodnot, pouzivame jako levy bod open hodnotu close[0]
|
||||
lookbackprice = state.bars.vwap[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]
|
||||
#update -- lookback je pole z toho co mame
|
||||
#dalsi vyarianta-- lookback je pole z toho všeho co mame
|
||||
#lookbackprice = Average(state.bars.vwap)
|
||||
lookbacktime = state.bars.time[0]
|
||||
state.ilog(e=f"IND {name} slope - not enough data bereme left bod open", slope_lookback=slope_lookback)
|
||||
|
||||
|
||||
|
||||
#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]
|
||||
|
||||
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
|
||||
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
|
||||
@ -533,7 +539,7 @@ def next(data, state: StrategyState):
|
||||
state.indicators[name+"MA"][-1]=slopeMA
|
||||
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
|
||||
#slope = slopeMA
|
||||
|
||||
@ -752,7 +758,11 @@ def next(data, state: StrategyState):
|
||||
# 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
|
||||
#+ varianta - skoncit breakeven
|
||||
|
||||
@ -768,43 +778,68 @@ def next(data, state: StrategyState):
|
||||
# #zda trailing zastavit na brakeeven
|
||||
# SL_trailing_stop_at_breakeven_short = true
|
||||
# SL_trailing_stop_at_breakeven_long = true
|
||||
if direction == TradeDirection.LONG:
|
||||
smer = "long"
|
||||
else:
|
||||
smer = "short"
|
||||
if int(state.positions) != 0 and float(state.avgp)>0 and state.vars.pending is None:
|
||||
|
||||
options = safe_get(state.vars, 'exit_conditions', None)
|
||||
if options is None:
|
||||
state.ilog(e="Trail SL. No options for exit conditions in stratvars.")
|
||||
return
|
||||
if int(state.positions) < 0:
|
||||
direction = TradeDirection.SHORT
|
||||
smer = "short"
|
||||
else:
|
||||
direction = TradeDirection.LONG
|
||||
smer = "long"
|
||||
|
||||
if safe_get(options, 'SL_trailing_enabled_'+str(smer), False) is True:
|
||||
stop_breakeven = safe_get(options, 'SL_trailing_stop_at_breakeven_'+str(smer), False)
|
||||
def_SL = safe_get(options, 'SL_defval_'+str(smer), 0.01)
|
||||
offset = safe_get(options, "SL_trailing_offset_"+str(smer), 0.01)
|
||||
|
||||
#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)):
|
||||
state.ilog(e=f"SL trail stop at breakeven {str(smer)} SL:{state.vars.activeTrade.stoploss_value} UNCHANGED", stop_breakeven=stop_breakeven)
|
||||
options = safe_get(state.vars, 'exit_conditions', None)
|
||||
if options is None:
|
||||
state.ilog(e="Trail SL. No options for exit conditions in stratvars.")
|
||||
return
|
||||
|
||||
#IDEA: Nyni posouvame SL o offset, mozna ji posunout jen o direktivu step ?
|
||||
if safe_get(options, 'SL_trailing_enabled_'+str(smer), False) is True:
|
||||
stop_breakeven = safe_get(options, 'SL_trailing_stop_at_breakeven_'+str(smer), False)
|
||||
def_SL = safe_get(options, 'SL_defval_'+str(smer), 0.01)
|
||||
offset = safe_get(options, "SL_trailing_offset_"+str(smer), 0.01)
|
||||
|
||||
offset_normalized = normalize_tick(offset) #to ticks and from options
|
||||
def_SL_normalized = normalize_tick(def_SL)
|
||||
if direction == TradeDirection.LONG:
|
||||
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)
|
||||
if (move_SL_threshold) < data['close']:
|
||||
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)
|
||||
elif direction == TradeDirection.SHORT:
|
||||
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)
|
||||
if (move_SL_threshold) > data['close']:
|
||||
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)
|
||||
#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)):
|
||||
state.ilog(e=f"SL trail STOP at breakeven {str(smer)} SL:{state.vars.activeTrade.stoploss_value} UNCHANGED", stop_breakeven=stop_breakeven)
|
||||
return
|
||||
|
||||
#IDEA: Nyni posouvame SL o offset, mozna ji posunout jen o direktivu step ?
|
||||
|
||||
offset_normalized = normalize_tick(offset) #to ticks and from options
|
||||
def_SL_normalized = normalize_tick(def_SL)
|
||||
if direction == TradeDirection.LONG:
|
||||
move_SL_threshold = state.vars.activeTrade.stoploss_value + offset_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']:
|
||||
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)
|
||||
elif direction == TradeDirection.SHORT:
|
||||
move_SL_threshold = state.vars.activeTrade.stoploss_value - offset_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']:
|
||||
state.vars.activeTrade.stoploss_value -= offset_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():
|
||||
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}")
|
||||
|
||||
#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:
|
||||
#EOD EXIT - TBD
|
||||
|
||||
#SL TRAILING
|
||||
trail_SL_if_required(direction=TradeDirection.SHORT)
|
||||
#FORCED EXIT PRI KONCI DNE
|
||||
|
||||
#SL - execution
|
||||
if curr_price > state.vars.activeTrade.stoploss_value:
|
||||
state.ilog(e=f"STOPLOSS reached on SHORT", curr_price=curr_price, trade=state.vars.activeTrade)
|
||||
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
|
||||
close_position(direction=TradeDirection.SHORT, reason="SL REACHED")
|
||||
return
|
||||
|
||||
#CLOSING BASED ON EXIT CONDITIONS
|
||||
if exit_conditions_met(TradeDirection.SHORT):
|
||||
res = state.buy(size=abs(int(state.positions)))
|
||||
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)
|
||||
close_position(direction=TradeDirection.SHORT, reason="EXIT COND MET")
|
||||
return
|
||||
|
||||
#PROFIT
|
||||
@ -853,37 +877,19 @@ def next(data, state: StrategyState):
|
||||
max_price_signal = curr_price<=max_price
|
||||
#OPTIMALIZACE pri stoupajícím angle
|
||||
if max_price_signal or sell_protection_enabled() is False:
|
||||
res = state.buy(size=abs(int(state.positions)))
|
||||
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)
|
||||
close_position(direction=TradeDirection.SHORT, reason=f"PROFIT or MAXPROFIT REACHED {max_price_signal=}")
|
||||
return
|
||||
#mame long
|
||||
elif int(state.positions) > 0:
|
||||
#EOD EXIT - TBD
|
||||
|
||||
#SL - trailing
|
||||
trail_SL_if_required(direction=TradeDirection.LONG)
|
||||
|
||||
#SL - execution
|
||||
if curr_price < state.vars.activeTrade.stoploss_value:
|
||||
state.ilog(e=f"STOPLOSS reached on LONG", curr_price=curr_price, trade=state.vars.activeTrade)
|
||||
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
|
||||
close_position(direction=TradeDirection.LONG, reason="SL REACHED")
|
||||
return
|
||||
|
||||
if exit_conditions_met(TradeDirection.LONG):
|
||||
res = state.sell(size=abs(int(state.positions)))
|
||||
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)
|
||||
close_position(direction=TradeDirection.LONG, reason="EXIT CONDS MET")
|
||||
return
|
||||
|
||||
#PROFIT
|
||||
@ -894,12 +900,7 @@ def next(data, state: StrategyState):
|
||||
max_price_signal = curr_price>=max_price
|
||||
#OPTIMALIZACE pri stoupajícím angle
|
||||
if max_price_signal or sell_protection_enabled() is False:
|
||||
res = state.sell(size=state.positions)
|
||||
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)
|
||||
close_position(direction=TradeDirection.LONG, reason=f"PROFIT or MAXPROFIT REACHED {max_price_signal=}")
|
||||
return
|
||||
|
||||
def execute_prescribed_trades():
|
||||
@ -939,6 +940,7 @@ def next(data, state: StrategyState):
|
||||
#normalizuji dle aktualni ceny
|
||||
sl_defvalue_normalized = normalize_tick(sl_defvalue)
|
||||
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.vars.pending = state.vars.activeTrade.id
|
||||
elif state.vars.activeTrade.direction == TradeDirection.SHORT:
|
||||
@ -952,6 +954,7 @@ def next(data, state: StrategyState):
|
||||
#normalizuji dle aktualni ceny
|
||||
sl_defvalue_normalized = normalize_tick(sl_defvalue)
|
||||
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.vars.pending = state.vars.activeTrade.id
|
||||
else:
|
||||
@ -966,7 +969,7 @@ def next(data, state: StrategyState):
|
||||
def execute_asr():
|
||||
pass
|
||||
|
||||
#preconditions and conditions of BUY SIGNAL
|
||||
#preconditions and conditions of LONG/SHORT SIGNAL
|
||||
def conditions_met(signalname: str, direction: TradeDirection):
|
||||
if direction == TradeDirection.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['blockbuy_active'] = (state.vars.blockbuy == 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['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")
|
||||
return
|
||||
|
||||
validfrom = safe_get(options, "validfrom", 0)
|
||||
validto = safe_get(options, "validto", 0)
|
||||
#check working windows
|
||||
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)
|
||||
on_confirmed_only = safe_get(options, 'on_confirmed_only', False)
|
||||
plugin = safe_get(options, 'plugin', None)
|
||||
short_enabled = safe_get(state.vars, "short_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
|
||||
if plugin:
|
||||
execute_signal_generator_plugin(name)
|
||||
@ -1122,6 +1140,9 @@ def next(data, state: StrategyState):
|
||||
if trade is None:
|
||||
return -1
|
||||
|
||||
#SL - trailing
|
||||
trail_SL_management()
|
||||
|
||||
eval_close_position()
|
||||
#SELL STOPLOSS
|
||||
#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_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)
|
||||
state.vars.pending = None
|
||||
#obsahuje aktivni Trade a jeho nastaveni
|
||||
|
||||
Binary file not shown.
@ -199,6 +199,12 @@ class RunArchive(BaseModel):
|
||||
end_positions_avgp: float = 0
|
||||
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
|
||||
class RunArchiveDetail(BaseModel):
|
||||
id: UUID
|
||||
@ -208,6 +214,7 @@ class RunArchiveDetail(BaseModel):
|
||||
indicators: List[dict]
|
||||
statinds: dict
|
||||
trades: List[TradeUpdate]
|
||||
ext_data: Optional[dict]
|
||||
|
||||
# class Trade(BaseModel):
|
||||
# order: Order
|
||||
|
||||
@ -595,12 +595,14 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
|
||||
# flattened_indicators[key]= value
|
||||
# flattened_indicators_list.append(flattened_indicators)
|
||||
|
||||
|
||||
runArchiveDetail: RunArchiveDetail = RunArchiveDetail(id = runner.id,
|
||||
name=runner.run_name,
|
||||
bars=strat.state.bars,
|
||||
indicators=flattened_indicators_list,
|
||||
statinds=strat.state.statinds,
|
||||
trades=strat.state.tradeList)
|
||||
trades=strat.state.tradeList,
|
||||
ext_data=strat.state.extData)
|
||||
with lock:
|
||||
resh = db_arch_h.insert(runArchive.__dict__)
|
||||
resd = insert_archive_detail(runArchiveDetail)
|
||||
|
||||
@ -5,6 +5,7 @@ var CHART_SHOW_TEXT = false
|
||||
// var volumeSeries = null
|
||||
var markersLine = null
|
||||
var avgBuyLine = null
|
||||
var slLine = []
|
||||
//TRANSFORM object returned from REST API get_arch_run_detail
|
||||
//to series and markers required by lightweigth chart
|
||||
//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 volume = []
|
||||
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) => {
|
||||
sbars = {};
|
||||
svolume = {};
|
||||
@ -117,7 +161,7 @@ function transform_data(data) {
|
||||
marker["text"] += (trade.position_qty == 0) ? closed_trade_marker_and_profit : ""
|
||||
} else {
|
||||
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)
|
||||
@ -153,7 +197,11 @@ function transform_data(data) {
|
||||
transformed["avgp_markers"] = avgp_markers
|
||||
transformed["markers"] = markers
|
||||
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
|
||||
return transformed
|
||||
}
|
||||
@ -541,9 +589,45 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
||||
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_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) {
|
||||
avgBuyLine = chart.addLineSeries({
|
||||
// title: "avgpbuyline",
|
||||
|
||||
@ -3,6 +3,7 @@ var pbiList = []
|
||||
var ws = null;
|
||||
var logcnt = 0
|
||||
var positionsPriceLine = null
|
||||
var stoplossPriceLine = null
|
||||
var limitkaPriceLine = null
|
||||
var angleSeries = {}
|
||||
//var angleSeries_slow = 1
|
||||
@ -200,6 +201,24 @@ function connect(event) {
|
||||
candlestickSeries.removePriceLine(positionsPriceLine)
|
||||
}
|
||||
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")) {
|
||||
|
||||
Binary file not shown.
@ -514,7 +514,14 @@ class Strategy:
|
||||
|
||||
#vkladame average price and positions, pokud existuji
|
||||
#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
|
||||
try:
|
||||
@ -652,6 +659,8 @@ class StrategyState:
|
||||
self.iter_log_list = []
|
||||
self.profit = 0
|
||||
self.tradeList = []
|
||||
#nova promenna pro externi data do ArchiveDetaili, napr. pro zobrazeni v grafu, je zde např. SL history
|
||||
self.extData = {}
|
||||
self.mode = None
|
||||
|
||||
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
|
||||
import pickle
|
||||
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 typing import List
|
||||
import tomli
|
||||
@ -208,6 +208,8 @@ def json_serial(obj):
|
||||
return obj.__dict__
|
||||
if type(obj) is Intervals:
|
||||
return obj.__dict__
|
||||
if type(obj) is SLHistory:
|
||||
return obj.__dict__
|
||||
|
||||
raise TypeError (str(obj)+"Type %s not serializable" % type(obj))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user