feat(V2): IBKR simple write tools (place/amend/cancel/close)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -45,3 +45,44 @@ async def test_get_tick_uses_cache_or_subscribes():
|
||||
)
|
||||
assert res["last_price"] == 99.5
|
||||
ws.subscribe_tick.assert_awaited_once_with(42)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_place_order_enforces_leverage():
|
||||
client = MagicMock()
|
||||
client.get_account = AsyncMock(return_value={
|
||||
"netliquidation": {"amount": 10000},
|
||||
})
|
||||
client.place_order = AsyncMock(return_value={"order_id": "O1"})
|
||||
creds = {"max_leverage": 2}
|
||||
res = await t.place_order(
|
||||
client, t.PlaceOrderReq(symbol="AAPL", side="buy", qty=10),
|
||||
creds=creds, last_price=100.0,
|
||||
)
|
||||
assert res["order_id"] == "O1"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cancel_order_calls_client():
|
||||
client = MagicMock()
|
||||
client.cancel_order = AsyncMock(return_value={"order_id": "O1", "canceled": True})
|
||||
res = await t.cancel_order(client, t.CancelOrderReq(order_id="O1"))
|
||||
assert res["canceled"] is True
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_place_order_rejects_excessive_leverage():
|
||||
from fastapi import HTTPException
|
||||
client = MagicMock()
|
||||
client.get_account = AsyncMock(return_value={
|
||||
"netliquidation": {"amount": 1000},
|
||||
})
|
||||
creds = {"max_leverage": 2}
|
||||
# Order notional = 100*100 = 10000 vs equity 1000 → ratio 10x >> 2x cap → 403
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await t.place_order(
|
||||
client, t.PlaceOrderReq(symbol="AAPL", side="buy", qty=100),
|
||||
creds=creds, last_price=100.0,
|
||||
)
|
||||
assert exc_info.value.status_code == 403
|
||||
assert exc_info.value.detail["error"] == "LEVERAGE_CAP_EXCEEDED"
|
||||
|
||||
Reference in New Issue
Block a user