Skip to main content

订单、仓位与杠杆:下单流程完整技术文档

版本: v1.0
日期: 2026-04-13
适用范围: ZTDX.io USDT 保证金永续合约


目录​

  1. 概述
  2. 核心概念
  3. 下单请求
  4. 杠杆验证
  5. 保证金计算与余额冻结
  6. 撮合引擎处理
  7. 成交后仓位处理
  8. 仓位生命周期
  9. 强平价格计算
  10. 同方向加仓
  11. 反方向对冲与平仓
  12. 完整流程图
  13. 公式汇总
  14. 设计注意事项
  15. API 参考

1. 概述​

ZTDX.io 永续合约的下单流程涉及三个核心实体的交互:

实体说明
订单(Order)用户提交的交易指令,携带杠杆参数
仓位(Position)订单撮合成交后产生或更新的持仓记录
杠杆(Leverage)决定保证金需求和仓位规模的倍数因子

核心设计原则:

  • 杠杆跟随订单:每笔订单独立指定杠杆,而非全局设置
  • 最大杠杆按交易对配置:不同交易对有不同的最大杠杆上限
  • 仓位按方向合并:同一用户、同一交易对、同一方向仅维持一个仓位
  • 反方向自动对冲:新订单方向与已有仓位相反时,优先平仓

2. 核心概念​

2.1 杠杆的作用​

杠杆本质上是一个资金效率倍数器,它影响两个方面:

下单时 — 决定需要冻结多少保证金:

所需保证金 = 名义价值 / 杠杆

持仓时 — 决定仓位规模和强平距离:

仓位规模 = 保证金 × 杠杆
强平距离 ∝ 1 / 杠杆 (杠杆越高,强平价格越近)

2.2 杠杆范围​

参数值说明
最小杠杆1x所有交易对统一
每交易对最大杠杆market_configs.max_leverage按交易对在服务端独立配置
兜底最大杠杆(/api/v1)50x交易对无配置时,POST /api/v1/orders 校验兜底为 50
兜底最大杠杆(/fapi)125x交易对无配置时,POST /fapi/v1/leverage 校验兜底为 125

注意: 两套 API 面在交易对缺少配置时的兜底上限不一致(/api/v1 为 50,/fapi 为 125),这是当前实现的真实行为。

2.3 保证金体系​

参数值说明
维持保证金率(MMR)0.5%低于此比例触发强制平仓
开仓费0(已移除)2026-04-29 起移除 0.1% 开仓费;改为按笔 maker/taker 费累计到 accumulated_trading_fee,平仓时按比例收取
保证金缓冲0.5%下单时额外冻结,覆盖手续费和滑点
最小保证金$10单笔订单最低保证金
最小仓位规模$10低于此值不创建仓位(market_configs.min_order_size_usd,默认 10)

3. 下单请求​

3.1 请求端点​

POST /api/v1/orders

重要 — 两套 API 面的区分: 本文档描述的是原生 /api/v1 面的下单流程:请求体使用 snake_case 字段、每单携带 leverage、JWT 认证时需要 body 内 EIP-712 签名(时间戳 5 分钟有效窗口)。另有一套 Binance 风格的 /fapi/v1/order 开发者面:它不接受每单 leverage 与 signature 参数,杠杆来自 POST /fapi/v1/leverage 持久化的按用户+交易对设置。两套面请勿混用参数。

3.2 请求参数​

参数类型必填说明
symbolString是交易对,如 BTCUSDT
sideEnum是BUY 或 SELL
order_typeEnum是LIMIT 或 MARKET(另支持 TP/SL 触发单类型)
priceDecimal限价必填委托价格
amountDecimal是下单数量(代币数量)
leverageInteger是杠杆倍数(1 ~ max_leverage)
signatureStringJWT 必填EIP-712 签名
timestampIntegerJWT 必填Unix 时间戳(秒,±300 秒有效窗口)

3.3 EIP-712 签名内容​

签名覆盖以下字段,确保杠杆参数不可篡改(注意 price、amount 是 string 类型):

CreateOrder(
address wallet,
string symbol,
string side,
string orderType,
string price,
string amount,
uint32 leverage,
uint256 timestamp
)

注意: API Key(HMAC)认证方式下,body 内 EIP-712 签名被豁免,signature 和 timestamp 为可选参数。


4. 杠杆验证​

订单提交后,系统按以下顺序验证杠杆:

4.1 验证流程​

请求中的 leverage
│
▼
① 检查 leverage ≥ 1
│
▼
② 读取交易对配置,获取该交易对的最大杠杆
│
▼
③ 检查 leverage ≤ max_leverage
│
▼
④ 验证通过 → 继续下单流程

4.2 交易对杠杆配置​

每个交易对的杠杆上限由服务端配置管理,可通过 Admin API 动态调整,无需重启服务。调整后对新订单立即生效。

4.3 验证失败响应​

/api/v1 面(POST /api/v1/orders)返回 HTTP 400 与字符串错误码,交易对无配置时上限兜底为 50:

{
"error": "杠杆倍数必须在1-50之间",
"code": "INVALID_LEVERAGE"
}

/fapi 面(POST /fapi/v1/leverage)返回 Binance 风格错误码 -4028,交易对无配置时上限兜底为 125:

{
"code": -4028,
"msg": "Leverage 200 is not valid. Max: 125"
}

注意: 两面的兜底上限不一致(50 vs 125),这是当前实现的真实行为。错误码 -1128 并不存在。


5. 保证金计算与余额冻结​

杠杆验证通过后,系统计算本次订单所需的保证金并冻结用户余额。

5.1 标准保证金计算​

当用户没有反方向仓位时,使用标准公式:

名义价值 = amount × price
基础保证金 = 名义价值 / leverage
缓冲金额 = 基础保证金 × 0.5%
所需保证金 = 基础保证金 + 缓冲金额

计算示例:

参数值
交易对BTCUSDT
方向BUY
数量1 BTC
价格$60,000
杠杆10x
名义价值 = 1 × $60,000 = $60,000
基础保证金 = $60,000 / 10 = $6,000
缓冲金额 = $6,000 × 0.5% = $30
所需保证金 = $6,000 + $30 = $6,030

5.2 对冲保证金计算​

当用户已有反方向仓位时,保证金需求会降低:

场景 A:订单完全平掉反向仓位​

条件: 订单名义价值 ≤ 反向仓位规模
所需保证金 = 订单名义价值 × 0.5% (仅需手续费)

示例: 持有 $50,000 空仓,下买单 $30,000

所需保证金 = $30,000 × 0.5% = $150 (而非 $30,000/leverage)

场景 B:订单平掉反向仓位后还有剩余​

条件: 订单名义价值 > 反向仓位规模
净增部分 = 订单名义价值 - 反向仓位规模
净增保证金 = 净增部分 / leverage
缓冲 = 净增保证金 × 0.5%
所需保证金 = 净增保证金 + 缓冲

示例: 持有 $50,000 空仓,下买单 $80,000,杠杆 10x

净增部分 = $80,000 - $50,000 = $30,000
净增保证金 = $30,000 / 10 = $3,000
缓冲 = $3,000 × 0.5% = $15
所需保证金 = $3,000 + $15 = $3,015

场景 C:无反方向仓位​

使用 5.1 节的标准公式。

5.3 余额冻结​

验证用户可用余额充足后,执行冻结:

  1. 将本次订单所需保证金从「可用余额」划入「冻结余额」
  2. 订单对象记录 frozen_margin(冻结金额),用于订单成交或取消时精确释放
  3. 冻结操作与订单落库在同一事务内完成,保证一致性

6. 撮合引擎处理​

6.1 订单提交到撮合引擎​

保证金冻结完成后,订单写入数据库(status = pending),随后提交到内存撮合引擎:

matching_engine.submit_order(
order_id,
symbol,
user_address,
side,
order_type,
amount,
price,
leverage ← 杠杆传入撮合引擎
)

6.2 撮合过程​

撮合引擎按价格-时间优先算法匹配买卖订单。成交时产生 TradeEvent:

TradeEvent {
symbol: "BTCUSDT",
trade_id: UUID,
maker_order_id: UUID, // 挂单方
taker_order_id: UUID, // 吃单方
maker_address: "0x...",
taker_address: "0x...",
side: "buy", // 吃单方方向
price: 60000.0, // 成交价
amount: 1.0, // 成交数量
maker_fee: 12.0, // 0.02% of $60,000
taker_fee: 30.0, // 0.05% of $60,000
maker_leverage: 5, // 挂单方杠杆
taker_leverage: 10, // 吃单方杠杆
timestamp: ...
}

关键点: 成交事件中保留了双方各自的杠杆值(maker_leverage 和 taker_leverage),因为它们可能不同。

6.3 订单状态更新​

订单类型全部成交部分成交未成交
市价单filledpartially_filledcancelled(IOC 特性)
限价单filledpartially_filledopen(挂入订单簿)

7. 成交后仓位处理​

成交事件通过 Broadcast Channel 发送到持久化 Worker,Worker 在写入成交记录后更新仓位。

7.1 并发控制​

仓位更新在同一用户同一交易对维度上串行执行,防止并发更新冲突。实现为 Postgres 事务级咨询锁(阻塞式排队,非轮询):

键 = hash(user + symbol)
BEGIN
SET LOCAL lock_timeout = '5s'
SELECT pg_advisory_xact_lock(键) -- 阻塞等待,由 Postgres 原生 FIFO 排队
→ 获得锁: 继续执行
→ 超过 5s: lock_timeout 触发,报错回滚
锁随事务提交/回滚自动释放

旧版实现(pg_try_advisory_xact_lock 每 500ms 轮询、最多 10 次)已废弃:轮询期间占用连接池连接,在做市商高并发场景下会造成积压。

7.2 仓位方向确定​

成交方向吃单方仓位方向挂单方仓位方向
BUY多头(Long)空头(Short)
SELL空头(Short)多头(Long)

7.3 仓位处理决策树​

对于成交的每一方(maker 和 taker),系统按以下逻辑处理:

成交事件
│
▼
查询反方向仓位
│
├─ 存在反向仓位
│ │
│ ├─ 反向仓位 ≥ 成交规模 → 减少反向仓位(部分平仓或全部平仓)
│ │ → 结束,不创建新仓位
│ │
│ └─ 反向仓位 < 成交规模 → 全部平掉反向仓位
│ → 计算剩余规模
│ → 继续创建新仓位(使用剩余规模)
│
└─ 无反向仓位
│
▼
查询同方向仓位
│
├─ 存在同向仓位 → 合并仓位(加仓)
│
└─ 无同向仓位 → 创建新仓位

8. 仓位生命周期​

8.1 仓位创建​

当需要创建新仓位时,系统按以下方式计算仓位参数:

输入:
leverage = 订单中的杠杆值
execution_price = 成交价格

计算:
size_in_usd = 成交规模(USD) // 仓位名义规模
size_in_tokens = size_in_usd / execution_price // 仓位代币数量
position_fee = 0 // 开仓费已于 2026-04-29 移除
collateral_amount = size_in_usd / leverage // 保证金,不扣任何费用
liquidation_price = 根据杠杆和方向计算(见第 9 节)

手续费口径(2026-04-29 起): 不再收取 0.1% 开仓费。每笔成交的 maker/taker 手续费累计记录到仓位的 accumulated_trading_fee 字段,在平仓(减仓按比例)时结算收取。

仓位记录包含的字段:

字段说明
size_in_usd仓位名义规模
size_in_tokens仓位代币数量
collateral_amount保证金(= size_in_usd / leverage,不扣开仓费)
entry_price成交价 / 加权平均入场价
leverage杠杆倍数
liquidation_price强平价格
accumulated_trading_fee累计交易手续费(按笔累加,平仓时收取)
unrealized_pnl未实现盈亏(初始为 0)
realized_pnl已实现盈亏(初始为 0)
status仓位状态,初始为 open

8.2 仓位状态​

状态说明
open活跃持仓
closed用户主动平仓
liquidated触发强制平仓

8.3 计算示例​

场景:用户以 10x 杠杆买入 1 BTC @ $60,000

步骤计算结果
成交规模1 × $60,000$60,000
保证金$60,000 / 10$6,000
开仓费已移除$0
仓位规模$60,000$60,000
代币数量$60,000 / $60,0001 BTC
强平价格$60,000 × (1 − 1/10 + 0.005)$54,300

9. 强平价格计算​

强平价格由入场价、杠杆和维持保证金率共同决定。

9.1 多头(Long)强平价格​

liquidation_price = entry_price × (1 − 1/leverage + maintenance_margin_rate)

直观理解:价格下跌到保证金无法覆盖维持保证金要求时触发强平。MMR 项使强平价高于纯爆仓价(entry × (1 − 1/leverage)),即在保证金彻底亏完之前触发。

9.2 空头(Short)强平价格​

liquidation_price = entry_price × (1 + 1/leverage − maintenance_margin_rate)

直观理解:价格上涨到保证金无法覆盖维持保证金要求时触发强平。

9.3 不同杠杆下的强平距离​

以 BTC 入场价 $60,000 为例,维持保证金率 0.5%:

杠杆多头强平价距入场价空头强平价距入场价
2x$30,300-49.5%$89,700+49.5%
5x$48,300-19.5%$71,700+19.5%
10x$54,300-9.5%$65,700+9.5%
20x$57,300-4.5%$62,700+4.5%
50x$59,100-1.5%$60,900+1.5%
100x$59,700-0.5%$60,300+0.5%

结论: 强平距离 ≈ 1/leverage − MMR。杠杆每翻一倍,强平距离约减半。100x 杠杆下,价格波动 0.5% 即触发强平。

9.4 初始公式 vs 存量仓位重算​

上述理想化公式(假设 collateral = size/leverage 且费用为 0)仅在开仓创建新仓位时使用一次。对存量仓位(加仓合并、扣除资金费/借贷费之后),强平价按实际保证金 + 累计费用重算,与强平引擎的触发条件(剩余保证金 = size × MMR)严格一致:

fees = accumulated_funding_fee + accumulated_borrowing_fee
min_collateral = size_in_usd × MMR

多头: liq_price = (min_collateral − collateral_amount + fees + size_in_usd) / size_in_tokens
空头: liq_price = (collateral_amount − fees + size_in_usd − min_collateral) / size_in_tokens

(结果向下限定为不小于 0。)


10. 同方向加仓​

当用户已有同方向仓位时,新成交会合并到现有仓位中。

10.1 合并逻辑​

同向合并只更新规模、代币数、保证金与入场价,不修改 leverage 字段:

新总规模(USD) = 原规模 + 新成交规模
新总代币数 = 原代币数 + 新成交代币数
新入场价 = 新总规模(USD) / 新总代币数 ← 加权平均
新保证金 = 原保证金 + 新成交规模/新订单杠杆 (无开仓费扣除)
leverage 字段 = 保持原值不变 ← 不覆盖、不加权
新强平价格 = 按实际保证金口径重算(见 §9.4 的存量仓位公式)

新订单的杠杆值只影响本次保证金增量(新成交规模 / 新订单杠杆),不会写入仓位的 leverage 字段。

10.2 加仓示例​

第一笔:10x 杠杆买入 1 BTC @ $60,000

字段值
size_in_usd$60,000
size_in_tokens1.0 BTC
entry_price$60,000
collateral$6,000(无开仓费扣除)
leverage10
liquidation_price$54,300

第二笔:20x 杠杆买入 0.5 BTC @ $62,000

新成交规模 = 0.5 × $62,000 = $31,000,保证金增量 = $31,000 / 20 = $1,550

字段计算新值
size_in_usd$60,000 + $31,000$91,000
size_in_tokens1.0 + 0.51.5 BTC
entry_price$91,000 / 1.5$60,666.67
collateral$6,000 + $1,550$7,550
leverage保持不变10
liquidation_price($91,000 × 0.005 − $7,550 + $91,000) / 1.5$55,936.67

强平价按 §9.4 的存量仓位公式计算(费用暂计 0):(min_collateral − collateral + size) / tokens = (455 − 7,550 + 91,000) / 1.5 ≈ $55,936.67。

10.3 重要注意事项​

  • 仓位的 leverage 字段在加仓合并时保持不变,始终反映首次开仓的杠杆
  • 保证金(collateral_amount)是历次加仓增量的累加值;每次增量由该笔订单的杠杆决定
  • 仓位的有效杠杆(size_in_usd / collateral_amount)会随不同杠杆的加仓而偏离 leverage 字段(上例中 $91,000 / $7,550 ≈ 12.05x)
  • 强平价格按实际保证金重算(§9.4),与真实风险一致,不会因字段覆盖而突变

11. 反方向对冲与平仓​

11.1 完全平仓​

当新订单方向与现有仓位相反,且订单规模 ≤ 仓位规模时:

场景: 持有 $60,000 多仓,下卖单 $60,000

处理:
1. 计算已实现 PnL = (卖出价 - 入场价) × 代币数量
2. 将 PnL 加入用户余额
3. 释放仓位保证金到可用余额
4. 释放订单冻结保证金(如果有)
5. 仓位状态 → closed

11.2 部分平仓​

场景: 持有 $60,000 多仓,下卖单 $30,000

处理:
1. 仓位规模减半: $60,000 → $30,000
2. 代币数量减半
3. 保证金按比例释放
4. 入场价不变
5. 已实现 PnL 入账
6. 仓位状态保持 open

11.3 反转仓位​

场景: 持有 $50,000 多仓,下卖单 $80,000

处理:
1. 先全部平掉 $50,000 多仓(计算 PnL,释放保证金)
2. 剩余 $30,000 作为新空仓开仓
3. 新空仓使用订单中的杠杆
4. 新空仓保证金 = $30,000 / leverage(无开仓费扣除)

11.4 对冲时的保证金优势​

反向下单时保证金需求显著降低:

场景所需保证金说明
无仓位,开 $60,000 多仓 (10x)$6,030标准计算
持有 $60,000 空仓,开 $60,000 多仓$300仅手续费(完全平仓)
持有 $60,000 空仓,开 $80,000 多仓 (10x)$2,010仅净增 $20,000 的保证金

12. 完整流程图​

用户提交订单
POST /api/v1/orders
│ { symbol, side, order_type, price, amount, leverage, signature, timestamp }
│
▼
┌──────────────────────────────────────────────────┐
│ ① 请求验证 │
│ │
│ 交易对可交易? ─── 否 → 返回错误 │
│ │ 是 │
│ 时间戳有效?(5分钟窗口)─── 否 → 返回错误 │
│ │ 是 │
│ 1 ≤ leverage ≤ max_leverage? ─── 否 → 返回错误 │
│ │ 是 │
│ amount > 0? ─── 否 → 返回错误 │
│ │ 是 │
│ 限价单有 price? ─── 否 → 返回错误 │
│ │ 是 │
│ EIP-712 签名验证 ─── 失败 → 返回错误 │
│ │ 通过 │
└───────┼──────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ ② 保证金计算 │
│ │
│ 查询反向仓位 ────────────────────┐ │
│ │ │ │
│ ┌────┴────┐ ┌────────────┐ ┌─┴──────────┐ │
│ │ 无反向 │ │ 订单≤反向 │ │ 订单>反向 │ │
│ │ 仓位 │ │ 仓位 │ │ 仓位 │ │
│ ├─────────┤ ├────────────┤ ├────────────┤ │
│ │标准保证金│ │仅手续费 │ │净增部分 │ │
│ │= 名义值 │ │= 名义值 │ │的保证金 │ │
│ │ /杠杆 │ │ × 0.5% │ │=(净额/杠杆) │ │
│ │ +0.5% │ │ │ │ +0.5% │ │
│ └────┬────┘ └─────┬─────┘ └─────┬──────┘ │
│ └──────────────┴──────────────┘ │
│ │ │
└──────────────────────┼───────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ ③ 余额检查与冻结 │
│ │
│ 可用余额 ≥ 所需保证金? ─── 否 → 返回余额不足 │
│ │ 是 │
│ available -= 所需保证金 │
│ frozen += 所需保证金 │
│ 订单写入 DB(status = pending, frozen_margin) │
└───────┼──────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ ④ 撮合引擎匹配 │
│ │
│ submit_order(leverage) → orderbook.match_order() │
│ │ │
│ ┌────┴──────────┐ ┌────────────────────────┐ │
│ │ 成交 │ │ 未成交(限价单) │ │
│ │ → TradeEvent │ │ → 挂入订单簿等待 │ │
│ │ maker_lev │ │ status = open │ │
│ │ taker_lev │ │ │ │
│ └────┬──────────┘ └────────────────────────┘ │
└───────┼──────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ ⑤ 成交持久化 │
│ │
│ 记录成交(含双方杠杆) │
│ 累加订单已成交数量 │
│ 记录返佣收益(如适用) │
└───────┼──────────────────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ ⑥ 仓位更新 │
│ (串行互斥保护, 最多重试 3 次) │
│ │
│ 对 maker 和 taker 分别执行: │
│ │
│ 查反向仓位 ─┬─ 有且 ≥ 成交 → 减仓/平仓 │
│ ├─ 有且 < 成交 → 平反向 + 开新仓 │
│ └─ 无 → 查同向仓位 │
│ │ │
│ ┌──────────┴──────────┐ │
│ │ 有同向仓位 │ 无同向仓位 │
│ │ → 合并仓位 │ → 创建新仓位 │
│ │ 加权平均入场价 │ │
│ │ 累加保证金 │ │
│ │ 杠杆字段不变 │ │
│ │ 按实际保证金 │ │
│ │ 重算强平价格 │ │
│ └─────────────────────┘ │
│ │
│ 成交标记为仓位同步完成 │
└──────────────────────────────────────────────────┘

13. 公式汇总​

13.1 保证金相关​

公式说明
required_margin = (amount × price / leverage) × 1.005下单所需保证金(含 0.5% 缓冲)
position_fee = 0开仓费已于 2026-04-29 移除
collateral_amount = size_in_usd / leverage仓位保证金(不扣费)
accumulated_trading_fee += 每笔成交的 maker/taker 费交易手续费按笔累计,平仓时按比例收取

13.2 仓位相关​

公式说明
size_in_usd = collateral × leverage仓位名义规模
size_in_tokens = size_in_usd / execution_price仓位代币数量
entry_price = total_size_usd / total_size_tokens加权平均入场价(加仓时)

13.3 强平价格​

初始开仓(理想化公式,仅创建新仓位时用一次):

方向公式
多头liq_price = entry_price × (1 − 1/leverage + MMR)
空头liq_price = entry_price × (1 + 1/leverage − MMR)

存量仓位(按实际保证金 + 累计费用重算,加仓/扣费后使用):

方向公式
多头liq_price = (size_in_usd × MMR − collateral + fees + size_in_usd) / size_in_tokens
空头liq_price = (collateral − fees + size_in_usd − size_in_usd × MMR) / size_in_tokens

其中 MMR(维持保证金率)= 0.5%,fees = accumulated_funding_fee + accumulated_borrowing_fee

13.4 盈亏计算​

方向公式
多头未实现 PnL(mark_price - entry_price) × size_in_tokens
空头未实现 PnL(entry_price - mark_price) × size_in_tokens

13.5 手续费​

类型费率计算基础
Maker Fee0.02%(基础费率)成交名义价值
Taker Fee0.05%(基础费率)成交名义价值
Position Fee(开仓费)0(2026-04-29 起移除)—
Liquidation Fee0.5%仓位名义规模

Maker/taker 费按笔累计到仓位的 accumulated_trading_fee,在平仓(减仓按比例)时结算收取,不在开仓时从保证金中扣除。


14. 设计注意事项​

14.1 加仓时杠杆字段保持不变​

当前行为: 同向加仓合并时,仓位的 leverage 字段保持首次开仓的值不变;新订单的杠杆只用于计算本次保证金增量(新成交规模 / 新订单杠杆)。

初始: 5x 杠杆, $10,000 保证金, $50,000 仓位, leverage 字段 = 5
加仓: 50x 杠杆下单 $50,000 → 保证金增量 = $50,000 / 50 = $1,000

合并后:
保证金 = $11,000(累加)
仓位规模 = $100,000
leverage 字段 = 5(不变)
有效杠杆 = $100,000 / $11,000 ≈ 9.1x
强平价格按实际保证金($11,000)+ 累计费用重算 ← 与真实风险一致(§9.4)

建议: leverage 字段仅是首次开仓的历史记录;评估风险时使用有效杠杆(size_in_usd / collateral_amount)和仓位返回的 liquidation_price(已按实际保证金口径计算)。

14.2 并发安全​

  • 仓位更新在同一用户同一交易对上串行执行,保证互斥
  • 互斥通过 Postgres 事务级咨询锁实现:SET LOCAL lock_timeout = '5s' + 阻塞式 pg_advisory_xact_lock,由数据库原生排队,超时 5 秒报错回滚(旧版 500ms × 10 次轮询方案已废弃)
  • 持久化 Worker 限制并发度,避免突发成交冲击数据库

14.3 失败恢复​

  • 成交持久化失败的交易进入死信队列,由运维侧统一处理
  • 仓位更新最多重试 3 次(间隔 100ms)
  • 每条成交记录带同步状态标记,用于追踪仓位是否已写入

15. API 参考​

说明: §15.1 属于原生 /api/v1 面;§15.2、§15.3 属于 Binance 风格 /fapi 面。两套面的请求/响应形状完全不同,请勿混用。

15.1 下单(/api/v1 原生面)​

POST /api/v1/orders

请求体:
{
"symbol": "BTCUSDT",
"side": "BUY",
"order_type": "LIMIT",
"price": "60000",
"amount": "1.0",
"leverage": 10,
"signature": "0x...",
"timestamp": 1712966400
}

响应:
{
"order_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "open",
"filled_amount": "0",
"remaining_amount": "1.0",
"average_price": "0",
"created_at": 1712966400000
}

响应为扁平 JSON(无 {code, data} 信封):order_id、status、filled_amount、remaining_amount、average_price(无成交时为 0)、created_at(毫秒时间戳)。不返回 frozen_margin。

15.2 调整杠杆(/fapi 开发者面)​

POST /fapi/v1/leverage

请求体:
{
"symbol": "BTCUSDT",
"leverage": 20
}

响应:
{
"leverage": 20,
"maxNotionalValue": "...",
"symbol": "BTCUSDT"
}

注意: 该设置按「用户 + 交易对」持久化,作用于后续通过 /fapi/v1/order 提交的新订单(/fapi/v1/order 不接受每单 leverage 参数,也不需要 EIP-712 signature)。它不会修改已有仓位的杠杆和强平价格,也不影响 /api/v1/orders(后者每单显式携带 leverage)。

15.3 查询仓位(/fapi 开发者面)​

GET /fapi/v1/positionRisk

响应(Binance 风格数组,无信封):
[
{
"symbol": "BTCUSDT",
"positionAmt": "1.0",
"entryPrice": "60000",
"breakEvenPrice": "60000",
"markPrice": "61500",
"unRealizedProfit": "1500",
"leverage": "10",
"marginType": "isolated",
"isolatedMargin": "6000",
"positionSide": "LONG",
"notional": "60000",
"isolatedWallet": "6000",
"updateTime": 1712966400000
}
]

注意: 该端点是 Binance 兼容形状(camelCase:positionAmt / entryPrice / unRealizedProfit / ...),不包含 liquidation_price、margin_ratio 等原生面字段。需要强平价等原生字段请使用 /api/v1 面的仓位查询端点。