From f869164ed039091785a6fdc383d120b0f81cce5c Mon Sep 17 00:00:00 2001 From: David Brazda Date: Sun, 16 Apr 2023 10:37:16 +0200 Subject: [PATCH] consolidation process added --- testy/moduleTests/backtestInterfaceTest.py | 46 +++++++++++++ testy/moduleTests/liveInterfaceTest.py | 57 ++++++++++++++++ testy/{testStore => testStore.py} | 0 v2realbot/ENTRY_backtest_strategyVykladaci.py | 63 +++++++++++++++++- v2realbot/__pycache__/config.cpython-310.pyc | Bin 2546 -> 2572 bytes .../__pycache__/backtester.cpython-310.pyc | Bin 18056 -> 18058 bytes v2realbot/backtesting/backtester.py | 6 +- .../backtest_interface.cpython-310.pyc | Bin 3725 -> 3806 bytes .../live_interface.cpython-310.pyc | Bin 5269 -> 5289 bytes v2realbot/interfaces/live_interface.py | 4 +- v2realbot/main.py | 2 +- 11 files changed, 170 insertions(+), 8 deletions(-) create mode 100644 testy/moduleTests/backtestInterfaceTest.py create mode 100644 testy/moduleTests/liveInterfaceTest.py rename testy/{testStore => testStore.py} (100%) diff --git a/testy/moduleTests/backtestInterfaceTest.py b/testy/moduleTests/backtestInterfaceTest.py new file mode 100644 index 0000000..1909d27 --- /dev/null +++ b/testy/moduleTests/backtestInterfaceTest.py @@ -0,0 +1,46 @@ +from v2realbot.config import Keys, get_key +from v2realbot.enums.enums import Mode, Account, OrderSide +from alpaca.trading.enums import OrderSide, OrderStatus, TradeEvent, OrderType +from v2realbot.common.model import TradeUpdate, Order +from v2realbot.interfaces.live_interface import LiveInterface +from v2realbot.interfaces.backtest_interface import BacktestInterface +from v2realbot.backtesting.backtester import Backtester +from datetime import datetime +from v2realbot.utils.utils import zoneNY +from uuid import UUID, uuid4 + +def callback(): + print("callback entry") + + +start = datetime(2023, 4, 10, 9, 30, 0, 0, tzinfo=zoneNY) +end = datetime(2023, 4, 10, 9, 35, 0, 0, tzinfo=zoneNY) +btdata: list = [] +cash=10000 +#key = get_key(mode=Mode.PAPER, account=Account.ACCOUNT1) +symbol = "BAC" + +bt = Backtester(symbol = symbol, order_fill_callback= callback, btdata=btdata, cash=cash, bp_from=start, bp_to=end) + +bt.open_orders = [Order(id=uuid4(), + submitted_at = datetime(2023, 3, 17, 9, 30, 0, 0, tzinfo=zoneNY), + symbol = "BAC", + qty = 1, + status = OrderStatus.ACCEPTED, + order_type = OrderType.LIMIT, + side = OrderSide.SELL, + limit_price=22.4), + Order(id=uuid4(), + submitted_at = datetime(2023, 3, 17, 9, 30, 00, 0, tzinfo=zoneNY), + symbol = "BAC", + qty = 1, + order_type = OrderType.MARKET, + status = OrderStatus.ACCEPTED, + side = OrderSide.BUY)] + +bt_interface = BacktestInterface(symbol=symbol, bt=bt) + +orderlist = bt.get_open_orders(symbol=symbol, side=None) + +print(orderlist) +print(len(orderlist)) \ No newline at end of file diff --git a/testy/moduleTests/liveInterfaceTest.py b/testy/moduleTests/liveInterfaceTest.py new file mode 100644 index 0000000..49af66a --- /dev/null +++ b/testy/moduleTests/liveInterfaceTest.py @@ -0,0 +1,57 @@ +from v2realbot.config import Keys, get_key +from v2realbot.enums.enums import Mode, Account, OrderSide +from v2realbot.interfaces.live_interface import LiveInterface +from msgpack import packb, unpackb +key = get_key(mode=Mode.PAPER, account=Account.ACCOUNT1) +symbol = "BAC" +li = LiveInterface(symbol=symbol, key=key) + + +##tady jsem skoncil - otestovat tento kod na variantach +# pendinbuys na PAPER +#pak dat do Vykladaci ENTRY a otestovat i na BT +data = {} +data["index"] = 30 +consolidation_bar_count = 10 +pendingbuys = {'22dd3fe21-2c61-4ddd-b7df-cbdb3c1f7b79': '29.63', 'fe7b4baa-ef61-4867-b111-b1c3fc016dce': '29.59', '40253d42-bc00-4476-8f7a-28449fc00080': '29.57'} + +##konzolidace kazdy Nty bar dle nastaveni +if int(data["index"])%int(consolidation_bar_count) == 0: + print("***Consolidation ENTRY***") + + orderlist = li.get_open_orders(symbol=symbol, side=None) + #print(orderlist) + pendingbuys_new = {} + limitka = None + jevylozeno = 1 + for o in orderlist: + if o.side == OrderSide.SELL: + print("Puvodni LIMITKA", limitka) + limitka = o.id + print("Přepsaná LIMITKA", limitka) + if o.side == OrderSide.BUY: + pendingbuys_new[str(o.id)]=o.limit_price + + if pendingbuys_new != pendingbuys: + print("ROZDILNA PENDINGBUYS přepsána") + print("OLD",pendingbuys) + pendingbuys = unpackb(packb(pendingbuys_new)) + print("NEW", pendingbuys) + print("OLD jevylozeno",jevylozeno) + if len(pendingbuys) > 0: + jevylozeno = 1 + else: + jevylozeno = 0 + print("NEW jevylozeno",jevylozeno) + + #print(limitka) + #print(pendingbuys_new) + #print(pendingbuys) + #print(len(pendingbuys)) + #print(len(pendingbuys_new)) + #print(jevylozeno) + print("***CONSOLIDATION EXIT***") + +else: + print("no time for consolidation", data["index"]) + diff --git a/testy/testStore b/testy/testStore.py similarity index 100% rename from testy/testStore rename to testy/testStore.py diff --git a/v2realbot/ENTRY_backtest_strategyVykladaci.py b/v2realbot/ENTRY_backtest_strategyVykladaci.py index 7f1caaa..49dfe44 100644 --- a/v2realbot/ENTRY_backtest_strategyVykladaci.py +++ b/v2realbot/ENTRY_backtest_strategyVykladaci.py @@ -2,13 +2,14 @@ import os,sys sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from v2realbot.strategy.base import StrategyState from v2realbot.strategy.StrategyOrderLimitVykladaci import StrategyOrderLimitVykladaci -from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account +from v2realbot.enums.enums import RecordType, StartBarAlign, Mode, Account, OrderSide from v2realbot.indicators.indicators import ema from v2realbot.utils.utils import ltp, isrising, isfalling,trunc,AttributeDict, zoneNY, price2dec, dict_replace_value from datetime import datetime from icecream import install, ic from rich import print from threading import Event +from msgpack import packb, unpackb import asyncio import os import tomli @@ -22,6 +23,10 @@ Vykladaci strategie refactored z původního engine Params: (maxpozic = 200, chunk = 50, MA = 6, Trend = 6, profit = 0.02, lastbuyindex=-6, pendingbuys={},limitka = None, jevylozeno=0, ticks2reset = 0.04, blockbuy=0) +Pozor na symbolu nesmi byt dalsi cizí otevrene objednavky: +Pravidelny konzolidacni process da SELL order da do limitka, BUY - do pole pendingbuys + +consolidation_bar_count - pocet baru po kterych se triggeruje konzolidační proces Více nakupuje oproti Dokupovaci. Tady vylozime a nakupujeme 5 pozic hned. Pri dokupovaci se dokupuje, az na zaklade dalsich triggeru. Do budoucna vice ridit nakupy pri klesani - napr. vyložení jen 2-3 pozic a další dokupy až po triggeru. @@ -39,7 +44,8 @@ stratvars = AttributeDict(maxpozic = 250, vykladka=5, curve = [0.01, 0.01, 0.01, 0, 0.02, 0.02, 0.01,0.01, 0.01,0.03, 0.01, 0.01, 0.01,0.04, 0.01,0.01, 0.01,0.05, 0.01,0.01, 0.01,0.01, 0.06,0.01, 0.01,0.01, 0.01], blockbuy = 0, - ticks2reset = 0.04) + ticks2reset = 0.04, + consolidation_bar_count = 10) ##toto rozparsovat a strategii spustit stejne jako v main toml_string = """ [[strategies]] @@ -171,6 +177,7 @@ def next(data, state: StrategyState): res = asyncio.run(state.cancel_pending_buys()) + #PENDING BUYS SPENT - PART #pokud mame vylozeno a pendingbuys se vyklepou a # 1 vykladame idned znovu # vyloz() @@ -183,7 +190,57 @@ def next(data, state: StrategyState): state.vars.blockbuy = 0 state.vars.jevylozeno = 0 - #TODO toto dodelat + #TODO toto dodelat konzolidaci a mozna lock na limitku a pendingbuys a jevylozeno ?? + + #kdykoliv se muze notifikace ztratit + # - pendingbuys - vsechny open orders buy + # - limitka - open order sell + + ##CONSOLIDATION PART kazdy Nty bar dle nastaveni + if int(data["index"])%int(state.vars.consolidation_bar_count) == 0: + print("***Consolidation ENTRY***") + + orderlist = state.interface.get_open_orders(symbol=state.symbol, side=None) + #print(orderlist) + pendingbuys_new = {} + limitka_old = state.vars.limitka + print("Puvodni LIMITKA", limitka_old) + state.vars.limitka = None + for o in orderlist: + if o.side == OrderSide.SELL: + state.vars.limitka = o.id + if o.side == OrderSide.BUY: + pendingbuys_new[str(o.id)]=o.limit_price + + print("Nová LIMITKA", state.vars.limitka) + if pendingbuys_new != state.vars.pendingbuys: + print("ROZDILNA PENDINGBUYS přepsána") + print("OLD",state.vars.pendingbuys) + state.vars.pendingbuys = unpackb(packb(pendingbuys_new)) + print("NEW", state.vars.pendingbuys) + else: + print("PENDINGBUYS sedí - necháváme", state.vars.pendingbuys) + print("OLD jevylozeno", state.vars.jevylozeno) + if len(state.vars.pendingbuys) > 0: + state.vars.jevylozeno = 1 + else: + state.vars.jevylozeno = 0 + print("NEW jevylozeno", state.vars.jevylozeno) + + #print(limitka) + #print(pendingbuys_new) + #print(pendingbuys) + #print(len(pendingbuys)) + #print(len(pendingbuys_new)) + #print(jevylozeno) + print("***CONSOLIDATION EXIT***") + + else: + print("no time for consolidation", data["index"]) + + + + #pokud je vylozeno a mame pozice a neexistuje limitka - pak ji vytvorim # if int(state.oe.poz)>0 and state.oe.limitka == 0: # #pro jistotu updatujeme pozice diff --git a/v2realbot/__pycache__/config.cpython-310.pyc b/v2realbot/__pycache__/config.cpython-310.pyc index 7a5c5de925bf34790944cfea598951faba22d7a3..0f906eab68619e698c107d36ca409ca1e664b002 100644 GIT binary patch delta 380 zcmXAky-osA5QX=`vVSbQu*G2Lq74a5f`uut(Sano zkP>$tMowHvV;VA;fvli8%tC%f3z&mB%!6GN*c0KB!1J&$ey@;lQXsE{xcoEnyb0=I zuS-waB^Vd%sLuv79qS$TSRdpLW7v1ZSO3iw>P@4xd)6IL>hZ5=g%o*N_DFFO$iGDK zrqL3wE9+#550zzOMSzc(Xu$84UH&8fU*y+n;5yrl_FhP<`!(A1588e!Z1ER$Ek9j= lRNz;e;g(+wX;`cKjdlnVTe~CHhM1aCl9)t}XoNrMtABvvU3mZi delta 312 zcmW-cKTE@45QlSVnm0+4G;Pzg_MeJ~LlhiT$R|(`7je2piuWq&V5u%n4k_Z`65em% z>KM?E;1>{tOd=w1%$#J1xN(1PspHc#|YSrjLC*Lvtz?|cT<9W4fuET=5F&CYf#b=pUp&rd` l*i*Vl`Q=({sW-6#u?nmRihRks2X~EQt`>j`mabmy<$nnpPtyPZ diff --git a/v2realbot/backtesting/__pycache__/backtester.cpython-310.pyc b/v2realbot/backtesting/__pycache__/backtester.cpython-310.pyc index 965fe2d79659923990db48d071977b710d9b5831..3a4718716941afb8eedb0bb1e1d229444260582b 100644 GIT binary patch delta 234 zcmeC^W$fx@h!;-~Z!<5Zbq+P?9!cxjm ztOgWesbK_*FfU-OVOhw?$WSO&!yL?@$vXMDhQFkrCR>pp(6k~85TOeq6hMUipTEHd_pJy delta 241 zcmeC`W$fr>h$&ngr$7GKTNGD;DQOLNH9GCX+yKd2hGwNy(xpvMGjSQo!?V)gkvM1H>i4?JuHM3%!fK`9GRHdp~=9U#hVG2aUv54PI$ zdSWk;g6k;N4Df%~@7fHHF;X7*eHIhGf@`hW>)Bn4jl!ZVvoX}kUH_YgZZ&s2=X$pv z+H4%OFLN@hJ7xB?kd;S3Yp+H)J?5~HhKP& zS}G!4oU;-1Tb>h|KC^7bO8j?qoaFhR>f~iXiM_$zLO7pLB)9rI6@E>dCR6;rwz(gZ zqhT3A_`Qcx1)!W38;Bd`ZPW_$1WNB9h<>0by^A0NL~3p2vz7I-Dhk8|*J(EIquH61 z(!v9BGTj-zm{{1niU!vJ{(J05sV~)PA~?H_?$Zcog1}PruX~d}OY|Rp@W0sEEVALw z*bQ`4F5K5pG!3T3HQhV>X>w1LIHHbqTHLaBTGvK~**&+}wqG74MmnkR%QDWPcBqy^ zF%{&w3wD79Kp!PZiR_M5oBTJuaZjAv9nhZ(ZM2)+w(VXVnZ_Fxk%vNQvEMT9q*_(% z0jSDpYv#9Y=t~$Cv*!m+==j~ZPp*LB@Uh5XQsde5o0@39JinD*xEG5^E1#hqIiVFj zAG{dBxNk)xp3jmk0>c`{ybG}V27hFX@jucl%UFwZ31^Ynh4D9g%xT-A$;&Uce-UvN z2sSt~W^^3wWk_U#KQZR^i?E6l#u1K`mJgTh42tTO>o>zlcDfTlP_D6VS2FRL|41#Y?Af==FzcuVv2><{9 delta 1713 zcmb7EPj4GV6rY*>W3TOXLU7Z>B#{sa#7&_s6iQ2I8mlQPq(R^mQ6IXjJ==EOwbzj;1zRY{}esP9&_Lo-AQo;#0gM2$*&nrC>6xw#(roAn=fh#Uqby5bzt9h(?y7${N9y11rw;88^7O#||l0TqBjt#`9&! z_xx}8i6WBP8AF?*YJ;fcMHXI(eNTk#*l&AL?6$j#dZMG971aXLZEbc)H} z^lzpSU?@QCe;s@a^0u)=%kl@~?#>ME!6qkqvHbEJh7qF$rz z$BtSSDmH_$g(wzo?8Ko18x)*i=+~;Z?+6Vw^VaH@pRH{^Ny`$82nlmBIZ80m8ojNG zjLq|OQT}WW5fpD>j0!xDS_Q-~IdKNPN1VhGnreKIia3ixQ8CtU-nzM2F;s(v!g@)E zhzq!F(Bw%R#KZtjPH;}{WmfJk;D$Fr{P*06URzsVSINcO82%25p(J2Jbj zJMaE4bn!l-VP)by4Af7oYb2YA*__}q1VnhC*!NkwNVlh|Zu6m>vwSrd3G?}&;T3Z* z2z6U{-N0>nqm!Vz{<5_nBBzo5j_}YC=jt$vIl4Vrb)}iBf2F=9QaqNr&~!UZFE}|f zON&>TM^c$-+;#aZ*QnxLK&J+i{mOk0#u|>F(+wj(_QOs(J8xhOBS;!-`Bc{P^QIcf zak-mc`65*jRvUsHJAze5CVFwK(^*!-c^q4;0K(^(^QtTr_zi5qF`h*P4B#ely25XI zYThd^sy+$t8UWPfFNF(M8MGUazbyYMT-iAdR>~7^ghX$IaO<8!)wmagZk%X-Cl(iR z*9Ryr;gSZ&TwFo(BNQK_P=^ayi)$zb4bbAxA{$w95o5 z6Ga7AK9BXFNAb(3f**@!j=CFoViv(1zL*@q#zEwE)7D0cC~&ApJ*aDsd)8s?phq0` z$UXK19q#c8DHBeV?`AJyL;O^_!rHkQ{$|lVTbBc z?aPZx*;1om(-qQfoVFBxM3Q)5O+gILtxrf|DOL|3j!VWEC47yQA%%hXsy5w<|Aezw P%dR|bRGVrMmlE5##H7smK4Plr52VbAux|A zML9(U$P?Zy#aze5m@;`LuNtQzBSS4SBSV$=1GS@O!an>+ou`Xb%VP42s%TmJ< z&JfJN!cf9qsS7lm6=*nL2}cT33FqWCfmCU(A|9YIMS?)$7K?v?t6vc>i0=+0CjSx8 z5Yq+mB!EN|S9)qmP--_WGg`nMv=+If;WJqk5D>WBuE+W ' % str(current_thread().name) ic.configureOutput(prefix=threadName) -ic.disable() +#ic.disable() """"" Main entry point of the bot. Starts strategies according to config file, each in separate thread.