basic bot: set unix fileformat, add KBI handling to cancel order submission

basic_buy_bot
Tyler Goodlet 2023-06-26 13:43:59 -04:00
parent 63a6c6efde
commit 5690595064
1 changed files with 146 additions and 143 deletions

View File

@ -1,143 +1,146 @@
import tractor import tractor
import trio import trio
from uuid import uuid4 from uuid import uuid4
from piker.clearing import ( from piker.clearing import (
open_ems, open_ems,
OrderClient, OrderClient,
) )
# TODO: we should probably expose these top level in this subsys? # TODO: we should probably expose these top level in this subsys?
from piker.clearing._messages import ( from piker.clearing._messages import (
Order, Order,
Status, Status,
BrokerdPosition, BrokerdPosition,
) )
async def wait_for_order_status( async def wait_for_order_status(
trades_stream: tractor.MsgStream, trades_stream: tractor.MsgStream,
oid: str, oid: str,
expect_status: str, expect_status: str,
) -> tuple[ ) -> tuple[
list[Status], list[Status],
list[BrokerdPosition], list[BrokerdPosition],
]: ]:
''' '''
Wait for a specific order status for a given dialog, return msg flow Wait for a specific order status for a given dialog, return msg flow
up to that msg and any position update msgs in a tuple. up to that msg and any position update msgs in a tuple.
''' '''
# Wait for position message before moving on to verify flow(s) # Wait for position message before moving on to verify flow(s)
# for the multi-order position entry/exit. # for the multi-order position entry/exit.
status_msgs: list[Status] = [] status_msgs: list[Status] = []
pp_msgs: list[BrokerdPosition] = [] pp_msgs: list[BrokerdPosition] = []
async for msg in trades_stream: async for msg in trades_stream:
match msg: match msg:
case {'name': 'position'}: case {'name': 'position'}:
ppmsg = BrokerdPosition(**msg) ppmsg = BrokerdPosition(**msg)
pp_msgs.append(ppmsg) pp_msgs.append(ppmsg)
case { case {
'name': 'status', 'name': 'status',
}: }:
msg = Status(**msg) msg = Status(**msg)
status_msgs.append(msg) status_msgs.append(msg)
# if we get the status we expect then return all # if we get the status we expect then return all
# collected msgs from the brokerd dialog up to the # collected msgs from the brokerd dialog up to the
# exected msg B) # exected msg B)
if ( if (
msg.resp == expect_status msg.resp == expect_status
and msg.oid == oid and msg.oid == oid
): ):
return status_msgs, pp_msgs return status_msgs, pp_msgs
async def bot_main(): async def bot_main():
''' '''
Boot the piker runtime, open an ems connection, submit Boot the piker runtime, open an ems connection, submit
and process orders statuses in real-time. and process orders statuses in real-time.
''' '''
from piker.service import maybe_open_pikerd from piker.service import maybe_open_pikerd
port: int = 6666 # non-default pikerd addr port: int = 6666 # non-default pikerd addr
ll: str = 'info' ll: str = 'info'
reg_addr: tuple[str, int] = ('127.0.0.1', port) reg_addr: tuple[str, int] = ('127.0.0.1', port)
# open an order ctl client # open an order ctl client
client: OrderClient client: OrderClient
trades_stream: tractor.MsgStream trades_stream: tractor.MsgStream
accounts: list[str] accounts: list[str]
fqme: str = 'btcusdt.usdtm.perp.binance' fqme: str = 'btcusdt.usdtm.perp.binance'
async with ( async with (
# init and sync actor-service runtime # init and sync actor-service runtime
maybe_open_pikerd( maybe_open_pikerd(
registry_addr=reg_addr, # registry_addr=reg_addr,
loglevel=ll, loglevel=ll,
debug_mode=False, debug_mode=False,
), ),
tractor.wait_for_actor( tractor.wait_for_actor(
'pikerd', 'pikerd',
arbiter_sockaddr=reg_addr, # arbiter_sockaddr=reg_addr,
), ),
open_ems( open_ems(
fqme, fqme,
mode='paper', # {'live', 'paper'} mode='paper', # {'live', 'paper'}
loglevel=ll, loglevel=ll,
) as ( ) as (
client, # OrderClient client, # OrderClient
trades_stream, # tractor.MsgStream startup_pps, trades_stream, # tractor.MsgStream startup_pps,
_, # positions _, # positions
accounts, accounts,
_, # dialogs _, # dialogs
) )
): ):
print(f'Loaded binance accounts: {accounts}') print(f'Loaded binance accounts: {accounts}')
price: float = 10e3 # non-clearable price: float = 30e3 # non-clearable
size: float = 0.01 size: float = 0.01
oid: str = str(uuid4()) oid: str = str(uuid4())
order = Order( order = Order(
exec_mode='live', # {'dark', 'live', 'alert'} exec_mode='live', # {'dark', 'live', 'alert'}
action='buy', # TODO: remove this from our schema? action='buy', # TODO: remove this from our schema?
oid=oid, oid=oid,
account='paper', # use binance.usdtm for binance futes account='paper', # use binance.usdtm for binance futes
size=size, size=size,
symbol=fqme, symbol=fqme,
price=price, price=price,
brokers=['binance'], brokers=['binance'],
) )
await client.send(order) await client.send(order)
msgs, pps = await wait_for_order_status( msgs, pps = await wait_for_order_status(
trades_stream, trades_stream,
oid, oid,
'open' 'open'
) )
assert not pps assert not pps
assert msgs[-1].oid == oid assert msgs[-1].oid == oid
# cancel the open order try:
await client.cancel(oid) # wait for ctl-c from user..
msgs, pps = await wait_for_order_status( await trio.sleep_forever()
trades_stream, except KeyboardInterrupt:
oid, # cancel the open order
'canceled' await client.cancel(oid)
) msgs, pps = await wait_for_order_status(
trades_stream,
oid,
'canceled'
if __name__ == '__main__': )
trio.run(bot_main)
if __name__ == '__main__':
trio.run(bot_main)