Skip to content

Commit be7523d

Browse files
authored
Version 0.21.0 (#230)
Add support for grouping Fix bug in market_close for builder-deployed perps
1 parent 8baad66 commit be7523d

File tree

4 files changed

+72
-14
lines changed

4 files changed

+72
-14
lines changed

examples/basic_tpsl.py

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,21 @@ def main():
1010
parser.add_argument("--is_buy", action="store_true")
1111
args = parser.parse_args()
1212

13-
address, info, exchange = example_utils.setup(constants.TESTNET_API_URL, skip_ws=True)
13+
_, _, exchange = example_utils.setup(constants.TESTNET_API_URL, skip_ws=True)
1414

1515
is_buy = args.is_buy
16-
# Place an order that should execute by setting the price very aggressively
17-
order_result = exchange.order("ETH", is_buy, 0.02, 2500 if is_buy else 1500, {"limit": {"tif": "Gtc"}})
16+
coin = "ETH"
17+
sz = 0.02
18+
px = 3500 if is_buy else 2500
19+
trigger_px = 2600 if is_buy else 3400
20+
sl_px = 2500 if is_buy else 3500
21+
# Place an order that should execute by setting the price very aggressively, the above prices were set when ETH was at 3000
22+
order_result = exchange.order(coin, is_buy, sz, px, {"limit": {"tif": "Gtc"}})
1823
print(order_result)
1924

2025
# Place a stop order
21-
stop_order_type = {"trigger": {"triggerPx": 1600 if is_buy else 2400, "isMarket": True, "tpsl": "sl"}}
22-
stop_result = exchange.order("ETH", not is_buy, 0.02, 1500 if is_buy else 2500, stop_order_type, reduce_only=True)
26+
stop_order_type = {"trigger": {"triggerPx": trigger_px, "isMarket": True, "tpsl": "sl"}}
27+
stop_result = exchange.order("ETH", not is_buy, sz, sl_px, stop_order_type, reduce_only=True)
2328
print(stop_result)
2429

2530
# Cancel the order
@@ -30,8 +35,8 @@ def main():
3035
print(cancel_result)
3136

3237
# Place a tp order
33-
tp_order_type = {"trigger": {"triggerPx": 1600 if is_buy else 2400, "isMarket": True, "tpsl": "tp"}}
34-
tp_result = exchange.order("ETH", not is_buy, 0.02, 2500 if is_buy else 1500, tp_order_type, reduce_only=True)
38+
tp_order_type = {"trigger": {"triggerPx": px, "isMarket": True, "tpsl": "tp"}}
39+
tp_result = exchange.order("ETH", not is_buy, sz, px, tp_order_type, reduce_only=True)
3540
print(tp_result)
3641

3742
# Cancel the order
@@ -41,6 +46,49 @@ def main():
4146
cancel_result = exchange.cancel("ETH", status["resting"]["oid"])
4247
print(cancel_result)
4348

49+
# Alternatively use grouping to place the parent order and child TP/SL in a single action
50+
orders = [
51+
{
52+
"coin": "ETH",
53+
"is_buy": is_buy,
54+
"sz": sz,
55+
"limit_px": px,
56+
"order_type": {"limit": {"tif": "Gtc"}},
57+
"reduce_only": False,
58+
},
59+
{
60+
"coin": "ETH",
61+
"is_buy": not is_buy,
62+
"sz": sz,
63+
"limit_px": px,
64+
"order_type": {
65+
"trigger": {
66+
"isMarket": True,
67+
"triggerPx": px,
68+
"tpsl": "tp",
69+
}
70+
},
71+
"reduce_only": True,
72+
},
73+
{
74+
"coin": coin,
75+
"is_buy": not is_buy,
76+
"sz": sz,
77+
"limit_px": sl_px,
78+
"order_type": {
79+
"trigger": {
80+
"isMarket": True,
81+
"triggerPx": trigger_px,
82+
"tpsl": "sl",
83+
}
84+
},
85+
"reduce_only": True,
86+
},
87+
]
88+
89+
resp = exchange.bulk_orders(orders, grouping="normalTpsl")
90+
print(resp)
91+
4492

4593
if __name__ == "__main__":
4694
main()

hyperliquid/exchange.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from hyperliquid.utils.signing import (
1212
CancelByCloidRequest,
1313
CancelRequest,
14+
Grouping,
1415
ModifyRequest,
1516
OidOrCloid,
1617
OrderRequest,
@@ -48,6 +49,10 @@
4849
)
4950

5051

52+
def _get_dex(coin: str) -> str:
53+
return coin.split(":")[0] if ":" in coin else ""
54+
55+
5156
class Exchange(API):
5257
# Default Max Slippage for Market Orders 5%
5358
DEFAULT_SLIPPAGE = 0.05
@@ -91,7 +96,7 @@ def _slippage_price(
9196
coin = self.info.name_to_coin[name]
9297
if not px:
9398
# Get midprice
94-
dex = coin.split(":")[0] if ":" in coin else ""
99+
dex = _get_dex(coin)
95100
px = float(self.info.all_mids(dex)[coin])
96101

97102
asset = self.info.coin_to_asset[coin]
@@ -132,15 +137,17 @@ def order(
132137
order["cloid"] = cloid
133138
return self.bulk_orders([order], builder)
134139

135-
def bulk_orders(self, order_requests: List[OrderRequest], builder: Optional[BuilderInfo] = None) -> Any:
140+
def bulk_orders(
141+
self, order_requests: List[OrderRequest], builder: Optional[BuilderInfo] = None, grouping: Grouping = "na"
142+
) -> Any:
136143
order_wires: List[OrderWire] = [
137144
order_request_to_order_wire(order, self.info.name_to_asset(order["coin"])) for order in order_requests
138145
]
139146
timestamp = get_timestamp_ms()
140147

141148
if builder:
142149
builder["b"] = builder["b"].lower()
143-
order_action = order_wires_to_order_action(order_wires, builder)
150+
order_action = order_wires_to_order_action(order_wires, builder, grouping)
144151

145152
signature = sign_l1_action(
146153
self.wallet,
@@ -243,7 +250,8 @@ def market_close(
243250
address = self.account_address
244251
if self.vault_address:
245252
address = self.vault_address
246-
positions = self.info.user_state(address)["assetPositions"]
253+
dex = _get_dex(coin)
254+
positions = self.info.user_state(address, dex)["assetPositions"]
247255
for position in positions:
248256
item = position["position"]
249257
if coin != item["coin"]:

hyperliquid/utils/signing.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Any
2+
13
import time
24
from decimal import Decimal
35

@@ -496,11 +498,11 @@ def order_request_to_order_wire(order: OrderRequest, asset: int) -> OrderWire:
496498
return order_wire
497499

498500

499-
def order_wires_to_order_action(order_wires, builder=None):
501+
def order_wires_to_order_action(order_wires: list[OrderWire], builder: Any = None, grouping: Grouping = "na") -> Any:
500502
action = {
501503
"type": "order",
502504
"orders": order_wires,
503-
"grouping": "na",
505+
"grouping": grouping,
504506
}
505507
if builder:
506508
action["builder"] = builder

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "poetry.core.masonry.api"
55

66
[tool.poetry]
77
name = "hyperliquid-python-sdk"
8-
version = "0.20.1"
8+
version = "0.21.0"
99
description = "SDK for Hyperliquid API trading with Python."
1010
readme = "README.md"
1111
authors = ["Hyperliquid <hello@hyperliquid.xyz>"]

0 commit comments

Comments
 (0)