Logo
新用户订阅 RPC,首月享 6.5 折优惠查看优惠
OnFinality Learn
RPC 故障排查阅读约 12 分钟

Hyperliquid API 错误处理:解读订单拒绝、保证金与预言机检查

解读 Hyperliquid /info 和 /exchange 的订单拒绝:保证金、风险限额、未平仓合约上限、预言机价格检查以及仅做市商保护。

TL;DR

Hyperliquid 的 REST API 将只读的 /info 与签名的 /exchange 操作分开。当订单失败时,响应包含状态为“rejected”的订单状态以及人类可读的原因和数字代码,或一个“error”对象。本文解释了保证金、风险、未平仓合约、预言机价格和执行模式拒绝背后的机制,并提供了一个可复现的客户端来捕获和解读这些拒绝。

直接回答:Hyperliquid API 中订单拒绝的位置

当您向 Hyperliquid 的签名 /exchange 端点提交订单时,API 不会因业务层面的失败而抛出 HTTP 错误。相反,响应包含一个 order statuses 数组。每个元素对应您发送的一个订单;失败的订单具有 status: "rejected"statuses_reason 字符串,例如 InsufficientMarginPriceOutOfBand。对于包装失败(例如格式错误的请求或交易禁令),响应是一个 JSON 对象,包含 response 字符串,如 "Order price is above the maximum allowed price for this asset"error 对象。这在 Hyperliquid 文档 中有记录,并且与 HTTP 429 速率限制错误不同,后者在我们的 Hyperliquid API 速率限制 指南中有所介绍。

关键见解:您必须检查订单状态和原因,而不仅仅是 HTTP 状态代码。200 响应仍然可能包含被拒绝的订单。本文解读了您在生产环境中会遇到的各种拒绝类型,并展示了如何以编程方式处理它们。

机制:Hyperliquid 在接受订单前如何验证

Hyperliquid 的撮合引擎在订单能够挂单或成交之前会执行一系列检查。这些检查在服务器端强制执行,与客户端验证分开。引擎会评估您的账户权益、当前头寸、杠杆、未平仓合约和预言机价格。如果任何检查失败,订单将被拒绝并附上具体原因。

只读的 /info 端点提供了您进行预验证所需的上下文:/info/meta 返回资产元数据,包括 maxLeverageszDecimalsmaxSz/info/clearinghouseState 提供您的账户权益和保证金摘要;/info/assetCtxs 提供当前的预言机价格和未平仓合约。然后,签名的 /exchange 端点以原子方式应用最终检查。

Hyperliquid 的文档在 错误部分 中列出了错误代码和原因。独立的集成,如 Hyperliquid Python SDKccxt,将这些映射到异常,但理解原始字符串对于健壮的自动化至关重要。

拒绝类型及其含义

生产客户端会遇到几种拒绝类型。每种类型对应一个特定的原因字符串或响应文本。下表总结了它们;确切的字符串在 Hyperliquid 文档中有记录,并且可能会演变。

保证金和权益检查InsufficientMarginInsufficientAccountValue 表示您的账户没有足够的权益或保证金来支持订单的名义价值。这通常发生在您在没有增加资金的情况下增加头寸,或者未实现亏损减少了权益时。

风险和杠杆检查RiskLimitsMaxPositionSize 表示订单将超过您的风险限额或资产的最大头寸大小。当您请求的杠杆超过 /info/meta 中资产的 maxLeverage 时,会出现 Leverage too high

未平仓合约上限 – 当资产未平仓合约达到上限时,会出现 Cannot increase position when open interest is at cap(或类似)的原因。这是市场范围的保护,不是账户级别的问题。

预言机价格检查PriceOutOfBand 或响应字符串 "Order price is above the maximum allowed price for this asset" 表示您的限价与当前预言机价格相差太远。Hyperliquid 强制执行最大偏移以防止错误打印。

执行模式保护PostOnlyWouldTakeLiquidity 表示您的仅做市商订单会与现有订单成交,因此被拒绝以保持仅做市商的意图。当订单会增加头寸而不是减少头寸时,会发生仅减仓违规。

一个关键的实际区别在于被直接拒绝的订单与被接受但后来失败的订单。当Hyperliquid的API返回拒绝时,响应数组中的订单状态条目表示该订单从未被放置;该订单的任何现有挂单或工作状态保持不变。相比之下,成功提交会导致“挂单”或“已成交”状态,对于多腿或部分成交,数组可能包含每条腿的多个条目。因此,调用者不应将数组视为全有或全无:单个拒绝并不意味着其他腿没有执行,部分成交也不意味着整个订单被拒绝。这种粒度对于准确的记账以及决定是否重试、取消或调整剩余腿至关重要。

  • 始终检查 statuses_reason 字段以获取每个订单的失败信息。
  • 对于包装错误,解析 response 字符串或 error 对象。
  • 不要依赖 HTTP 状态代码;200 可能包含被拒绝的订单。

可复现的客户端:捕获并解读拒绝

以下 Python 脚本使用官方 Hyperliquid SDK 提交一个故意不可能的价格(例如,高于预言机 10%)的订单,以触发 PriceOutOfBand 拒绝。它打印订单状态、原因和数字代码。将私钥替换为测试网私钥,并使用测试网 API URL https://api.hyperliquid-testnet.xyz,如 Hyperliquid 文档 所述。

此脚本是安全的,因为它使用测试网和不可能的价格,因此没有真实资金风险。切勿在主网上使用真实余额运行此类测试。

import json
from hyperliquid.exchange import Exchange
from hyperliquid.info import Info
from eth_account import Account

# Testnet configuration - replace with your testnet private key
account = Account.from_key('0x...')  # your testnet private key
base_url = 'https://api.hyperliquid-testnet.xyz'
info = Info(base_url, skip_ws=True)
exchange = Exchange(account, base_url)

# Fetch asset metadata and oracle price
meta = info.meta()
asset = 'BTC'
asset_index = next(i for i, a in enumerate(meta['universe']) if a['name'] == asset)
oracle_price = float(info.all_mids()[asset])

# Intentionally impossible price: 10% above oracle
bad_price = round(oracle_price * 1.10, 1)

# Build and submit order
order = {
    "coin": asset,
    "is_buy": True,
    "sz": 0.001,
    "limit_px": bad_price,
    "order_type": {"limit": {"tif": "Gtc"}},
    "reduce_only": False
}
result = exchange.order(order)
print(json.dumps(result, indent=2))

# Expected output (testnet, may vary):
# {
#   "status": "ok",
#   "response": {
#     "type": "order",
#     "data": {
#       "statuses": [
#         {
#           "resting": {"oid": 123456},
#           "status": "rejected",
#           "statuses_reason": "PriceOutOfBand"
#         }
#       ]
#     }
#   }
# }

结果表:将拒绝原因映射到操作

使用下表作为起点。确切的原因字符串在 Hyperliquid 文档中有记录;请根据您的 SDK 版本进行验证。当您运行客户端时,填写“在您的设置中观察到”列。

  • | 原因/响应 | 类型 | 推荐操作 | 在您的设置中观察到 |
  • |---|---|---|---|
  • | InsufficientMargin | 保证金 | 减少规模或添加资金;通过 /info/clearinghouseState 检查权益 | |
  • | RiskLimits | 风险 | 减少头寸规模或等待风险限额重置 | |
  • | Cannot increase position when open interest is at cap | 未平仓合约 | 取消并等待;考虑其他资产 | |
  • | PriceOutOfBand | 预言机 | 将价格限制在预言机允许的范围内 | |
  • | PostOnlyWouldTakeLiquidity | 执行模式 | 取消并作为可成交订单重新提交或调整价格 | |
  • | ReduceOnly would increase position | 执行模式 | 检查您的 reduce_only 标志和当前头寸 | |

失败/修复清单:在生产环境中处理拒绝

当您的机器人收到拒绝时,请按照以下清单决定下一步操作。目标是避免盲目重试,这可能会放大损失或导致重复拒绝。

1. 解析拒绝原因。 从每个订单状态中提取 statuses_reason。对于包装错误,解析 response 字符串。

2. 预先检查保证金和名义价值。 在提交之前,查询 /info/clearinghouseState 以确认可用保证金。将订单的名义价值与您的权益以及 /info/meta 中资产的 maxLeverage 进行比较。

3. 限制在预言机范围内。 如果您收到 PriceOutOfBand,从 /info/assetCtxs 获取当前预言机价格,并将您的限价设置在允许的偏移内(例如,大多数资产为 5%,但请查阅文档)。

4. 检查仅做市商和仅减仓标志。 如果您收到 PostOnlyWouldTakeLiquidity,要么取消并作为常规限价订单重新提交,要么将价格调整到价差的另一侧。对于仅减仓违规,请验证您当前的头寸和订单方向。

5. 使用新价格重新提交或取消。 对于与价格相关的拒绝,使用更正后的价格重新提交。对于保证金或风险拒绝,在调整账户或订单规模之前不要重试。

6. 记录并发出警报。 记录完整的拒绝负载以进行调试。使用结构化日志按原因跟踪拒绝频率。

为了生产环境的稳健性,考虑采用保守的重试并升级策略,以避免不必要的风险。首先,在提交前将客户端的名义金额限制在当前标记价格带内,如Hyperliquid的API指南所述,以减少价格超出范围拒绝的可能性。如果仍然发生价格超出范围拒绝,请取消任何挂单并以带内更新价格重新提交。对于所有其他硬拒绝(例如与保证金、风险或未平仓合约相关的拒绝),不要静默重试;相反,将其映射到本地警报或错误日志以供人工审查。这种方法确保暂时性问题自动处理,而持续性问题则升级处理,并且与Hyperliquid的记录行为一致。请根据官方文档和您自己的测试验证这些建议,以针对您的特定用例进行调整。

局限性与权衡

Hyperliquid 的拒绝原因是人类可读的,但不能保证在协议升级中保持稳定。文档指出错误代码可能会更改;始终优雅地处理未知原因。

预言机价格范围并非对所有资产都是固定的百分比;它可能会变化。检查每个资产的 metaassetCtxs,不要硬编码通用偏移。

未平仓合约上限是动态的,并且可能随着头寸的开立和平仓而变化。由于未平仓合约上限导致的拒绝可能是暂时的;短暂延迟后重试可能会成功,但避免激进的重试。

本指南侧重于业务层面的拒绝。有关 HTTP 层面的问题,如超时和速率限制,请参阅我们的 Hyperliquid RPC 超时Hyperliquid API 速率限制 指南。

后续步骤:构建健壮的集成

既然您了解了拒绝的各个方面,就可以强化您的交易机器人。首先实现上述预检查逻辑,然后添加一个拒绝处理程序,将每个原因映射到操作。使用测试网模拟各种场景——保证金不足、仅做市商将成交、价格超出范围——以验证您的处理程序。

有关完整的 Hyperliquid 设置,请查看我们的 Hyperliquid 网络概述Hyperliquid 端点(RPC 助手) 以选择可靠的端点。如果您使用 WebSocket 流进行实时更新,请参阅我们的 Hyperliquid WebSocket 订阅和重连 指南。对于历史数据需求,请查看 查询 Hyperliquid 历史市场数据

如果您在 OnFinality 上构建,我们的 API 服务 提供对 Hyperliquid 和其他网络的托管访问。有关计划,请参阅 定价。有关更多故障排除指南,请访问 OnFinality Learn 中心

永远不用担心基础设施

OnFinality 消除了 DevOps 的繁重工作,让您能够更聪明、更快地构建。

开始