Skip to content

Commit 735c65a

Browse files
committed
Use ib.sleep for IBKR market data updates
1 parent 4ea6291 commit 735c65a

4 files changed

Lines changed: 52 additions & 6 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "quant-platform-kit"
7-
version = "0.7.14"
7+
version = "0.7.15"
88
description = "Shared broker adapters, domain models, execution ports, and notification utilities for QuantStrategyLab strategies."
99
readme = "README.md"
1010
requires-python = ">=3.9"

src/quant_platform_kit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""QuantPlatformKit public package surface."""
22

3-
__version__ = "0.7.14"
3+
__version__ = "0.7.15"
44

55
from .common.models import (
66
ExecutionReport,

src/quant_platform_kit/ibkr/market_data.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ def _set_market_data_type(ib: Any, market_data_type: int) -> None:
139139
setter(market_data_type)
140140

141141

142+
def _wait_for_market_data(ib: Any, wait_seconds: float) -> None:
143+
if not wait_seconds:
144+
return
145+
sleeper = getattr(ib, "sleep", None)
146+
if callable(sleeper):
147+
sleeper(wait_seconds)
148+
return
149+
import time as time_module
150+
151+
time_module.sleep(wait_seconds)
152+
142153

143154
def _collect_quote_snapshots(
144155
ib: Any,
@@ -151,10 +162,7 @@ def _collect_quote_snapshots(
151162
symbol: ib.reqMktData(contract, "", False, False)
152163
for symbol, contract in contracts
153164
}
154-
if wait_seconds:
155-
import time as time_module
156-
157-
time_module.sleep(wait_seconds)
165+
_wait_for_market_data(ib, wait_seconds)
158166

159167
as_of = datetime.utcnow()
160168
snapshots: dict[str, QuoteSnapshot] = {}

tests/test_ibkr_market_data.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,44 @@ def reqMktData(self, contract, *_args):
148148

149149

150150

151+
152+
def test_fetch_quote_snapshots_uses_ib_sleep_when_available(self) -> None:
153+
class DeferredTicker(FakeTicker):
154+
def __init__(self):
155+
super().__init__(-1.0, close=float("nan"), bid=None, ask=None)
156+
157+
class SleepAwareIB(FakeIB):
158+
def __init__(self):
159+
super().__init__()
160+
self.tickers = []
161+
self.sleep_calls = []
162+
163+
def reqMktData(self, contract, *_args):
164+
ticker = DeferredTicker()
165+
self.tickers.append(ticker)
166+
return ticker
167+
168+
def sleep(self, seconds):
169+
self.sleep_calls.append(seconds)
170+
for ticker in self.tickers:
171+
ticker.last = 101.8
172+
ticker.close = 101.8
173+
ticker.bid = 101.7
174+
ticker.ask = 101.9
175+
176+
ib = SleepAwareIB()
177+
snapshots = fetch_quote_snapshots(
178+
ib,
179+
{"SPY"},
180+
wait_seconds=0.1,
181+
retry_wait_seconds=0,
182+
attempts_per_data_type=1,
183+
stock_factory=FakeContract,
184+
)
185+
186+
self.assertEqual(snapshots["SPY"].last_price, 101.8)
187+
self.assertEqual(ib.sleep_calls, [0.1])
188+
151189
def test_fetch_quote_snapshots_retries_same_market_data_type_before_fallback(self) -> None:
152190
class RetrySameTypeIB(FakeIB):
153191
def __init__(self):

0 commit comments

Comments
 (0)