diff --git a/README.md b/README.md index 7bdf00ce..74cb5eeb 100644 --- a/README.md +++ b/README.md @@ -222,6 +222,12 @@ settings. By default, production trading uses port 7496, and paper trading uses `read_only` is a boolean value that is used to enable trading. By default `read_only=True`, preventing trading. Use `read_only=False` to enable trading. +`is_fa` is a boolean value that is used to indicate if an account is a financial advisor (FA) account or a regular acccount. + By using `is_fa=True`, FA account configuration details are requested. By default `is_fa=False`. + If `is_fa=True` is used on a non-FA account, everything should work fine, but there will be error messages. + If `is_fa=False` (the default) is used on a FA account, FA account configurations will not be populated in tables such as + `accounts_groups`, `accounts_allocation_profiles`, and `accounts_aliases`. + `order_id_strategy` is the strategy used for obtaining new order ids. Order id algorithms have tradeoffs in execution time, support for multiple, concurrent sessions, and avoidance of TWS bugs. * `OrderIdStrategy.RETRY` (default) - Request a new order ID from TWS every time one is needed. Retry if TWS does not respond quickly. This usually avoids a TWS bug where it does not always respond. * `OrderIdStrategy.BASIC` - Request a new order ID from TWS every time one is needed. Does not retry, so it may deadlock if TWS does not respond. @@ -243,6 +249,14 @@ client = dhib.IbSessionTws(host="host.docker.internal", port=7497, read_only=Tru client.connect() ``` +For a read-only financial advisor (FA) session that does not allow trading: +```python +import deephaven_ib as dhib + +client = dhib.IbSessionTws(host="host.docker.internal", port=7497, read_only=True, is_fa=True) +client.connect() +``` + After `client.connect()` is called, TWS requires that the connection be accepted. ![](docs/assets/accept-connection.png) diff --git a/src/deephaven_ib/__init__.py b/src/deephaven_ib/__init__.py index ca936121..bd927b60 100644 --- a/src/deephaven_ib/__init__.py +++ b/src/deephaven_ib/__init__.py @@ -320,6 +320,7 @@ class IbSessionTws: download_short_rates (bool): True to download a short rates table. order_id_strategy (OrderIdStrategy): strategy for obtaining new order ids. read_only (bool): True to create a read only client that can not trade; false to create a read-write client that can trade. Default is true. + is_fa (bool): True for financial advisor accounts; false otherwise. Default is false. Tables: @@ -395,12 +396,12 @@ class IbSessionTws: _tables_raw: Dict[str, Table] _tables: Dict[str, Table] - def __init__(self, host: str = "", port: int = 7497, client_id: int = 0, download_short_rates: bool = True, order_id_strategy: OrderIdStrategy = OrderIdStrategy.RETRY, read_only:bool = True): + def __init__(self, host: str = "", port: int = 7497, client_id: int = 0, download_short_rates: bool = True, order_id_strategy: OrderIdStrategy = OrderIdStrategy.RETRY, read_only: bool = True, is_fa: bool = False): self._host = host self._port = port self._client_id = client_id self._read_only = read_only - self._client = IbTwsClient(download_short_rates=download_short_rates, order_id_strategy=order_id_strategy, read_only=read_only) + self._client = IbTwsClient(download_short_rates=download_short_rates, order_id_strategy=order_id_strategy, read_only=read_only, is_fa=is_fa) self._tables_raw = {f"raw_{k}": v for k, v in self._client.tables.items()} self._tables = dict(sorted(IbSessionTws._make_tables(self._tables_raw).items())) diff --git a/src/deephaven_ib/_tws/tws_client.py b/src/deephaven_ib/_tws/tws_client.py index a03126f7..6638333f 100644 --- a/src/deephaven_ib/_tws/tws_client.py +++ b/src/deephaven_ib/_tws/tws_client.py @@ -76,8 +76,9 @@ class IbTwsClient(EWrapper, EClient): _accounts_managed: Set[str] _order_id_strategy: OrderIdStrategy _read_only: bool + _is_fa: bool - def __init__(self, download_short_rates: bool, order_id_strategy: OrderIdStrategy, read_only: bool): + def __init__(self, download_short_rates: bool, order_id_strategy: OrderIdStrategy, read_only: bool, is_fa: bool): EWrapper.__init__(self) EClient.__init__(self, wrapper=self) self._table_writers = IbTwsClient._build_table_writers() @@ -91,6 +92,7 @@ def __init__(self, download_short_rates: bool, order_id_strategy: OrderIdStrateg self._accounts_managed = None self._order_id_strategy = order_id_strategy self._read_only = read_only + self._is_fa = is_fa tables = {name: tw.table() for (name, tw) in self._table_writers.items()} @@ -357,11 +359,14 @@ def _subscribe(self) -> None: """Subscribe to IB data.""" self.reqFamilyCodes() - self.requestFA(1) # request GROUPS. See FaDataTypeEnum. - #TODO: see https://github.com/deephaven-examples/deephaven-ib/issues/32 - #TODO: see https://github.com/deephaven-examples/deephaven-ib/issues/5 - # self.requestFA(2) # request PROFILE. See FaDataTypeEnum. - self.requestFA(3) # request ACCOUNT ALIASES. See FaDataTypeEnum. + + if self._is_fa: + self.requestFA(1) # request GROUPS. See FaDataTypeEnum. + #TODO: see https://github.com/deephaven-examples/deephaven-ib/issues/32 + #TODO: see https://github.com/deephaven-examples/deephaven-ib/issues/5 + # self.requestFA(2) # request PROFILE. See FaDataTypeEnum. + self.requestFA(3) # request ACCOUNT ALIASES. See FaDataTypeEnum. + self.request_account_summary("All") self.request_account_pnl("All") self.request_account_overview("All")