diff --git a/src/quant_platform_kit/ibkr/market_data.py b/src/quant_platform_kit/ibkr/market_data.py index be36ec1..fa650a0 100644 --- a/src/quant_platform_kit/ibkr/market_data.py +++ b/src/quant_platform_kit/ibkr/market_data.py @@ -253,7 +253,9 @@ def fetch_quote_snapshots( attempts_per_data_type = max(int(attempts_per_data_type or 1), 1) setter = getattr(ib, "reqMarketDataType", None) - market_data_types = (1, 2, 4) if callable(setter) else (1,) + # Prefer delayed data before live data so accounts without live subscriptions do + # not emit noisy IBKR 10089 permission errors before falling back. + market_data_types = (3, 4, 1, 2) if callable(setter) else (1,) try: for market_data_type in market_data_types: diff --git a/tests/test_ibkr_market_data.py b/tests/test_ibkr_market_data.py index 37f642e..e140e2e 100644 --- a/tests/test_ibkr_market_data.py +++ b/tests/test_ibkr_market_data.py @@ -237,7 +237,7 @@ def reqMktData(self, contract, *_args): key = (self.market_data_type, contract.symbol) attempt = self.market_data_attempts.get(key, 0) self.market_data_attempts[key] = attempt + 1 - if self.market_data_type == 1 and attempt == 0: + if self.market_data_type == 3 and attempt == 0: return FakeTicker(-1.0, close=float("nan"), bid=None, ask=None) return FakeTicker(101.8, close=101.8, bid=101.7, ask=101.9) @@ -252,7 +252,8 @@ def reqMktData(self, contract, *_args): ) self.assertEqual(snapshots["SPY"].last_price, 101.8) - self.assertEqual(ib.market_data_attempts[(1, "SPY")], 2) + self.assertEqual(ib.market_data_attempts[(3, "SPY")], 2) + self.assertEqual(ib.market_data_type_calls, [3, 1]) self.assertNotIn(2, ib.market_data_type_calls) self.assertNotIn(4, ib.market_data_type_calls) @@ -269,9 +270,9 @@ def reqMarketDataType(self, market_data_type): def reqMktData(self, contract, *_args): self.last_market_data_contract = contract - if self.market_data_type == 1: + if self.market_data_type == 3: return FakeTicker(-1.0, close=float("nan"), bid=None, ask=None) - if self.market_data_type == 2: + if self.market_data_type == 4: return FakeTicker(-1.0, close=float("nan"), bid=None, ask=None) return FakeTicker(-1.0, close=101.8, bid=None, ask=None) @@ -284,7 +285,7 @@ def reqMktData(self, contract, *_args): ) self.assertEqual(snapshots["SPY"].last_price, 101.8) - self.assertEqual(ib.market_data_type_calls, [1, 2, 4, 1]) + self.assertEqual(ib.market_data_type_calls, [3, 4, 1, 1]) if __name__ == "__main__":