refactor direktiv - skoro hotovo

This commit is contained in:
David Brazda
2023-07-13 22:40:41 +02:00
parent 2a9b2a1c7c
commit 2c7d279303
9 changed files with 353 additions and 437 deletions

46
testy/getdirective.py Normal file
View File

@ -0,0 +1,46 @@
#ROZPRACOVANE pri vytvareni OR/AND dynamickych buysignalu
# indicator.ema
# length = 3
# buy_if_below = 15
# OR.buy_if_below = 15 #totozne s predchozim, staci kdyz jedna podminka plati
# AND.buy_if_below = 15 #musi platiti vsechny podminky u vsech indikatoru
#TOTO dodelat
#nejspis v INITU nahrat vsechny buysignal directivy do jednoho dictu
#a ten pouzivat v celem lifecyclu
#tato funkce by je mohla vytvorit
# vysledek: {'AND': [('ema', 'ema20')], 'OR': []}
#tato funkce vytvori dictionary typu podminek (OR/AND) a indikatoru s direktivami buy_if
# do OR jsou dane i bez prefixu
# {'AND': [('nazev indikatoru', 'nazev direktivy', 'hodnotadirektivy')], 'OR': []}
def get_indicators_with_buy_directive():
starts_with = "buy_if"
reslist = dict(AND=[], OR=[])
for indname, indsettings in vars["indicators"].items():
for option,value in indsettings.items():
if option.startswith(starts_with):
reslist["OR"].append((indname, option, value))
if option == "AND":
#vsechny buy direktivy, ktere jsou pod AND
for key, val in value.items():
if key.startswith(starts_with):
reslist["AND"].append((indname, key, val))
if option == "OR" :
#vsechny buy direktivy, ktere jsou pod OR
for key, val in value.items():
if key.startswith(starts_with):
reslist["OR"].append((indname, key, val))
return reslist
vars = {'maxpozic': 2000, 'def_mode_from': 2000, 'chunk': 100, 'profit': 0.014, 'def_profit': 0.01, 'max_profit': 0.03, 'vykladka': 1, 'curve': [0.03, 0.01, 0.01, 0.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.03, 0.02, 0, 0, 0.02, 0, 0, 0, 0.02], 'ticks2reset': 0.06, 'consolidation_bar_count': 5, 'first_buy_market': True, 'first_buy_market_def_mode': False, 'market_buy_multiplier': 1, 'rsi_dont_buy_above': 70, 'bigwave_slope_above': 0.12, 'minimum_slope': -0.1, 'open_rush': 30, 'close_rush': 30, 'lastbuy_offset': 5, 'last_buy_offset_reset_after_sell': False, 'buy_only_on_confirmed': False, 'indicators': {'ema': {'type': 'EMA', 'source': 'close', 'length': 5, 'on_confirmed_only': False, 'AND': {'buy_if_crossed_down': 'ema20'}}, 'ema20': {'type': 'EMA', 'source': 'close', 'length': 20, 'on_confirmed_only': False}, 'RSI14': {'type': 'RSI', 'RSI_length': 14, 'source': 'vwap', 'MA_length': 5}, 'slope': {'type': 'slope', 'on_confirmed_only': False, 'MA_length': 5, 'slope_lookback': 10, 'lookback_offset': 3, 'minimum_slope': -0.1, 'maximum_slope': 0.2}, 'slopeLP': {'type': 'slopeLP', 'on_confirmed_only': False, 'leftpoint': 'baropen', 'slope_lookback': 8, 'lookback_offset': 4, 'minimum_slope': -0.09, 'maximum_slope': 0.2}, 'slope10': {'type': 'slope', 'on_confirmed_only': False, 'MA_length': 5, 'slope_lookback': 60, 'lookback_offset': 20, 'minimum_slope': -0.1, 'maximum_slope': 0.45}, 'slope20': {'type': 'slope', 'on_confirmed_only': False, 'MA_length': 5, 'slope_lookback': 120, 'lookback_offset': 25, 'minimum_slope': -0.1, 'dont_buy_above': 0.3, 'maximum_slope': 0.45}}, 'sell_protection': {'enabled': False, 'slopeMA_rising': 2, 'rsi_not_falling': 3}, 'sell_in_progress': False, 'mode': None, 'last_tick_price': 48.41, 'last_50_deltas': [0.027251, 2.050578, 0.205957, 2.226359, 0.00071, 4.034629, 0.0, 0.387769, 2.779256, 1.735168, 1.208257, 0.729469, 1.215035, 2.510941, 4.126465, 0.0, 0.89464, 0.863604, 0.363522, 0.808834, 3.007671, 1.450134, 5.292132, 2.532213, 0.0, 2.185073, 3.185483, 1.664617, 1.972669, 1.552979, 0.45697, 1.370411, 1.125679, 0.0, 0.390609, 0.770417, 0.050253, 1.652531, 0.729488, 0.788619, 0.873404, 1.013351, 0.045697, 2.992692, 4.046475, 0.165393, 0.0, 5.635894, 0.0, 3.558663], 'last_tick_volume': 200, 'next_new': 1, 'lastbuyindex': 103, 'last_update_time': 1689001643.057809, 'reverse_position_waiting_amount': 0, 'pendingbuys': {}, 'limitka': None, 'limitka_price': None, 'jevylozeno': 0, 'blockbuy': 0, 'ticks2reset_backup': 0.06}
a = get_indicators_with_buy_directive()
print(a)

View File

@ -1,4 +1,4 @@
from v2realbot.utils.utils import isfalling, isrising
test1_threshold = 28.905 test1_threshold = 28.905
bacma = [] bacma = []
@ -10,54 +10,32 @@ bacma.append([28.91,28.90,28.89,28.88,28.87])
bacma.append([28.91,28.90,28.89,28.88,28.87,28.86]) bacma.append([28.91,28.90,28.89,28.88,28.87,28.86])
#is_pivot function to check if there is A shaped pivot in the list, each leg consists of N points pole = [1,2,3,2,1,2,3,4,5,6,2,1]
def is_pivot(list, leg):
"""check if there is A shaped pivot in the list, each leg consists of N points"""
try:
if len(list) < leg*2+1:
return False
else:
if list[-leg-1] < list[-leg] and list[-leg] > list[-leg+1] and list[-leg-1] > list[-leg-2] and list[-leg] > list[-leg+2]:
return True
else:
return False
except IndexError:
return False
#is_pivot function to check if there is A(V) shaped pivot in the list, each leg consists of N points
#middle point is the shared one [1,2,3,2,1] - one leg is [1,2,3] second leg is [3,2,1]
def crossed_up(threshold, list): def is_pivot(stock_prices_list, leg_number, type: str = "A"):
"""check if threshold has crossed up last thresholdue in list""" if len(stock_prices_list) < (2 * leg_number)-1:
try: print("Not enough values in the list")
if threshold < list[-1] and threshold >= list[-2]:
return True
else:
return False
except IndexError:
return False return False
def crossed_down(threshold, list): left_leg = stock_prices_list[-2*leg_number+1:-leg_number+1]
"""check if threshold has crossed down last thresholdue in list""" print(left_leg)
try: right_leg = stock_prices_list[-leg_number:]
if threshold > list[-1] and threshold <= list[-2]: print(right_leg)
if type == "A":
if isrising(left_leg) and isfalling(right_leg):
return True
else:
return False
elif type == "V":
if isfalling(left_leg) and isrising(right_leg):
return True return True
else: else:
return False return False
except IndexError:
return False
def crossed(threshold, list):
"""check if threshold has crossed last thresholdue in list"""
if crossed_down(threshold, list) or crossed_up(threshold, list):
return True
else: else:
print("Unknown type")
return False return False
for i in bacma: print(is_pivot(pole, 3))
print(i)
print(f"threshold crossed down {i}", threshold_crossed_down(test1_threshold, i))
print(f"threshold crossed up {i}", threshold_crossed_up(test1_threshold, i))

10
testy/testcrosseddown.py Normal file
View File

@ -0,0 +1,10 @@
from v2realbot.utils.utils import crossed_down
pole = [48.495432098765434, 48.48296296296296, 48.480617283950615, 48.47475308641976, 48.467543209876546]
thr = 48.4778923123465
res = crossed_down(threshold=thr, list=pole)
print(res)

View File

@ -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, Average, crossed_down, crossed_up 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, is_pivot
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
@ -217,7 +217,7 @@ def next(data, state: StrategyState):
last_price = price2dec(state.interface.get_last_price(state.symbol)) last_price = price2dec(state.interface.get_last_price(state.symbol))
#profit = float(state.vars.profit) #profit = float(state.vars.profit)
price = last_price 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) state.ilog(e="BUY Vykladame", msg=f"first price {price=} {vykladka=}", curve=curve, 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 ##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 ##VAR - na zaklade conf. muzeme jako prvni posilat MARKET order
@ -352,154 +352,6 @@ def next(data, state: StrategyState):
modded_section = section modded_section = section
return safe_get(modded_section, name, safe_get(section, name, default)) return safe_get(modded_section, name, safe_get(section, name, default))
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
# [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():
#populuje indikator typu SLOPE
#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())
#TODO predelat na dynamicky type=RSI, source = ["close", "vwap","hlcc4"]
def populate_rsi_indicator():
#RSI14 INDICATOR
try:
rsi_length = int(safe_get(state.vars, "rsi_length",14))
source = state.bars.vwap #[-rsi_length:] #state.bars.vwap
#cekame na dostatek dat
if len(source) > rsi_length:
rsi_res = rsi(source, rsi_length)
rsi_value = trunc(rsi_res[-1],3)
state.indicators.RSI14[-1]=rsi_value
else:
state.ilog(e=f"RSI {rsi_length=} necháváme 0", message="not enough source data")
#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(): def populate_cbar_rsi_indicator():
#CBAR RSI indicator #CBAR RSI indicator
options = safe_get(state.vars.indicators, 'crsi', None) options = safe_get(state.vars.indicators, 'crsi', None)
@ -520,108 +372,24 @@ def next(data, state: StrategyState):
state.ilog(e=f"CRSI {crsi_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
#TODO predelat na dynamicky - tzn. vstup je nazev slopu a i z nej se dotahne minimum slope
#gets all indicators of type slow and check which they have dont_buy_below_minimum
# [stratvars.indicators.slope]
# type = "slope"
# dont_buy_below = -0.10
#get all indicators of type slow and check whether they have dont_buy_below_minimum
# if so, it evaluates if it is below current value
def slope_too_low():
retboolList = []
desc = ""
for indname, indsettings in state.vars.indicators.items():
for option,value in indsettings.items():
if (option == "type" and value == "slope") or (option == "type" and value == "slopeLP"):
#pokud zde mame dont_buy_below
minimum_val = safe_get(indsettings, "dont_buy_below", None)
if minimum_val is not None:
#minimum_val = float(safe_get(indsettings, "minimum_slope", 1))
#pokud exisuje MA, měříme na MA, jinak na standardu
try:
curr_val = state.indicators[indname+"MA"][-1]
except KeyError:
curr_val = state.indicators[indname][-1]
ret = (curr_val < minimum_val)
if ret:
desc += f"ID:{indname}/{curr_val} below {minimum_val=} /"
else:
desc += f"ID:{indname}{curr_val} OK above {minimum_val=} /"
retboolList.append(ret)
else:
desc += f"ID:{indname} - no min set /"
retboolList.append(False)
#pokud obsahuje aspon jedno true
slopelow = any(retboolList)
#DEBUG - poté zapsat jen když je True
if slopelow:
state.ilog(e=f"SLOPELOW {slopelow}", msg=desc)
return slopelow
#gets all indicators of type slow and check which they have dont_buy_above
# [stratvars.indicators.slope]
# type = "slope"
# dont_buy_above = 0.20
#get all indicators of type slow and check whether they have dont_buy_above
# if so, it evaluates if it is above current value
def slope_too_high():
retboolList = []
desc = ""
for indname, indsettings in state.vars.indicators.items():
for option,value in indsettings.items():
if (option == "type" and value == "slope") or (option == "type" and value == "slopeLP"):
#pokud zde mame dont_buy_above
maximum_val = safe_get(indsettings, "dont_buy_above", None)
if maximum_val is not None:
#pokud exisuje MA, měříme na MA, jinak na standardu
try:
curr_val = state.indicators[indname+"MA"][-1]
except KeyError:
curr_val = state.indicators[indname][-1]
ret = (curr_val > maximum_val)
if ret:
desc += f"ID:{indname}/{curr_val} above {maximum_val=} /"
else:
desc += f"ID:{indname}{curr_val} OK below {maximum_val=} /"
retboolList.append(ret)
else:
desc += f"ID:{indname} - no max set /"
retboolList.append(False)
#pokud obsahuje aspon jedno true
slopehigh = any(retboolList)
#DEBUG - poté zapsat jen když je True
if slopehigh:
state.ilog(e=f"SLOPEHIGH {slopehigh}", msg=desc)
return slopehigh
#resetujeme, kdyz 1) je aktivni buy protection 2) kdyz to ujede #resetujeme, kdyz 1) je aktivni buy protection 2) kdyz to ujede
#TODO mozna tick2reset spoustet jednou za X opakovani #TODO mozna tick2reset spoustet jednou za X opakovani
def pendingbuys_optimalization(): def pendingbuys_optimalization():
if len(state.vars.pendingbuys)>0: if len(state.vars.pendingbuys)>0:
if buy_protection_enabled(): #misto volani buy_protection vytvarime direktivu cancel_pendingbuys
#state.ilog(e="PENDINGBUYS reset", message=inspect.currentframe().f_code.co_name)
#pouze jako OR
#cancel_pendingbuys_above
#cancel_pendingbuys_below
pb_dict= get_work_dict_with_directive(starts_with="cancel_pendingbuys_if")
state.ilog(e=f"CANCEL PB work_dict", message=pb_dict)
#u techto ma smysl pouze OR
cond = create_conditions_from_directives(pb_dict, "OR")
result, conditions_met = eval_cond_dict(cond)
state.ilog(e=f"CANCEL PB =OR= {result}", **conditions_met)
if result:
res = asyncio.run(state.cancel_pending_buys()) res = asyncio.run(state.cancel_pending_buys())
state.ilog(e="CANCEL pendingbuyes", pb=state.vars.pendingbuys, res=res) state.ilog(e="CANCEL pendingbuyes", pb=state.vars.pendingbuys, res=res)
else: else:
@ -645,18 +413,6 @@ def next(data, state: StrategyState):
state.vars.jevylozeno = 0 state.vars.jevylozeno = 0
state.ilog(e="PB prazdne nastavujeme: neni vylozeno", jevylozeno=state.vars.jevylozeno) 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}", message=cond_met)
return result
def sell_protection_enabled(): def sell_protection_enabled():
options = safe_get(state.vars, 'sell_protection', None) options = safe_get(state.vars, 'sell_protection', None)
if options is None: if options is None:
@ -669,148 +425,223 @@ def next(data, state: StrategyState):
disable_sell_proteciton_when['disabled_in_config'] = safe_get(options, 'enabled', False) is False disable_sell_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_sell_proteciton_when['disable_if_positions_above'] = int(safe_get(options, 'disable_if_positions_above', 0)) < state.positions
#testing preconditions #testing preconditions
result, conditions_met = eval_cond_dict(disable_sell_proteciton_when) result, conditions_met = eval_cond_dict(disable_sell_proteciton_when)
if result: if result:
state.ilog(e=f"SELL_PROTECTION DISABLED by precondition {conditions_met}") state.ilog(e=f"SELL_PROTECTION DISABLED by {conditions_met}", **conditions_met)
return False return False
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) work_dict_dont_sell_if = get_work_dict_with_directive(starts_with="dont_sell_if")
state.ilog(e=f"SELL PROTECTION work_dict", message=work_dict_dont_sell_if)
#TODO zkusit pro pevny profit, jednoduse pozdrzet prodej - dokud tick_price roste nebo se drzi tak neprodavat, pokud klesne prodat or_cond = create_conditions_from_directives(work_dict_dont_sell_if, "OR")
#mozna mit dva mody - pri vetsi volatilite pouzivat momentum, pri mensi nebo kdyz potrebuju pryc, tak prodat hned result, conditions_met = eval_cond_dict(or_cond)
state.ilog(e=f"SELL PROTECTION =OR= {result}", **conditions_met)
#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,safe_get(options, 'slopeMA_rising', 2))
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)
result, conditions_met = eval_cond_dict(dont_sell_when)
if result: if result:
state.ilog(e=f"SELL_PROTECTION {conditions_met} enabled") return True
return result
#OR neprosly testujeme AND
and_cond = create_conditions_from_directives(work_dict_dont_sell_if, "AND")
result, conditions_met = eval_cond_dict(and_cond)
state.ilog(e=f"SELL PROTECTION =AND= {result}", **conditions_met)
return result
# #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)
# #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
#puvodni nastaveni
# slopeMA_rising = 2
#     rsi_not_falling = 3
# #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())
# ##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)
# #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 do budoucna zdynamictit
# #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,safe_get(options, 'slopeMA_rising', 2))
# 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)
# 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 #preconditions and conditions of BUY SIGNAL
def buy_conditions_met(): def conditions_met():
#preconditions #preconditions - TODO zdynamictit
dont_buy_when = dict(AND=dict(), OR=dict()) dont_buy_when = dict(AND=dict(), OR=dict())
#OBECNE DONT BUYS
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
dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (int(state.vars.lastbuyindex) + int(safe_get(state.vars, "lastbuy_offset",3))) dont_buy_when['last_buy_offset_too_soon'] = data['index'] < (int(state.vars.lastbuyindex) + int(safe_get(state.vars, "lastbuy_offset",3)))
dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1) dont_buy_when['blockbuy_active'] = (state.vars.blockbuy == 1)
dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1) dont_buy_when['jevylozeno_active'] = (state.vars.jevylozeno == 1)
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['slope_too_high'] = slope_too_high()
dont_buy_when['open_rush'] = is_open_rush(datetime.fromtimestamp(data['updated']).astimezone(zoneNY), safe_get(state.vars, "open_rush",0)) 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['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)
dont_buy_when['reverse_position_waiting_amount_not_0'] = (state.vars.reverse_position_waiting_amount != 0)
#testing preconditions #testing preconditions
result, cond_met = eval_cond_dict(dont_buy_when) result, cond_met = eval_cond_dict(dont_buy_when)
if result: if result:
state.ilog(e=f"BUY precondition not met {cond_met}", message=cond_met) state.ilog(e=f"BUY PRECOND GENERAL not met {cond_met}", message=cond_met)
return False return False
#conditions - bud samostatne nebo v groupe - ty musi platit dohromady #SPECIFICKE DONT BUYS - direktivy zacinajici dont_buy
buy_cond = dict(AND=dict(), OR=dict()) #dont_buy_below = value nebo nazev indikatoru
##add buy conditions here #dont_buy_above = value nebo hazev indikatoru
#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 #do INITU
#buy mame kazdy potvrzeny, tzn. rsi falling muze byt jen 2 work_dict_dont_buy = get_work_dict_with_directive(starts_with="dont_buy_if")
#buy_cond['AND']['slopeMA_falling'] = isfalling(state.indicators.slopeMA,3) state.ilog(e=f"BUY PRECOND DONTBUY work_dict", message=work_dict_dont_buy)
#buy_cond['AND']['rsi_is_rising'] = isrising(state.indicators.RSI14,2) #u techto ma smysl pouze OR
#buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) precond = create_conditions_from_directives(work_dict_dont_buy, "OR")
result, conditions_met = eval_cond_dict(precond)
state.ilog(e=f"BUY PRECOND DONTBUY =OR= {result}", **conditions_met)
if result:
return False
#puvodni buy conditiony RSI pod + EMA klesajici #tyto timto nahrazeny - dat do konfigurace
#buy_cond["AND"]["rsi_buy_signal_below"] = state.indicators.RSI14[-1] < safe_get(state.vars, "rsi_buy_signal_below",40) #dont_buy_when['rsi_too_high'] = state.indicators.RSI14[-1] > safe_get(state.vars, "rsi_dont_buy_above",50)
#buy_cond["AND"]["ema_trend_is_falling"] = isfalling(state.indicators.ema,state.vars.Trend) #dont_buy_when['slope_too_low'] = slope_too_low()
#dont_buy_when['slope_too_high'] = slope_too_high()
#dont_buy_when['rsi_is_zero'] = (state.indicators.RSI14[-1] == 0)
#dont_buy_when['reverse_position_waiting_amount_not_0'] = (state.vars.reverse_position_waiting_amount != 0)
#cela tato sekce prepracovana do dynamickych podminek
#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["AND"]['crsi_below_crsi_buy_limit'] = state.cbar_indicators.CRSI[-1] < safe_get(state.vars, "crsi_buy_signal_below",25)
#buy_cond["AND"]['slopeMA_is_below_limit'] = state.indicators.slopeMA[-1] < safe_get(state.vars, "slopeMA_buy_signal_below",1)
#TBD nize prepracovat do funkce a pouzit obecne
# do pole podminek pridame podminky z indikatoru, ktere maji nastavenou direktivu buy_if_cross_down(up)
#buy_cond["AND"].update(get_conditions_from_indicators_with_directive("buy_if_cross_down"))
#u indikatoru muzoun byt tyto directivy pro generovani buysignalu #u indikatoru muzoun byt tyto directivy pro generovani buysignalu
# buy_if_crossed_down - kdyz prekrocil dolu # buy_if_crossed_down - kdyz prekrocil dolu, VALUE: hodnota nebo nazev indikatoru
# buy_if_crossed_up - kdyz prekrocil nahoru # buy_if_crossed_up - kdyz prekrocil nahoru, VALUE: hodnota nebo nazev indikatoru
# buy_if_is_falling - kdyz je klesajici po N # buy_if_falling - kdyz je klesajici po N, VALUE: hodnota
# buy_if_is_rising - kdyz je rostouci po N # buy_if_rising - kdyz je rostouci po N, VALUE: hodnota
# buy_if_is_below - kdyz je pod prahem # buy_if_below - kdyz je pod prahem, VALUE: hodnota nebo nazev indikatoru
# buy_if_is_above - kdyz je nad prahem # buy_if_above - kdyz je nad prahem, VALUE: hodnota nebo nazev indikatoru
# buy_if_pivot_a - kdyz je pivot A. VALUE: delka nohou
# buy_if_pivot_v - kdyz je pivot V. VALUE: delka nohou
# direktivy se mohou nachazet v podsekci AND nebo OR - daneho indikatoru (nebo na volno, pak = OR)
# OR - staci kdyz plati jedna takova podminka a buysignal je aktivni
# AND - musi platit vsechny podminky ze vsech indikatoru, aby byl buysignal aktivni
#sekce pro dynamicke vytvareni podminek - pokud indikatory maji nastavenou buysignal direktivu #populate work dict - muze byt i jen jednou v INIT nebo 1x za cas
#dotahneme si jejich value a vytvorime podminku (plati AND) #dict oindexovane podminkou (OR/AND) obsahuje vsechny buy_if direktivy v tuplu (nazevind,direktiva,hodnota
# {'AND': [('nazev indikatoru', 'nazev direktivy', 'hodnotadirektivy')], 'OR': []}
work_dict_buy_if = get_work_dict_with_directive(starts_with="buy_if")
state.ilog(e=f"BUY SIGNAL work_dict", message=work_dict_buy_if)
indicators_with_is_above = get_indicators_with_directive("buy_if_is_above") buy_or_cond = create_conditions_from_directives(work_dict_buy_if, "OR")
for indicator, value in indicators_with_is_above: result, conditions_met = eval_cond_dict(buy_or_cond)
buy_cond["AND"]["buy_if_is_above_"+indicator] = get_source_or_MA(indicator)[-1] > value state.ilog(e=f"BUY SIGNAL =OR= {result}", **conditions_met)
if result:
return True
#OR neprosly testujeme AND
buy_and_cond = create_conditions_from_directives(work_dict_buy_if, "AND")
result, conditions_met = eval_cond_dict(buy_and_cond)
state.ilog(e=f"BUY SIGNAL =AND= {result}", **conditions_met)
return result
indicators_with_is_below = get_indicators_with_directive("buy_if_is_below") #preklad direktivy podle typu, pokud je int anebo float - je to primo hodnota
for indicator, value in indicators_with_is_below: #pokud je str, jde o indikator a dotahujeme posledni hodnotu z nej
buy_cond["AND"]["buy_if_is_below_"+indicator] = get_source_or_MA(indicator)[-1] < value def value_or_indicator(value):
if isinstance(value, (int, float)):
return value
elif isinstance(value, str):
try:
#pokud existuje MA bereme MA jinak standard
ret = get_source_or_MA(indicator=value)[-1]
state.ilog(e=f"Pro porovnani bereme posledni hodnotu {ret} z indikatoru {value}")
except Exception as e :
ret = 0
state.ilog(e=f"Neexistuje indikator s nazvem {value} vracime 0" + str(e) + format_exc())
return ret
indicators_with_is_falling = get_indicators_with_directive("buy_if_is_falling") #funkce vytvori podminky (bud pro AND/OR) z pracovniho dict
for indicator, value in indicators_with_is_falling: def create_conditions_from_directives(work_dict, cond_type):
buy_cond["AND"]["buy_if_is_falling_"+indicator] = isfalling(get_source_or_MA(indicator),value) cond = {}
cond[cond_type] = {}
for indname, directive, value in work_dict[cond_type]:
#direktivy zobecnime ve tvaru prefix_ACTION
# ACTIONS = is_above, is_below, is_falling, is_rising, crossed_up, crossed_down, is_pivot_a, is_pivot_v
#OBECNE DIREKTIVY - REUSOVATELNE
if directive.endswith("above"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = get_source_or_MA(indname)[-1] > value_or_indicator(value)
elif directive.endswith("below"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = get_source_or_MA(indname)[-1] < value_or_indicator(value)
elif directive.endswith("falling"):
if directive.endswith("not_falling"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = not isfalling(get_source_or_MA(indname),value)
else:
cond[cond_type][directive+"_"+indname+"_"+str(value)] = isfalling(get_source_or_MA(indname),value)
elif directive.endswith("rising"):
if directive.endswith("not_rising"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = not isrising(get_source_or_MA(indname),value)
else:
cond[cond_type][directive+"_"+indname+"_"+str(value)] = isrising(get_source_or_MA(indname),value)
elif directive.endswith("crossed_down"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = buy_if_crossed_down(indname, value_or_indicator(value))
elif directive.endswith("crossed_up"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = buy_if_crossed_up(indname, value_or_indicator(value))
elif directive.endswith("pivot_a"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = is_pivot(source=get_source_or_MA(indname), leg_number=value, type="A")
elif directive.endswith("pivot_v"):
cond[cond_type][directive+"_"+indname+"_"+str(value)] = is_pivot(source=get_source_or_MA(indname), leg_number=value, type="V")
#PRIPADNE DALSI SPECIFICKE ZDE
# elif directive == "buy_if_necospecifckeho":
# pass
return cond
indicators_with_is_rising = get_indicators_with_directive("buy_if_is_rising") #tato funkce vytvori dictionary typu podminek (OR/AND)
for indicator, value in indicators_with_is_rising: # z indikatoru, ktere obsahuji direktivami daneho typu(buy_if, dont_buy_when)
buy_cond["AND"]["buy_if_is_rising_"+indicator] = isrising(get_source_or_MA(indicator),value) # v tuplu (nazevind,direktiva,hodnota)
# do OR jsou dane i bez prefixu
# {'AND': [('nazev indikatoru', 'nazev direktivy', 'hodnotadirektivy')], 'OR': []}
def get_work_dict_with_directive(starts_with: str):
reslist = dict(AND=[], OR=[])
indicators_with_cross_down = get_indicators_with_directive("buy_if_crossed_down")
for indicator, value in indicators_with_cross_down:
buy_cond["AND"]["buy_if_crossed_down_"+indicator] = buy_if_crossed_down(indicator, value)
indicators_with_cross_up = get_indicators_with_directive("buy_if_crossed_up")
for indicator, value in indicators_with_cross_up:
buy_cond["AND"]["buy_if_crossed_up_"+indicator] = buy_if_crossed_up(indicator, value)
#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 {result} {conditions_met}")
return result
#vrati vsechny indikatory, ktere obsahuji danou directivu a vrati v listu tuple (nazev, hodnota)
def get_indicators_with_directive(directive):
reslist = []
for indname, indsettings in state.vars.indicators.items(): for indname, indsettings in state.vars.indicators.items():
for option,value in indsettings.items(): for option,value in indsettings.items():
if option == directive: if option.startswith(starts_with):
reslist.append((indname, value)) reslist["OR"].append((indname, option, value))
return reslist if option == "AND":
#vsechny buy direktivy, ktere jsou pod AND
for key, val in value.items():
if key.startswith(starts_with):
reslist["AND"].append((indname, key, val))
if option == "OR" :
#vsechny buy direktivy, ktere jsou pod OR
for key, val in value.items():
if key.startswith(starts_with):
reslist["OR"].append((indname, key, val))
return reslist
def get_source_or_MA(indicator): def get_source_or_MA(indicator):
#pokud ma, pouzije MAcko, pokud ne tak standardni indikator #pokud ma, pouzije MAcko, pokud ne tak standardni indikator
@ -832,7 +663,7 @@ def next(data, state: StrategyState):
return res return res
def eval_buy(): def eval_buy():
if buy_conditions_met(): if conditions_met():
vyloz() vyloz()
def populate_cbar_tick_price_indicator(): def populate_cbar_tick_price_indicator():
@ -863,11 +694,11 @@ def next(data, state: StrategyState):
#print(state.indicators.items()) #print(state.indicators.items())
for key in state.indicators: for key in state.indicators:
if key != 'time': if key != 'time':
last_ind_vals[key] = state.indicators[key][-5:] last_ind_vals[key] = state.indicators[key][-6:]
for key in state.cbar_indicators: for key in state.cbar_indicators:
if key != 'time': if key != 'time':
last_ind_vals[key] = state.cbar_indicators[key][-5:] last_ind_vals[key] = state.cbar_indicators[key][-6:]
# for key in state.secondary_indicators: # for key in state.secondary_indicators:
# if key != 'time': # if key != 'time':
@ -918,14 +749,14 @@ def next(data, state: StrategyState):
if on_confirmed_only is False or (on_confirmed_only is True and data['confirmed']==1): if on_confirmed_only is False or (on_confirmed_only is True and data['confirmed']==1):
try: try:
source = state.bars[req_source][-ema_length:] source = state.bars[req_source][-ema_length:]
if len(source) > ema_length: #if len(source) > ema_length:
ema_value = ema(source, ema_length) ema_value = ema(source, ema_length)
val = ema_value[-1] val = round(ema_value[-1],4)
state.indicators[name][-1]= val state.indicators[name][-1]= val
#state.indicators[name][-1]= round2five(val) #state.indicators[name][-1]= round2five(val)
state.ilog(e=f"IND {name} EMA {val} {ema_length=}") state.ilog(e=f"IND {name} EMA {val} {ema_length=}")
else: #else:
state.ilog(e=f"IND {name} EMA necháváme 0", message="not enough source data", source=source, ema_length=ema_length) # state.ilog(e=f"IND {name} EMA necháváme 0", message="not enough source data", source=source, ema_length=ema_length)
except Exception as e: except Exception as e:
state.ilog(e=f"IND ERROR {name} EMA necháváme 0", message=str(e)+format_exc()) state.ilog(e=f"IND ERROR {name} EMA necháváme 0", message=str(e)+format_exc())
@ -958,14 +789,14 @@ def next(data, state: StrategyState):
#cekame na dostatek dat #cekame na dostatek dat
if len(source) > rsi_length: if len(source) > rsi_length:
rsi_res = rsi(source, rsi_length) rsi_res = rsi(source, rsi_length)
rsi_value = trunc(rsi_res[-1],4) rsi_value = round(rsi_res[-1],4)
state.indicators[name][-1]=rsi_value state.indicators[name][-1]=rsi_value
state.ilog(e=f"IND {name} RSI {rsi_value}") state.ilog(e=f"IND {name} RSI {rsi_value}")
if rsi_MA_length is not None: if rsi_MA_length is not None:
src = state.indicators[name][-rsi_MA_length:] src = state.indicators[name][-rsi_MA_length:]
rsi_MA_res = ema(src, rsi_MA_length) rsi_MA_res = ema(src, rsi_MA_length)
rsi_MA_value = rsi_MA_res[-1] rsi_MA_value = round(rsi_MA_res[-1],4)
state.indicators[name+"MA"][-1]=rsi_MA_value state.indicators[name+"MA"][-1]=rsi_MA_value
state.ilog(e=f"IND {name} RSIMA {rsi_MA_value}") state.ilog(e=f"IND {name} RSIMA {rsi_MA_value}")
@ -1077,7 +908,7 @@ def next(data, state: StrategyState):
if slope_MA_length is not None: if slope_MA_length is not None:
source = state.indicators[name][-slope_MA_length:] source = state.indicators[name][-slope_MA_length:]
slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap
slopeMA = slopeMAseries[-1] slopeMA = round(slopeMAseries[-1],5)
state.indicators[name+"MA"][-1]=slopeMA state.indicators[name+"MA"][-1]=slopeMA
last_slopesMA = state.indicators[name+"MA"][-10:] last_slopesMA = state.indicators[name+"MA"][-10:]
@ -1089,7 +920,6 @@ def next(data, state: StrategyState):
print(f"Exception in {name} slope Indicator section", str(e)) print(f"Exception in {name} slope Indicator section", str(e))
state.ilog(e=f"EXCEPTION in {name}", msg="Exception in slope Indicator section" + str(e) + format_exc()) state.ilog(e=f"EXCEPTION in {name}", msg="Exception in slope Indicator section" + str(e) + format_exc())
def populate_dynamic_slope_indicator(name): def populate_dynamic_slope_indicator(name):
options = safe_get(state.vars.indicators, name, None) options = safe_get(state.vars.indicators, name, None)
if options is None: if options is None:
@ -1167,7 +997,7 @@ def next(data, state: StrategyState):
if slope_MA_length is not None: if slope_MA_length is not None:
source = state.indicators[name][-slope_MA_length:] source = state.indicators[name][-slope_MA_length:]
slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap slopeMAseries = ema(source, slope_MA_length) #state.bars.vwap
slopeMA = slopeMAseries[-1] slopeMA = round(slopeMAseries[-1],4)
state.indicators[name+"MA"][-1]=slopeMA state.indicators[name+"MA"][-1]=slopeMA
last_slopesMA = state.indicators[name+"MA"][-10:] last_slopesMA = state.indicators[name+"MA"][-10:]
@ -1231,7 +1061,8 @@ def next(data, state: StrategyState):
#lp = state.interface.get_last_price(symbol=state.symbol) #lp = state.interface.get_last_price(symbol=state.symbol)
lp = data['close'] 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())}", pb=str(state.vars.pendingbuys), last_price=lp, data=data, stratvars=str(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())}", pb=str(state.vars.pendingbuys), last_price=lp, data=data, stratvars=str(state.vars))
state.ilog(e="Indikatory", msg=str(get_last_ind_vals())) inds = get_last_ind_vals()
state.ilog(e="Indikatory", **inds)
eval_buy() eval_buy()
pendingbuys_optimalization() pendingbuys_optimalization()
@ -1244,16 +1075,20 @@ def init(state: StrategyState):
#pro vsechny indikatory, ktere maji ve svych stratvars TYPE inicializujeme #pro vsechny indikatory, ktere maji ve svych stratvars TYPE inicializujeme
for indname, indsettings in state.vars.indicators.items(): for indname, indsettings in state.vars.indicators.items():
for option,value in indsettings.items(): for option,value in indsettings.items():
if option == "type": #inicializujeme nejenom typizovane
state.indicators[indname] = [] #if option == "type":
#pokud ma MA_length incializujeme i MA variantu state.indicators[indname] = []
if safe_get(indsettings, 'MA_length', False): #pokud ma MA_length incializujeme i MA variantu
state.indicators[indname+"MA"] = [] if safe_get(indsettings, 'MA_length', False):
#specifika pro slope state.indicators[indname+"MA"] = []
if value == "slope": #specifika pro slope
#inicializujeme statinds (pro uhel na FE) if value == "slope":
state.statinds[indname] = dict(minimum_slope=safe_get(indsettings, 'minimum_slope', -1), maximum_slope=safe_get(indsettings, 'maximum_slope', 1)) #inicializujeme statinds (pro uhel na FE)
state.statinds[indname] = dict(minimum_slope=safe_get(indsettings, 'minimum_slope', -1), maximum_slope=safe_get(indsettings, 'maximum_slope', 1))
#TODO presunout inicializaci work_dict u podminek - sice hodnoty nepujdou zmenit, ale zlepsi se performance
#pripadne udelat refresh kazdych x-iterací
state.vars['sell_in_progress'] = False state.vars['sell_in_progress'] = False
state.vars.mode = None state.vars.mode = None
state.vars.last_tick_price = 0 state.vars.last_tick_price = 0
@ -1263,14 +1098,21 @@ def init(state: StrategyState):
state.vars.lastbuyindex = 0 state.vars.lastbuyindex = 0
state.vars.last_update_time = 0 state.vars.last_update_time = 0
state.vars.reverse_position_waiting_amount = 0 state.vars.reverse_position_waiting_amount = 0
#INIT promenne, ktere byly zbytecne ve stratvars
state.vars.pendingbuys={}
state.vars.limitka = None
state.vars.limitka_price=0
state.vars.jevylozeno=0
state.vars.blockbuy = 0
state.vars["ticks2reset_backup"] = state.vars.ticks2reset state.vars["ticks2reset_backup"] = state.vars.ticks2reset
#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.cbar_indicators['CRSI'] = [] state.cbar_indicators['CRSI'] = []
#state.secondary_indicators['SRSI'] = [] #state.secondary_indicators['SRSI'] = []
state.indicators['ema'] = [] #state.indicators['ema'] = []
state.indicators['RSI14'] = [] #state.indicators['RSI14'] = []
initialize_dynamic_indicators() initialize_dynamic_indicators()

View File

@ -209,7 +209,7 @@ def _modify_stratin(stratin: StrategyInstance, stratin_id: UUID):
if cs.is_stratin_running(id=stratin_id): if cs.is_stratin_running(id=stratin_id):
res,id = cs.modify_stratin_running(si=stratin, id=stratin_id) res,id = cs.modify_stratin_running(si=stratin, id=stratin_id)
else: else:
res, id = cs.modify_stratin(si=stratin, id=stratin_id) res, id = cs.modify_stratin(si=stratin, id=stratin_id)
if res == 0: return id if res == 0: return id
elif res == -2: elif res == -2:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error not found: {res}:{id}") raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"Error not found: {res}:{id}")

7
v2realbot/slicingtest.py Normal file
View File

@ -0,0 +1,7 @@
word = "buy_if_not_something"
if word.endswith("something") and word[:-len] == "not_":
print("Word meets the condition.")
else:
print("Word does not meet the condition.")

View File

@ -22,6 +22,7 @@ settings = {}
settings settings
//ostatni indicatory nez vwap, volume a bary //ostatni indicatory nez vwap, volume a bary
indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, priceScaleId: "right", lastValueVisible: false}, indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
{name: "ema20", titlevisible: false, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
{name: "tick_volume", histogram: true, titlevisible: true, embed: true, display: true, priceScaleId: '', lastValueVisible: false}, {name: "tick_volume", histogram: true, titlevisible: true, embed: true, display: true, priceScaleId: '', lastValueVisible: false},
{name: "tick_price", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false}, {name: "tick_price", titlevisible: true, embed: true, display: true, priceScaleId: "right", lastValueVisible: false},
{name: "ivwap", titlevisible: true, embed: true, display: false, priceScaleId: "right", lastValueVisible: false}, {name: "ivwap", titlevisible: true, embed: true, display: false, priceScaleId: "right", lastValueVisible: false},
@ -38,6 +39,7 @@ indConfig = [ {name: "ema", titlevisible: false, embed: true, display: true, pri
{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: "middle", lastValueVisible: false}, {name: "RSI14", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
{name: "RSI14MA", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
{name: "CRSI", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false}, {name: "CRSI", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
{name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false}, {name: "aroon", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},
{name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false}, {name: "apo", titlevisible: true, embed: true, display: true, priceScaleId: "middle", lastValueVisible: false},

View File

@ -23,10 +23,36 @@ import numpy as np
import pandas as pd import pandas as pd
from collections import deque from collections import deque
#is_pivot function to check if there is A(V) shaped pivot in the list, each leg consists of N points
#middle point is the shared one [1,2,3,2,1] - one leg is [1,2,3] second leg is [3,2,1]
def is_pivot(source: list, leg_number: int, type: str = "A"):
if len(source) < (2 * leg_number)-1:
print("Not enough values in the list")
return False
left_leg = source[-2*leg_number+1:-leg_number+1]
right_leg = source[-leg_number:]
if type == "A":
if isrising(left_leg) and isfalling(right_leg):
return True
else:
return False
elif type == "V":
if isfalling(left_leg) and isrising(right_leg):
return True
else:
return False
else:
print("Unknown type")
return False
def crossed_up(threshold, list): def crossed_up(threshold, list):
"""check if threshold has crossed up last thresholdue in list""" """check if threshold has crossed up last thresholdue in list"""
try: try:
if threshold < list[-1] and threshold >= list[-2]: #upraveno, ze threshold muze byt vetsi nez predpredposledni
if threshold < list[-1] and threshold >= list[-2] or threshold < list[-1] and threshold >= list[-3]:
return True return True
else: else:
return False return False
@ -36,7 +62,8 @@ def crossed_up(threshold, list):
def crossed_down(threshold, list): def crossed_down(threshold, list):
"""check if threshold has crossed down last thresholdue in list""" """check if threshold has crossed down last thresholdue in list"""
try: try:
if threshold > list[-1] and threshold <= list[-2]: #upraveno, ze threshold muze byt mensi nez predpredposledni
if threshold > list[-1] and threshold <= list[-2] or threshold > list[-1] and threshold <= list[-3]:
return True return True
else: else:
return False return False
@ -281,13 +308,17 @@ def is_open_hours(dt, business_hours: dict = None):
and dt.date() not in holidays \ and dt.date() not in holidays \
and business_hours["from"] <= dt.time() < business_hours["to"] and business_hours["from"] <= dt.time() < business_hours["to"]
def isfalling(pole: list, pocet: int): #vraci zda dane pole je klesajici (bud cele a nebo jen pocet poslednich)
def isfalling(pole: list, pocet: int = None):
if pocet is None: pocet = len(pole)
if len(pole)<pocet: return False if len(pole)<pocet: return False
pole = pole[-pocet:] pole = pole[-pocet:]
res = all(i > j for i, j in zip(pole, pole[1:])) res = all(i > j for i, j in zip(pole, pole[1:]))
return res return res
def isrising(pole: list, pocet: int): #vraci zda dane pole je roustouci (bud cele a nebo jen pocet poslednich)
def isrising(pole: list, pocet: int = None):
if pocet is None: pocet = len(pole)
if len(pole)<pocet: return False if len(pole)<pocet: return False
pole = pole[-pocet:] pole = pole[-pocet:]
res = all(i < j for i, j in zip(pole, pole[1:])) res = all(i < j for i, j in zip(pole, pole[1:]))