|
@@ -109,14 +109,14 @@ def descending_candles_response() -> DummyResponse:
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
-def instrument_response() -> DummyResponse:
|
|
|
|
|
|
|
+def instrument_response(symbol: str = "BTC-USDT-SWAP") -> DummyResponse:
|
|
|
return DummyResponse(
|
|
return DummyResponse(
|
|
|
{
|
|
{
|
|
|
"code": "0",
|
|
"code": "0",
|
|
|
"msg": "",
|
|
"msg": "",
|
|
|
"data": [
|
|
"data": [
|
|
|
{
|
|
{
|
|
|
- "instId": "BTC-USDT-SWAP",
|
|
|
|
|
|
|
+ "instId": symbol,
|
|
|
"instType": "SWAP",
|
|
"instType": "SWAP",
|
|
|
"ctVal": "0.001",
|
|
"ctVal": "0.001",
|
|
|
"lotSz": "1",
|
|
"lotSz": "1",
|
|
@@ -279,6 +279,42 @@ def instrument_with_non_finite_numeric_response() -> DummyResponse:
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def instrument_with_wrong_symbol_response() -> DummyResponse:
|
|
|
|
|
+ return DummyResponse(
|
|
|
|
|
+ {
|
|
|
|
|
+ "code": "0",
|
|
|
|
|
+ "msg": "",
|
|
|
|
|
+ "data": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "instId": "ETH-USDT-SWAP",
|
|
|
|
|
+ "instType": "SWAP",
|
|
|
|
|
+ "ctVal": "0.001",
|
|
|
|
|
+ "lotSz": "1",
|
|
|
|
|
+ "minSz": "1",
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def instrument_with_wrong_type_response() -> DummyResponse:
|
|
|
|
|
+ return DummyResponse(
|
|
|
|
|
+ {
|
|
|
|
|
+ "code": "0",
|
|
|
|
|
+ "msg": "",
|
|
|
|
|
+ "data": [
|
|
|
|
|
+ {
|
|
|
|
|
+ "instId": "BTC-USDT-SWAP",
|
|
|
|
|
+ "instType": "FUTURES",
|
|
|
|
|
+ "ctVal": "0.001",
|
|
|
|
|
+ "lotSz": "1",
|
|
|
|
|
+ "minSz": "1",
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def ticker_with_non_finite_numeric_response() -> DummyResponse:
|
|
def ticker_with_non_finite_numeric_response() -> DummyResponse:
|
|
|
return DummyResponse({"code": "0", "msg": "", "data": [{"instId": "BTC-USDT-SWAP", "last": "Infinity"}]})
|
|
return DummyResponse({"code": "0", "msg": "", "data": [{"instId": "BTC-USDT-SWAP", "last": "Infinity"}]})
|
|
|
|
|
|
|
@@ -364,7 +400,7 @@ def test_signed_demo_request_attaches_headers():
|
|
|
def test_signed_post_request_uses_actual_serialized_body_bytes():
|
|
def test_signed_post_request_uses_actual_serialized_body_bytes():
|
|
|
session = DummySession(
|
|
session = DummySession(
|
|
|
[
|
|
[
|
|
|
- instrument_response(),
|
|
|
|
|
|
|
+ instrument_response(symbol="ETH-USDT-SWAP"),
|
|
|
account_config_response(pos_mode="long_short_mode"),
|
|
account_config_response(pos_mode="long_short_mode"),
|
|
|
leverage_response(),
|
|
leverage_response(),
|
|
|
place_order_response(),
|
|
place_order_response(),
|
|
@@ -503,7 +539,7 @@ def test_place_demo_order_validates_size_before_setting_leverage():
|
|
|
def test_limit_short_order_uses_sell_and_short_pos_side():
|
|
def test_limit_short_order_uses_sell_and_short_pos_side():
|
|
|
session = DummySession(
|
|
session = DummySession(
|
|
|
[
|
|
[
|
|
|
- instrument_response(),
|
|
|
|
|
|
|
+ instrument_response(symbol="ETH-USDT-SWAP"),
|
|
|
account_config_response(pos_mode="long_short_mode"),
|
|
account_config_response(pos_mode="long_short_mode"),
|
|
|
leverage_response(),
|
|
leverage_response(),
|
|
|
place_order_response(),
|
|
place_order_response(),
|
|
@@ -642,6 +678,22 @@ def test_get_last_price_rejects_non_finite_numeric_field():
|
|
|
client.get_last_price(symbol="BTC-USDT-SWAP")
|
|
client.get_last_price(symbol="BTC-USDT-SWAP")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+def test_get_instrument_meta_rejects_mismatched_symbol():
|
|
|
|
|
+ session = DummySession([instrument_with_wrong_symbol_response()])
|
|
|
|
|
+ client = OkxClient(config=sample_config(), session=session)
|
|
|
|
|
+
|
|
|
|
|
+ with pytest.raises(ValueError, match="okx response payload is invalid"):
|
|
|
|
|
+ client.get_instrument_meta(symbol="BTC-USDT-SWAP")
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def test_get_instrument_meta_rejects_non_swap_type():
|
|
|
|
|
+ session = DummySession([instrument_with_wrong_type_response()])
|
|
|
|
|
+ client = OkxClient(config=sample_config(), session=session)
|
|
|
|
|
+
|
|
|
|
|
+ with pytest.raises(ValueError, match="okx response payload is invalid"):
|
|
|
|
|
+ client.get_instrument_meta(symbol="BTC-USDT-SWAP")
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def test_place_demo_order_raises_when_order_id_is_missing():
|
|
def test_place_demo_order_raises_when_order_id_is_missing():
|
|
|
session = DummySession(
|
|
session = DummySession(
|
|
|
[
|
|
[
|
|
@@ -676,6 +728,23 @@ def test_place_demo_order_rejects_invalid_leverage_before_okx():
|
|
|
assert session.request_paths == []
|
|
assert session.request_paths == []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+@pytest.mark.parametrize(
|
|
|
|
|
+ ("symbol", "leverage", "pos_side", "expected_message"),
|
|
|
|
|
+ [
|
|
|
|
|
+ ("BTC-USDT", 2, "long", "swap instrument is required"),
|
|
|
|
|
+ ("BTC-USDT-SWAP", 4, "long", "leverage is invalid"),
|
|
|
|
|
+ ("BTC-USDT-SWAP", 2, "net", "pos_side is invalid"),
|
|
|
|
|
+ ],
|
|
|
|
|
+)
|
|
|
|
|
+def test_set_leverage_validates_public_boundary_inputs(symbol, leverage, pos_side, expected_message):
|
|
|
|
|
+ session = DummySession([])
|
|
|
|
|
+ client = OkxClient(config=sample_config(), session=session)
|
|
|
|
|
+
|
|
|
|
|
+ with pytest.raises(ValueError, match=expected_message):
|
|
|
|
|
+ client.set_leverage(symbol=symbol, leverage=leverage, pos_side=pos_side)
|
|
|
|
|
+ assert session.request_paths == []
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
def test_place_demo_order_rejects_unknown_action_before_okx():
|
|
def test_place_demo_order_rejects_unknown_action_before_okx():
|
|
|
session = DummySession([])
|
|
session = DummySession([])
|
|
|
signal = TradeSignal(
|
|
signal = TradeSignal(
|