做市商
Aftermath 永续合约做市商集成指南——重报价循环、数据格式、实时行情与风控。
Aftermath 永续合约没有指定做市商计划,没有特殊返佣,也没有延迟优势。任何人都可以在这里做市。
技术集成问题请加入我们的 Discord,或在 X 上私信我们。
API 基础信息
API 前缀
https://v2-preview.aftermath.finance/api/...
Agent skills
OpenAPI 规范是字段名和类型的唯一权威来源。请从规范生成类型定义,不要手写请求体。
推荐的集成方式
我们推荐使用永续合约原生 REST 接口(/api/perpetuals/account/transactions/*),而非 CCXT 层。原生接口让您完全掌控 Gas 管理,并可使用 PTB(可编程交易块)等 Sui 原生特性。
所有原生接口都返回一个 TxKindResponse,其中包含 base64 编码的 TransactionKind。您需要将其解码、包装成完整的 Transaction、用钱包签名,再通过您的 Sui 客户端提交。
核心接口
取消并下单(POST /api/perpetuals/account/transactions/cancel-and-place-orders)
这是做市商的主力接口。它在单个 PTB 内原子性地取消现有订单并放置新订单,比分开发送取消和下单交易省下可观的 Gas。两个操作之间不存在中间状态,重报价过程中盘口深度永远不会归零。刷新报价或管理订单网格,就用这个接口。
放置限价单(POST /api/perpetuals/account/transactions/place-limit-order)
用于单笔下单。支持在同一笔交易中内联附加 SL/TP(止损/止盈)。
放置市价单(POST /api/perpetuals/account/transactions/place-market-order)
以市价立即成交,同样支持内联 SL/TP。
放置阶梯订单(POST /api/perpetuals/account/transactions/place-scale-order)
在单笔交易中把仓位规模分布到一个价格区间上。适合 DCA(定投)式建仓、流动性阶梯,或把风险分散到多个价位。
TWAP(时间加权平均价格)订单(POST /api/perpetuals/account/transactions/create-twap-orders、edit-twap-orders、cancel-twap-orders)
将一定规模的成交安排在一段时间内分批执行。已排期和已处理的数量可通过 POST /api/perpetuals/account/twap-order-datas 读取。适合逐步消化累积的库存,而不必一次性付出价差成本。
重报价循环
cancel-and-place-orders 是您每天要调用几千次的接口,值得把每个字段都弄清楚。
accountId
数字账户 ID,以 BigInt 字符串发送("123n")。从金库报价时改用 vaultId。
accountCapId
可选,授权该交易的账户权限凭证对象 ID。
walletAddress
必填。接收退回的 Gas 币。
marketId
必填。报价所在的清算所。
orderIdsToCancel
链上分配的订单 ID,以 BigInt 字符串表示。省略则不取消任何订单。
clientOrderIdsToCancel
按您自己的 ID 取消,而非链上 ID。可与 orderIdsToCancel 组合使用。
shouldAbortOnMissingId
默认为 false。见下文——这个默认值正是您想要的。
ordersToPlace
{ side, price, size, clientOrderId? } 数组。省略则不下任何单。
orderType
整批订单的执行类型。见下表。
reduceOnly
若为 true,所下订单永远不会增加仓位规模。
hasPosition
必填。账户当前在该市场是否持有仓位。
expiryTimestamp
可选,所下订单的到期时间(毫秒时间戳)。
leverage
可选,为所下订单覆盖杠杆设置。
shouldDeallocateFreeCollateral
若为 true,在同一笔交易内把未支撑仓位的保证金清扫回钱包。
sponsor
{ walletAddress },用于 Gas 池代付。
builderCode
{ integratorId, integratorFee }——仅当您以集成商身份路由订单流时才需要。
txKind
已有的 base64 TransactionKind,在其基础上扩展,把重报价合入您自己更大的 PTB。
订单类型
orderType 作用于 ordersToPlace 中的每一笔订单:
0
GTC
挂在订单簿上,直到成交或被取消。
1
FOK
必须一次全部成交,否则整单取消。
2
Post-Only
仅在不会立即撮合的情况下才加入订单簿;若会吃掉流动性则被拒绝。
3
IOC
立即成交能成交的部分,其余取消。
做市商应使用 2 报价。它保证您永远不会跨越盘口,也永远不用付吃单方 (Taker) 费用。
客户端订单 ID
每笔订单都可携带可选的 clientOrderId——由您自选的 u64,以 BigInt 字符串发送。给报价打上自己的 ID,就能通过 clientOrderIdsToCancel 取消,全程不必读回链上分配的 ID。
这从重报价循环中省去了一次往返。不再是下单 → 读回订单 ID → 按链上 ID 取消 → 再下单,而是始终针对策略已知的 ID 报价。客户端订单 ID 也会出现在仓位状态的 pendingOrders 和订单数据流中,因此可以直接用自己的账本核对成交。
place-limit-order 接受 clientOrderId;place-scale-order 以 clientOrderIds 形式接受。
ID 缺失默认不算错误
您准备取消的订单,可能在决策与交易上链之间的窗口里已经成交或过期。shouldAbortOnMissingId: false(默认值)时,交易会容忍缺失的 ID:其余取消操作和所有新订单照常执行。
只有当"部分生效的重报价"对您来说比"完全不重报价"更糟时,才设为 true。对大多数报价策略而言并非如此——交易中止会把过期报价留在订单簿上,而那正是您想解决的问题。
示例请求
side 为 0 表示买单,1 表示卖单。
数据格式规则
大多数首次集成失败都出在这四条规则上。
BigInt 字段需要尾缀 n。 原生 BigInt 字段是带 n 后缀的 JSON 字符串——"123n"。纯数字 123 和 "123" 都会失败。响应也以同样的格式返回。并非所有数字都是 BigInt:普通计数器和毫秒时间戳仍是普通 JSON 数字,请遵循各接口的 schema,不要全局转换。
accountId 是数字,不是对象 ID。 原生接口接收数字账户 ID。CCXT 写入接口在同名字段下接收账户权限凭证对象 ID(0x...),CCXT 读取接口则使用 accountNumber。在应填数字 accountId 的地方传入 0x... 权限凭证 ID,是最常见的集成故障。
预览响应是"成功或错误"联合体。 /api/perpetuals/account/previews/* 可能返回 HTTP 200,但响应体是 { "error": "..." } 并带有响应头 X-Error-Message: true。读取成功字段前先检查错误结构——单看 200 并不代表预览成功。
响应是确定性排序的。 市场按交易对符号排序,仓位按市场 ID 排序,挂单中的买单和卖单各自按订单 ID 排序。您可以对相邻两次账户快照按位置做差异比对,不必每次轮询都重建映射。
实时行情数据
所有实时数据流——订单簿、预言机、市场状态、账户更新和 K 线——都复用同一个 WebSocket:
wss://v2-preview.aftermath.finance/api/perpetuals/ws/updates
连接 open 后,按数据流逐个发送 JSON 帧订阅:
报价机器人通常需要的数据流:
topOfOrderbook
分桶的前 N 档快照。每帧都是完整快照,无需 REST 初始化,也无需维护增量。
orderbook
全深度增量,用于分桶盘口快照不够用的场景。
oracle
该市场的预言机价格更新。
userOrders
您账户的订单更新,包含 clientOrderId。
userCollateralChanges
您账户的保证金资产变动。
marketCandles
1m … 1mo 各周期的 OHLCV 更新。
完整的帧 schema、错误帧和客户端示例见 WebSockets 页面。
重连后先重新同步,再恢复处理。 重新拉取快照,原子性地替换本地状态,然后再继续应用增量。绝不要从断连前的内存状态继续。
如果您更习惯 SSE(Server-Sent Events),可使用 /api/ccxt/stream/* 下的 SSE 数据流。
风险控制
发送前先校验规模。 POST /api/perpetuals/account/max-order-size 返回给定 marketId 和 side(0 买、1 卖)下,账户在当前风险限额内可下的最大订单。放大报价规模或调整杠杆前先调用它,不要靠交易失败来发现限额。
没有"死人开关"。 API 不提供定时取消或断连自动过期的接口。进程挂掉后,您的报价会一直留在订单簿上。请构建一个心跳终止开关,在策略循环停滞时取消全部挂单,并同时挂接到 SIGINT/SIGTERM 和心跳超时。退出前确认取消操作已上链。
账户状态会立即过期。 任何成交、取消、存入、提取或杠杆变更之后,先刷新账户和仓位状态,再计算下一次报价。
串行化一切触及同一 coin 对象的操作。 并发的已签名交易可能在同一个 USDC coin 或 Gas coin 上竞争,因版本冲突或 equivocation 错误而失败。请串行化保证金资产操作,并给并行提交者各自独立的 Gas coin。
Gas 优化
最大的 Gas 节省来自交易结构。用 cancel-and-place-orders 原子性执行,而不是分开调用,每次订单更新可将 Gas 降低约 7 倍。
低效:分开的交易
高效:原子化取消并下单 + 批量
实用建议
始终使用
cancel-and-place-orders——绝不把取消和下单作为两笔交易分开发送。每次调用批量提交 5 笔以上订单——
ordersToPlace数组接受多笔订单。单笔交易订单越多,每笔订单的 Gas 越低。一笔交易报双边——买单和卖单放进同一个
ordersToPlace数组。使用 Post-Only(
orderType: 2)——保证以挂单方 (Maker) 身份成交,避免 Taker 费用。用
clientOrderId标记订单——按自己的 ID 取消,省去读回环节。使用代理钱包——通过
grant-agent-wallet把签名委托给代理钱包,主密钥保持冷存储。代理钱包可以交易,但无法提取保证金资产。使用 Gas 池代付——预先注资 Gas 池(
/api/gas-pool/*),并传入sponsor: { walletAddress },让 Gas 成本可预测。用
txKind组合交易——传入已有的TransactionKind,把重报价折叠进更大的 PTB,而不是发两笔交易。不要自行添加预言机更新——API 在内部处理预言机数据的新鲜度。
不要为插队而多付 Gas——高优先级 Gas 交易会被加收额外的 Taker 费用(市场参数中的
priorityTakerFee),该参数未设置时此类交易会被直接拒绝。参见参考 Gas 价格。
CCXT
如果贵司已运行在 CCXT 基础设施上,我们同样支持 CCXT 标准接口,参见 CCXT 文档。注意 CCXT 接口返回的是 transactionBytes 和 signingDigest,而非原始 TransactionKind,因此您对 Gas 和 PTB 组合的控制会更少。请对 signingDigest 而非 transactionBytes 签名,并提交 signatures[]——当发送方与 Gas 拥有者不同时,两个签名都放进该数组。
CCXT 的 OrderRequest 也比原生接口更窄:/api/ccxt/build/createOrders 不支持 timeInForce 和 postOnly,即使发送也会被忽略。如果只挂单 (Post Only) 报价对您很重要——对做市商来说理应如此——请使用原生接口。
完整 API 参考见 Swagger 文档。
Last updated