feat(mcp-deribit,mcp-bybit): add place_combo_order
Deribit: private/create_combo + place_order sul combo instrument → una sola crociata di spread invece di N (slippage atteso ridotto su strutture liquide). ACL core + leverage cap su tutti i leg. Bybit: place_batch_order su category=option (atomic multi-leg, 1 round-trip API). Reject su category != option (perp/linear non supportano batch nativo). orderLinkId auto-generato per leg. Tutti i test: deribit 48/48, bybit 123/123. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,7 @@ def mock_client():
|
||||
c.set_leverage = AsyncMock(return_value={"status": "leverage_set"})
|
||||
c.switch_position_mode = AsyncMock(return_value={"status": "mode_switched"})
|
||||
c.transfer_asset = AsyncMock(return_value={"transfer_id": "tx"})
|
||||
c.place_combo_order = AsyncMock(return_value={"orders": [{"order_id": "ord-1"}, {"order_id": "ord-2"}]})
|
||||
return c
|
||||
|
||||
|
||||
@@ -88,9 +89,28 @@ WRITE_ENDPOINTS = [
|
||||
("/tools/set_leverage", {"category": "linear", "symbol": "BTCUSDT", "leverage": 5}),
|
||||
("/tools/switch_position_mode", {"category": "linear", "symbol": "BTCUSDT", "mode": "hedge"}),
|
||||
("/tools/transfer_asset", {"coin": "USDT", "amount": 10.0, "from_type": "UNIFIED", "to_type": "FUND"}),
|
||||
("/tools/place_combo_order", {
|
||||
"category": "option",
|
||||
"legs": [
|
||||
{"symbol": "BTC-30APR26-75000-C-USDT", "side": "Buy", "qty": 0.01, "order_type": "Limit", "price": 5.0},
|
||||
{"symbol": "BTC-30APR26-80000-C-USDT", "side": "Sell", "qty": 0.01, "order_type": "Limit", "price": 3.0},
|
||||
],
|
||||
}),
|
||||
]
|
||||
|
||||
|
||||
def test_place_combo_order_min_legs(http):
|
||||
r = http.post(
|
||||
"/tools/place_combo_order",
|
||||
json={
|
||||
"category": "option",
|
||||
"legs": [{"symbol": "X", "side": "Buy", "qty": 1, "order_type": "Limit", "price": 1.0}],
|
||||
},
|
||||
headers=CORE,
|
||||
)
|
||||
assert r.status_code == 422
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path,payload", READ_ENDPOINTS)
|
||||
def test_read_core_ok(http, path, payload):
|
||||
r = http.post(path, json=payload, headers=CORE)
|
||||
|
||||
Reference in New Issue
Block a user