1+ from pprint import pformat
2+ from functools import partial
3+ from decimal import Decimal
4+ from typing import Callable
5+
16import tractor
27import trio
38from uuid import uuid4
49
10+ from piker .accounting import dec_digits
511from piker .clearing import (
612 open_ems ,
713 OrderClient ,
814)
9-
1015# TODO: we should probably expose these top level in this subsys?
1116from piker .clearing ._messages import (
1217 Order ,
1318 Status ,
1419 BrokerdPosition ,
1520)
21+ from piker .data import (
22+ Flume ,
23+ open_feed ,
24+ Feed ,
25+ ShmArray ,
26+ )
1627
1728
1829async def wait_for_order_status (
@@ -66,25 +77,24 @@ async def bot_main():
6677
6778 ll : str = 'info'
6879
69- # open an order ctl client
80+ # open an order ctl client, live data feed, trio nursery for
81+ # spawning an order trailer task
7082 client : OrderClient
7183 trades_stream : tractor .MsgStream
84+ feed : Feed
7285 accounts : list [str ]
7386
7487 fqme : str = 'btcusdt.usdtm.perp.binance'
7588
7689 async with (
7790
91+ # TODO: do this implicitly inside `open_ems()` ep below?
7892 # init and sync actor-service runtime
7993 maybe_open_pikerd (
8094 loglevel = ll ,
81- debug_mode = False ,
95+ debug_mode = True ,
8296
8397 ),
84- tractor .wait_for_actor (
85- 'pikerd' ,
86- ),
87-
8898 open_ems (
8999 fqme ,
90100 mode = 'paper' , # {'live', 'paper'}
@@ -97,14 +107,81 @@ async def bot_main():
97107 _ , # positions
98108 accounts ,
99109 _ , # dialogs
100- )
110+ ),
111+
112+ open_feed (
113+ fqmes = [fqme ],
114+ loglevel = ll ,
115+
116+ # TODO: if you want to throttle via downsampling
117+ # how many tick updates your feed received on
118+ # quote streams B)
119+ # tick_throttle=10,
120+ ) as feed ,
121+
122+ trio .open_nursery () as tn ,
101123 ):
102124 print (f'Loaded binance accounts: { accounts } ' )
103125
104- price : float = 30e3 # non-clearable
126+ flume : Flume = feed .flumes [fqme ]
127+ min_tick = Decimal (flume .mkt .price_tick )
128+ min_tick_digits : int = dec_digits (min_tick )
129+ price_round : Callable = partial (
130+ round ,
131+ ndigits = min_tick_digits ,
132+ )
133+
134+ quote_stream : trio .abc .ReceiveChannel = feed .streams ['binance' ]
135+
136+
137+ clear_margin : float = 0.9995
138+
139+ async def trailer (
140+ order : Order ,
141+ ):
142+ # ref shm OHLCV array
143+ s_shm : ShmArray = flume .rt_shm
144+ m_shm : ShmArray = flume .hist_shm
145+
146+ # NOTE: if you wanted to frame ticks by type like the
147+ # the quote throttler does.
148+ # from piker.data._sampling import frame_ticks
149+
150+ async for quotes in quote_stream :
151+ for fqme , quote in quotes .items ():
152+ for tick in quote .get ('ticks' , ()):
153+ print (
154+ f'{ fqme } ticks:\n { pformat (tick )} \n \n '
155+ f'last 1s OHLC:\n { s_shm .array [- 1 ]} \n '
156+ f'last 1m OHLC:\n { m_shm .array [- 1 ]} \n '
157+ )
158+
159+ # always keep live limit 2% below last
160+ # clearing price
161+ if tick ['type' ] == 'trade' :
162+ await client .update (
163+ uuid = order .oid ,
164+ price = price_round (
165+ clear_margin
166+ *
167+ tick ['price' ]
168+ ),
169+ )
170+ msgs , pps = await wait_for_order_status (
171+ trades_stream ,
172+ oid ,
173+ 'open'
174+ )
175+
176+
177+ # setup order dialog via first msg
105178 size : float = 0.01
179+ price : float = price_round (
180+ clear_margin
181+ *
182+ flume .first_quote ['last' ]
183+ )
106184 oid : str = str (uuid4 ())
107-
108185 order = Order (
109186 exec_mode = 'live' , # {'dark', 'live', 'alert'}
110187 action = 'buy' , # TODO: remove this from our schema?
@@ -116,6 +193,7 @@ async def bot_main():
116193 price = price ,
117194 brokers = ['binance' ],
118195 )
196+
119197 await client .send (order )
120198
121199 msgs , pps = await wait_for_order_status (
@@ -127,6 +205,9 @@ async def bot_main():
127205 assert not pps
128206 assert msgs [- 1 ].oid == oid
129207
208+ # start "trailer task" which tracks rt quote stream
209+ tn .start_soon (trailer , order )
210+
130211 try :
131212 # wait for ctl-c from user..
132213 await trio .sleep_forever ()
@@ -138,6 +219,7 @@ async def bot_main():
138219 oid ,
139220 'canceled'
140221 )
222+ raise
141223
142224
143225if __name__ == '__main__' :
0 commit comments