mintrade delta pro kulomet,slowscope,strvrs enhncm
This commit is contained in:
@ -1018,9 +1018,9 @@ for t in tradeList:
|
|||||||
trade_dict.timestamp.append(t.timestamp)
|
trade_dict.timestamp.append(t.timestamp)
|
||||||
trade_dict.symbol.append(t.order.symbol)
|
trade_dict.symbol.append(t.order.symbol)
|
||||||
trade_dict.side.append(t.order.side)
|
trade_dict.side.append(t.order.side)
|
||||||
trade_dict.qty.append(t.qty)
|
trade_dict.qty.append(int(t.qty))
|
||||||
trade_dict.price.append(t.price)
|
trade_dict.price.append(t.price)
|
||||||
trade_dict.position_qty.append(t.position_qty)
|
trade_dict.position_qty.append(int(t.position_qty))
|
||||||
trade_dict.value.append(t.value)
|
trade_dict.value.append(t.value)
|
||||||
trade_dict.cash.append(t.cash)
|
trade_dict.cash.append(t.cash)
|
||||||
trade_dict.order_type.append(t.order.order_type)
|
trade_dict.order_type.append(t.order.order_type)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from v2realbot.strategy.StrategyOrderLimitVykladaciNormalizedMYSELL import Strat
|
|||||||
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType
|
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType
|
||||||
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.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
|
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
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
#from icecream import install, ic
|
#from icecream import install, ic
|
||||||
#from rich import print
|
#from rich import print
|
||||||
@ -33,6 +33,7 @@ potvrzený CBAR
|
|||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
stratvars = AttributeDict(maxpozic = 400,
|
stratvars = AttributeDict(maxpozic = 400,
|
||||||
def_mode_from = 200,
|
def_mode_from = 200,
|
||||||
chunk = 10,
|
chunk = 10,
|
||||||
@ -108,7 +109,7 @@ def next(data, state: StrategyState):
|
|||||||
#state.ilog(e=f"STANDARD mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions)
|
#state.ilog(e=f"STANDARD mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_limitka_price():
|
def get_profit_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)
|
||||||
#v MYSELL hrajeme i na 3 desetinna cisla - TBD mozna hrat jen na 5ky (0.125, 0.130, 0.135 atp.)
|
#v MYSELL hrajeme i na 3 desetinna cisla - TBD mozna hrat jen na 5ky (0.125, 0.130, 0.135 atp.)
|
||||||
@ -117,6 +118,11 @@ def next(data, state: StrategyState):
|
|||||||
else:
|
else:
|
||||||
return price2dec(cena+get_tick(cena,float(state.vars.profit)),3)
|
return price2dec(cena+get_tick(cena,float(state.vars.profit)),3)
|
||||||
|
|
||||||
|
def get_max_profit_price():
|
||||||
|
max_profit = float(safe_get(state.vars, "max_profit",0.03))
|
||||||
|
cena = float(state.avgp)
|
||||||
|
return price2dec(cena+get_tick(cena,max_profit),3)
|
||||||
|
|
||||||
def optimize_qty_multiplier():
|
def optimize_qty_multiplier():
|
||||||
akt_pozic = int(state.positions)/int(state.vars.chunk)
|
akt_pozic = int(state.positions)/int(state.vars.chunk)
|
||||||
multiplier = 1
|
multiplier = 1
|
||||||
@ -124,7 +130,7 @@ def next(data, state: StrategyState):
|
|||||||
#zatim jednoduse pokud je akt. pozice 1 nebo 3 chunky (<4) tak zdvojnásubuju
|
#zatim jednoduse pokud je akt. pozice 1 nebo 3 chunky (<4) tak zdvojnásubuju
|
||||||
#aneb druhy a treti nakup
|
#aneb druhy a treti nakup
|
||||||
if akt_pozic > 0 and akt_pozic < 4:
|
if akt_pozic > 0 and akt_pozic < 4:
|
||||||
multiplier = safe_get(state.vars, "market_buy_multiplier", 2)
|
multiplier = safe_get(state.vars, "market_buy_multiplier", 1)
|
||||||
state.ilog(e=f"BUY MULTIPLIER: {multiplier}")
|
state.ilog(e=f"BUY MULTIPLIER: {multiplier}")
|
||||||
return multiplier
|
return multiplier
|
||||||
|
|
||||||
@ -252,8 +258,9 @@ def next(data, state: StrategyState):
|
|||||||
curr_price = float(data['close'])
|
curr_price = float(data['close'])
|
||||||
state.ilog(e="Eval SELL", price=curr_price, pos=state.positions, avgp=state.avgp, sell_in_progress=state.vars.sell_in_progress)
|
state.ilog(e="Eval SELL", price=curr_price, pos=state.positions, avgp=state.avgp, sell_in_progress=state.vars.sell_in_progress)
|
||||||
if int(state.positions) > 0 and float(state.avgp)>0 and state.vars.sell_in_progress is False:
|
if int(state.positions) > 0 and float(state.avgp)>0 and state.vars.sell_in_progress is False:
|
||||||
goal_price = get_limitka_price()
|
goal_price = get_profit_price()
|
||||||
state.ilog(e=f"Goal price {goal_price}")
|
max_price = get_max_profit_price()
|
||||||
|
state.ilog(e=f"Goal price {goal_price} max price {max_price}")
|
||||||
|
|
||||||
#pokud je cena vyssi
|
#pokud je cena vyssi
|
||||||
if curr_price>=goal_price:
|
if curr_price>=goal_price:
|
||||||
@ -261,12 +268,12 @@ def next(data, state: StrategyState):
|
|||||||
#TODO cekat az slope prestane intenzivn erust, necekat az na klesani
|
#TODO cekat az slope prestane intenzivn erust, necekat az na klesani
|
||||||
#TODO mozna cekat na nejaky signal RSI
|
#TODO mozna cekat na nejaky signal RSI
|
||||||
#TODO pripadne pokud dosahne TGTBB prodat ihned
|
#TODO pripadne pokud dosahne TGTBB prodat ihned
|
||||||
|
max_price_signal = curr_price>=max_price
|
||||||
#OPTIMALIZACE pri stoupajícím angle
|
#OPTIMALIZACE pri stoupajícím angle
|
||||||
if sell_protection_enabled() is False:
|
if max_price_signal or sell_protection_enabled() is False:
|
||||||
state.interface.sell(size=state.positions)
|
state.interface.sell(size=state.positions)
|
||||||
state.vars.sell_in_progress = True
|
state.vars.sell_in_progress = True
|
||||||
state.ilog(e=f"market SELL was sent {curr_price=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress)
|
state.ilog(e=f"market SELL was sent {curr_price=} {max_price_signal=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress)
|
||||||
#pokud je cena nizsi, testujeme REVERSE POZITION PROTECTION
|
#pokud je cena nizsi, testujeme REVERSE POZITION PROTECTION
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
@ -312,9 +319,39 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# None - standard, defaults mode - attributes are read from general stratvars section
|
||||||
|
# other modes - attributtes are read from mode specific stratvars section, defaults to general section
|
||||||
|
#WIP
|
||||||
|
def set_mode():
|
||||||
|
state.vars.mode = None
|
||||||
|
|
||||||
|
#dotahne hodnotu z prislusne sekce
|
||||||
|
#pouziva se namisto safe_get
|
||||||
|
# stratvars
|
||||||
|
# buysignal = 1
|
||||||
|
# stratvars.mode1
|
||||||
|
# buysignal = 2
|
||||||
|
# PARAMS:
|
||||||
|
# - section: napr. stratvars.buysignal
|
||||||
|
# - var name: MA_length
|
||||||
|
# - default: defaultní hodnota, kdyz nenalezeno
|
||||||
|
# Kroky: 1)
|
||||||
|
# vrati danou hodnotu nastaveni podle aktualniho modu state.vars.mode
|
||||||
|
# pokud je None, vrati pro standardni mod, pokud neni nalezeno vrati default
|
||||||
|
# EXAMPLE:
|
||||||
|
# get_modded_vars("state")
|
||||||
|
#get_modded_vars(state.vars, 'buysignal', 1) - namista safe_get
|
||||||
|
|
||||||
|
#WIP
|
||||||
|
def get_modded_vars(section, name: str, default = None):
|
||||||
|
if state.vars.mode is None:
|
||||||
|
return safe_get(section, name, default)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
modded_section = section[state.vars.mode]
|
||||||
|
except KeyError:
|
||||||
|
modded_section = section
|
||||||
|
return safe_get(modded_section, name, safe_get(section, name, default))
|
||||||
|
|
||||||
def populate_ema_indicator():
|
def populate_ema_indicator():
|
||||||
#BAR EMA INDICATOR -
|
#BAR EMA INDICATOR -
|
||||||
@ -336,6 +373,63 @@ def next(data, state: StrategyState):
|
|||||||
#evaluate buy signal
|
#evaluate buy signal
|
||||||
#consolidation
|
#consolidation
|
||||||
|
|
||||||
|
# [stratvars.indicators.slope]
|
||||||
|
# lookback
|
||||||
|
# lookback_offset
|
||||||
|
def populate_slow_slope_indicator():
|
||||||
|
options = safe_get(state.vars.indicators, 'slow_slope', None)
|
||||||
|
if options is None:
|
||||||
|
state.ilog(e="No options for slow slope in stratvars")
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
#SLOW SLOPE INDICATOR
|
||||||
|
#úhel stoupání a klesání vyjádřený mezi -1 až 1
|
||||||
|
#pravý bod přímky je aktuální cena, levý je průměr X(lookback offset) starších hodnot od slope_lookback.
|
||||||
|
#obsahuje statický indikátor (angle) pro vizualizaci
|
||||||
|
try:
|
||||||
|
slow_slope = 99
|
||||||
|
slope_lookback = safe_get(options, 'slope_lookback', 100)
|
||||||
|
minimum_slope = safe_get(options, 'minimum_slope', 25)
|
||||||
|
maximum_slope = safe_get(options, "maximum_slope",0.9)
|
||||||
|
lookback_offset = safe_get(options, 'lookback_offset', 25)
|
||||||
|
|
||||||
|
if len(state.bars.close) > (slope_lookback + lookback_offset):
|
||||||
|
array_od = slope_lookback + lookback_offset
|
||||||
|
array_do = slope_lookback
|
||||||
|
lookbackprice_array = state.bars.vwap[-array_od:-array_do]
|
||||||
|
#obycejný prumer hodnot
|
||||||
|
lookbackprice = round(sum(lookbackprice_array)/lookback_offset,3)
|
||||||
|
lookbacktime = state.bars.time[-slope_lookback]
|
||||||
|
else:
|
||||||
|
#kdyz neni dostatek hodnot, pouzivame jako levy bod open hodnotu close[0]
|
||||||
|
lookbackprice = state.bars.close[0]
|
||||||
|
lookbacktime = state.bars.time[0]
|
||||||
|
state.ilog(e="Slow Slope - not enough data bereme left bod open", slope_lookback=slope_lookback, slope=state.indicators.slope, slopeMA=state.indicators.slopeMA)
|
||||||
|
|
||||||
|
#výpočet úhlu - a jeho normalizace
|
||||||
|
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
|
||||||
|
slope = round(slope, 4)
|
||||||
|
state.indicators.slow_slope[-1]=slope
|
||||||
|
|
||||||
|
#angle je ze slope
|
||||||
|
state.statinds.angle_slow = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=lookbacktime, lookbackprice=lookbackprice, minimum_slope=minimum_slope, maximum_slope=maximum_slope)
|
||||||
|
|
||||||
|
#slope MA vyrovna vykyvy ve slope, dále pracujeme se slopeMA
|
||||||
|
slope_MA_length = safe_get(options, 'MA_length', 5)
|
||||||
|
source = state.indicators.slow_slope[-slope_MA_length:]
|
||||||
|
slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap
|
||||||
|
slopeMA = slopeMAseries[-1]
|
||||||
|
state.indicators.slow_slopeMA[-1]=slopeMA
|
||||||
|
|
||||||
|
state.ilog(e=f"SLOW {slope=} {slopeMA=}", msg=f"{lookbackprice=}", lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-10:], last_slopesMA=state.indicators.slopeMA[-10:])
|
||||||
|
#dale pracujeme s timto MAckovanym slope
|
||||||
|
#slope = slopeMA
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print("Exception in NEXT Slow Slope Indicator section", str(e))
|
||||||
|
state.ilog(e="EXCEPTION", msg="Exception in Slow Slope Indicator section" + str(e) + format_exc())
|
||||||
|
|
||||||
def populate_slope_indicator():
|
def populate_slope_indicator():
|
||||||
#SLOPE INDICATOR
|
#SLOPE INDICATOR
|
||||||
#úhel stoupání a klesání vyjádřený mezi -1 až 1
|
#úhel stoupání a klesání vyjádřený mezi -1 až 1
|
||||||
@ -396,32 +490,37 @@ def next(data, state: StrategyState):
|
|||||||
state.ilog(e=f"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc())
|
state.ilog(e=f"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc())
|
||||||
#state.indicators.RSI14[-1]=0
|
#state.indicators.RSI14[-1]=0
|
||||||
|
|
||||||
# def populate_cbar_rsi_indicator():
|
def populate_cbar_rsi_indicator():
|
||||||
# #CBAR RSI indicator
|
#CBAR RSI indicator
|
||||||
# try:
|
options = safe_get(state.vars.indicators, 'crsi', None)
|
||||||
# crsi_length = int(safe_get(state.vars, "crsi_length",14))
|
if options is None:
|
||||||
# source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap
|
state.ilog(e="No options for crsi in stratvars")
|
||||||
# crsi_res = rsi(source, crsi_length)
|
return
|
||||||
# crsi_value = trunc(crsi_res[-1],3)
|
|
||||||
# state.cbar_indicators.CRSI[-1]=crsi_value
|
|
||||||
# #state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
|
|
||||||
# except Exception as e:
|
|
||||||
# state.ilog(e=f"CRSI {crsi_length=} necháváme 0", message=str(e)+format_exc())
|
|
||||||
# #state.indicators.RSI14[-1]=0
|
|
||||||
|
|
||||||
def populate_secondary_rsi_indicator():
|
|
||||||
#SBAR RSI indicator
|
|
||||||
try:
|
try:
|
||||||
srsi_length = int(safe_get(state.vars, "srsi_length",14))
|
crsi_length = int(safe_get(options, 'crsi_length', 14))
|
||||||
source = state.secondary_indicators.sec_price #[-rsi_length:] #state.bars.vwap
|
source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap
|
||||||
srsi_res = rsi(source, srsi_length)
|
crsi_res = rsi(source, crsi_length)
|
||||||
srsi_value = trunc(srsi_res[-1],3)
|
crsi_value = crsi_res[-1]
|
||||||
state.secondary_indicators.SRSI[-1]=srsi_value
|
state.cbar_indicators.CRSI[-1]=crsi_value
|
||||||
#state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
|
#state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
state.ilog(e=f"SRSI {srsi_length=} necháváme 0", message=str(e)+format_exc())
|
state.ilog(e=f"CRSI {crsi_length=} necháváme 0", message=str(e)+format_exc())
|
||||||
#state.indicators.RSI14[-1]=0
|
#state.indicators.RSI14[-1]=0
|
||||||
|
|
||||||
|
# def populate_secondary_rsi_indicator():
|
||||||
|
# #SBAR RSI indicator
|
||||||
|
# try:
|
||||||
|
# srsi_length = int(safe_get(state.vars, "srsi_length",14))
|
||||||
|
# source = state.secondary_indicators.sec_price #[-rsi_length:] #state.bars.vwap
|
||||||
|
# srsi_res = rsi(source, srsi_length)
|
||||||
|
# srsi_value = trunc(srsi_res[-1],3)
|
||||||
|
# state.secondary_indicators.SRSI[-1]=srsi_value
|
||||||
|
# #state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
|
||||||
|
# except Exception as e:
|
||||||
|
# state.ilog(e=f"SRSI {srsi_length=} necháváme 0", message=str(e)+format_exc())
|
||||||
|
# #state.indicators.RSI14[-1]=0
|
||||||
|
|
||||||
def slope_too_low():
|
def slope_too_low():
|
||||||
return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope)
|
return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope)
|
||||||
|
|
||||||
@ -470,6 +569,25 @@ def next(data, state: StrategyState):
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
def sell_protection_enabled():
|
def sell_protection_enabled():
|
||||||
|
options = safe_get(state.vars, 'sell_protection', None)
|
||||||
|
if options is None:
|
||||||
|
state.ilog(e="No options for sell protection in stratvars")
|
||||||
|
return False
|
||||||
|
|
||||||
|
disable_sell_proteciton_when = dict(AND=dict(), OR=dict())
|
||||||
|
|
||||||
|
#preconditions
|
||||||
|
disable_sell_proteciton_when['disabled_in_config'] = safe_get(options, 'enabled', False) is False
|
||||||
|
#too good to be true (maximum profit)
|
||||||
|
#disable_sell_proteciton_when['tgtbt_reached'] = safe_get(options, 'tgtbt', False) is False
|
||||||
|
|
||||||
|
|
||||||
|
#testing preconditions
|
||||||
|
result, conditions_met = eval_cond_dict(disable_sell_proteciton_when)
|
||||||
|
if result:
|
||||||
|
state.ilog(e=f"SELL_PROTECTION DISABLED by precondition {conditions_met}")
|
||||||
|
return False
|
||||||
|
|
||||||
dont_sell_when = dict(AND=dict(), OR=dict())
|
dont_sell_when = dict(AND=dict(), OR=dict())
|
||||||
##add conditions here
|
##add conditions here
|
||||||
|
|
||||||
@ -477,9 +595,13 @@ def next(data, state: StrategyState):
|
|||||||
|
|
||||||
#pokud je slope too high, pak prodavame jakmile slopeMA zacne klesat, napr. 4MA (TODO 3)
|
#pokud je slope too high, pak prodavame jakmile slopeMA zacne klesat, napr. 4MA (TODO 3)
|
||||||
|
|
||||||
|
#TODO zkusit pro pevny profit, jednoduse pozdrzet prodej - dokud tick_price roste nebo se drzi tak neprodavat, pokud klesne prodat
|
||||||
|
#mozna mit dva mody - pri vetsi volatilite pouzivat momentum, pri mensi nebo kdyz potrebuju pryc, tak prodat hned
|
||||||
|
|
||||||
|
|
||||||
#toto docasne pryc dont_sell_when['slope_too_high'] = slope_too_high() and not isfalling(state.indicators.slopeMA,4)
|
#toto docasne pryc dont_sell_when['slope_too_high'] = slope_too_high() and not isfalling(state.indicators.slopeMA,4)
|
||||||
dont_sell_when['AND']['slopeMA_rising'] = isrising(state.indicators.slopeMA,2)
|
dont_sell_when['AND']['slopeMA_rising'] = isrising(state.indicators.slopeMA,safe_get(options, 'slopeMA_rising', 2))
|
||||||
dont_sell_when['AND']['rsi_not_falling'] = not isfalling(state.indicators.RSI14,3)
|
dont_sell_when['AND']['rsi_not_falling'] = not isfalling(state.indicators.RSI14,safe_get(options, 'rsi_not_falling',3))
|
||||||
#dont_sell_when['rsi_dont_buy'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
|
#dont_sell_when['rsi_dont_buy'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
|
||||||
|
|
||||||
result, conditions_met = eval_cond_dict(dont_sell_when)
|
result, conditions_met = eval_cond_dict(dont_sell_when)
|
||||||
@ -492,7 +614,6 @@ def next(data, state: StrategyState):
|
|||||||
#preconditions
|
#preconditions
|
||||||
dont_buy_when = dict(AND=dict(), OR=dict())
|
dont_buy_when = dict(AND=dict(), OR=dict())
|
||||||
|
|
||||||
|
|
||||||
if safe_get(state.vars, "buy_only_on_confirmed",True):
|
if safe_get(state.vars, "buy_only_on_confirmed",True):
|
||||||
dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0)
|
dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0)
|
||||||
#od posledniho vylozeni musi ubehnout N baru
|
#od posledniho vylozeni musi ubehnout N baru
|
||||||
@ -563,7 +684,8 @@ def next(data, state: StrategyState):
|
|||||||
# state.indicators.tick_volume[-1] = state.indicators.tick_volume[-2]
|
# state.indicators.tick_volume[-1] = state.indicators.tick_volume[-2]
|
||||||
# else:
|
# else:
|
||||||
|
|
||||||
tick_price = round2five(data['close'])
|
#tick_price = round2five(data['close'])
|
||||||
|
tick_price = data['close']
|
||||||
tick_delta_volume = data['volume'] - state.vars.last_tick_volume
|
tick_delta_volume = data['volume'] - state.vars.last_tick_volume
|
||||||
|
|
||||||
#docasne dame pryc volume deltu a davame absolutni cislo
|
#docasne dame pryc volume deltu a davame absolutni cislo
|
||||||
@ -588,16 +710,24 @@ def next(data, state: StrategyState):
|
|||||||
if key != 'time':
|
if key != 'time':
|
||||||
last_ind_vals[key] = state.cbar_indicators[key][-5:]
|
last_ind_vals[key] = state.cbar_indicators[key][-5:]
|
||||||
|
|
||||||
for key in state.secondary_indicators:
|
# for key in state.secondary_indicators:
|
||||||
if key != 'time':
|
# if key != 'time':
|
||||||
last_ind_vals[key] = state.secondary_indicators[key][-5:]
|
# last_ind_vals[key] = state.secondary_indicators[key][-5:]
|
||||||
|
|
||||||
return last_ind_vals
|
return last_ind_vals
|
||||||
|
|
||||||
conf_bar = data['confirmed']
|
conf_bar = data['confirmed']
|
||||||
|
|
||||||
|
#PROCES DELTAS - to function
|
||||||
last_update_delta = round((float(data['updated']) - state.vars.last_update_time),6) if state.vars.last_update_time != 0 else 0
|
last_update_delta = round((float(data['updated']) - state.vars.last_update_time),6) if state.vars.last_update_time != 0 else 0
|
||||||
state.vars.last_update_time = float(data['updated'])
|
state.vars.last_update_time = float(data['updated'])
|
||||||
state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}")
|
|
||||||
|
if len(state.vars.last_50_deltas) >=50:
|
||||||
|
state.vars.last_50_deltas.pop(0)
|
||||||
|
state.vars.last_50_deltas.append(last_update_delta)
|
||||||
|
avg_delta = Average(state.vars.last_50_deltas)
|
||||||
|
|
||||||
|
state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}---AVGdelta:{avg_delta}")
|
||||||
|
|
||||||
#kroky pro CONFIRMED BAR only
|
#kroky pro CONFIRMED BAR only
|
||||||
if conf_bar == 1:
|
if conf_bar == 1:
|
||||||
@ -609,13 +739,17 @@ def next(data, state: StrategyState):
|
|||||||
state.vars.last_tick_volume = 0
|
state.vars.last_tick_volume = 0
|
||||||
state.vars.next_new = 1
|
state.vars.next_new = 1
|
||||||
|
|
||||||
|
#zatim takto na confirm
|
||||||
|
populate_slow_slope_indicator()
|
||||||
|
|
||||||
#SRSI
|
#SRSI
|
||||||
populate_secondary_rsi_indicator()
|
#populate_secondary_rsi_indicator()
|
||||||
|
|
||||||
#kroky pro CONTINOUS TICKS only
|
#kroky pro CONTINOUS TICKS only
|
||||||
else:
|
else:
|
||||||
#CBAR INDICATOR pro tick price a deltu VOLUME
|
#CBAR INDICATOR pro tick price a deltu VOLUME
|
||||||
populate_cbar_tick_price_indicator()
|
populate_cbar_tick_price_indicator()
|
||||||
|
populate_cbar_rsi_indicator()
|
||||||
|
|
||||||
|
|
||||||
#SPOLECNA LOGIKA - bar indikatory muzeme populovat kazdy tick (dobre pro RT GUI), ale uklada se stejne az pri confirmu
|
#SPOLECNA LOGIKA - bar indikatory muzeme populovat kazdy tick (dobre pro RT GUI), ale uklada se stejne az pri confirmu
|
||||||
@ -628,7 +762,8 @@ def next(data, state: StrategyState):
|
|||||||
consolidation()
|
consolidation()
|
||||||
|
|
||||||
#HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru
|
#HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru
|
||||||
lp = state.interface.get_last_price(symbol=state.symbol)
|
#lp = state.interface.get_last_price(symbol=state.symbol)
|
||||||
|
lp = data['close']
|
||||||
state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, data=data, stratvars=state.vars)
|
state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, data=data, stratvars=state.vars)
|
||||||
state.ilog(e="Indikatory", msg=str(get_last_ind_vals()))
|
state.ilog(e="Indikatory", msg=str(get_last_ind_vals()))
|
||||||
|
|
||||||
@ -640,7 +775,9 @@ def init(state: StrategyState):
|
|||||||
print("INIT v main",state.name)
|
print("INIT v main",state.name)
|
||||||
|
|
||||||
state.vars['sell_in_progress'] = False
|
state.vars['sell_in_progress'] = False
|
||||||
|
state.vars.mode = None
|
||||||
state.vars.last_tick_price = 0
|
state.vars.last_tick_price = 0
|
||||||
|
state.vars.last_50_deltas = []
|
||||||
state.vars.last_tick_volume = 0
|
state.vars.last_tick_volume = 0
|
||||||
state.vars.next_new = 0
|
state.vars.next_new = 0
|
||||||
state.vars.last_buysignal_index = 0
|
state.vars.last_buysignal_index = 0
|
||||||
@ -649,13 +786,20 @@ def init(state: StrategyState):
|
|||||||
#state.cbar_indicators['ivwap'] = []
|
#state.cbar_indicators['ivwap'] = []
|
||||||
state.cbar_indicators['tick_price'] = []
|
state.cbar_indicators['tick_price'] = []
|
||||||
state.cbar_indicators['tick_volume'] = []
|
state.cbar_indicators['tick_volume'] = []
|
||||||
state.secondary_indicators['SRSI'] = []
|
state.cbar_indicators['CRSI'] = []
|
||||||
|
#state.secondary_indicators['SRSI'] = []
|
||||||
state.indicators['ema'] = []
|
state.indicators['ema'] = []
|
||||||
state.indicators['slope'] = []
|
state.indicators['slope'] = []
|
||||||
state.indicators['slopeMA'] = []
|
state.indicators['slopeMA'] = []
|
||||||
|
state.indicators['slow_slope'] = []
|
||||||
|
state.indicators['slow_slopeMA'] = []
|
||||||
state.indicators['RSI14'] = []
|
state.indicators['RSI14'] = []
|
||||||
#static indicators - those not series based
|
#static indicators - those not series based
|
||||||
state.statinds['angle'] = dict(minimum_slope=state.vars["minimum_slope"], maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20))
|
state.statinds['angle'] = dict(minimum_slope=state.vars["minimum_slope"], maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20))
|
||||||
|
#state.statinds['angle_slow'] = dict(minimum_slope=safe_get(state.vars.indicators.slow_slope, "minimum_slope",-2), maximum_slope=safe_get(state.vars.indicators.slow_slope, "maximum_slope",2))
|
||||||
|
state.statinds['angle_slow'] = dict(minimum_slope=state.vars['indicators']['slow_slope']["minimum_slope"], maximum_slope=state.vars['indicators']['slow_slope']["maximum_slope"])
|
||||||
|
|
||||||
|
|
||||||
state.vars["ticks2reset_backup"] = state.vars.ticks2reset
|
state.vars["ticks2reset_backup"] = state.vars.ticks2reset
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|||||||
599
v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py
Normal file
599
v2realbot/ENTRY_Vykladaci_RSI_MYSELL_old.py
Normal file
@ -0,0 +1,599 @@
|
|||||||
|
import os,sys
|
||||||
|
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
from v2realbot.strategy.base import StrategyState
|
||||||
|
from v2realbot.strategy.StrategyOrderLimitVykladaciNormalizedMYSELL import StrategyOrderLimitVykladaciNormalizedMYSELL
|
||||||
|
from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide, OrderType
|
||||||
|
from v2realbot.indicators.indicators import ema
|
||||||
|
from v2realbot.indicators.oscillators import rsi
|
||||||
|
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
|
||||||
|
from datetime import datetime
|
||||||
|
#from icecream import install, ic
|
||||||
|
#from rich import print
|
||||||
|
from threading import Event
|
||||||
|
from msgpack import packb, unpackb
|
||||||
|
import asyncio
|
||||||
|
import os
|
||||||
|
from traceback import format_exc
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
""""
|
||||||
|
Využívá: StrategyOrderLimitVykladaciNormalizedMYSELL
|
||||||
|
|
||||||
|
Kopie RSI Normalizovane Vykladaci navíc s řízením prodeje.
|
||||||
|
Nepoužíváme LIMITKU.
|
||||||
|
|
||||||
|
Required CBAR. (pouze se změnou ceny)
|
||||||
|
|
||||||
|
nepotvrzený CBAR bez minticku (pouze se změnou ceny)
|
||||||
|
- se používá pro žízení prodeje
|
||||||
|
|
||||||
|
potvrzený CBAR
|
||||||
|
- se používá pro BUY
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
stratvars = AttributeDict(maxpozic = 400,
|
||||||
|
def_mode_from = 200,
|
||||||
|
chunk = 10,
|
||||||
|
MA = 2,
|
||||||
|
Trend = 2,
|
||||||
|
profit = 0.02,
|
||||||
|
def_profit = 0.01,
|
||||||
|
lastbuyindex=-6,
|
||||||
|
pendingbuys={},
|
||||||
|
limitka = None,
|
||||||
|
limitka_price = None,
|
||||||
|
jevylozeno=0,
|
||||||
|
vykladka=5,
|
||||||
|
curve = [0.01, 0.01, 0.01, 0, 0.02, 0.02, 0.01,0.01, 0.01,0.03, 0.01, 0.01, 0.01,0.04, 0.01,0.01, 0.01,0.05, 0.01,0.01, 0.01,0.01, 0.06,0.01, 0.01,0.01, 0.01],
|
||||||
|
curve_def = [0.02, 0.02, 0.02, 0, 0, 0.02, 0, 0, 0, 0.02],
|
||||||
|
blockbuy = 0,
|
||||||
|
ticks2reset = 0.04,
|
||||||
|
consolidation_bar_count = 10,
|
||||||
|
slope_lookback = 300,
|
||||||
|
lookback_offset = 20,
|
||||||
|
minimum_slope = -0.05,
|
||||||
|
first_buy_market = False
|
||||||
|
)
|
||||||
|
##toto rozparsovat a strategii spustit stejne jako v main
|
||||||
|
toml_string = """
|
||||||
|
[[strategies]]
|
||||||
|
name = "V1 na BAC"
|
||||||
|
symbol = "BAC"
|
||||||
|
script = "ENTRY_backtest_strategyVykladaci"
|
||||||
|
class = "StrategyOrderLimitVykladaci"
|
||||||
|
open_rush = 0
|
||||||
|
close_rush = 0
|
||||||
|
[strategies.stratvars]
|
||||||
|
maxpozic = 200
|
||||||
|
chunk = 10
|
||||||
|
MA = 6
|
||||||
|
Trend = 5
|
||||||
|
profit = 0.02
|
||||||
|
lastbuyindex=-6
|
||||||
|
pendingbuys={}
|
||||||
|
limitka = "None"
|
||||||
|
jevylozeno=0
|
||||||
|
vykladka=5
|
||||||
|
curve = [0.01, 0.01, 0.01,0.01, 0.02, 0.01,0.01, 0.01,0.03, 0.01, 0.01, 0.01,0.04, 0.01,0.01, 0.01,0.05, 0.01,0.01, 0.01,0.01, 0.06,0.01, 0.01,0.01, 0.01]
|
||||||
|
blockbuy = 0
|
||||||
|
ticks2reset = 0.04
|
||||||
|
[[strategies.add_data]]
|
||||||
|
symbol="BAC"
|
||||||
|
rectype="bar"
|
||||||
|
timeframe=5
|
||||||
|
update_ltp=true
|
||||||
|
align="round"
|
||||||
|
mintick=0
|
||||||
|
minsize=100
|
||||||
|
exthours=false
|
||||||
|
"""
|
||||||
|
|
||||||
|
def next(data, state: StrategyState):
|
||||||
|
print(10*"*","NEXT START",10*"*")
|
||||||
|
#ic(state.avgp, state.positions)
|
||||||
|
#ic(state.vars)
|
||||||
|
#ic(data)
|
||||||
|
|
||||||
|
#
|
||||||
|
def is_defensive_mode():
|
||||||
|
akt_pozic = int(state.positions)
|
||||||
|
max_pozic = int(state.vars.maxpozic)
|
||||||
|
def_mode_from = safe_get(state.vars, "def_mode_from",max_pozic/2)
|
||||||
|
if akt_pozic >= int(def_mode_from):
|
||||||
|
#state.ilog(e=f"DEFENSIVE mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
#state.ilog(e=f"STANDARD mode ACTIVE {state.vars.def_mode_from=}", msg=state.positions)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def get_limitka_price():
|
||||||
|
def_profit = safe_get(state.vars, "def_profit",state.vars.profit)
|
||||||
|
cena = float(state.avgp)
|
||||||
|
#v MYSELL hrajeme i na 3 desetinna cisla - TBD mozna hrat jen na 5ky (0.125, 0.130, 0.135 atp.)
|
||||||
|
if is_defensive_mode():
|
||||||
|
return price2dec(cena+get_tick(cena,float(def_profit)),3)
|
||||||
|
else:
|
||||||
|
return price2dec(cena+get_tick(cena,float(state.vars.profit)),3)
|
||||||
|
|
||||||
|
def consolidation():
|
||||||
|
##CONSOLIDATION PART - moved here, musí být před nákupem, jinak to dělalo nepořádek v pendingbuys
|
||||||
|
#docasne zkusime konzolidovat i kdyz neni vylozeno (aby se srovnala limitka ve vsech situacich)
|
||||||
|
if state.vars.jevylozeno == 1 or 1==1:
|
||||||
|
##CONSOLIDATION PART kazdy Nty bar dle nastaveni
|
||||||
|
if int(data["index"])%int(state.vars.consolidation_bar_count) == 0:
|
||||||
|
print("***CONSOLIDATION ENTRY***")
|
||||||
|
state.ilog(e="CONSOLIDATION ENTRY ***")
|
||||||
|
|
||||||
|
orderlist = state.interface.get_open_orders(symbol=state.symbol, side=None)
|
||||||
|
#pro jistotu jeste dotahneme aktualni pozice
|
||||||
|
state.avgp, state.positions = state.interface.pos()
|
||||||
|
|
||||||
|
#print(orderlist)
|
||||||
|
pendingbuys_new = {}
|
||||||
|
#zaciname s cistym stitem
|
||||||
|
state.vars.limitka = None
|
||||||
|
state.vars.limitka_price = None
|
||||||
|
for o in orderlist:
|
||||||
|
if o.side == OrderSide.BUY and o.order_type == OrderType.LIMIT:
|
||||||
|
pendingbuys_new[str(o.id)]=float(o.limit_price)
|
||||||
|
|
||||||
|
if pendingbuys_new != state.vars.pendingbuys:
|
||||||
|
state.ilog(e="Rozdilna PB prepsana", pb_new=pendingbuys_new, pb_old = state.vars.pendingbuys)
|
||||||
|
print("ROZDILNA PENDINGBUYS přepsána")
|
||||||
|
print("OLD",state.vars.pendingbuys)
|
||||||
|
state.vars.pendingbuys = unpackb(packb(pendingbuys_new))
|
||||||
|
print("NEW", state.vars.pendingbuys)
|
||||||
|
else:
|
||||||
|
print("PENDINGBUYS sedí - necháváme", state.vars.pendingbuys)
|
||||||
|
state.ilog(e="PB sedi nechavame", pb_new=pendingbuys_new, pb_old = state.vars.pendingbuys)
|
||||||
|
print("OLD jevylozeno", state.vars.jevylozeno)
|
||||||
|
if len(state.vars.pendingbuys) > 0:
|
||||||
|
state.vars.jevylozeno = 1
|
||||||
|
else:
|
||||||
|
state.vars.jevylozeno = 0
|
||||||
|
print("NEW jevylozeno", state.vars.jevylozeno)
|
||||||
|
state.ilog(e="Nove jevylozeno", msg=state.vars.jevylozeno)
|
||||||
|
|
||||||
|
print("***CONSOLIDATION EXIT***")
|
||||||
|
state.ilog(e="CONSOLIDATION EXIT ***")
|
||||||
|
else:
|
||||||
|
state.ilog(e="No time for consolidation", msg=data["index"])
|
||||||
|
print("no time for consolidation", data["index"])
|
||||||
|
#mozna presunout o level vys
|
||||||
|
def vyloz():
|
||||||
|
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
|
||||||
|
#curve = [0.01, 0.01, 0, 0, 0.01, 0, 0, 0, 0.02, 0, 0, 0, 0.03, 0,0,0,0,0, 0.02, 0,0,0,0,0,0, 0.02]
|
||||||
|
curve = state.vars.curve
|
||||||
|
##defenzivni krivka pro
|
||||||
|
curve_def = state.vars.curve_def
|
||||||
|
#vykladani po 5ti kusech, když zbývají 2 a méně, tak děláme nový výklad
|
||||||
|
vykladka = state.vars.vykladka
|
||||||
|
#kolik muzu max vylozit
|
||||||
|
kolikmuzu = int((int(state.vars.maxpozic) - int(state.positions))/int(state.vars.chunk))
|
||||||
|
akt_pozic = int(state.positions)
|
||||||
|
max_pozic = int(state.vars.maxpozic)
|
||||||
|
|
||||||
|
if akt_pozic >= max_pozic:
|
||||||
|
state.ilog(e="MAX pozic reached, cannot vyklad")
|
||||||
|
return
|
||||||
|
|
||||||
|
#mame polovinu a vic vylozeno, pouzivame defenzicni krivku
|
||||||
|
if is_defensive_mode():
|
||||||
|
state.ilog(e="DEF: Pouzivame defenzivni krivku", akt_pozic=akt_pozic, max_pozic=max_pozic, curve_def=curve_def)
|
||||||
|
curve = curve_def
|
||||||
|
#zaroven docasne menime ticks2reset na defenzivni 0.06
|
||||||
|
state.vars.ticks2reset = 0.06
|
||||||
|
state.ilog(e="DEF: Menime tick2reset na 0.06", ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup)
|
||||||
|
else:
|
||||||
|
#vracime zpet, pokud bylo zmeneno
|
||||||
|
if state.vars.ticks2reset != state.vars.ticks2reset_backup:
|
||||||
|
state.vars.ticks2reset = state.vars.ticks2reset_backup
|
||||||
|
state.ilog(e="DEF: Menime tick2reset zpet na"+str(state.vars.ticks2reset), ticks2reset=state.vars.ticks2reset, ticks2reset_backup=state.vars.ticks2reset_backup)
|
||||||
|
|
||||||
|
if kolikmuzu < vykladka: vykladka = kolikmuzu
|
||||||
|
|
||||||
|
if len(curve) < vykladka:
|
||||||
|
vykladka = len(curve)
|
||||||
|
qty = int(state.vars.chunk)
|
||||||
|
last_price = price2dec(state.interface.get_last_price(state.symbol))
|
||||||
|
#profit = float(state.vars.profit)
|
||||||
|
price = last_price
|
||||||
|
state.ilog(e="BUY Vykladame", msg=f"first price {price=} {vykladka=}", curve=curve, ema=state.indicators.ema[-1], trend=state.vars.Trend, price=price, vykladka=vykladka)
|
||||||
|
##prvni se vyklada na aktualni cenu, další jdou podle krivky, nula v krivce zvyšuje množství pro následující iteraci
|
||||||
|
|
||||||
|
##VAR - na zaklade conf. muzeme jako prvni posilat MARKET order
|
||||||
|
if safe_get(state.vars, "first_buy_market") == True:
|
||||||
|
#pri defenzivnim rezimu pouzivame vzdy LIMIT order
|
||||||
|
if is_defensive_mode():
|
||||||
|
state.ilog(e="DEF mode on, odesilame jako prvni limitku")
|
||||||
|
state.buy_l(price=price, size=qty)
|
||||||
|
else:
|
||||||
|
state.ilog(e="Posilame jako prvni MARKET order")
|
||||||
|
state.buy(size=qty)
|
||||||
|
else:
|
||||||
|
state.buy_l(price=price, size=qty)
|
||||||
|
print("prvni limitka na aktuální cenu. Další podle křivky", price, qty)
|
||||||
|
for i in range(0,vykladka-1):
|
||||||
|
price = price2dec(float(price - get_tick(price, curve[i])))
|
||||||
|
if price == last_price:
|
||||||
|
qty = qty + int(state.vars.chunk)
|
||||||
|
else:
|
||||||
|
state.buy_l(price=price, size=qty)
|
||||||
|
#print(i,"BUY limitka - delta",curve[i]," cena:", price, "mnozstvi:", qty)
|
||||||
|
qty = int(state.vars.chunk)
|
||||||
|
last_price = price
|
||||||
|
state.vars.blockbuy = 1
|
||||||
|
state.vars.jevylozeno = 1
|
||||||
|
state.vars.last_buysignal_index = data['index']
|
||||||
|
|
||||||
|
def eval_sell():
|
||||||
|
""""
|
||||||
|
TBD
|
||||||
|
Když je RSI nahoře tak neprodávat, dokud 1) RSI neprestane stoupat 2)nedosahne to nad im not greedy limit
|
||||||
|
"""
|
||||||
|
##mame pozice
|
||||||
|
##aktualni cena je vetsi nebo rovna cene limitky
|
||||||
|
#muzeme zde jet i na pulcenty
|
||||||
|
curr_price = float(data['close'])
|
||||||
|
state.ilog(e="Eval SELL", price=curr_price, pos=state.positions, avgp=state.avgp, sell_in_progress=state.vars.sell_in_progress)
|
||||||
|
if int(state.positions) > 0 and float(state.avgp)>0 and state.vars.sell_in_progress is False:
|
||||||
|
goal_price = get_limitka_price()
|
||||||
|
state.ilog(e=f"Goal price {goal_price}")
|
||||||
|
if curr_price>=goal_price:
|
||||||
|
|
||||||
|
#TODO cekat az slope prestane intenzivn erust, necekat az na klesani
|
||||||
|
#TODO mozna cekat na nejaky signal RSI
|
||||||
|
#TODO pripadne pokud dosahne TGTBB prodat ihned
|
||||||
|
|
||||||
|
#OPTIMALIZACE pri stoupajícím angle
|
||||||
|
if sell_protection_enabled() is False:
|
||||||
|
state.interface.sell(size=state.positions)
|
||||||
|
state.vars.sell_in_progress = True
|
||||||
|
state.ilog(e=f"market SELL was sent {curr_price=}", positions=state.positions, avgp=state.avgp, sellinprogress=state.vars.sell_in_progress)
|
||||||
|
|
||||||
|
def populate_ema_indicator():
|
||||||
|
#BAR EMA INDICATOR -
|
||||||
|
#plnime MAcko - nyni posilame jen N poslednich hodnot
|
||||||
|
#zaroven osetrujeme pripady, kdy je malo dat a ukladame nulu
|
||||||
|
try:
|
||||||
|
ma = int(state.vars.MA)
|
||||||
|
#poslednich ma hodnot
|
||||||
|
source = state.bars.close[-ma:] #state.bars.vwap
|
||||||
|
ema_value = ema(source, ma)
|
||||||
|
|
||||||
|
##pokus MACKO zakrouhlit na tri desetina a petku
|
||||||
|
state.indicators.ema[-1]=round2five(ema_value[-1])
|
||||||
|
##state.indicators.ema[-1]=trunc(ema_value[-1],3)
|
||||||
|
#state.ilog(e=f"EMA {state.indicators.ema[-1]}", ema_last=state.indicators.ema[-6:])
|
||||||
|
except Exception as e:
|
||||||
|
state.ilog(e="EMA nechavame 0", message=str(e)+format_exc())
|
||||||
|
#state.indicators.ema[-1]=(0)
|
||||||
|
#evaluate buy signal
|
||||||
|
#consolidation
|
||||||
|
|
||||||
|
def populate_slope_indicator():
|
||||||
|
#SLOPE INDICATOR
|
||||||
|
#úhel stoupání a klesání vyjádřený mezi -1 až 1
|
||||||
|
#pravý bod přímky je aktuální cena, levý je průměr X(lookback offset) starších hodnot od slope_lookback.
|
||||||
|
#obsahuje statický indikátor (angle) pro vizualizaci
|
||||||
|
try:
|
||||||
|
slope = 99
|
||||||
|
slope_lookback = int(state.vars.slope_lookback)
|
||||||
|
minimum_slope = float(state.vars.minimum_slope)
|
||||||
|
lookback_offset = int(state.vars.lookback_offset)
|
||||||
|
|
||||||
|
if len(state.bars.close) > (slope_lookback + lookback_offset):
|
||||||
|
array_od = slope_lookback + lookback_offset
|
||||||
|
array_do = slope_lookback
|
||||||
|
lookbackprice_array = state.bars.vwap[-array_od:-array_do]
|
||||||
|
#obycejný prumer hodnot
|
||||||
|
lookbackprice = round(sum(lookbackprice_array)/lookback_offset,3)
|
||||||
|
|
||||||
|
#výpočet úhlu - a jeho normalizace
|
||||||
|
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
|
||||||
|
slope = round(slope, 4)
|
||||||
|
state.indicators.slope[-1]=slope
|
||||||
|
|
||||||
|
#angle je ze slope
|
||||||
|
state.statinds.angle = dict(time=state.bars.time[-1], price=state.bars.close[-1], lookbacktime=state.bars.time[-slope_lookback], lookbackprice=lookbackprice, minimum_slope=minimum_slope, maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20))
|
||||||
|
|
||||||
|
#slope MA vyrovna vykyvy ve slope, dále pracujeme se slopeMA
|
||||||
|
slope_MA_length = 5
|
||||||
|
source = state.indicators.slope[-slope_MA_length:]
|
||||||
|
slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap
|
||||||
|
slopeMA = slopeMAseries[-1]
|
||||||
|
state.indicators.slopeMA[-1]=slopeMA
|
||||||
|
|
||||||
|
state.ilog(e=f"{slope=} {slopeMA=}", msg=f"{lookbackprice=}", lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-10:], last_slopesMA=state.indicators.slopeMA[-10:])
|
||||||
|
|
||||||
|
#dale pracujeme s timto MAckovanym slope
|
||||||
|
slope = slopeMA
|
||||||
|
else:
|
||||||
|
#pokud plnime historii musime ji plnit od zacatku, vsehcny idenitifkatory maji spolecny time
|
||||||
|
#kvuli spravnemu zobrazovani na gui
|
||||||
|
#state.indicators.slopeMA[-1]=0
|
||||||
|
#state.indicators.slopeMA.append(0)
|
||||||
|
state.ilog(e="Slope - not enough data", slope_lookback=slope_lookback, slope=state.indicators.slope, slopeMA=state.indicators.slopeMA)
|
||||||
|
except Exception as e:
|
||||||
|
print("Exception in NEXT Slope Indicator section", str(e))
|
||||||
|
state.ilog(e="EXCEPTION", msg="Exception in Slope Indicator section" + str(e) + format_exc())
|
||||||
|
|
||||||
|
def populate_rsi_indicator():
|
||||||
|
#RSI14 INDICATOR
|
||||||
|
try:
|
||||||
|
rsi_length = int(safe_get(state.vars, "rsi_length",14))
|
||||||
|
source = state.bars.close #[-rsi_length:] #state.bars.vwap
|
||||||
|
rsi_res = rsi(source, rsi_length)
|
||||||
|
rsi_value = trunc(rsi_res[-1],3)
|
||||||
|
state.indicators.RSI14[-1]=rsi_value
|
||||||
|
#state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
|
||||||
|
except Exception as e:
|
||||||
|
state.ilog(e=f"RSI {rsi_length=} necháváme 0", message=str(e)+format_exc())
|
||||||
|
#state.indicators.RSI14[-1]=0
|
||||||
|
|
||||||
|
def populate_cbar_rsi_indicator():
|
||||||
|
#CBAR RSI indicator
|
||||||
|
try:
|
||||||
|
crsi_length = int(safe_get(state.vars, "crsi_length",14))
|
||||||
|
source = state.cbar_indicators.tick_price #[-rsi_length:] #state.bars.vwap
|
||||||
|
crsi_res = rsi(source, crsi_length)
|
||||||
|
crsi_value = trunc(crsi_res[-1],3)
|
||||||
|
state.cbar_indicators.CRSI[-1]=crsi_value
|
||||||
|
#state.ilog(e=f"RSI {rsi_length=} {rsi_value=} {rsi_dont_buy=} {rsi_buy_signal=}", rsi_indicator=state.indicators.RSI14[-5:])
|
||||||
|
except Exception as e:
|
||||||
|
state.ilog(e=f"CRSI {crsi_length=} necháváme 0", message=str(e)+format_exc())
|
||||||
|
#state.indicators.RSI14[-1]=0
|
||||||
|
|
||||||
|
def slope_too_low():
|
||||||
|
return state.indicators.slopeMA[-1] < float(state.vars.minimum_slope)
|
||||||
|
|
||||||
|
def slope_too_high():
|
||||||
|
return state.indicators.slopeMA[-1] > float(safe_get(state.vars, "bigwave_slope_above",0.20))
|
||||||
|
|
||||||
|
#resetujeme, kdyz 1) je aktivni buy protection 2) kdyz to ujede
|
||||||
|
#TODO mozna tick2reset spoustet jednou za X opakovani
|
||||||
|
def pendingbuys_optimalization():
|
||||||
|
if len(state.vars.pendingbuys)>0:
|
||||||
|
if buy_protection_enabled():
|
||||||
|
#state.ilog(e="PENDINGBUYS reset", message=inspect.currentframe().f_code.co_name)
|
||||||
|
res = asyncio.run(state.cancel_pending_buys())
|
||||||
|
state.ilog(e="CANCEL pendingbuyes", pb=state.vars.pendingbuys, res=res)
|
||||||
|
else:
|
||||||
|
#pokud mame vylozeno a cena je vetsi nez tick2reset
|
||||||
|
maxprice = max(state.vars.pendingbuys.values())
|
||||||
|
if state.interface.get_last_price(state.symbol) > float(maxprice) + get_tick(maxprice, float(state.vars.ticks2reset)):
|
||||||
|
res = asyncio.run(state.cancel_pending_buys())
|
||||||
|
state.ilog(e=f"UJELO to. Rusime PB", msg=f"{state.vars.ticks2reset=}", pb=state.vars.pendingbuys)
|
||||||
|
|
||||||
|
#PENDING BUYS SPENT - PART
|
||||||
|
#pokud mame vylozeno a pendingbuys se vyklepou a
|
||||||
|
# 1 vykladame idned znovu
|
||||||
|
# vyloz()
|
||||||
|
# 2 nebo - počkat zase na signál a pokračovat dál
|
||||||
|
# state.vars.blockbuy = 0
|
||||||
|
# state.vars.jevylozeno = 0
|
||||||
|
# 3 nebo - počkat na signál s enablovaným lastbuy indexem (tzn. počká nutně ještě pár barů)
|
||||||
|
#podle BT vyhodnejsi vylozit ihned
|
||||||
|
if len(state.vars.pendingbuys) == 0:
|
||||||
|
state.vars.blockbuy = 0
|
||||||
|
state.vars.jevylozeno = 0
|
||||||
|
state.ilog(e="PB prazdne nastavujeme: neni vylozeno", jevylozeno=state.vars.jevylozeno)
|
||||||
|
|
||||||
|
##kdy nesmí být žádné nákupní objednávky - zruší se
|
||||||
|
def buy_protection_enabled():
|
||||||
|
dont_buy_when = dict(AND=dict(), OR=dict())
|
||||||
|
##add conditions here
|
||||||
|
dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
|
||||||
|
dont_buy_when['slope_too_low'] = slope_too_low()
|
||||||
|
|
||||||
|
result, cond_met = eval_cond_dict(dont_buy_when)
|
||||||
|
if result:
|
||||||
|
state.ilog(e=f"BUY_PROTECTION {cond_met}")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def sell_protection_enabled():
|
||||||
|
dont_sell_when = dict(AND=dict(), OR=dict())
|
||||||
|
##add conditions here
|
||||||
|
|
||||||
|
#IDENTIFIKOVAce rustoveho MOMENTA - pokud je momentum, tak prodávat později
|
||||||
|
|
||||||
|
#pokud je slope too high, pak prodavame jakmile slopeMA zacne klesat, napr. 4MA (TODO 3)
|
||||||
|
|
||||||
|
#toto docasne pryc dont_sell_when['slope_too_high'] = slope_too_high() and not isfalling(state.indicators.slopeMA,4)
|
||||||
|
dont_sell_when['AND']['slopeMA_rising'] = isrising(state.indicators.slopeMA,2)
|
||||||
|
dont_sell_when['AND']['rsi_not_falling'] = not isfalling(state.indicators.RSI14,3)
|
||||||
|
#dont_sell_when['rsi_dont_buy'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
|
||||||
|
|
||||||
|
result, conditions_met = eval_cond_dict(dont_sell_when)
|
||||||
|
if result:
|
||||||
|
state.ilog(e=f"SELL_PROTECTION {conditions_met} enabled")
|
||||||
|
return result
|
||||||
|
|
||||||
|
#preconditions and conditions of BUY SIGNAL
|
||||||
|
def buy_conditions_met():
|
||||||
|
#preconditions
|
||||||
|
dont_buy_when = dict(AND=dict(), OR=dict())
|
||||||
|
|
||||||
|
|
||||||
|
if safe_get(state.vars, "buy_only_on_confirmed",True):
|
||||||
|
dont_buy_when['bar_not_confirmed'] = (data['confirmed'] == 0)
|
||||||
|
#od posledniho vylozeni musi ubehnout N baru
|
||||||
|
dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (state.vars.last_buysignal_index + 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)
|
||||||
|
dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
|
||||||
|
dont_buy_when['slope_too_low'] = slope_too_low()
|
||||||
|
dont_buy_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0))
|
||||||
|
dont_buy_when['close_rush'] = is_close_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "close_rush",0))
|
||||||
|
dont_buy_when['rsi_is_zero'] = (state.indicators.RSI14[-1] == 0)
|
||||||
|
|
||||||
|
#testing preconditions
|
||||||
|
result, cond_met = eval_cond_dict(dont_buy_when)
|
||||||
|
if result:
|
||||||
|
state.ilog(e=f"BUY precondition not met {cond_met}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
#conditions - bud samostatne nebo v groupe - ty musi platit dohromady
|
||||||
|
buy_cond = dict(AND=dict(), OR=dict())
|
||||||
|
##add buy conditions here
|
||||||
|
#cond groups ["AND"]
|
||||||
|
#cond groups ["OR"]
|
||||||
|
#no cond group - takes first
|
||||||
|
#TEST BUY SIGNALu z cbartick_price - 3klesave za sebou
|
||||||
|
#buy_cond['tick_price_falling_trend'] = isfalling(state.cbar_indicators.tick_price,state.vars.Trend)
|
||||||
|
|
||||||
|
#slopeMA jde dolu, rsi jde nahoru
|
||||||
|
#buy mame kazdy potvrzeny, tzn. rsi falling muze byt jen 2
|
||||||
|
|
||||||
|
#buy_cond['AND']['slopeMA_falling'] = isfalling(state.indicators.slopeMA,3)
|
||||||
|
#buy_cond['AND']['rsi_is_rising'] = isrising(state.indicators.RSI14,2)
|
||||||
|
#buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
|
||||||
|
|
||||||
|
#puvodni buy conditiony RSI pod + EMA klesajici
|
||||||
|
#buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
|
||||||
|
#buy_cond["AND"]["ema_trend_is_falling"] = isfalling(state.indicators.ema,state.vars.Trend)
|
||||||
|
|
||||||
|
#pouze RSI nizke a RSI klesa
|
||||||
|
buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
|
||||||
|
buy_cond["AND"]["rsi_is_falling"] = isfalling(state.indicators.RSI14,state.vars.Trend)
|
||||||
|
|
||||||
|
#buy_cond['crsi_below_crsi_buy_limit'] = state.cbar_indicators.CRSI[-1] < safe_get(state.vars, "crsi_buy_signal_below",30)
|
||||||
|
|
||||||
|
#slopME klesa a RSI začalo stoupat
|
||||||
|
# buy_cond["AND"]["rsi_is_rising2"] = isrising(state.indicators.RSI14,2)
|
||||||
|
# buy_cond['AND']['slopeMA_falling_Trend'] = isfalling(state.indicators.slopeMA,state.vars.Trend)
|
||||||
|
# buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40)
|
||||||
|
|
||||||
|
|
||||||
|
#zkusit jako doplnkovy BUY SIGNAL 3 klesavy cbar RSI pripadne TICK PRICE
|
||||||
|
|
||||||
|
result, conditions_met = eval_cond_dict(buy_cond)
|
||||||
|
if result:
|
||||||
|
state.ilog(e=f"BUY SIGNAL {conditions_met}")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def eval_buy():
|
||||||
|
if buy_conditions_met():
|
||||||
|
vyloz()
|
||||||
|
|
||||||
|
def populate_cbar_tick_price_indicator():
|
||||||
|
try:
|
||||||
|
#pokud v potvrzovacím baru nebyly zmeny, nechavam puvodni hodnoty
|
||||||
|
# if tick_delta_volume == 0:
|
||||||
|
# state.indicators.tick_price[-1] = state.indicators.tick_price[-2]
|
||||||
|
# state.indicators.tick_volume[-1] = state.indicators.tick_volume[-2]
|
||||||
|
# else:
|
||||||
|
|
||||||
|
tick_price = round2five(data['close'])
|
||||||
|
tick_delta_volume = data['volume'] - state.vars.last_tick_volume
|
||||||
|
|
||||||
|
#docasne dame pryc volume deltu a davame absolutni cislo
|
||||||
|
state.cbar_indicators.tick_price[-1] = tick_price
|
||||||
|
state.cbar_indicators.tick_volume[-1] = tick_delta_volume
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
state.ilog(e=f"TICK PRICE {tick_price} VOLUME {tick_delta_volume} {conf_bar=}", prev_price=state.vars.last_tick_price, prev_volume=state.vars.last_tick_volume)
|
||||||
|
|
||||||
|
state.vars.last_tick_price = tick_price
|
||||||
|
state.vars.last_tick_volume = data['volume']
|
||||||
|
|
||||||
|
def get_last_ind_vals():
|
||||||
|
last_ind_vals = {}
|
||||||
|
#print(state.indicators.items())
|
||||||
|
for key in state.indicators:
|
||||||
|
if key != 'time':
|
||||||
|
last_ind_vals[key] = state.indicators[key][-5:]
|
||||||
|
|
||||||
|
for key in state.cbar_indicators:
|
||||||
|
if key != 'time':
|
||||||
|
last_ind_vals[key] = state.cbar_indicators[key][-5:]
|
||||||
|
return last_ind_vals
|
||||||
|
|
||||||
|
conf_bar = data['confirmed']
|
||||||
|
last_update_delta = round((float(data['updated']) - state.vars.last_update_time),6) if state.vars.last_update_time != 0 else 0
|
||||||
|
state.vars.last_update_time = float(data['updated'])
|
||||||
|
state.ilog(e=f"---{data['index']}-{conf_bar}--delta:{last_update_delta}")
|
||||||
|
|
||||||
|
#kroky pro CONFIRMED BAR only
|
||||||
|
if conf_bar == 1:
|
||||||
|
#logika pouze pro potvrzeny bar
|
||||||
|
state.ilog(e="BAR potvrzeny")
|
||||||
|
|
||||||
|
|
||||||
|
#pri potvrzem CBARu nulujeme counter volume pro tick based indicator
|
||||||
|
state.vars.last_tick_volume = 0
|
||||||
|
state.vars.next_new = 1
|
||||||
|
|
||||||
|
#kroky pro CONTINOUS TICKS only
|
||||||
|
else:
|
||||||
|
#CBAR INDICATOR pro tick price a deltu VOLUME
|
||||||
|
populate_cbar_tick_price_indicator()
|
||||||
|
populate_cbar_rsi_indicator()
|
||||||
|
|
||||||
|
#SPOLECNA LOGIKA - bar indikatory muzeme populovat kazdy tick (dobre pro RT GUI), ale uklada se stejne az pri confirmu
|
||||||
|
|
||||||
|
|
||||||
|
populate_ema_indicator()
|
||||||
|
populate_slope_indicator()
|
||||||
|
populate_rsi_indicator()
|
||||||
|
eval_sell()
|
||||||
|
consolidation()
|
||||||
|
|
||||||
|
#HLAVNI ITERACNI LOG JESTE PRED AKCI - obsahuje aktualni hodnoty vetsiny parametru
|
||||||
|
lp = state.interface.get_last_price(symbol=state.symbol)
|
||||||
|
state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),3)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)} DEF:{str(is_defensive_mode())}", last_price=lp, data=data, stratvars=state.vars)
|
||||||
|
state.ilog(e="Indikatory", msg=str(get_last_ind_vals()))
|
||||||
|
|
||||||
|
eval_buy()
|
||||||
|
pendingbuys_optimalization()
|
||||||
|
|
||||||
|
def init(state: StrategyState):
|
||||||
|
#place to declare new vars
|
||||||
|
print("INIT v main",state.name)
|
||||||
|
|
||||||
|
state.vars['sell_in_progress'] = False
|
||||||
|
state.vars.last_tick_price = 0
|
||||||
|
state.vars.last_tick_volume = 0
|
||||||
|
state.vars.next_new = 0
|
||||||
|
state.vars.last_buysignal_index = 0
|
||||||
|
state.vars.last_update_time = 0
|
||||||
|
#state.cbar_indicators['ivwap'] = []
|
||||||
|
state.cbar_indicators['tick_price'] = []
|
||||||
|
state.cbar_indicators['tick_volume'] = []
|
||||||
|
state.cbar_indicators['CRSI'] = []
|
||||||
|
state.indicators['ema'] = []
|
||||||
|
state.indicators['slope'] = []
|
||||||
|
state.indicators['slopeMA'] = []
|
||||||
|
state.indicators['RSI14'] = []
|
||||||
|
#static indicators - those not series based
|
||||||
|
state.statinds['angle'] = dict(minimum_slope=state.vars["minimum_slope"], maximum_slope=safe_get(state.vars, "bigwave_slope_above",0.20))
|
||||||
|
state.vars["ticks2reset_backup"] = state.vars.ticks2reset
|
||||||
|
|
||||||
|
def main():
|
||||||
|
name = os.path.basename(__file__)
|
||||||
|
se = Event()
|
||||||
|
pe = Event()
|
||||||
|
s = StrategyOrderLimitVykladaciNormalizedMYSELL(name = name, symbol = "BAC", account=Account.ACCOUNT1, next=next, init=init, stratvars=stratvars, open_rush=10, close_rush=0, pe=pe, se=se, ilog_save=True)
|
||||||
|
s.set_mode(mode = Mode.BT,
|
||||||
|
debug = False,
|
||||||
|
start = datetime(2023, 4, 14, 10, 42, 0, 0, tzinfo=zoneNY),
|
||||||
|
end = datetime(2023, 4, 14, 14, 35, 0, 0, tzinfo=zoneNY),
|
||||||
|
cash=100000)
|
||||||
|
|
||||||
|
#na sekundovem baru nezaokrouhlovat MAcko
|
||||||
|
s.add_data(symbol="BAC",rectype=RecordType.BAR,timeframe=2,minsize=100,update_ltp=True,align=StartBarAlign.ROUND,mintick=0, exthours=False)
|
||||||
|
#s.add_data(symbol="C",rectype=RecordType.BAR,timeframe=1,filters=None,update_ltp=True,align=StartBarAlign.ROUND,mintick=0)
|
||||||
|
|
||||||
|
s.start()
|
||||||
|
print("zastavujeme")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
@ -181,7 +181,7 @@ class Backtester:
|
|||||||
todel.append(order)
|
todel.append(order)
|
||||||
changes = 1
|
changes = 1
|
||||||
else:
|
else:
|
||||||
print("NOT EXECUTED {a}")
|
print(f"NOT EXECUTED {a}")
|
||||||
#ic("NOT EXECUTED",a)
|
#ic("NOT EXECUTED",a)
|
||||||
##ic("istodel",todel)
|
##ic("istodel",todel)
|
||||||
#vymazu z pending orderu vschny zprocesovane nebo ty na výmaz
|
#vymazu z pending orderu vschny zprocesovane nebo ty na výmaz
|
||||||
@ -317,7 +317,7 @@ class Backtester:
|
|||||||
return -1
|
return -1
|
||||||
|
|
||||||
if not fill_time:
|
if not fill_time:
|
||||||
#ic("not FILLED")
|
print("not FILLED")
|
||||||
return 0
|
return 0
|
||||||
else:
|
else:
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@ from alpaca.data.enums import DataFeed
|
|||||||
from v2realbot.enums.enums import Mode, Account, FillCondition
|
from v2realbot.enums.enums import Mode, Account, FillCondition
|
||||||
from appdirs import user_data_dir
|
from appdirs import user_data_dir
|
||||||
|
|
||||||
|
#minimalni vzdalenost mezi trady, kterou agregator pousti pro CBAR(0.001 - blokuje mensi nez 1ms)
|
||||||
|
AGG_MIN_TRADE_DELTA = 0.003
|
||||||
#normalized price for tick 0.01
|
#normalized price for tick 0.01
|
||||||
NORMALIZED_TICK_BASE_PRICE = 30.00
|
NORMALIZED_TICK_BASE_PRICE = 30.00
|
||||||
LOG_RUNNER_EVENTS = False
|
LOG_RUNNER_EVENTS = False
|
||||||
@ -20,6 +22,8 @@ BT_FILL_LOG_SURROUNDING_TRADES = 10
|
|||||||
# slow - price has to be bigger <
|
# slow - price has to be bigger <
|
||||||
BT_FILL_CONDITION_BUY_LIMIT = FillCondition.SLOW
|
BT_FILL_CONDITION_BUY_LIMIT = FillCondition.SLOW
|
||||||
BT_FILL_CONDITION_SELL_LIMIT = FillCondition.SLOW
|
BT_FILL_CONDITION_SELL_LIMIT = FillCondition.SLOW
|
||||||
|
#TBD TODO not implemented yet
|
||||||
|
BT_FILL_PRICE_MARKET_ORDER_PREMIUM = 0.005
|
||||||
#backend counter of api requests
|
#backend counter of api requests
|
||||||
COUNT_API_REQUESTS = False
|
COUNT_API_REQUESTS = False
|
||||||
#stratvars that cannot be changed in gui
|
#stratvars that cannot be changed in gui
|
||||||
|
|||||||
@ -11,7 +11,7 @@ from v2realbot.utils.utils import AttributeDict, zoneNY, dict_replace_value, Sto
|
|||||||
from v2realbot.utils.ilog import delete_logs
|
from v2realbot.utils.ilog import delete_logs
|
||||||
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
|
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, AGG_MIN_TRADE_DELTA
|
||||||
import importlib
|
import importlib
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
from tinydb import TinyDB, Query, where
|
from tinydb import TinyDB, Query, where
|
||||||
@ -436,10 +436,14 @@ def populate_metrics_output_directory(strat: StrategyInstance):
|
|||||||
trade_dict.qty.append(t.qty)
|
trade_dict.qty.append(t.qty)
|
||||||
trade_dict.price.append(t.price)
|
trade_dict.price.append(t.price)
|
||||||
trade_dict.position_qty.append(t.position_qty)
|
trade_dict.position_qty.append(t.position_qty)
|
||||||
trade_dict.value.append(t.value)
|
|
||||||
trade_dict.cash.append(t.cash)
|
|
||||||
trade_dict.order_type.append(t.order.order_type)
|
trade_dict.order_type.append(t.order.order_type)
|
||||||
trade_dict.pos_avg_price.append(t.pos_avg_price)
|
#backtest related additional attributtes, not present on LIVE
|
||||||
|
try:
|
||||||
|
trade_dict.value.append(t.value)
|
||||||
|
trade_dict.cash.append(t.cash)
|
||||||
|
trade_dict.pos_avg_price.append(t.pos_avg_price)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
trade_df = pd.DataFrame(trade_dict)
|
trade_df = pd.DataFrame(trade_dict)
|
||||||
trade_df = trade_df.set_index('timestamp',drop=False)
|
trade_df = trade_df.set_index('timestamp',drop=False)
|
||||||
@ -470,6 +474,7 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
|
|||||||
settings = dict(resolution=strat.state.timeframe,
|
settings = dict(resolution=strat.state.timeframe,
|
||||||
rectype=strat.state.rectype,
|
rectype=strat.state.rectype,
|
||||||
configs=dict(
|
configs=dict(
|
||||||
|
AGG_MIN_TRADE_DELTA=AGG_MIN_TRADE_DELTA,
|
||||||
BT_FILL_CONS_TRADES_REQUIRED=BT_FILL_CONS_TRADES_REQUIRED,
|
BT_FILL_CONS_TRADES_REQUIRED=BT_FILL_CONS_TRADES_REQUIRED,
|
||||||
BT_FILL_LOG_SURROUNDING_TRADES=BT_FILL_LOG_SURROUNDING_TRADES,
|
BT_FILL_LOG_SURROUNDING_TRADES=BT_FILL_LOG_SURROUNDING_TRADES,
|
||||||
BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT,
|
BT_FILL_CONDITION_BUY_LIMIT=BT_FILL_CONDITION_BUY_LIMIT,
|
||||||
@ -527,16 +532,16 @@ def archive_runner(runner: Runner, strat: StrategyInstance):
|
|||||||
#print("is not numpy", key, value)
|
#print("is not numpy", key, value)
|
||||||
flattened_indicators[key]= value
|
flattened_indicators[key]= value
|
||||||
flattened_indicators_list.append(flattened_indicators)
|
flattened_indicators_list.append(flattened_indicators)
|
||||||
flattened_indicators = {}
|
# flattened_indicators = {}
|
||||||
for key, value in strat.state.secondary_indicators.items():
|
# for key, value in strat.state.secondary_indicators.items():
|
||||||
if isinstance(value, ndarray):
|
# if isinstance(value, ndarray):
|
||||||
#print("is numpy", key,value)
|
# #print("is numpy", key,value)
|
||||||
flattened_indicators[key]= value.tolist()
|
# flattened_indicators[key]= value.tolist()
|
||||||
#print("changed numpy:",value.tolist())
|
# #print("changed numpy:",value.tolist())
|
||||||
else:
|
# else:
|
||||||
#print("is not numpy", key, value)
|
# #print("is not numpy", key, value)
|
||||||
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,
|
||||||
|
|||||||
Binary file not shown.
@ -11,7 +11,7 @@ import threading
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from msgpack import unpackb
|
from msgpack import unpackb
|
||||||
import os
|
import os
|
||||||
from config import DATA_DIR
|
from config import DATA_DIR, AGG_MIN_TRADE_DELTA
|
||||||
|
|
||||||
class TradeAggregator:
|
class TradeAggregator:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
@ -66,6 +66,7 @@ class TradeAggregator:
|
|||||||
self.barindex = 1
|
self.barindex = 1
|
||||||
self.diff_price = True
|
self.diff_price = True
|
||||||
self.preconfBar = {}
|
self.preconfBar = {}
|
||||||
|
self.trades_too_close = False
|
||||||
|
|
||||||
async def ingest_trade(self, indata, symbol):
|
async def ingest_trade(self, indata, symbol):
|
||||||
"""
|
"""
|
||||||
@ -244,6 +245,11 @@ class TradeAggregator:
|
|||||||
self.diff_price = True
|
self.diff_price = True
|
||||||
self.last_price = data['p']
|
self.last_price = data['p']
|
||||||
|
|
||||||
|
if float(data['t']) - float(self.lasttimestamp) < AGG_MIN_TRADE_DELTA:
|
||||||
|
self.trades_too_close = True
|
||||||
|
else:
|
||||||
|
self.trades_too_close = False
|
||||||
|
|
||||||
#spočteme vwap - potřebujeme předchozí hodnoty
|
#spočteme vwap - potřebujeme předchozí hodnoty
|
||||||
self.vwaphelper += (data['p'] * data['s'])
|
self.vwaphelper += (data['p'] * data['s'])
|
||||||
self.newBar['updated'] = data['t']
|
self.newBar['updated'] = data['t']
|
||||||
@ -333,7 +339,16 @@ class TradeAggregator:
|
|||||||
#print(self.newBar)
|
#print(self.newBar)
|
||||||
|
|
||||||
#pro (nepotvrzeny) cbar vracime jen pri zmene ceny
|
#pro (nepotvrzeny) cbar vracime jen pri zmene ceny
|
||||||
if self.diff_price is True:
|
|
||||||
|
#nevracime pokud predchozi timestamp a novy od sebe nema alespon 1 ms (vyhneme se kulometum)
|
||||||
|
#127788.123000 127788.124000 (rozdil 0.001)
|
||||||
|
|
||||||
|
|
||||||
|
#zkousime pustit i stejnou cenu(potrebujeme kvuli MYSELLU), ale blokoval kulomet,tzn. trady mensi nez AGG_MIN_TRADE_DELTA (1ms)
|
||||||
|
#if self.diff_price is True:
|
||||||
|
|
||||||
|
#pripadne jeste vratit jako subpodminkiu
|
||||||
|
if self.trades_too_close is False:
|
||||||
return [self.newBar]
|
return [self.newBar]
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|||||||
@ -259,19 +259,24 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
intitialize_candles()
|
intitialize_candles()
|
||||||
candlestickSeries.setData(AllCandleSeriesesData.get(interval));
|
candlestickSeries.setData(AllCandleSeriesesData.get(interval));
|
||||||
|
|
||||||
|
remove_indicators();
|
||||||
|
btnElement = document.getElementById("indicatorsButtons")
|
||||||
|
if (btnElement) {
|
||||||
|
container1.removeChild(btnElement);
|
||||||
|
}
|
||||||
|
|
||||||
if (interval == native_resolution) {
|
if (interval == native_resolution) {
|
||||||
//indicators are in native resolution only
|
//indicators are in native resolution only
|
||||||
display_indicators(data);
|
display_indicators(data, true);
|
||||||
var indbuttonElement = populate_indicator_buttons();
|
var indbuttonElement = populate_indicator_buttons(true);
|
||||||
container1.append(indbuttonElement);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
remove_indicators();
|
//na nepuvodnim grafu zobrazit jako offset a zobrazit jako neviditelne
|
||||||
btnElement = document.getElementById("indicatorsButtons")
|
display_indicators(data,false,30)
|
||||||
if (btnElement) {
|
//buttonky jako vypnute
|
||||||
container1.removeChild(btnElement);
|
var indbuttonElement = populate_indicator_buttons(false);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
container1.append(indbuttonElement);
|
||||||
|
|
||||||
display_buy_markers();
|
display_buy_markers();
|
||||||
|
|
||||||
@ -284,7 +289,8 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
//pro kazdy identifikator zobrazime button na vypnuti zapnuti
|
//pro kazdy identifikator zobrazime button na vypnuti zapnuti
|
||||||
//vybereme barvu pro kazdy identifikator
|
//vybereme barvu pro kazdy identifikator
|
||||||
//zjistime typ idenitfikatoru - zatim right vs left
|
//zjistime typ idenitfikatoru - zatim right vs left
|
||||||
function display_indicators(data) {
|
// input: data, offset(zobrazovat pouze hodnoty kazdych N sekund, visible)
|
||||||
|
function display_indicators(data, visible, offset) {
|
||||||
//console.log("indikatory", JSON.stringify(data.indicators,null,2))
|
//console.log("indikatory", JSON.stringify(data.indicators,null,2))
|
||||||
//podobne v livewebsokcets.js - dat do jedne funkce
|
//podobne v livewebsokcets.js - dat do jedne funkce
|
||||||
if (data.hasOwnProperty("indicators")) {
|
if (data.hasOwnProperty("indicators")) {
|
||||||
@ -331,6 +337,16 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
//if (indicators.time[index] !== undefined) {
|
//if (indicators.time[index] !== undefined) {
|
||||||
//{console.log("problem",key,last)}
|
//{console.log("problem",key,last)}
|
||||||
time = indicators.time[index]
|
time = indicators.time[index]
|
||||||
|
|
||||||
|
//pokud je nastaveny offset (zobrazujeme pouze bod vzdaleny N sekund od posledniho)
|
||||||
|
//vynechavame prvni iteraci, aby se nam naplnil last_time
|
||||||
|
if (offset && last_time !==0) {
|
||||||
|
if (last_time + offset > time) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (last_time>=time) {
|
if (last_time>=time) {
|
||||||
console.log(key, "problem v case - zarovnano",time, last_time, element)
|
console.log(key, "problem v case - zarovnano",time, last_time, element)
|
||||||
|
|
||||||
@ -437,6 +453,7 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
|
|
||||||
//add options
|
//add options
|
||||||
obj.series.applyOptions({
|
obj.series.applyOptions({
|
||||||
|
visible: visible,
|
||||||
lastValueVisible: false,
|
lastValueVisible: false,
|
||||||
priceLineVisible: false,
|
priceLineVisible: false,
|
||||||
});
|
});
|
||||||
@ -456,19 +473,21 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
//vwap a volume zatim jen v detailnim zobrazeni
|
||||||
|
if (!offset) {
|
||||||
|
//display vwap and volume
|
||||||
|
initialize_vwap()
|
||||||
|
vwapSeries.setData(transformed_data["vwap"])
|
||||||
|
|
||||||
//display vwap and volume
|
initialize_volume()
|
||||||
initialize_vwap()
|
volumeSeries.setData(transformed_data["volume"])
|
||||||
vwapSeries.setData(transformed_data["vwap"])
|
console.log("volume")
|
||||||
|
}
|
||||||
initialize_volume()
|
|
||||||
volumeSeries.setData(transformed_data["volume"])
|
|
||||||
console.log("volume")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove_indicators() {
|
function remove_indicators() {
|
||||||
//reset COLORS
|
//reset COLORS
|
||||||
colors = reset_colors
|
colors = reset_colors.slice()
|
||||||
|
|
||||||
//remove CUSTOMS indicators if exists
|
//remove CUSTOMS indicators if exists
|
||||||
indList.forEach((element, index, array) => {
|
indList.forEach((element, index, array) => {
|
||||||
@ -479,9 +498,11 @@ function chart_archived_run(archRecord, data, oneMinuteBars) {
|
|||||||
//remove BASIC indicators
|
//remove BASIC indicators
|
||||||
if (vwapSeries) {
|
if (vwapSeries) {
|
||||||
chart.removeSeries(vwapSeries)
|
chart.removeSeries(vwapSeries)
|
||||||
|
vwapSeries = null;
|
||||||
}
|
}
|
||||||
if (volumeSeries) {
|
if (volumeSeries) {
|
||||||
chart.removeSeries(volumeSeries)
|
chart.removeSeries(volumeSeries)
|
||||||
|
volumeSeries = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -71,16 +71,15 @@ $(document).ready(function () {
|
|||||||
// record2.history = "";
|
// record2.history = "";
|
||||||
//jsonString2 = JSON.stringify(record2, null, 2);
|
//jsonString2 = JSON.stringify(record2, null, 2);
|
||||||
|
|
||||||
|
$('#diff_first').text(record1.name);
|
||||||
document.getElementById('first').innerHTML = '<pre>'+JSON.stringify(record1, null, 2)+'</pre>'
|
$('#diff_second').text(record2.name);
|
||||||
$('#diff_first').text(record1.name);
|
|
||||||
$('#diff_second').text(record2.name);
|
|
||||||
|
|
||||||
//mozna parse?
|
|
||||||
|
|
||||||
var delta = compareObjects(record1, record2)
|
var delta = compareObjects(record1, record2)
|
||||||
const htmlMarkup1 = `<pre>{\n${generateHTML(record2, delta)}}\n</pre>`;
|
const htmlMarkup2 = `<pre>{\n${generateHTML(record2, delta)}}\n</pre>`;
|
||||||
document.getElementById('second').innerHTML = htmlMarkup1;
|
document.getElementById('second').innerHTML = htmlMarkup2;
|
||||||
|
|
||||||
|
const htmlMarkup1 = `<pre>{\n${generateHTML(record1, delta)}}\n</pre>`;
|
||||||
|
document.getElementById('first').innerHTML = htmlMarkup1;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//$('#button_compare').attr('disabled','disabled');
|
//$('#button_compare').attr('disabled','disabled');
|
||||||
|
|||||||
@ -5,6 +5,7 @@ var logcnt = 0
|
|||||||
var positionsPriceLine = null
|
var positionsPriceLine = null
|
||||||
var limitkaPriceLine = null
|
var limitkaPriceLine = null
|
||||||
var angleSeries = 1
|
var angleSeries = 1
|
||||||
|
var angleSeries_slow = 1
|
||||||
var cbar = false
|
var cbar = false
|
||||||
|
|
||||||
//get details of runner to populate chart status
|
//get details of runner to populate chart status
|
||||||
@ -54,7 +55,7 @@ function connect(event) {
|
|||||||
ws.onmessage = function(event) {
|
ws.onmessage = function(event) {
|
||||||
var parsed_data = JSON.parse(event.data)
|
var parsed_data = JSON.parse(event.data)
|
||||||
|
|
||||||
console.log(JSON.stringify(parsed_data))
|
//console.log(JSON.stringify(parsed_data))
|
||||||
|
|
||||||
// //check received data and display lines
|
// //check received data and display lines
|
||||||
// if (parsed_data.hasOwnProperty("bars")) {
|
// if (parsed_data.hasOwnProperty("bars")) {
|
||||||
@ -238,6 +239,34 @@ function connect(event) {
|
|||||||
angleSeries.setData(dataPoints)
|
angleSeries.setData(dataPoints)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (klic === "angle_slow") {
|
||||||
|
|
||||||
|
//nejsou vsechny hodnoty
|
||||||
|
if (Object.keys(hodnota).length > 2) {
|
||||||
|
// console.log("angle nalezen");
|
||||||
|
// console.log(JSON.stringify(hodnota));
|
||||||
|
if (angleSeries_slow !== 1) {
|
||||||
|
// console.log("angle neni jedna" + toString(angleSeries))
|
||||||
|
chart.removeSeries(angleSeries_slow)
|
||||||
|
}
|
||||||
|
|
||||||
|
angleSeries_slow = chart.addLineSeries({
|
||||||
|
//title: key,
|
||||||
|
lineWidth: 2,
|
||||||
|
lineStyle: 2,
|
||||||
|
color: "#8c52c7",
|
||||||
|
lastValueVisible: false,
|
||||||
|
priceLineVisible: false,
|
||||||
|
priceLineWidth: 0,
|
||||||
|
priceLineStyle: 3
|
||||||
|
})
|
||||||
|
dataPoints = [{time: hodnota.lookbacktime, value: hodnota.lookbackprice},{ time: hodnota.time, value: hodnota.price}]
|
||||||
|
// console.log("pridano")
|
||||||
|
// console.log(toString(dataPoints))
|
||||||
|
angleSeries_slow.setData(dataPoints)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -312,13 +312,17 @@ $(document).ready(function () {
|
|||||||
//jsonString2 = JSON.stringify(rec2, null, 2);
|
//jsonString2 = JSON.stringify(rec2, null, 2);
|
||||||
|
|
||||||
|
|
||||||
document.getElementById('first').innerHTML = '<pre>'+JSON.stringify(rec1, null, 2)+'</pre>'
|
//document.getElementById('first').innerHTML = '<pre>'+JSON.stringify(rec1, null, 2)+'</pre>'
|
||||||
$('#diff_first').text(rec1.name);
|
$('#diff_first').text(rec1.name);
|
||||||
$('#diff_second').text(rec2.name);
|
$('#diff_second').text(rec2.name);
|
||||||
|
|
||||||
var delta = compareObjects(rec1, rec2)
|
var delta = compareObjects(rec1, rec2)
|
||||||
const htmlMarkup = `<pre>{\n${generateHTML(rec2, delta)}}\n</pre>`;
|
const htmlMarkup2 = `<pre>{\n${generateHTML(rec2, delta)}}\n</pre>`;
|
||||||
document.getElementById('second').innerHTML = htmlMarkup;
|
document.getElementById('second').innerHTML = htmlMarkup2;
|
||||||
|
|
||||||
|
//var delta1 = compareObjects(rec2, rec1)
|
||||||
|
const htmlMarkup1 = `<pre>{\n${generateHTML(rec1, delta)}}\n</pre>`;
|
||||||
|
document.getElementById('first').innerHTML = htmlMarkup1;
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
//$('#button_compare').attr('disabled','disabled');
|
//$('#button_compare').attr('disabled','disabled');
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
|
||||||
API_KEY = localStorage.getItem("api-key")
|
API_KEY = localStorage.getItem("api-key")
|
||||||
var chart = null
|
var chart = null
|
||||||
var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"]
|
var colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"]
|
||||||
var reset_colors = colors
|
var reset_colors = ["#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957","#8B1874","#B71375","#B46060","#61c740","#BE6DB7","#898121","#4389d9","#00425A","#B5D5C5","#e61957"]
|
||||||
var indList = []
|
var indList = []
|
||||||
var verticalSeries=null
|
var verticalSeries=null
|
||||||
var candlestickSeries = null
|
var candlestickSeries = null
|
||||||
@ -27,10 +27,12 @@ indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, pri
|
|||||||
{name: "ivwap", titlevisible: true, embed: true, display: false, priceScaleId: "right", lastValueVisible: false},
|
{name: "ivwap", titlevisible: true, embed: true, display: false, priceScaleId: "right", lastValueVisible: false},
|
||||||
{name: "slope", titlevisible: true, embed: true, display: false, priceScaleId: "middle", lastValueVisible: false},
|
{name: "slope", titlevisible: true, embed: true, display: false, priceScaleId: "middle", lastValueVisible: false},
|
||||||
{name: "slopeMA", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
|
{name: "slopeMA", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
|
||||||
|
{name: "slow_slope", titlevisible: true, embed: true, display: false, priceScaleId: "middle", lastValueVisible: false},
|
||||||
|
{name: "slow_slopeMA", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
|
||||||
{name: "emaSlow", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
|
{name: "emaSlow", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
|
||||||
{name: "emaFast", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
|
{name: "emaFast", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
|
||||||
{name: "RSI14", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
{name: "RSI14", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
||||||
{name: "SRSI", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
{name: "CRSI", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
||||||
{name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
{name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
||||||
{name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
{name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
||||||
{name: "ppo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
{name: "ppo", titlevisible: true, embed: true, display: true, priceScaleId: "left", lastValueVisible: false},
|
||||||
@ -294,7 +296,7 @@ function initialize_vwap() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function populate_indicator_buttons() {
|
function populate_indicator_buttons(def) {
|
||||||
var buttonElement = document.createElement('div');
|
var buttonElement = document.createElement('div');
|
||||||
buttonElement.id = "indicatorsButtons"
|
buttonElement.id = "indicatorsButtons"
|
||||||
buttonElement.classList.add('switcher');
|
buttonElement.classList.add('switcher');
|
||||||
@ -305,7 +307,9 @@ function populate_indicator_buttons() {
|
|||||||
itemEl.id = "IND"+index;
|
itemEl.id = "IND"+index;
|
||||||
itemEl.style.color = item.series.options().color;
|
itemEl.style.color = item.series.options().color;
|
||||||
itemEl.classList.add('switcher-item');
|
itemEl.classList.add('switcher-item');
|
||||||
|
if (def) {
|
||||||
itemEl.classList.add('switcher-active-item');
|
itemEl.classList.add('switcher-active-item');
|
||||||
|
}
|
||||||
itemEl.addEventListener('click', function() {
|
itemEl.addEventListener('click', function() {
|
||||||
onItemClicked1(index);
|
onItemClicked1(index);
|
||||||
});
|
});
|
||||||
@ -464,9 +468,15 @@ Mousetrap.bind('x', function() {
|
|||||||
|
|
||||||
// for (let key in obj1) {
|
// for (let key in obj1) {
|
||||||
// if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
|
// if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
|
||||||
// const nestedDiff = compareObjects(obj1[key], obj2[key]);
|
// if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
|
||||||
// if (Object.keys(nestedDiff).length > 0) {
|
// if (!arraysAreEqual(obj1[key], obj2[key])) {
|
||||||
// diff[key] = nestedDiff;
|
// diff[key] = obj2[key];
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// const nestedDiff = compareObjects(obj1[key], obj2[key]);
|
||||||
|
// if (Object.keys(nestedDiff).length > 0) {
|
||||||
|
// diff[key] = nestedDiff;
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
// } else if (obj1[key] !== obj2[key]) {
|
// } else if (obj1[key] !== obj2[key]) {
|
||||||
// diff[key] = obj2[key];
|
// diff[key] = obj2[key];
|
||||||
@ -476,52 +486,42 @@ Mousetrap.bind('x', function() {
|
|||||||
// return diff;
|
// return diff;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// function generateHTML(obj, diff, indent = '') {
|
|
||||||
// let html = '';
|
|
||||||
|
|
||||||
// for (let key in obj) {
|
|
||||||
// const value = obj[key];
|
|
||||||
|
|
||||||
// if (typeof value === 'object' && value !== null) {
|
|
||||||
// const nestedDiff = diff[key] || {};
|
|
||||||
// const nestedIndent = indent + ' ';
|
|
||||||
// html += `${indent}"${key}": {\n${generateHTML(value, nestedDiff, nestedIndent)}${indent}},\n`;
|
|
||||||
// } else {
|
|
||||||
// if (key in diff) {
|
|
||||||
// html += `${indent}"${key}": <span class="highlighted">${JSON.stringify(value)}</span>,\n`;
|
|
||||||
// } else {
|
|
||||||
// html += `${indent}"${key}": ${JSON.stringify(value)},\n`;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return html;
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
function compareObjects(obj1, obj2) {
|
function compareObjects(obj1, obj2) {
|
||||||
const diff = {};
|
const diff = {};
|
||||||
|
|
||||||
for (let key in obj1) {
|
for (let key in obj1) {
|
||||||
if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
|
if (!(key in obj2)) {
|
||||||
if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
|
diff[key] = obj1[key];
|
||||||
if (!arraysAreEqual(obj1[key], obj2[key])) {
|
continue;
|
||||||
diff[key] = obj2[key];
|
}
|
||||||
}
|
|
||||||
} else {
|
if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object') {
|
||||||
const nestedDiff = compareObjects(obj1[key], obj2[key]);
|
if (Array.isArray(obj1[key]) && Array.isArray(obj2[key])) {
|
||||||
if (Object.keys(nestedDiff).length > 0) {
|
if (!arraysAreEqual(obj1[key], obj2[key])) {
|
||||||
diff[key] = nestedDiff;
|
diff[key] = obj2[key];
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
} else if (obj1[key] !== obj2[key]) {
|
const nestedDiff = compareObjects(obj1[key], obj2[key]);
|
||||||
diff[key] = obj2[key];
|
if (Object.keys(nestedDiff).length > 0) {
|
||||||
}
|
diff[key] = nestedDiff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (obj1[key] !== obj2[key]) {
|
||||||
|
diff[key] = obj2[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return diff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (let key in obj2) {
|
||||||
|
if (!(key in obj1)) {
|
||||||
|
diff[key] = obj2[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function arraysAreEqual(arr1, arr2) {
|
function arraysAreEqual(arr1, arr2) {
|
||||||
if (arr1.length !== arr2.length) {
|
if (arr1.length !== arr2.length) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Binary file not shown.
@ -192,55 +192,55 @@ class Strategy:
|
|||||||
|
|
||||||
#pokud jsou nastaveny secondary - zatím skrz stratvars - pripadne do do API
|
#pokud jsou nastaveny secondary - zatím skrz stratvars - pripadne do do API
|
||||||
#zatim jedno, predelat pak na list
|
#zatim jedno, predelat pak na list
|
||||||
if safe_get(self.state.vars, "secondary_timeframe",None):
|
# if safe_get(self.state.vars, "secondary_timeframe",None):
|
||||||
self.process_secondary_indicators(item)
|
# self.process_secondary_indicators(item)
|
||||||
|
|
||||||
|
|
||||||
#tady jsem skoncil
|
# #tady jsem skoncil
|
||||||
def process_secondary_indicators(self, item):
|
# def process_secondary_indicators(self, item):
|
||||||
#toto je voláno každý potvrzený CBAR
|
# #toto je voláno každý potvrzený CBAR
|
||||||
resolution = int(safe_get(self.state.vars, "secondary_timeframe",10))
|
# resolution = int(safe_get(self.state.vars, "secondary_timeframe",10))
|
||||||
if int(item['resolution']) >= int(resolution) or int(resolution) % int(item['resolution']) != 0:
|
# if int(item['resolution']) >= int(resolution) or int(resolution) % int(item['resolution']) != 0:
|
||||||
self.state.ilog(e=f"Secondary res {resolution} must be higher than main resolution {item['resolution']} a jejim delitelem")
|
# self.state.ilog(e=f"Secondary res {resolution} must be higher than main resolution {item['resolution']} a jejim delitelem")
|
||||||
|
|
||||||
#prvni vytvori pocatecni
|
# #prvni vytvori pocatecni
|
||||||
if safe_get(self.secondary_res_start_time, resolution, None) is None:
|
# if safe_get(self.secondary_res_start_time, resolution, None) is None:
|
||||||
self.secondary_res_start_time[resolution] = item['time']
|
# self.secondary_res_start_time[resolution] = item['time']
|
||||||
self.secondary_res_start_index[resolution] = int(item['index'])
|
# self.secondary_res_start_index[resolution] = int(item['index'])
|
||||||
self.state.ilog(e=f"INIT SECINDS {self.secondary_res_start_time[resolution]=} {self.secondary_res_start_index[resolution]=}")
|
# self.state.ilog(e=f"INIT SECINDS {self.secondary_res_start_time[resolution]=} {self.secondary_res_start_index[resolution]=}")
|
||||||
|
|
||||||
start_timestamp = datetime.timestamp(self.secondary_res_start_time[resolution])
|
# start_timestamp = datetime.timestamp(self.secondary_res_start_time[resolution])
|
||||||
self.state.ilog(e=f"SECINDS EVAL", start_time=start_timestamp,start_time_plus=start_timestamp + resolution, aktual=datetime.timestamp(item['time']))
|
# self.state.ilog(e=f"SECINDS EVAL", start_time=start_timestamp,start_time_plus=start_timestamp + resolution, aktual=datetime.timestamp(item['time']))
|
||||||
#pokud uz jsme prekrocili okno, ukladame hodnotu
|
# #pokud uz jsme prekrocili okno, ukladame hodnotu
|
||||||
if start_timestamp + resolution <= datetime.timestamp(item['time']):
|
# if start_timestamp + resolution <= datetime.timestamp(item['time']):
|
||||||
self.state.ilog(e=f"SECINDS okno prekroceno")
|
# self.state.ilog(e=f"SECINDS okno prekroceno")
|
||||||
|
|
||||||
index_from = self.secondary_res_start_index[resolution] - int(item['index']) -1
|
# index_from = self.secondary_res_start_index[resolution] - int(item['index']) -1
|
||||||
|
|
||||||
#vytvorime cas a vyplnime data
|
# #vytvorime cas a vyplnime data
|
||||||
for key in self.state.secondary_indicators:
|
# for key in self.state.secondary_indicators:
|
||||||
if key == 'time':
|
# if key == 'time':
|
||||||
#nastavujeme aktualni cas
|
# #nastavujeme aktualni cas
|
||||||
self.state.secondary_indicators['time'].append(item['time'])
|
# self.state.secondary_indicators['time'].append(item['time'])
|
||||||
#self.state.secondary_indicators['time'].append(self.secondary_res_start_time[resolution] )
|
# #self.state.secondary_indicators['time'].append(self.secondary_res_start_time[resolution] )
|
||||||
|
|
||||||
#pro cenu vyplnime aktualni cenou, pro ostatni 0
|
# #pro cenu vyplnime aktualni cenou, pro ostatni 0
|
||||||
elif key == 'sec_price':
|
# elif key == 'sec_price':
|
||||||
#do ceny dame ceny v tomto okne
|
# #do ceny dame ceny v tomto okne
|
||||||
|
|
||||||
source = self.state.bars['vwap']
|
# source = self.state.bars['vwap']
|
||||||
#source = self.state.bars['close']
|
# #source = self.state.bars['close']
|
||||||
|
|
||||||
self.state.ilog(e=f"SECINDS pocitame z hodnot", hodnty=source[index_from:])
|
# self.state.ilog(e=f"SECINDS pocitame z hodnot", hodnty=source[index_from:])
|
||||||
self.state.secondary_indicators[key].append(Average(self.state.bars['close'][index_from:]))
|
# self.state.secondary_indicators[key].append(Average(self.state.bars['close'][index_from:]))
|
||||||
else:
|
# else:
|
||||||
self.state.secondary_indicators[key].append(0)
|
# self.state.secondary_indicators[key].append(0)
|
||||||
|
|
||||||
self.state.ilog(e="SECIND populated", sec_price=self.state.secondary_indicators['sec_price'][-5:])
|
# self.state.ilog(e="SECIND populated", sec_price=self.state.secondary_indicators['sec_price'][-5:])
|
||||||
|
|
||||||
#priprava start hodnot pro dalsi iteraci
|
# #priprava start hodnot pro dalsi iteraci
|
||||||
self.secondary_res_start_time[resolution] = item['time']
|
# self.secondary_res_start_time[resolution] = item['time']
|
||||||
self.secondary_res_start_index[resolution] = int(item['index'])
|
# self.secondary_res_start_index[resolution] = int(item['index'])
|
||||||
|
|
||||||
|
|
||||||
""""refresh positions and avgp - for CBAR once per confirmed, for BARS each time"""
|
""""refresh positions and avgp - for CBAR once per confirmed, for BARS each time"""
|
||||||
@ -493,12 +493,12 @@ class Strategy:
|
|||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
#secondaries
|
#secondaries
|
||||||
if len(self.state.secondary_indicators) > 0 and item['confirmed'] == 1:
|
# if len(self.state.secondary_indicators) > 0 and item['confirmed'] == 1:
|
||||||
for key, value in self.state.secondary_indicators.items():
|
# for key, value in self.state.secondary_indicators.items():
|
||||||
try:
|
# try:
|
||||||
rt_out["indicators"][key]= value[-1]
|
# rt_out["indicators"][key]= value[-1]
|
||||||
except IndexError:
|
# except IndexError:
|
||||||
pass
|
# pass
|
||||||
|
|
||||||
#same for static indicators
|
#same for static indicators
|
||||||
if len(self.state.statinds) > 0:
|
if len(self.state.statinds) > 0:
|
||||||
@ -635,7 +635,7 @@ class StrategyState:
|
|||||||
self.indicators = AttributeDict(time=[])
|
self.indicators = AttributeDict(time=[])
|
||||||
self.cbar_indicators = AttributeDict(time=[])
|
self.cbar_indicators = AttributeDict(time=[])
|
||||||
#secondary timeframe indicators
|
#secondary timeframe indicators
|
||||||
self.secondary_indicators = AttributeDict(time=[], sec_price=[])
|
#self.secondary_indicators = AttributeDict(time=[], sec_price=[])
|
||||||
self.statinds = AttributeDict()
|
self.statinds = AttributeDict()
|
||||||
#these methods can be overrided by StrategyType (to add or alter its functionality)
|
#these methods can be overrided by StrategyType (to add or alter its functionality)
|
||||||
self.buy = self.interface.buy
|
self.buy = self.interface.buy
|
||||||
|
|||||||
Reference in New Issue
Block a user