pridany metriky a bugfixy pro live run
This commit is contained in:
@ -6,7 +6,7 @@ from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, Orde
|
|||||||
from v2realbot.indicators.indicators import ema
|
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, get_tick, 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 datetime import datetime
|
from datetime import datetime
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
import json
|
import json
|
||||||
@ -173,13 +173,13 @@ def next(data, state: StrategyState):
|
|||||||
#vrati true pokud dany indikator prekrocil threshold dolu
|
#vrati true pokud dany indikator prekrocil threshold dolu
|
||||||
def buy_if_crossed_down(indicator, value):
|
def buy_if_crossed_down(indicator, value):
|
||||||
res = crossed_down(threshold=value, list=get_source_or_MA(indicator))
|
res = crossed_down(threshold=value, list=get_source_or_MA(indicator))
|
||||||
state.ilog(e=f"buy_if_crossed_down {indicator} {value} {res}")
|
state.ilog(e=f"signal_if_crossed_down {indicator} {value} {res}")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
#vrati true pokud dany indikator prekrocil threshold nahoru
|
#vrati true pokud dany indikator prekrocil threshold nahoru
|
||||||
def buy_if_crossed_up(indicator, value):
|
def buy_if_crossed_up(indicator, value):
|
||||||
res = crossed_up(threshold=value, list=get_source_or_MA(indicator))
|
res = crossed_up(threshold=value, list=get_source_or_MA(indicator))
|
||||||
state.ilog(e=f"buy_if_crossed_up {indicator} {value} {res}")
|
state.ilog(e=f"signal_if_crossed_up {indicator} {value} {res}")
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def populate_cbar_tick_price_indicator():
|
def populate_cbar_tick_price_indicator():
|
||||||
@ -625,6 +625,36 @@ def next(data, state: StrategyState):
|
|||||||
# state.ilog(e=f"SELL_PROTECTION {conditions_met} enabled")
|
# state.ilog(e=f"SELL_PROTECTION {conditions_met} enabled")
|
||||||
# return result
|
# return result
|
||||||
|
|
||||||
|
def normalize_tick(tick: float, price: float = None, return_two_decimals: bool = False):
|
||||||
|
"""
|
||||||
|
Pokud je nastaveno v direktive:
|
||||||
|
#zda normalizovat vsechyn ticky (tzn. profit, maxprofit, SL atp.)
|
||||||
|
Normalize_ticks= true
|
||||||
|
Normalized Tick base price = 30
|
||||||
|
|
||||||
|
prevede normalizovany tick na tick odpovidajici vstupni cene
|
||||||
|
vysledek je zaokoruhleny na 2 des.mista
|
||||||
|
|
||||||
|
u cen pod 30, vrací 0.01. U cen nad 30 vrací pomerne zvetsene,
|
||||||
|
|
||||||
|
"""
|
||||||
|
#nemusime dodavat cenu, bereme aktualni
|
||||||
|
if price is None:
|
||||||
|
price = data["close"]
|
||||||
|
|
||||||
|
normalize_ticks = safe_get(state.vars, "normalize_ticks",False)
|
||||||
|
normalized_base_price = safe_get(state.vars, "normalized_base_price",30)
|
||||||
|
if normalize_ticks:
|
||||||
|
if price<normalized_base_price:
|
||||||
|
return tick
|
||||||
|
else:
|
||||||
|
#ratio of price vs base price
|
||||||
|
ratio = price/normalized_base_price
|
||||||
|
normalized_tick = ratio*tick
|
||||||
|
return price2dec(normalized_tick) if return_two_decimals else normalized_tick
|
||||||
|
else:
|
||||||
|
return tick
|
||||||
|
|
||||||
def get_default_sl_value(direction: TradeDirection):
|
def get_default_sl_value(direction: TradeDirection):
|
||||||
if direction == TradeDirection.LONG:
|
if direction == TradeDirection.LONG:
|
||||||
smer = "long"
|
smer = "long"
|
||||||
@ -641,12 +671,12 @@ def next(data, state: StrategyState):
|
|||||||
def get_profit_target_price():
|
def get_profit_target_price():
|
||||||
def_profit = safe_get(state.vars, "def_profit",state.vars.profit)
|
def_profit = safe_get(state.vars, "def_profit",state.vars.profit)
|
||||||
cena = float(state.avgp)
|
cena = float(state.avgp)
|
||||||
return price2dec(cena+get_tick(cena,float(state.vars.profit)),3) if state.positions > 0 else price2dec(cena-get_tick(cena,float(state.vars.profit)),3)
|
return price2dec(cena+normalize_tick(float(state.vars.profit)),3) if int(state.positions) > 0 else price2dec(cena-normalize_tick(float(state.vars.profit)),3)
|
||||||
|
|
||||||
def get_max_profit_price():
|
def get_max_profit_price():
|
||||||
max_profit = float(safe_get(state.vars, "max_profit",0.03))
|
max_profit = float(safe_get(state.vars, "max_profit",0.03))
|
||||||
cena = float(state.avgp)
|
cena = float(state.avgp)
|
||||||
return price2dec(cena+get_tick(cena,max_profit),3) if state.positions > 0 else price2dec(cena-get_tick(cena,max_profit),3)
|
return price2dec(cena+normalize_tick(max_profit),3) if int(state.positions) > 0 else price2dec(cena-normalize_tick(max_profit),3)
|
||||||
|
|
||||||
#TBD pripadne opet dat parsovani pole do INITu
|
#TBD pripadne opet dat parsovani pole do INITu
|
||||||
|
|
||||||
@ -668,7 +698,7 @@ def next(data, state: StrategyState):
|
|||||||
disable_exit_proteciton_when['disabled_in_config'] = safe_get(options, 'enabled', False) is False
|
disable_exit_proteciton_when['disabled_in_config'] = safe_get(options, 'enabled', False) is False
|
||||||
#too good to be true (maximum profit)
|
#too good to be true (maximum profit)
|
||||||
#disable_sell_proteciton_when['tgtbt_reached'] = safe_get(options, 'tgtbt', False) is False
|
#disable_sell_proteciton_when['tgtbt_reached'] = safe_get(options, 'tgtbt', False) is False
|
||||||
disable_exit_proteciton_when['disable_if_positions_above'] = int(safe_get(options, 'disable_if_positions_above', 0)) < abs(state.positions)
|
disable_exit_proteciton_when['disable_if_positions_above'] = int(safe_get(options, 'disable_if_positions_above', 0)) < abs(int(state.positions))
|
||||||
|
|
||||||
#testing preconditions
|
#testing preconditions
|
||||||
result, conditions_met = eval_cond_dict(disable_exit_proteciton_when)
|
result, conditions_met = eval_cond_dict(disable_exit_proteciton_when)
|
||||||
@ -747,20 +777,22 @@ 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 ?
|
||||||
|
|
||||||
offset_normalized = get_tick(data['close'],offset) #to ticks and from options
|
offset_normalized = normalize_tick(offset) #to ticks and from options
|
||||||
def_SL_normalized = get_tick(data['close'],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)
|
||||||
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)
|
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)
|
||||||
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)
|
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)
|
||||||
@ -788,7 +820,7 @@ def next(data, state: StrategyState):
|
|||||||
#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)
|
state.ilog(e=f"STOPLOSS reached on SHORT", curr_price=curr_price, trade=state.vars.activeTrade)
|
||||||
res = state.buy(size=abs(state.positions))
|
res = state.buy(size=abs(int(state.positions)))
|
||||||
if isinstance(res, int) and res < 0:
|
if isinstance(res, int) and res < 0:
|
||||||
raise Exception(f"error in required operation STOPLOSS BUY {res}")
|
raise Exception(f"error in required operation STOPLOSS BUY {res}")
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
@ -797,7 +829,7 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
#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(state.positions))
|
res = state.buy(size=abs(int(state.positions)))
|
||||||
if isinstance(res, int) and res < 0:
|
if isinstance(res, int) and res < 0:
|
||||||
raise Exception(f"error in required operation EXIT COND BUY {res}")
|
raise Exception(f"error in required operation EXIT COND BUY {res}")
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
@ -813,7 +845,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.buy(size=abs(state.positions))
|
res = state.buy(size=abs(int(state.positions)))
|
||||||
if isinstance(res, int) and res < 0:
|
if isinstance(res, int) and res < 0:
|
||||||
raise Exception(f"error in required operation PROFIT BUY {res}")
|
raise Exception(f"error in required operation PROFIT BUY {res}")
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
@ -838,7 +870,7 @@ def next(data, state: StrategyState):
|
|||||||
return
|
return
|
||||||
|
|
||||||
if exit_conditions_met(TradeDirection.LONG):
|
if exit_conditions_met(TradeDirection.LONG):
|
||||||
res = state.sell(size=abs(state.positions))
|
res = state.sell(size=abs(int(state.positions)))
|
||||||
if isinstance(res, int) and res < 0:
|
if isinstance(res, int) and res < 0:
|
||||||
raise Exception(f"error in required operation EXIT COND SELL {res}")
|
raise Exception(f"error in required operation EXIT COND SELL {res}")
|
||||||
state.vars.pending = state.vars.activeTrade.id
|
state.vars.pending = state.vars.activeTrade.id
|
||||||
@ -872,6 +904,7 @@ def next(data, state: StrategyState):
|
|||||||
for trade in state.vars.prescribedTrades:
|
for trade in state.vars.prescribedTrades:
|
||||||
if trade.status == TradeStatus.READY and trade.direction == TradeDirection.LONG and (trade.entry_price is None or trade.entry_price >= data['close']):
|
if trade.status == TradeStatus.READY and trade.direction == TradeDirection.LONG and (trade.entry_price is None or trade.entry_price >= data['close']):
|
||||||
trade.status = TradeStatus.ACTIVATED
|
trade.status = TradeStatus.ACTIVATED
|
||||||
|
trade.last_update = datetime.fromtimestamp(state.time).astimezone(zoneNY)
|
||||||
state.ilog(e=f"evaluated SHORT {str(trade)}", prescrTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)))
|
state.ilog(e=f"evaluated SHORT {str(trade)}", prescrTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)))
|
||||||
state.vars.activeTrade = trade
|
state.vars.activeTrade = trade
|
||||||
break
|
break
|
||||||
@ -881,6 +914,7 @@ def next(data, state: StrategyState):
|
|||||||
if trade.status == TradeStatus.READY and trade.direction == TradeDirection.SHORT and (trade.entry_price is None or trade.entry_price <= data['close']):
|
if trade.status == TradeStatus.READY and trade.direction == TradeDirection.SHORT and (trade.entry_price is None or trade.entry_price <= data['close']):
|
||||||
state.ilog(e=f"evaluaed SHORT {str(trade)}", prescTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)))
|
state.ilog(e=f"evaluaed SHORT {str(trade)}", prescTrades=json.loads(json.dumps(state.vars.prescribedTrades, default=json_serial)))
|
||||||
trade.status = TradeStatus.ACTIVATED
|
trade.status = TradeStatus.ACTIVATED
|
||||||
|
trade.last_update = datetime.fromtimestamp(state.time).astimezone(zoneNY)
|
||||||
state.vars.activeTrade = trade
|
state.vars.activeTrade = trade
|
||||||
break
|
break
|
||||||
|
|
||||||
@ -895,7 +929,7 @@ def next(data, state: StrategyState):
|
|||||||
if state.vars.activeTrade.stoploss_value is None:
|
if state.vars.activeTrade.stoploss_value is None:
|
||||||
sl_defvalue = get_default_sl_value(direction=state.vars.activeTrade.direction)
|
sl_defvalue = get_default_sl_value(direction=state.vars.activeTrade.direction)
|
||||||
#normalizuji dle aktualni ceny
|
#normalizuji dle aktualni ceny
|
||||||
sl_defvalue_normalized = get_tick(data['close'],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
|
||||||
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
|
||||||
@ -908,7 +942,7 @@ def next(data, state: StrategyState):
|
|||||||
if state.vars.activeTrade.stoploss_value is None:
|
if state.vars.activeTrade.stoploss_value is None:
|
||||||
sl_defvalue = get_default_sl_value(direction=state.vars.activeTrade.direction)
|
sl_defvalue = get_default_sl_value(direction=state.vars.activeTrade.direction)
|
||||||
#normalizuji dle aktualni ceny
|
#normalizuji dle aktualni ceny
|
||||||
sl_defvalue_normalized = get_tick(data['close'],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
|
||||||
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
|
||||||
@ -1028,25 +1062,27 @@ def next(data, state: StrategyState):
|
|||||||
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)
|
||||||
|
long_enabled = safe_get(state.vars, "long_enabled",True)
|
||||||
|
|
||||||
#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)
|
||||||
else:
|
else:
|
||||||
#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 conditions_met(signalname=name, direction=TradeDirection.LONG):
|
if long_enabled and conditions_met(signalname=name, direction=TradeDirection.LONG):
|
||||||
state.vars.prescribedTrades.append(Trade(
|
state.vars.prescribedTrades.append(Trade(
|
||||||
id=uuid4(),
|
id=uuid4(),
|
||||||
validfrom=datetime.now(tz=zoneNY),
|
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
|
||||||
status=TradeStatus.READY,
|
status=TradeStatus.READY,
|
||||||
direction=TradeDirection.LONG,
|
direction=TradeDirection.LONG,
|
||||||
entry_price=None,
|
entry_price=None,
|
||||||
stoploss_value = None))
|
stoploss_value = None))
|
||||||
elif conditions_met(signalname=name, direction=TradeDirection.SHORT):
|
elif short_enabled and conditions_met(signalname=name, direction=TradeDirection.SHORT):
|
||||||
state.vars.prescribedTrades.append(Trade(
|
state.vars.prescribedTrades.append(Trade(
|
||||||
id=uuid4(),
|
id=uuid4(),
|
||||||
validfrom=datetime.now(tz=zoneNY),
|
last_update=datetime.fromtimestamp(state.time).astimezone(zoneNY),
|
||||||
status=TradeStatus.READY,
|
status=TradeStatus.READY,
|
||||||
direction=TradeDirection.SHORT,
|
direction=TradeDirection.SHORT,
|
||||||
entry_price=None,
|
entry_price=None,
|
||||||
|
|||||||
@ -18,12 +18,12 @@ class TradeStoplossType(str, Enum):
|
|||||||
|
|
||||||
class Trade(BaseModel):
|
class Trade(BaseModel):
|
||||||
id: UUID
|
id: UUID
|
||||||
validfrom: datetime
|
last_update: datetime
|
||||||
status: TradeStatus
|
status: TradeStatus
|
||||||
direction: TradeDirection
|
direction: TradeDirection
|
||||||
entry_price: Optional[float] = None
|
entry_price: Optional[float] = None
|
||||||
# stoploss_type: TradeStoplossType
|
# stoploss_type: TradeStoplossType
|
||||||
stoploss_value: Optional[float] = None
|
stoploss_value: Optional[float] = None
|
||||||
profit: Optional[float] = None
|
profit: Optional[float] = 0
|
||||||
profit_sum: Optional[float] = None
|
profit_sum: Optional[float] = 0
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,7 @@ from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, Orde
|
|||||||
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent
|
from v2realbot.common.model import StrategyInstance, Runner, RunRequest, RunArchive, RunArchiveDetail, RunArchiveChange, Bar, TradeEvent
|
||||||
from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Store, parse_toml_string, json_serial, is_open_hours, send_to_telegram
|
||||||
from v2realbot.utils.ilog import delete_logs
|
from v2realbot.utils.ilog import delete_logs
|
||||||
|
from v2realbot.common.PrescribedTradeModel import Trade, TradeDirection, TradeStatus, TradeStoplossType
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from threading import Thread, current_thread, Event, enumerate
|
from threading import Thread, current_thread, Event, enumerate
|
||||||
from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT, GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN
|
from v2realbot.config import STRATVARS_UNCHANGEABLES, ACCOUNT1_LIVE_API_KEY, ACCOUNT1_LIVE_SECRET_KEY, DATA_DIR,BT_FILL_CONS_TRADES_REQUIRED,BT_FILL_LOG_SURROUNDING_TRADES,BT_FILL_CONDITION_BUY_LIMIT,BT_FILL_CONDITION_SELL_LIMIT, GROUP_TRADES_WITH_TIMESTAMP_LESS_THAN
|
||||||
@ -466,9 +467,45 @@ def populate_metrics_output_directory(strat: StrategyInstance):
|
|||||||
#filt = max_positions['side'] == 'OrderSide.BUY'
|
#filt = max_positions['side'] == 'OrderSide.BUY'
|
||||||
res = dict(zip(max_positions['qty'], max_positions['count']))
|
res = dict(zip(max_positions['qty'], max_positions['count']))
|
||||||
|
|
||||||
#pridani klice obsahujici prescribed trades
|
#metrikz z prescribedTrades, pokud existuji
|
||||||
try:
|
try:
|
||||||
|
long_profit = 0
|
||||||
|
short_profit = 0
|
||||||
|
long_losses = 0
|
||||||
|
short_losses = 0
|
||||||
|
long_wins = 0
|
||||||
|
short_wins = 0
|
||||||
|
max_profit = 0
|
||||||
|
max_profit_time = None
|
||||||
|
for trade in strat.state.vars.prescribedTrades:
|
||||||
|
if trade.profit_sum > max_profit:
|
||||||
|
max_profit = trade.profit_sum
|
||||||
|
max_profit_time = trade.last_update
|
||||||
|
if trade.status == TradeStatus.ACTIVATED and trade.direction == TradeDirection.LONG:
|
||||||
|
if trade.profit is not None:
|
||||||
|
long_profit += trade.profit
|
||||||
|
if trade.profit < 0:
|
||||||
|
long_losses += trade.profit
|
||||||
|
if trade.profit > 0:
|
||||||
|
long_wins += trade.profit
|
||||||
|
if trade.status == TradeStatus.ACTIVATED and trade.direction == TradeDirection.SHORT:
|
||||||
|
if trade.profit is not None:
|
||||||
|
short_profit += trade.profit
|
||||||
|
if trade.profit < 0:
|
||||||
|
short_losses += trade.profit
|
||||||
|
if trade.profit > 0:
|
||||||
|
short_wins += trade.profit
|
||||||
|
res["long_profit"] = round(long_profit,2)
|
||||||
|
res["short_profit"] = round(short_profit,2)
|
||||||
|
res["long_losses"] = round(long_losses,2)
|
||||||
|
res["short_losses"] = round(short_losses,2)
|
||||||
|
res["long_wins"] = round(long_wins,2)
|
||||||
|
res["short_wins"] = round(short_wins,2)
|
||||||
|
res["max_profit"] = round(max_profit,2)
|
||||||
|
res["max_profit_time"] = str(max_profit_time)
|
||||||
|
#vlozeni celeho listu
|
||||||
res["prescr_trades"]=json.loads(json.dumps(strat.state.vars.prescribedTrades, default=json_serial))
|
res["prescr_trades"]=json.loads(json.dumps(strat.state.vars.prescribedTrades, default=json_serial))
|
||||||
|
|
||||||
except NameError:
|
except NameError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@ -351,7 +351,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="note" class="form-label">note</label>
|
<label for="note" class="form-label">note</label>
|
||||||
<textarea class="form-control" rows="2" id="note" name="note"></textarea>
|
<textarea class="form-control" rows="7" id="note" name="note"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="history" class="form-label">history</label>
|
<label for="history" class="form-label">history</label>
|
||||||
|
|||||||
@ -2,10 +2,12 @@ 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
|
||||||
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
|
||||||
|
from v2realbot.common.model import TradeUpdate
|
||||||
from alpaca.trading.enums import TradeEvent, OrderStatus
|
from alpaca.trading.enums import TradeEvent, OrderStatus
|
||||||
from v2realbot.indicators.indicators import ema
|
from v2realbot.indicators.indicators import ema
|
||||||
import json
|
import json
|
||||||
|
from datetime import datetime
|
||||||
#from rich import print
|
#from rich import print
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from alpaca.common.exceptions import APIError
|
from alpaca.common.exceptions import APIError
|
||||||
@ -49,7 +51,8 @@ class StrategyClassicSL(Strategy):
|
|||||||
#zapsat profit do prescr.trades
|
#zapsat profit do prescr.trades
|
||||||
for trade in self.state.vars.prescribedTrades:
|
for trade in self.state.vars.prescribedTrades:
|
||||||
if trade.id == self.state.vars.pending:
|
if trade.id == self.state.vars.pending:
|
||||||
trade.profit = trade_profit
|
trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
|
||||||
|
trade.profit += trade_profit
|
||||||
trade.profit_sum = self.state.profit
|
trade.profit_sum = self.state.profit
|
||||||
|
|
||||||
#zapsat update profitu do tradeList
|
#zapsat update profitu do tradeList
|
||||||
@ -96,7 +99,8 @@ class StrategyClassicSL(Strategy):
|
|||||||
#zapsat profit do prescr.trades
|
#zapsat profit do prescr.trades
|
||||||
for trade in self.state.vars.prescribedTrades:
|
for trade in self.state.vars.prescribedTrades:
|
||||||
if trade.id == self.state.vars.pending:
|
if trade.id == self.state.vars.pending:
|
||||||
trade.profit = trade_profit
|
trade.last_update = datetime.fromtimestamp(self.state.time).astimezone(zoneNY)
|
||||||
|
trade.profit += trade_profit
|
||||||
trade.profit_sum = self.state.profit
|
trade.profit_sum = self.state.profit
|
||||||
|
|
||||||
#zapsat update profitu do tradeList
|
#zapsat update profitu do tradeList
|
||||||
|
|||||||
Binary file not shown.
@ -423,6 +423,8 @@ class Strategy:
|
|||||||
async def order_updates(self, data: TradeUpdate):
|
async def order_updates(self, data: TradeUpdate):
|
||||||
if self.mode == Mode.LIVE or self.mode == Mode.PAPER:
|
if self.mode == Mode.LIVE or self.mode == Mode.PAPER:
|
||||||
now = datetime.now().timestamp()
|
now = datetime.now().timestamp()
|
||||||
|
#z alpakýho TradeEvent si udelame svuj rozsireny TradeEvent (obsahujici navic profit atp.)
|
||||||
|
data = TradeUpdate(**data.dict())
|
||||||
else:
|
else:
|
||||||
now = self.bt.time
|
now = self.bt.time
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -80,7 +80,11 @@ def crossed(threshold, list):
|
|||||||
|
|
||||||
def get_tick(price: float, normalized_ticks: float = 0.01):
|
def get_tick(price: float, normalized_ticks: float = 0.01):
|
||||||
"""
|
"""
|
||||||
prevede normalizovany tick na tick odpovidajici vstupni cene
|
Pozor existuje varianta "normalize_tick", ktera je lepsi a podporuje direktivy ve strategii:
|
||||||
|
Normalize_ticks= true
|
||||||
|
Normalized Tick base price = 30
|
||||||
|
Tahle verze pracuje s globalnim nastavenim.
|
||||||
|
Prevede normalizovany tick na tick odpovidajici vstupni cene
|
||||||
vysledek je zaokoruhleny na 2 des.mista
|
vysledek je zaokoruhleny na 2 des.mista
|
||||||
|
|
||||||
u cen pod 30, vrací 0.01. U cen nad 30 vrací pomerne zvetsene,
|
u cen pod 30, vrací 0.01. U cen nad 30 vrací pomerne zvetsene,
|
||||||
|
|||||||
Reference in New Issue
Block a user