bugfix a zakomentovan IC a podporen format f

This commit is contained in:
David Brazda
2023-04-23 21:21:06 +02:00
parent 83a7bb77da
commit 541aaa4ab8
25 changed files with 185 additions and 175 deletions

6
testy/fformat.py Normal file
View File

@ -0,0 +1,6 @@
d= 1
a = f"neco {d=} a nebo takhle {float(d)}"
print(a)

View File

@ -56,14 +56,14 @@ for day in cal_dates:
#odesíláme do queue
#jinak pass
else:
ic("cache not exists")
##"cache not exists")
#denni file není - loadujeme den z Alpacy
#ukládáme do cache s daily_file jako název
#pokud jde o dnešní den a nebyl konec trhu tak cache neukládáme
if datetime.now() < day.close:
print("not saving the cache, market still open today")
ic(datetime.now())
ic(day.close)
#ic(datetime.now())
#ic(day.close)
else:
pass
#save to daily cache file curr_dir+'/'+daily_file

View File

@ -16,10 +16,10 @@ Simple strategie pro test backtesting
def next(data, state: StrategyState):
print(10*"*","NEXT START",10*"*")
ic(state.avgp, state.positions)
ic(state.vars.limitka)
ic(state.vars.lastbuyindex)
ic(data)
#ic(state.avgp, state.positions)
#ic(state.vars.limitka)
#ic(state.vars.lastbuyindex)
#ic(data)
#print("last trade price")
#print(state.interface.get_last_price("BAC"))
#print(state.vars.novaprom)
@ -35,7 +35,7 @@ def next(data, state: StrategyState):
state.indicators.ema = ema(state.bars.hlcc4, state.vars.MA) #state.bars.vwap
#trochu prasarna, EMAcko trunc na 3 mista - kdyz se osvedci, tak udelat efektivne
state.indicators.ema = [trunc(i,3) for i in state.indicators.ema]
ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
#ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
except Exception as e:
print("No data for MA yet", str(e))
@ -57,8 +57,8 @@ def next(data, state: StrategyState):
if isfalling(state.indicators.ema,state.vars.Trend) and data['index'] > state.vars.lastbuyindex+state.vars.Trend: #and state.blockbuy == 0
print("BUY MARKET")
ic(data['updated'])
ic(state.time)
#ic(data['updated'])
#ic(state.time)
state.buy_l()

View File

@ -32,10 +32,10 @@ stratvars = AttributeDict(maxpozic = 250,
def next(data, state: StrategyState):
print(10*"*","NEXT START",10*"*")
ic(state.avgp, state.positions)
ic(state.vars.limitka)
ic(state.vars.lastbuyindex)
ic(data)
#ic(state.avgp, state.positions)
#ic(state.vars.limitka)
#ic(state.vars.lastbuyindex)
#ic(data)
#print("last trade price")
#print(state.interface.get_last_price("BAC"))
#print(state.vars.novaprom)
@ -51,7 +51,7 @@ def next(data, state: StrategyState):
state.indicators.ema = ema(state.bars.hlcc4, state.vars.MA) #state.bars.vwap
#trochu prasarna, EMAcko trunc na 3 mista - kdyz se osvedci, tak udelat efektivne
state.indicators.ema = [trunc(i,3) for i in state.indicators.ema]
ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
#ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
except Exception as e:
print("No data for MA yet", str(e))
@ -65,8 +65,8 @@ def next(data, state: StrategyState):
#proto dodělat LTP pro BT, neco jako get_last_price(self.state.time)
if isfalling(state.indicators.ema,state.vars.Trend) and data['index'] > state.vars.lastbuyindex+state.vars.Trend: #and state.blockbuy == 0
print("BUY MARKET")
ic(data['updated'])
ic(state.time)
#ic(data['updated'])
#ic(state.time)
state.buy_l()

View File

@ -89,9 +89,9 @@ exthours=false
def next(data, state: StrategyState):
print(10*"*","NEXT START",10*"*")
ic(state.avgp, state.positions)
ic(state.vars)
ic(data)
#ic(state.avgp, state.positions)
#ic(state.vars)
#ic(data)
#mozna presunout o level vys
def vyloz():
@ -128,7 +128,7 @@ def next(data, state: StrategyState):
last_price = price2dec(state.interface.get_last_price(state.symbol))
#profit = float(state.vars.profit)
price = last_price
state.ilog(e="BUY Vykladame", msg="first price"+str(price) + "pozic:"+str(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, 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
@ -176,7 +176,7 @@ def next(data, state: StrategyState):
state.indicators.ema = ema(state.bars.close, state.vars.MA) #state.bars.vwap
#trochu prasarna, EMAcko trunc na 3 mista - kdyz se osvedci, tak udelat efektivne
state.indicators.ema = [trunc(i,3) for i in state.indicators.ema]
ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
#ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
slope_lookback = int(state.vars.slope_lookback)
minimum_slope = float(state.vars.minimum_slope)
@ -192,17 +192,18 @@ def next(data, state: StrategyState):
array_do = slope_lookback
lookbackprice_array = state.bars.vwap[-array_od:-array_do]
#obycejný prumer hodnot
lookbackprice = sum(lookbackprice_array)/lookback_offset
lookbackprice = round(sum(lookbackprice_array)/lookback_offset,3)
#výpočet úhlu
slope = ((state.bars.close[-1] - lookbackprice)/lookbackprice)*100
slope = round(slope, 4)
state.indicators.slope.append(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)
#state.indicators.roc.append(roc)
#print("slope", state.indicators.slope[-5:])
state.ilog(e="Slope "+str(slope), msg="lookback price:"+str(lookbackprice), lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-10:])
state.ilog(e=f"{slope=}", msg=f"{lookbackprice=}", lookbackoffset=lookback_offset, minimum_slope=minimum_slope, last_slopes=state.indicators.slope[-10:])
#slope MA - cílem je identifikovat táhlá klesání, vypnout nákupy, až budou zase růsty
@ -262,18 +263,18 @@ def next(data, state: StrategyState):
if o.side == OrderSide.BUY:
pendingbuys_new[str(o.id)]=float(o.limit_price)
state.ilog(e="Konzolidace limitky", msg="limitka stejna?:"+str((str(limitka_old)==str(state.vars.limitka))), limitka_old=str(limitka_old), limitka_new=str(state.vars.limitka), limitka_new_price=state.vars.limitka_price, limitka_qty=limitka_qty, limitka_filled_qty=limitka_filled_qty)
state.ilog(e="Konzolidace limitky", msg=f"stejna:{(str(limitka_old)==str(state.vars.limitka))}", limitka_old=str(limitka_old), limitka_new=str(state.vars.limitka), limitka_new_price=state.vars.limitka_price, limitka_qty=limitka_qty, limitka_filled_qty=limitka_filled_qty)
#pokud mame
#neni limitka, ale mela by byt - vytváříme ji
if int(state.positions) > 0 and state.vars.limitka is None:
state.ilog(e="Limitka neni, ale mela by být.", msg="počet pozic aktualnich" + str(int(state.positions)))
state.ilog(e="Limitka neni, ale mela by být.", msg=f"{state.positions=}")
price=price2dec(float(state.avgp)+state.vars.profit)
state.vars.limitka = asyncio.run(state.interface.sell_l(price=price, size=int(state.positions)))
state.vars.limitka_price = price
if state.vars.limitka == -1:
state.ilog(e="Vytvoreni limitky neprobehlo, vracime None", msg=str(state.vars.limitka))
state.ilog(e="Vytvoreni limitky neprobehlo, vracime None", msg=f"{state.vars.limitka=}")
state.vars.limitka = None
state.vars.limitka_price = None
else:
@ -281,13 +282,13 @@ def next(data, state: StrategyState):
elif state.vars.limitka is not None and int(state.positions) > 0 and (int(state.positions) != int(limitka_qty)):
#limitka existuje, ale spatne mnostvi - updatujeme
state.ilog(e="Limitka existuje, ale spatne mnozstvi - updatujeme", msg="POS"+str(int(state.positions))+" lim_qty:"+str(limitka_qty), pos=state.positions, limitka_qty=limitka_qty)
state.ilog(e=f"Limitka existuje, ale spatne mnozstvi - updatujeme", msg=f"{state.positions=} {limitka_qty=}", pos=state.positions, limitka_qty=limitka_qty)
#snad to nespadne, kdyztak pridat exception handling
puvodni = state.vars.limitka
state.vars.limitka = asyncio.run(state.interface.repl(price=state.vars.limitka_price, orderid=state.vars.limitka, size=int(state.positions)))
if state.vars.limitka == -1:
state.ilog(e="Replace limitky neprobehl, vracime puvodni", msg=str(state.vars.limitka), puvodni=puvodni)
state.ilog(e="Replace limitky neprobehl, vracime puvodni", msg=f"{state.vars.limitka=}", puvodni=puvodni)
state.vars.limitka = puvodni
else:
limitka_qty = int(state.positions)
@ -326,7 +327,7 @@ def next(data, state: StrategyState):
#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="AVGP:"+str(round(float(state.avgp),2))+ "POS:" +str(state.positions)+" PROFIT:"+str(round(float(state.profit),2)), last_price=lp, stratvars=state.vars)
state.ilog(e="ENTRY", msg=f"LP:{lp} P:{state.positions}/{round(float(state.avgp),2)} profit:{round(float(state.profit),2)} Trades:{len(state.tradeList)}", last_price=lp, stratvars=state.vars)
#maxSlopeMA = -0.03
#SLOPE ANGLE PROTECTIONs
@ -341,23 +342,21 @@ def next(data, state: StrategyState):
print("OCHRANA SLOPE TOO HIGH")
# if slopeMA<maxSlopeMA:
# state.ilog(e="Slope MA too high "+str(slopeMA)+" max:"+str(maxSlopeMA))
state.ilog(e="Slope too high "+str(slope))
state.ilog(e=f"Slope too high {slope}")
if len(state.vars.pendingbuys)>0:
print("CANCEL PENDINGBUYS")
ic(state.vars.pendingbuys)
#ic(state.vars.pendingbuys)
res = asyncio.run(state.cancel_pending_buys())
ic(state.vars.pendingbuys)
#ic(state.vars.pendingbuys)
state.ilog(e="Rusime pendingbuyes", pb=state.vars.pendingbuys, res=res)
print("slope", slope)
print("min slope", minimum_slope)
if ic(state.vars.jevylozeno) == 0:
if state.vars.jevylozeno == 0:
print("Neni vylozeno, muzeme testovat nakup")
if isfalling(state.indicators.ema,state.vars.Trend) and slope > minimum_slope:
print("BUY MARKET")
ic(data['updated'])
ic(state.time)
#zatim vykladame full
#positions = int(int(state.vars.maxpozic)/int(state.vars.chunk))
vyloz()
@ -378,8 +377,7 @@ def next(data, state: StrategyState):
if state.interface.get_last_price(state.symbol) > float(maxprice) + float(state.vars.ticks2reset):
##TODO toto nejak vymyslet - duplikovat?
res = asyncio.run(state.cancel_pending_buys())
state.ilog(e="UJELO to o více " + str(state.vars.ticks2reset), msg="zrusene pb buye", pb=state.vars.pendingbuys)
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
@ -435,15 +433,11 @@ def init(state: StrategyState):
state.statinds['angle'] = {}
state.vars["ticks2reset_backup"] = state.vars.ticks2reset
#state.indicators['roc'] = []
#state.ilog(e="INIT", stratvars=state.vars)
def main():
try:
strat_settings = tomli.loads("]] this is invalid TOML [[")
except tomli.TOMLDecodeError:
print("Yep, definitely not valid.")
# try:
# strat_settings = tomli.loads("]] this is invalid TOML [[")
# except tomli.TOMLDecodeError:
# print("Yep, definitely not valid.")
#strat_settings = dict_replace_value(strat_settings, "None", None)

View File

@ -15,18 +15,18 @@ Simple strategie pro test backtesting
def next(data, state: StrategyState):
print(10*"*","NEXT START",10*"*")
ic(state.avgp, state.positions)
ic(state.vars.lastbuyindex)
ic(data)
ic(state.positions)
ic(state.vars.watched)
ic(state.vars.wait)
#ic(state.avgp, state.positions)
#ic(state.vars.lastbuyindex)
#ic(data)
#ic(state.positions)
#ic(state.vars.watched)
#ic(state.vars.wait)
try:
state.indicators.ema = ema(state.bars.hlcc4, state.vars.MA) #state.bars.vwap
#trochu prasarna, EMAcko trunc na 3 mista - kdyz se osvedci, tak udelat efektivne
state.indicators.ema = [trunc(i,3) for i in state.indicators.ema]
ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
#ic(state.vars.MA, state.vars.Trend, state.indicators.ema[-5:])
except Exception as e:
print("No data for MA yet", str(e))
@ -49,26 +49,26 @@ def next(data, state: StrategyState):
datetime.fromtimestamp(state.last_trade_time)
casbaru = datetime.fromtimestamp(state.last_trade_time)-data['time']
kupuj = casbaru.seconds > int(int(data['resolution']) * 0.4)
ic(kupuj)
ic(casbaru.seconds)
#ic(kupuj)
#ic(casbaru.seconds)
#kupujeme kdyz v druhe polovine baru je aktualni cena=low (nejnizsi)
#isrising(state.indicators.ema,state.vars.Trend)
#kdyz se v jednom baru pohneme o 2
if kupuj and data['confirmed'] != 1 and data['close'] == data['low'] and float(data['close']) + 0.01 < data['open'] and state.vars.wait is False and state.vars.watched is None:
print("BUY MARKET")
ic(data['updated'])
ic(state.time)
#ic(data['updated'])
#ic(state.time)
##updatneme realnou cenou po fillu
state.buy()
state.vars.wait = True
if state.vars.watched and state.vars.wait is False:
currprice = state.interface.get_last_price(symbol = state.symbol)
ic(currprice)
#ic(currprice)
if float(currprice) > (float(state.vars.watched) + float(state.vars.profit)):
ic(state.time)
ic("prodavame", currprice)
#ic(state.time)
#ic("prodavame", currprice)
print("PRODAVAME")
##vymyslet jak odchytavat obecne chyby a vracet cislo objednavky
state.interface.sell(size=1)

View File

@ -126,7 +126,7 @@ class Backtester:
# print("list before execution", self.open_orders)
if len(self.open_orders) == 0:
ic("no pend orders")
#ic("no pend orders")
return 0
changes = 0
@ -155,10 +155,10 @@ class Backtester:
# break
#pracovni list
ic("work_range 0:index_end")
ic(index_end)
#ic("work_range 0:index_end")
#ic(index_end)
work_range = self.btdata[0:index_end]
ic(len(work_range))
#ic(len(work_range))
#print("index_end", i)
#print("oriznuto",self.btdata[0:i+1])
@ -166,36 +166,37 @@ class Backtester:
#pokud je vyplneny symbol, tak jedeme jen tyto, jinak vsechny
print(order.id, datetime.timestamp(order.submitted_at), order.symbol, order.side, order.order_type, order.qty, order.limit_price, order.submitted_at)
if order.canceled_at:
ic("deleting canceled order",order.id)
#ic("deleting canceled order",order.id)
todel.append(order)
elif not self.symbol or order.symbol == self.symbol:
#pricteme mininimalni latency od submittu k fillu
if order.submitted_at.timestamp() + BT_DELAYS.sub_to_fill > float(intime):
ic("too soon for",order.id)
print(f"too soon for {order.id}")
#try to execute
else:
#try to execute specific order
a = self._execute_order(o = order, intime=intime, work_range=work_range)
if a == 1:
ic("EXECUTED")
#ic("EXECUTED")
todel.append(order)
changes = 1
else:
ic("NOT EXECUTED",a)
#ic("istodel",todel)
print("NOT EXECUTED {a}")
#ic("NOT EXECUTED",a)
##ic("istodel",todel)
#vymazu z pending orderu vschny zprocesovane nebo ty na výmaz
for i in todel:
self.open_orders.remove(i)
todel = {}
#tady udelat pripadny ořez self.btdata - priste zaciname od zacatku
#ic("before delete", len(self.btdata))
##ic("before delete", len(self.btdata))
#TEST zkusime to nemazat, jak ovlivni performance
#Mazeme, jinak je to hruza
#nechavame na konci trady, které muzeme potrebovat pro consekutivni pravidlo
del self.btdata[0:index_end-2-BT_FILL_CONS_TRADES_REQUIRED]
#ic("after delete",len(self.btdata[0:index_end]))
##ic("after delete",len(self.btdata[0:index_end]))
if changes: return 1
else: return 0
@ -214,8 +215,8 @@ class Backtester:
fill_time = None
fill_price = None
order_min_fill_time = o.submitted_at.timestamp() + BT_DELAYS.sub_to_fill
ic(order_min_fill_time)
ic(len(work_range))
#ic(order_min_fill_time)
#ic(len(work_range))
if o.order_type == OrderType.LIMIT:
if o.side == OrderSide.BUY:
@ -248,7 +249,7 @@ class Backtester:
if consec_cnt == BT_FILL_CONS_TRADES_REQUIRED:
#(1679081919.381649, 27.88)
ic(i)
#ic(i)
fill_time = i[0]
fill_price = i[1]
print("FILL LIMIT BUY at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
@ -278,7 +279,7 @@ class Backtester:
consec_cnt += 1
if consec_cnt == BT_FILL_CONS_TRADES_REQUIRED:
#(1679081919.381649, 27.88)
ic(i)
#ic(i)
fill_time = i[0]
fill_price = i[1]
print("FILL LIMIT SELL at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "at",i[1])
@ -296,7 +297,7 @@ class Backtester:
#najde prvni nejvetsi čas vetsi nez minfill
if i[0] > float(order_min_fill_time):
#(1679081919.381649, 27.88)
ic(i)
#ic(i)
fill_time = i[0]
fill_price = i[1]
print("FILL ",o.side,"MARKET at", fill_time, datetime.fromtimestamp(fill_time).astimezone(zoneNY), "cena", i[1])
@ -306,7 +307,7 @@ class Backtester:
return -1
if not fill_time:
ic("not FILLED")
#ic("not FILLED")
return 0
else:
@ -316,7 +317,7 @@ class Backtester:
o.filled_avg_price = float(fill_price)
o.status = OrderStatus.FILLED
ic(o.filled_at, o.filled_avg_price)
#ic(o.filled_at, o.filled_avg_price)
a = self.update_account(o = o)
if a < 0:
@ -396,13 +397,13 @@ class Backtester:
optimalized as bisect left
"""""
pos = bisect_left(self.btdata, (time,))
ic("vracime last price")
ic(time)
#ic("vracime last price")
#ic(time)
if pos == 0:
ic(self.btdata[0][1])
#ic(self.btdata[0][1])
return self.btdata[0][1]
afterTime, afterPrice = self.btdata[pos-1]
ic(afterPrice)
#ic(afterPrice)
return afterPrice
@ -412,8 +413,8 @@ class Backtester:
# #print(i)
# if self.btdata[i][0] >= time:
# break
# ic(time, self.btdata[i-1][1])
# ic("get last price")
# #ic(time, self.btdata[i-1][1])
# #ic("get last price")
# return self.btdata[i-1][1]
def submit_order(self, time: float, symbol: str, side: OrderSide, size: int, order_type: OrderType, price: float = None):
@ -493,7 +494,7 @@ class Backtester:
limit_price=(float(price) if price else None))
self.open_orders.append(order)
ic("order SUBMITTED", order)
#ic("order SUBMITTED", order)
return id

View File

@ -222,7 +222,7 @@ def save_history(id: UUID, st: object, runner: Runner, reason: str = None):
#zkousime precist profit z objektu
try:
profit = st.state.profit
trade_count = len(st.tradeList)
trade_count = len(st.state.tradeList)
except Exception as e:
profit = str(e)

View File

@ -93,8 +93,8 @@ class TradeAggregator:
#pokud projde TRADE s cenou 0.33% rozdilna oproti predchozi, pak vyhazujeme v ramci cisteni dat (cca 10ticku na 30USD)
pct_off = 0.33
#ic(ltp.price)
#ic(ltp.price[symbol])
##ic(ltp.price)
##ic(ltp.price[symbol])
try:
ltp.price[symbol]

View File

@ -63,7 +63,7 @@ class Trade_Offline_Streamer(Thread):
for i in self.streams:
self.uniquesymbols.add(i.symbol)
ic(self.uniquesymbols)
#ic(self.uniquesymbols)
##z unikatnich symbolu naplnime keys pro dictionary
# for i in self.uniquesymbols:
# self.to_run
@ -77,14 +77,14 @@ class Trade_Offline_Streamer(Thread):
for i in self.streams:
self.to_run[i.symbol].append(i)
ic(self.to_run)
#ic(self.to_run)
#prepare data
symbpole = []
for key in self.uniquesymbols:
symbpole.append(key)
#print(symbpole))
ic(self.time_from.astimezone(tz=zoneNY))
ic(self.time_to.astimezone(tz=zoneNY))
#ic(self.time_from.astimezone(tz=zoneNY))
#ic(self.time_to.astimezone(tz=zoneNY))
##PREPSAT jednoduse tak, aby podporovalo jen jeden symbol
#agregator2list bude mit vstup list
@ -92,7 +92,7 @@ class Trade_Offline_Streamer(Thread):
#REFACTOR STARTS HERE
calendar_request = GetCalendarRequest(start=self.time_from,end=self.time_to)
cal_dates = self.clientTrading.get_calendar(calendar_request)
ic(cal_dates)
#ic(cal_dates)
#zatim podpora pouze main session
#zatim podpora pouze 1 symbolu, predelat na froloop vsech symbolu ze symbpole
@ -134,8 +134,8 @@ class Trade_Offline_Streamer(Thread):
#pokud jde o dnešní den a nebyl konec trhu tak cache neukládáme
if day.open < datetime.now().astimezone(zoneNY) < day.close:
print("not saving the cache, market still open today")
ic(datetime.now().astimezone(zoneNY))
ic(day.open, day.close)
#ic(datetime.now().astimezone(zoneNY))
#ic(day.open, day.close)
else:
with open(file_path, 'wb') as fp:
pickle.dump(tradesResponse, fp)
@ -157,13 +157,13 @@ class Trade_Offline_Streamer(Thread):
wait_for_q = False
else:
wait_for_q = True
ic(wait_for_q)
#ic(wait_for_q)
# v tradesResponse je dict = Trades identifikovane symbolem
for symbol in tradesResponse:
#print(tradesResponse[symbol])
celkem = len(tradesResponse[symbol])
ic(symbol, celkem)
#ic(symbol, celkem)
#print("POCET: ", celkem)
cnt = 1
@ -173,13 +173,13 @@ class Trade_Offline_Streamer(Thread):
#protoze je zde cely den, poustime dal, jen ty relevantni
#pokud je start_time < trade < end_time
#datetime.fromtimestamp(parse_alpaca_timestamp(t['t']))
#ic(t['t'])
##ic(t['t'])
if self.time_from < to_datetime(t['t']) < self.time_to:
#poustime dal, jinak ne
if wait_for_q:
if 'Q' not in t['c']: continue
else:
ic("Q found poustime dal")
#ic("Q found poustime dal")
wait_for_q = False
#homogenizace timestampu s online streamem

View File

@ -3,7 +3,7 @@ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from v2realbot.enums.enums import Mode, Account
from v2realbot.config import WEB_API_KEY
from datetime import datetime
from icecream import install, ic
#from icecream import install, ic
import os
from rich import print
from threading import current_thread
@ -26,12 +26,12 @@ from threading import Thread
import asyncio
#from async io import Queue, QueueEmpty
install()
ic.configureOutput(includeContext=True)
def threadName():
return '%s |> ' % str(current_thread().name)
ic.configureOutput(prefix=threadName)
ic.disable()
# install()
# ic.configureOutput(includeContext=True)
# def threadName():
# return '%s |> ' % str(current_thread().name)
# ic.configureOutput(prefix=threadName)
# ic.disable()
"""""
Main entry point of the bot. Starts strategies according to config file, each
in separate thread.

View File

@ -82,7 +82,7 @@ function connect(event) {
logcnt++;
row = '<div data-toggle="collapse" data-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ logLine.message+'</div>'
row = '<div data-toggle="collapse" data-target="#rec'+logcnt+'">'+logLine.time + " " + logLine.event + ' - '+ (logLine.message == undefined ? "" : logLine.message) +'</div>'
str_row = JSON.stringify(logLine.details, null, 2)
row_detail = '<div id="rec'+logcnt+'" data-toggle="collapse" data-target="#rec'+logcnt+'"class="collapse pidi"><pre>' + str_row + '</pre></div>'

View File

@ -16,7 +16,7 @@ class StrategyOrderLimitKOKA(Strategy):
async def orderUpdateBuy(self, data: TradeUpdate):
if data.event == TradeEvent.FILL or data.event == TradeEvent.PARTIAL_FILL:
ic("vstupujeme do orderupdatebuy")
#ic("vstupujeme do orderupdatebuy")
print(data)
o: Order = data.order
#dostavame zde i celkové akutální množství - ukládáme
@ -39,18 +39,18 @@ class StrategyOrderLimitKOKA(Strategy):
async def orderUpdateSell(self, data: TradeUpdate):
if data.event == TradeEvent.PARTIAL_FILL:
ic("partial fill udpatujeme pozice")
#ic("partial fill udpatujeme pozice")
self.state.avgp, self.state.positions = self.interface.pos()
elif data.event == TradeEvent.FILL:
#muzeme znovu nakupovat, mazeme limitku
#self.state.blockbuy = 0
ic("notifikace sell mazeme limitku")
#ic("notifikace sell mazeme limitku")
self.state.vars.limitka = None
self.state.vars.lastbuyindex = -5
#this parent method is called by strategy just once before waiting for first data
def strat_init(self):
ic("strat INI function")
#ic("strat INI function")
#lets connect method overrides
self.state.buy = self.buy
self.state.buy_l = self.buy_l
@ -67,8 +67,8 @@ class StrategyOrderLimitKOKA(Strategy):
sizer = size
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
return self.state.interface.buy(size=sizer)
#pro experiment - nemame zde max mnozstvi
@ -78,9 +78,9 @@ class StrategyOrderLimitKOKA(Strategy):
#TODO pokud je cena 2 decimals, nechavam. pokud je 3 mistne delam round(x,2)
if price is None: price=trunc(self.state.interface.get_last_price(self.symbol),2)
ic(price)
#ic(price)
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
return self.state.interface.buy_l(price=price, size=size)

View File

@ -21,17 +21,17 @@ class StrategyOrderLimitVykladaci(Strategy):
async def orderUpdateBuy(self, data: TradeUpdate):
o: Order = data.order
##nejak to vymyslet, aby se dal poslat cely Trade a serializoval se
self.state.ilog(e="Příchozí BUY notifikace", msg="order status:"+o.status, trade=json.loads(json.dumps(data, default=json_serial)))
self.state.ilog(e="Příchozí BUY notif", msg=f"{o.status=}", trade=json.loads(json.dumps(data, default=json_serial)))
if o.status == OrderStatus.FILLED or o.status == OrderStatus.CANCELED:
#pokud existuje objednavka v pendingbuys - vyhodime ji
if self.state.vars.pendingbuys.pop(str(o.id), False):
self.state.ilog(e="Příchozí BUY notifikace - mazeme ji z pb", msg="order status:"+o.status, orderid=str(o.id), pb=self.state.vars.pendingbuys)
self.state.ilog(e="Příchozí BUY notif - mazeme ji z pb", msg=f"{o.status=}", orderid=str(o.id), pb=self.state.vars.pendingbuys)
print("limit buy filled or cancelled. Vyhazujeme z pendingbuys.")
ic(self.state.vars.pendingbuys)
#ic(self.state.vars.pendingbuys)
if data.event == TradeEvent.FILL or data.event == TradeEvent.PARTIAL_FILL:
ic("vstupujeme do orderupdatebuy")
#ic("vstupujeme do orderupdatebuy")
print(data)
#dostavame zde i celkové akutální množství - ukládáme
self.state.positions = data.position_qty
@ -59,7 +59,7 @@ class StrategyOrderLimitVykladaci(Strategy):
self.state.vars.limitka = puvodni
else:
self.state.vars.limitka_price = cena
self.state.ilog(e="Příchozí BUY notif - menime limitku", msg="order status:"+o.status, orderid=str(o.id), limitka=str(self.state.vars.limitka), limtka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni))
self.state.ilog(e="Příchozí BUY notif - menime limitku", msg=f"{o.status=}", orderid=str(o.id), limitka=str(self.state.vars.limitka), limtka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni))
except APIError as e:
self.state.ilog(e="API ERROR pri zmene limitky", msg=str(e), orderid=str(o.id), limitka=str(self.state.vars.limitka), limitka_price=self.state.vars.limitka_price, puvodni_limitka=str(puvodni))
@ -71,7 +71,7 @@ class StrategyOrderLimitVykladaci(Strategy):
async def orderUpdateSell(self, data: TradeUpdate):
self.state.ilog(e="Příchozí SELL notifikace", msg="order status:"+data.order.status, trade=json.loads(json.dumps(data, default=json_serial)))
self.state.ilog(e="Příchozí SELL notif", msg=f"{data.order.status=}", trade=json.loads(json.dumps(data, default=json_serial)))
#PROFIT
#profit pocitame z TradeUpdate.price a TradeUpdate.qty - aktualne provedene mnozstvi a cena
#naklady vypocteme z prumerne ceny, kterou mame v pozicich
@ -85,11 +85,11 @@ class StrategyOrderLimitVykladaci(Strategy):
trade_profit = (sold_amount - avg_costs)
self.state.profit += trade_profit
self.state.ilog(e="SELL not - PROFIT: "+str(round(float(trade_profit),3))+" celkem: "+str(round(float(self.state.profit),3)), msg=str(data.event), sold_amount=sold_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))
self.state.ilog(e=f"SELL not - PROFIT:{round(float(trade_profit),3)} celkem:{round(float(self.state.profit),3)}", msg=str(data.event), sold_amount=sold_amount, avg_costs=avg_costs, trade_qty=data.qty, trade_price=data.price, orderid=str(data.order.id))
if data.event == TradeEvent.PARTIAL_FILL:
self.state.ilog(e="SELL notifikace - Partial fill", msg="pouze update pozic", orderid=str(data.order.id))
ic("partial fill jen udpatujeme pozice")
#ic("partial fill jen udpatujeme pozice")
#TODO tento update mozna vyhodit a pockat vzdy na plny fill - otestovat az bude cas
self.state.avgp, self.state.positions = self.interface.pos()
elif data.event == TradeEvent.FILL or data.event == TradeEvent.CANCELED:
@ -97,20 +97,20 @@ class StrategyOrderLimitVykladaci(Strategy):
#muzeme znovu nakupovat, mazeme limitku, blockbuy a pendingbuys
#self.state.blockbuy = 0
ic("notifikace sell mazeme limitku a update pozic")
#ic("notifikace sell mazeme limitku a update pozic")
#updatujeme pozice
self.state.avgp, self.state.positions = self.interface.pos()
ic(self.state.avgp, self.state.positions)
#ic(self.state.avgp, self.state.positions)
self.state.vars.limitka = None
self.state.vars.limitka_price = None
self.state.vars.lastbuyindex = -5
self.state.vars.jevylozeno = 0
await self.state.cancel_pending_buys()
self.state.ilog(e="Příchozí SELL - FILL nebo CANCEL - mazeme limitku a pb", msg="order status:"+ data.order.status, orderid=str(data.order.id), pb=self.state.vars.pendingbuys)
self.state.ilog(e="Příchozí SELL - FILL nebo CANCEL - mazeme limitku a pb", msg=f"{data.order.status=}", orderid=str(data.order.id), pb=self.state.vars.pendingbuys)
#this parent method is called by strategy just once before waiting for first data
def strat_init(self):
ic("strat INI function")
#ic("strat INI function")
#lets connect method overrides
self.state.buy = self.buy
self.state.buy_l = self.buy_l
@ -141,7 +141,7 @@ class StrategyOrderLimitVykladaci(Strategy):
return 0
if size is None: size=self.state.vars.chunk
if price is None: price=price2dec((self.state.interface.get_last_price(self.symbol)))
ic(price)
#ic(price)
print("odesilame LIMIT s cenou/qty", price, size)
self.state.ilog(e="send LIMIT buy to if", msg="S:"+str(size)+" P:"+str(price), price=price, size=size)
order = self.state.interface.buy_l(price=price, size=size)
@ -149,9 +149,9 @@ class StrategyOrderLimitVykladaci(Strategy):
self.state.vars.pendingbuys[str(order)]=price
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
self.state.ilog(e="Odslano a ulozeno do pb", order=str(order), pb=self.state.vars.pendingbuys)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
self.state.ilog(e="Odeslan buy_l a ulozeno do pb", order=str(order), pb=self.state.vars.pendingbuys)
async def cancel_pending_buys(self):
print("cancel pending buys called.")
@ -161,11 +161,11 @@ class StrategyOrderLimitVykladaci(Strategy):
if len(self.state.vars.pendingbuys)>0:
tmp = copy.deepcopy(self.state.vars.pendingbuys)
for key in tmp:
ic(key)
#ic(key)
#nejprve vyhodime z pendingbuys
self.state.vars.pendingbuys.pop(key, False)
res = self.interface.cancel(key)
self.state.ilog(e="Pendingy zrusen pro"+str(key), orderid=str(key), res=str(res))
self.state.ilog(e=f"Pendingy zrusen pro{key=}", orderid=str(key), res=str(res))
print("CANCEL PENDING BUYS RETURN", res)
self.state.vars.pendingbuys={}
self.state.vars.jevylozeno = 0

View File

@ -50,7 +50,6 @@ class Strategy:
self.account = account
self.key = get_key(mode=self.mode, account=self.account)
self.rtqueue = None
self.tradeList = []
#TODO predelat na dynamické queues
@ -89,7 +88,7 @@ class Strategy:
"""Allow client to set LIVE or BACKTEST mode"""
def set_mode(self, mode: Mode, start: datetime = None, end: datetime = None, cash = None, debug: bool = False):
ic(f"mode {mode} selected")
#ic(f"mode {mode} selected")
if mode == Mode.BT and (not start or not end):
print("start/end required")
@ -171,7 +170,7 @@ class Strategy:
self.state.time = self.state.last_trade_time + BT_DELAYS.trigger_to_strat
elif self.mode == Mode.LIVE or self.mode == Mode.PAPER:
self.state.time = datetime.now().timestamp()
ic('time updated')
#ic('time updated')
def strat_loop(self, item):
##TODO do samostatne funkce
@ -191,24 +190,25 @@ class Strategy:
## BT - execute orders that should have been filled until this time
##do objektu backtest controller?
ic(self.state.time)
#ic(self.state.time)
if self.mode == Mode.BT:
ic(self.bt.time)
self.state.ilog(e="Before BT iter", msg=f"{self.bt.time=}")
#pozor backtester muze volat order_updates na minuly cas - nastavi si bt.time
self.bt.execute_orders_and_callbacks(self.state.time)
ic(self.bt.time)
#ic(self.bt.time)
ic(self.state.time)
#ic(self.state.time)
#volame jeste jednou update_times, kdyby si BT nastavil interfaces na jiny cas (v ramci callbacku notifikací)
self.update_times(item)
ic(self.state.time)
#ic(self.state.time)
if self.mode == Mode.BT:
ic(self.bt.time)
ic(len(self.btdata))
ic(self.bt.cash)
self.state.ilog(e="After BT iter", msg=f"{self.bt.time=}")
#ic(self.bt.time)
#ic(len(self.btdata))
#ic(self.bt.cash)
self.save_item_history(item)
#nevyhodit ten refresh do TypeLimit? asi ANO
@ -321,7 +321,7 @@ class Strategy:
#pokud jde o FILL zapisujeme do self.trades a notifikujeme
if data.event == TradeEvent.FILL:
self.tradeList.append(data)
self.state.tradeList.append(data)
##TradeUpdate objekt better?
order: Order = data.order
@ -342,9 +342,16 @@ class Strategy:
##kroky po iteraci
def after_iteration(self, item):
#sends real time updates to frontend if requested
self.send_rt_updates(item)
#DAT DO VNORENE FUNKCE
##check if real time chart is requested
# inicializace poplatna typu strategie (např. u LIMITu dotažení existující limitky)
def strat_init(self):
pass
def send_rt_updates(self, item):
##if real time chart is requested
##posilame dict s objekty: bars, trades podle cbaru, a dale indicators naplnene time a pripadnymi identifikatory (EMA)
if self.rtqueue is not None:
rt_out = dict()
@ -403,10 +410,6 @@ class Strategy:
#mazeme logy pokud neni na ws pozadovano
self.state.iter_log_list = []
# inicializace poplatna typu strategie (např. u LIMITu dotažení existující limitky)
def strat_init(self):
pass
@staticmethod
def append_bar(history_reference, new_bar: dict):
history_reference['open'].append(new_bar['open'])
@ -507,13 +510,20 @@ class StrategyState:
self.cancel_pending_buys = None
self.iter_log_list = []
self.profit = 0
self.tradeList = []
def ilog(self, e: str = None, msg: str = None, **kwargs):
if e is None:
row = dict(time=self.time, message=msg, details=kwargs)
if msg is None:
row = dict(time=self.time, details=kwargs)
else:
row = dict(time=self.time, message=msg, details=kwargs)
else:
row = dict(time=self.time, event=e, message=msg, details=kwargs)
if msg is None:
row = dict(time=self.time, event=e, details=kwargs)
else:
row = dict(time=self.time, event=e, message=msg, details=kwargs)
self.iter_log_list.append(row)
row["name"] = self.name
print(row)
#TBD mozna odsud to posilat do nejakeho struct logger jako napr. structlog
#TBD mozna odsud to posilat do nejakeho struct logger jako napr. structlog nebo loguru, separatni file podle name

View File

@ -31,7 +31,7 @@ class StrategyOrderLimit(Strategy):
async def orderUpdateBuy(self, data: TradeUpdate):
if data.event == TradeEvent.FILL or data.event == TradeEvent.PARTIAL_FILL:
ic("vstupujeme do orderupdatebuy")
#ic("vstupujeme do orderupdatebuy")
print(data)
o: Order = data.order
#dostavame zde i celkové akutální množství - ukládáme
@ -54,18 +54,18 @@ class StrategyOrderLimit(Strategy):
async def orderUpdateSell(self, data: TradeUpdate):
if data.event == TradeEvent.PARTIAL_FILL:
ic("partial fill udpatujeme pozice")
#ic("partial fill udpatujeme pozice")
self.state.avgp, self.state.positions = self.interface.pos()
elif data.event == TradeEvent.FILL:
#muzeme znovu nakupovat, mazeme limitku
#self.state.blockbuy = 0
ic("notifikace sell mazeme limitku")
#ic("notifikace sell mazeme limitku")
self.state.vars.limitka = None
self.state.vars.lastbuyindex = -5
#this parent method is called by strategy just once before waiting for first data
def strat_init(self):
ic("strat INI function")
#ic("strat INI function")
#lets connect method overrides
self.state.buy = self.buy
self.state.buy_l = self.buy_l
@ -82,8 +82,8 @@ class StrategyOrderLimit(Strategy):
sizer = size
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
return self.state.interface.buy(size=sizer)
#pro experiment - nemame zde max mnozstvi
@ -91,9 +91,9 @@ class StrategyOrderLimit(Strategy):
print("overriden buy limitka")
if size is None: size=self.state.vars.chunk
if price is None: price=trunc(self.state.interface.get_last_price(self.symbol)-0.01,2)
ic(price)
#ic(price)
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
return self.state.interface.buy_l(price=price, size=size)

View File

@ -15,7 +15,7 @@ class StrategyOrderLimitWatched(Strategy):
async def orderUpdateBuy(self, data: TradeUpdate):
if data.event == TradeEvent.FILL:
ic("orderbuyfill callback")
#ic("orderbuyfill callback")
print(data)
o: Order = data.order
#dostavame zde i celkové akutální množství - ukládáme
@ -30,11 +30,11 @@ class StrategyOrderLimitWatched(Strategy):
self.state.positions = data.position_qty
self.state.vars.watched = None
self.state.vars.wait = False
ic("SELL notifikace callback - prodano - muzeme znovu nakupovat")
#ic("SELL notifikace callback - prodano - muzeme znovu nakupovat")
#this parent method is called by strategy just once before waiting for first data
def strat_init(self):
ic("strat INI function")
#ic("strat INI function")
#lets connect method overrides
self.state.buy = self.buy
self.state.buy_l = self.buy_l
@ -51,8 +51,8 @@ class StrategyOrderLimitWatched(Strategy):
sizer = size
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
return self.state.interface.buy(size=sizer)
#pro experiment - nemame zde max mnozstvi
@ -60,9 +60,9 @@ class StrategyOrderLimitWatched(Strategy):
print("overriden buy limitka")
if size is None: size=self.state.vars.chunk
if price is None: price=trunc(self.state.interface.get_last_price(self.symbol)-0.01,2)
ic(price)
#ic(price)
self.state.blockbuy = 1
self.state.vars.lastbuyindex = self.state.bars['index'][-1]
ic(self.state.blockbuy)
ic(self.state.vars.lastbuyindex)
#ic(self.state.blockbuy)
#ic(self.state.vars.lastbuyindex)
return self.state.interface.buy_l(price=price, size=size)

View File

@ -6,7 +6,6 @@ import pytz
from dateutil import tz
from rich import print as richprint
import decimal
from icecream import ic
from v2realbot.enums.enums import RecordType, Mode, StartBarAlign
import pickle
import os
@ -94,7 +93,7 @@ def print(*args, **kwargs):
if QUIET_MODE:
pass
else:
#ic(*args, **kwargs)
####ic(*args, **kwargs)
richprint(*args, **kwargs)
def price2dec(price: float) -> float: