From 99eabe34c928b39381e4f717608ad62e7986fe69 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Mon, 6 Jun 2022 14:51:18 -0400 Subject: [PATCH] Convert `ib` backend into sub-package The single-file module was getting way out of hand size-wise with the new flex report parsing stuff so this starts the process of breaking things up into smaller modules oriented around trade, data, and ledger related endpoints. Add support for backends to declare sub-modules to enable in a `__enable_modules__: list[str]` module var which is parsed by the daemon spawning code passed to `tractor`'s `enable_modules: list[str]` input. --- piker/_daemon.py | 12 +++++- piker/brokers/ib/__init__.py | 54 +++++++++++++++++++++++++++ piker/brokers/{ib.py => ib/client.py} | 30 +++++---------- 3 files changed, 74 insertions(+), 22 deletions(-) create mode 100644 piker/brokers/ib/__init__.py rename piker/brokers/{ib.py => ib/client.py} (99%) diff --git a/piker/_daemon.py b/piker/_daemon.py index 999b8fce..e732a15d 100644 --- a/piker/_daemon.py +++ b/piker/_daemon.py @@ -426,9 +426,19 @@ async def spawn_brokerd( # ask `pikerd` to spawn a new sub-actor and manage it under its # actor nursery + modpath = brokermod.__name__ + broker_enable = [modpath] + for submodname in getattr( + brokermod, + '__enable_modules__', + [], + ): + subpath = f'{modpath}.{submodname}' + broker_enable.append(subpath) + portal = await _services.actor_n.start_actor( dname, - enable_modules=_data_mods + [brokermod.__name__], + enable_modules=_data_mods + broker_enable, loglevel=loglevel, debug_mode=_services.debug_mode, **tractor_kwargs diff --git a/piker/brokers/ib/__init__.py b/piker/brokers/ib/__init__.py new file mode 100644 index 00000000..877b0667 --- /dev/null +++ b/piker/brokers/ib/__init__.py @@ -0,0 +1,54 @@ +# piker: trading gear for hackers +# Copyright (C) Tyler Goodlet (in stewardship for pikers) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +""" +Interactive Brokers API backend. + +Sub-modules within break into the core functionalities: + +- ``broker.py`` part for orders / trading endpoints +- ``data.py`` for real-time data feed endpoints + +- ``client.py`` for the core API machinery which is ``trio``-ized + wrapping around ``ib_insync``. + +- ``report.py`` for the hackery to build manual pp calcs + to avoid ib's absolute bullshit FIFO style position + tracking.. + +""" +from .client import ( + get_client, + open_history_client, + open_symbol_search, + stream_quotes, + trades_dialogue, +) + +# tractor RPC enable arg +__enable_modules__: list[str] = [ + 'client', +] + +# passed to ``tractor.ActorNursery.start_actor()`` +_spawn_kwargs = { + 'infect_asyncio': True, +} + +# annotation to let backend agnostic code +# know if ``brokerd`` should be spawned with +# ``tractor``'s aio mode. +_infect_asyncio: bool = True diff --git a/piker/brokers/ib.py b/piker/brokers/ib/client.py similarity index 99% rename from piker/brokers/ib.py rename to piker/brokers/ib/client.py index 9b32521f..cbbbd8d4 100644 --- a/piker/brokers/ib.py +++ b/piker/brokers/ib/client.py @@ -15,11 +15,8 @@ # along with this program. If not, see . """ -Interactive Brokers API backend. - -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 -``infected_aio==True``. +``ib`` core API client machinery; mostly sane wrapping around +``ib_insync``. """ from __future__ import annotations @@ -61,12 +58,12 @@ import numpy as np import pendulum -from .. import config -from ..log import get_logger, get_console_log -from ..data._source import base_ohlc_dtype -from ..data._sharedmem import ShmArray -from ._util import SymbolNotFound, NoData -from ..clearing._messages import ( +from piker import config +from piker.log import get_logger, get_console_log +from piker.data._source import base_ohlc_dtype +from piker.data._sharedmem import ShmArray +from .._util import SymbolNotFound, NoData +from piker.clearing._messages import ( BrokerdOrder, BrokerdOrderAck, BrokerdStatus, BrokerdPosition, BrokerdCancel, BrokerdFill, BrokerdError, @@ -75,10 +72,7 @@ from ..clearing._messages import ( log = get_logger(__name__) -# passed to ``tractor.ActorNursery.start_actor()`` -_spawn_kwargs = { - 'infect_asyncio': True, -} + _time_units = { 's': ' sec', 'm': ' mins', @@ -118,12 +112,6 @@ _search_conf = { } -# annotation to let backend agnostic code -# know if ``brokerd`` should be spawned with -# ``tractor``'s aio mode. -_infect_asyncio: bool = True - - # overrides to sidestep pretty questionable design decisions in # ``ib_insync``: class NonShittyWrapper(Wrapper):