commit
1440e0b58f
|
@ -20,6 +20,7 @@ Interactive Brokers API backend.
|
||||||
Note the client runs under an ``asyncio`` loop (since ``ib_insync`` is
|
Note the client runs under an ``asyncio`` loop (since ``ib_insync`` is
|
||||||
built on it) and thus actor aware API calls must be spawned with
|
built on it) and thus actor aware API calls must be spawned with
|
||||||
``infected_aio==True``.
|
``infected_aio==True``.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from contextlib import asynccontextmanager as acm
|
from contextlib import asynccontextmanager as acm
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
|
@ -547,10 +548,12 @@ class Client:
|
||||||
# existing order so ask the client to create a new one (which it
|
# existing order so ask the client to create a new one (which it
|
||||||
# seems to do by allocating an int counter - collision prone..)
|
# seems to do by allocating an int counter - collision prone..)
|
||||||
reqid: int = None,
|
reqid: int = None,
|
||||||
) -> int:
|
|
||||||
"""Place an order and return integer request id provided by client.
|
|
||||||
|
|
||||||
"""
|
) -> int:
|
||||||
|
'''
|
||||||
|
Place an order and return integer request id provided by client.
|
||||||
|
|
||||||
|
'''
|
||||||
try:
|
try:
|
||||||
contract = self._contracts[symbol]
|
contract = self._contracts[symbol]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -1608,7 +1611,7 @@ async def handle_order_requests(
|
||||||
|
|
||||||
global _accounts2clients
|
global _accounts2clients
|
||||||
|
|
||||||
# request_msg: dict
|
request_msg: dict
|
||||||
async for request_msg in ems_order_stream:
|
async for request_msg in ems_order_stream:
|
||||||
log.info(f'Received order request {request_msg}')
|
log.info(f'Received order request {request_msg}')
|
||||||
|
|
||||||
|
|
|
@ -54,7 +54,8 @@ def mk_check(
|
||||||
action: str,
|
action: str,
|
||||||
|
|
||||||
) -> Callable[[float, float], bool]:
|
) -> Callable[[float, float], bool]:
|
||||||
"""Create a predicate for given ``exec_price`` based on last known
|
'''
|
||||||
|
Create a predicate for given ``exec_price`` based on last known
|
||||||
price, ``known_last``.
|
price, ``known_last``.
|
||||||
|
|
||||||
This is an automatic alert level thunk generator based on where the
|
This is an automatic alert level thunk generator based on where the
|
||||||
|
@ -62,7 +63,7 @@ def mk_check(
|
||||||
interest is; pick an appropriate comparison operator based on
|
interest is; pick an appropriate comparison operator based on
|
||||||
avoiding the case where the a predicate returns true immediately.
|
avoiding the case where the a predicate returns true immediately.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
# str compares:
|
# str compares:
|
||||||
# https://stackoverflow.com/questions/46708708/compare-strings-in-numba-compiled-function
|
# https://stackoverflow.com/questions/46708708/compare-strings-in-numba-compiled-function
|
||||||
|
|
||||||
|
@ -139,29 +140,32 @@ async def clear_dark_triggers(
|
||||||
book: _DarkBook,
|
book: _DarkBook,
|
||||||
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Core dark order trigger loop.
|
'''
|
||||||
|
Core dark order trigger loop.
|
||||||
|
|
||||||
Scan the (price) data feed and submit triggered orders
|
Scan the (price) data feed and submit triggered orders
|
||||||
to broker.
|
to broker.
|
||||||
|
|
||||||
"""
|
'''
|
||||||
# this stream may eventually contain multiple symbols
|
|
||||||
# XXX: optimize this for speed!
|
# XXX: optimize this for speed!
|
||||||
|
# TODO:
|
||||||
|
# - numba all this!
|
||||||
|
# - this stream may eventually contain multiple symbols
|
||||||
async for quotes in quote_stream:
|
async for quotes in quote_stream:
|
||||||
|
|
||||||
# TODO: numba all this!
|
|
||||||
|
|
||||||
# start = time.time()
|
# start = time.time()
|
||||||
for sym, quote in quotes.items():
|
for sym, quote in quotes.items():
|
||||||
|
execs = book.orders.get(sym, {})
|
||||||
execs = book.orders.get(sym, None)
|
|
||||||
if execs is None:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for tick in iterticks(
|
for tick in iterticks(
|
||||||
quote,
|
quote,
|
||||||
# dark order price filter(s)
|
# dark order price filter(s)
|
||||||
types=('ask', 'bid', 'trade', 'last')
|
types=(
|
||||||
|
'ask',
|
||||||
|
'bid',
|
||||||
|
'trade',
|
||||||
|
'last',
|
||||||
|
# 'dark_trade', # TODO: should allow via config?
|
||||||
|
)
|
||||||
):
|
):
|
||||||
price = tick.get('price')
|
price = tick.get('price')
|
||||||
ttype = tick['type']
|
ttype = tick['type']
|
||||||
|
@ -178,7 +182,6 @@ async def clear_dark_triggers(
|
||||||
) in (
|
) in (
|
||||||
tuple(execs.items())
|
tuple(execs.items())
|
||||||
):
|
):
|
||||||
|
|
||||||
if (
|
if (
|
||||||
not pred or
|
not pred or
|
||||||
ttype not in tf or
|
ttype not in tf or
|
||||||
|
@ -290,7 +293,8 @@ class TradesRelay:
|
||||||
|
|
||||||
|
|
||||||
class Router(BaseModel):
|
class Router(BaseModel):
|
||||||
'''Order router which manages and tracks per-broker dark book,
|
'''
|
||||||
|
Order router which manages and tracks per-broker dark book,
|
||||||
alerts, clearing and related data feed management.
|
alerts, clearing and related data feed management.
|
||||||
|
|
||||||
A singleton per ``emsd`` actor.
|
A singleton per ``emsd`` actor.
|
||||||
|
@ -521,7 +525,8 @@ async def translate_and_relay_brokerd_events(
|
||||||
router: Router,
|
router: Router,
|
||||||
|
|
||||||
) -> AsyncIterator[dict]:
|
) -> AsyncIterator[dict]:
|
||||||
'''Trades update loop - receive updates from ``brokerd`` trades
|
'''
|
||||||
|
Trades update loop - receive updates from ``brokerd`` trades
|
||||||
endpoint, convert to EMS response msgs, transmit **only** to
|
endpoint, convert to EMS response msgs, transmit **only** to
|
||||||
ordering client(s).
|
ordering client(s).
|
||||||
|
|
||||||
|
|
|
@ -155,8 +155,11 @@ class BrokerdOrder(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class BrokerdOrderAck(BaseModel):
|
class BrokerdOrderAck(BaseModel):
|
||||||
'''Immediate reponse to a brokerd order request providing
|
'''
|
||||||
the broker specifci unique order id.
|
Immediate reponse to a brokerd order request providing the broker
|
||||||
|
specific unique order id so that the EMS can associate this
|
||||||
|
(presumably differently formatted broker side ID) with our own
|
||||||
|
``.oid`` (which is a uuid4).
|
||||||
|
|
||||||
'''
|
'''
|
||||||
name: str = 'ack'
|
name: str = 'ack'
|
||||||
|
@ -203,7 +206,8 @@ class BrokerdStatus(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class BrokerdFill(BaseModel):
|
class BrokerdFill(BaseModel):
|
||||||
'''A single message indicating a "fill-details" event from the broker
|
'''
|
||||||
|
A single message indicating a "fill-details" event from the broker
|
||||||
if avaiable.
|
if avaiable.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
|
@ -227,9 +231,11 @@ class BrokerdFill(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class BrokerdError(BaseModel):
|
class BrokerdError(BaseModel):
|
||||||
'''Optional error type that can be relayed to emsd for error handling.
|
'''
|
||||||
|
Optional error type that can be relayed to emsd for error handling.
|
||||||
|
|
||||||
This is still a TODO thing since we're not sure how to employ it yet.
|
This is still a TODO thing since we're not sure how to employ it yet.
|
||||||
|
|
||||||
'''
|
'''
|
||||||
name: str = 'error'
|
name: str = 'error'
|
||||||
oid: str
|
oid: str
|
||||||
|
|
Loading…
Reference in New Issue