feat(V2): IBKR client read methods + conid LRU cache

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-05-03 20:29:11 +00:00
parent f4f4e4efd7
commit 611a2695a9
2 changed files with 176 additions and 0 deletions
+44
View File
@@ -86,3 +86,47 @@ async def test_request_raises_on_persistent_401(httpx_mock: HTTPXMock, client):
)
with pytest.raises(IBKRAuthError, match="after retry"):
await client.get_account()
@pytest.mark.asyncio
async def test_resolve_conid_caches(httpx_mock: HTTPXMock, client):
httpx_mock.add_response(
url=re.compile(r".*/tickle"), json={"session": "x"},
)
httpx_mock.add_response(
url=re.compile(r".*/trsrv/secdef/search.*symbol=AAPL"),
json=[{"conid": 265598, "symbol": "AAPL", "secType": "STK"}],
)
cid = await client.resolve_conid("AAPL", "STK")
assert cid == 265598
cid2 = await client.resolve_conid("AAPL", "STK")
assert cid2 == 265598
@pytest.mark.asyncio
async def test_get_positions(httpx_mock: HTTPXMock, client):
httpx_mock.add_response(url=re.compile(r".*/tickle"), json={})
httpx_mock.add_response(
url=re.compile(r".*/portfolio/DU1234/positions/0"),
json=[{"conid": 265598, "position": 10, "mktPrice": 150}],
)
res = await client.get_positions()
assert isinstance(res, list)
assert res[0]["position"] == 10
@pytest.mark.asyncio
async def test_get_ticker_resolves_and_fetches(httpx_mock: HTTPXMock, client):
httpx_mock.add_response(url=re.compile(r".*/tickle"), json={})
httpx_mock.add_response(
url=re.compile(r".*/trsrv/secdef/search.*symbol=AAPL"),
json=[{"conid": 265598, "symbol": "AAPL", "secType": "STK"}],
)
httpx_mock.add_response(
url=re.compile(r".*/iserver/marketdata/snapshot"),
json=[{"31": "150.5", "84": "150.4", "86": "150.6", "conid": 265598}],
)
snap = await client.get_ticker("AAPL", "stocks")
assert snap["last_price"] == 150.5
assert snap["bid"] == 150.4
assert snap["ask"] == 150.6