平台核心系统分为两个独立的业务域,通过严格的接口契约和单向依赖关系解耦:
两域严格禁止循环依赖,通过异步消息队列和指令发送实现通信。
| 模块 | 功能 | 关键产出 |
|---|---|---|
| L1 Account & Assets | 用户注册、多链充值、提现、余额管理 | 账户ID、钱包地址、余额快照 |
| L2 Order Routing | 订单分类、三模式路由、阈值决策 | 路由指令(INTERNAL/HL)、订单ID |
| L3 Platform B-book Execution | INTERNAL成交、仓位记账、费用结算 | 成交确认、仓位ID、成交价 |
| L4 HL Proxy Execution | HL下单、回执映射、价格校正 | HL订单ID、成交价、错误回执 |
| L7 Market Data | 行情订阅、缓存、同步 | 标记价格、资金费率、深度数据 |
| L8 Settlement & Reconciliation | PnL计算、资金费结算、对账 | 结算记录、盈亏单据、对账报告 |
❌ 直接修改用户余额(除成交/清算/提现) ❌ 自行触发清算(必须由风控域发指令) ❌ 对冲决策(完全由L6负责) ❌ 风控规则检查(超出订单格式验证范围)
| 模块 | 功能 | 关键产出 |
|---|---|---|
| Pre-Trade Risk Check | 下单前审批 | 通过/拒绝、原因、警告 |
| Exposure Monitor | 实时敞口计算、汇聚 | 净敞口、方向、实时更新 |
| Margin & Liquidation Engine | 保证金率计算、清算触发 | 保证金率、清算信号、执行ID |
| Hedge Engine (L6) | 对冲阈值、比例、指令生成 | 对冲指令、优先级、目标账户 |
| Risk Reserve Management | 准备金净值、流动性管理 | 准备金余额、可用额度、入账记录 |
| Circuit Breaker | 多维熔断监控 | 熔断状态、触发原因、回复条件 |
风控域 → 账本域:只读 + 发指令
账本域 → 风控域:只发事件
禁止反向调用
目的:订单下达前,验证是否满足风控条件
请求参数
{
"request_id": "order_req_20260409_001",
"user_id": "user_12345",
"symbol": "BTC",
"side": "LONG",
"size": 0.5,
"notional": 20000,
"leverage": 10,
"margin_mode": "ISOLATED",
"order_type": "MARKET",
"timestamp": 1712688000000
}
响应参数
{
"approved": true,
"order_id": "order_20260409_001",
"reject_reason": null,
"risk_warnings": [
"account_equity_low: 已用保证金占总权益的92%, 建议补充资金"
],
"metadata": {
"margin_ratio": 0.92,
"max_leverage_allowed": 15,
"user_risk_level": "MEDIUM"
}
}
错误码
| 错误码 | 含义 | HTTP Code |
|---|---|---|
| INSUFFICIENT_MARGIN | 保证金不足 | 400 |
| SYMBOL_SUSPENDED | 品种暂停交易 | 400 |
| EXPOSURE_LIMIT_EXCEEDED | 敞口超限 | 400 |
| USER_RESTRICTED | 用户被限制 | 403 |
| RESERVE_INSUFFICIENT | 风险准备金不足,不能新开INTERNAL订单 | 400 |
| LEVERAGE_EXCEED | 杠杆超过用户额度 | 400 |
幂等策略
request_id超时处理
调用者:L2 订单路由模块 使用频率:每笔订单
目的:账本域向风控域通知INTERNAL敞口变化(异步、非阻塞)
消息格式
{
"event_id": "exposure_evt_20260409_001",
"event_type": "OPEN",
"user_id": "user_12345",
"symbol": "BTC",
"direction": "LONG",
"position_size": 0.5,
"entry_price": 40000,
"delta_notional": 20000,
"current_exposure": {
"net_exposure": 45000,
"long_notional": 65000,
"short_notional": 20000
},
"timestamp": 1712688000000,
"source": "L3_EXECUTION"
}
生产者:L3(对赌执行)、L4(HL执行回执) 消费者:L6(对冲引擎、敞口监控) 传输方式:Redis Streams,at-least-once 确保单调性:消费端使用消息ID排序,幂等去重
超时处理
目的:风控域命令账本域执行用户仓位清算
请求参数
{
"trigger_id": "liq_trg_20260409_001",
"position_id": "pos_20260408_123",
"user_id": "user_12345",
"symbol": "BTC",
"direction": "LONG",
"position_size": 0.5,
"trigger_price": 38000,
"margin_ratio": 0.095,
"liquidation_type": "ISOLATED",
"execution_target": "INTERNAL",
"urgency": "HIGH",
"timestamp": 1712688000000
}
响应参数
{
"execution_id": "liq_exe_20260409_001",
"status": "EXECUTING",
"position_id": "pos_20260408_123",
"close_price": null,
"filled_size": 0,
"remaining_size": 0.5,
"estimated_loss": -2000,
"liquidation_fee": 2000,
"timestamp": 1712688000000
}
最终响应(成交后)
{
"execution_id": "liq_exe_20260409_001",
"status": "COMPLETED",
"close_price": 38500,
"filled_size": 0.5,
"actual_loss": -2250,
"liquidation_fee": 2000,
"platform_profit": 1600,
"reserve_fund_contribution": 400,
"settlement_time_ms": 2500
}
错误码
| 错误码 | 含义 |
|---|---|
| POSITION_ALREADY_CLOSED | 仓位已平 |
| POSITION_NOT_FOUND | 仓位不存在 |
| HL_UNAVAILABLE | HL清算失败(HL端仓位清算) |
| EXECUTION_TIMEOUT | 清算执行超时(>5s) |
| INSUFFICIENT_LIQUIDITY | 清算流动性不足 |
| UNAUTHORIZED | 指令来源非法 |
幂等策略
trigger_id超时处理
调用者:L6 风控域 使用频率:事件驱动(保证金率触发)
目的:风控域L6命令账本域L4在HL对冲平台净敞口
请求参数
{
"instruction_id": "hedge_instr_20260409_001",
"symbol": "BTC",
"direction": "SHORT",
"size": 0.4,
"leverage": 10,
"max_slippage_bps": 100,
"urgency": "NORMAL",
"reason": "net_exposure_500k_exceeded",
"timestamp": 1712688000000
}
响应参数
{
"execution_id": "hedge_exe_20260409_001",
"status": "EXECUTING",
"symbol": "BTC",
"direction": "SHORT",
"order_size": 0.4,
"hl_order_id": "hl_order_99999",
"timestamp": 1712688000000
}
最终响应(成交后)
{
"execution_id": "hedge_exe_20260409_001",
"status": "COMPLETED",
"symbol": "BTC",
"fill_price": 40100,
"filled_size": 0.4,
"notional_filled": 16040,
"taker_fee": 5.61,
"net_cost": 5.61,
"remaining_exposure": 100000,
"settlement_time_ms": 3200
}
错误码
| 错误码 | 含义 |
|---|---|
| HEDGE_ACCOUNT_INSUFFICIENT | 对冲账户保证金不足 |
| SLIPPAGE_EXCEEDED | 滑点超过限制 |
| HL_UNAVAILABLE | HL连接中断 |
| EXECUTION_TIMEOUT | 对冲指令超时 |
| INVALID_SIZE | 对冲大小超过限制 |
幂等策略
instruction_id超时处理
调用者:L6 对冲引擎 使用频率:阈值触发(敞口变化时)
目的:切换L2的三种路由模式(NORMAL_MODE / HL_MODE / BETTING_MODE)
请求参数
{
"change_id": "mode_chg_20260409_001",
"new_mode": "HL_MODE",
"trigger_type": "AUTO",
"operator_id": null,
"reason": "net_exposure_exceeded_1m_threshold",
"enforced": false,
"timestamp": 1712688000000
}
响应参数
{
"applied": true,
"change_id": "mode_chg_20260409_001",
"previous_mode": "NORMAL_MODE",
"new_mode": "HL_MODE",
"effective_at": 1712688000100,
"effective_for_ms": 0,
"auto_fallback_threshold": {
"trigger": "net_exposure_below_500k",
"fallback_mode": "NORMAL_MODE"
}
}
错误码
| 错误码 | 含义 |
|---|---|
| ALREADY_IN_MODE | 已处于该模式 |
| UNAUTHORIZED | 操作者无权限 |
| INVALID_MODE | 模式不合法 |
幂等策略
change_id超时处理
调用者:L6 风控域(自动)、L9 后台(手动) 使用频率:低频(分钟级)
目的:风控域查询用户账户状态,用于决策
请求参数
{
"user_id": "user_12345",
"include_details": false
}
响应参数
{
"user_id": "user_12345",
"total_equity": 100000,
"available_balance": 5000,
"frozen_margin": 60000,
"cross_margin_used": 35000,
"unrealized_pnl": 2500,
"positions": {
"internal": [
{
"position_id": "pos_001",
"symbol": "BTC",
"direction": "LONG",
"size": 0.5,
"entry_price": 40000,
"current_price": 41000,
"margin_used": 20000,
"margin_mode": "ISOLATED",
"unrealized_pnl": 500
}
],
"hyperliquid": [
{
"symbol": "ETH",
"direction": "SHORT",
"size": 10,
"entry_price": 2000,
"current_price": 1950,
"unrealized_pnl": 500
}
]
},
"margin_ratios": {
"account_level": 0.92,
"isolated_positions": [0.85, 0.78]
}
}
错误码
| 错误码 | 含义 |
|---|---|
| USER_NOT_FOUND | 用户不存在 |
| ACCOUNT_LOCKED | 账户锁定 |
超时处理
调用者:L6 对冲引擎、清算引擎、预风控检查 使用频率:高频(每秒多次)
| 范畴 | 通信方式 | 一致性保证 | 处理路径 |
|---|---|---|---|
| 核心路径:下单→成交→记账 | 同步事务 | ACID | 数据库事务 + 分布式锁 |
| 跨域通知:敞口/仓位变更 | 异步消息 | At-least-once | Redis Streams + 消费端幂等 |
| 指令下达:清算/对冲/模式切换 | 异步消息 | At-least-once | 指令队列 + 重试 + 幂等键 |
| 读操作:查询余额/仓位 | 同步查询 | 最终一致 | 缓存 + TTL + 版本号 |
定时全量对账(每小时一次)
1. 账本域导出:用户总equity、总仓位、总敞口、总风险值
2. 风控域导出:最新风险监控快照、清算黑名单、冻结列表
3. 比对维度:
- 用户总equity是否一致
- 净敞口数值是否一致
- 清算被执行仓位是否同步
4. 发现偏差 → 生成对账单 → 告警 → 人工审核 → 补偿事务
补偿事务示例
| 偏差场景 | 根本原因 | 补偿方案 |
|---|---|---|
| 清算执行失败,仓位未平 | HL连接断开或超时 | 重试3次(1s间隔) → 告警 → 人工确认 → 强制HL_MODE |
| 敞口数值不一致 | 成交事件丢失 | 扫描成交记录 → 补发敞口事件 → 重新计算对冲 |
| 风险准备金余额不对 | 入账记录丢失 | 核查用户亏损单据 → 补入账 → 告警 |
| 用户余额被篡改 | 异常操作日志 | 回滚到最近正确版本 + 人工审计 |
同步(强一致)
异步(最终一致)
代码示例
# 同步路径:订单处理
with db.transaction():
order = Order.create(user_id, symbol, side, size)
if route == 'INTERNAL':
position = Position.create(order)
balance.update(fee=-fee_amount)
else:
hl_order = hl_api.create_order(...)
db.commit()
# 异步通知:敞口变更
message_queue.publish('exposure_changes', {
'event_id': uuid4(),
'user_id': order.user_id,
'delta_notional': order.notional,
...
})
每个跨域接口都有幂等键:
request_id(客户端生成 + timestamp)trigger_id(风控系统生成)instruction_id(L6生成)change_id(控制系统生成)存储方案
CREATE TABLE idempotency_keys (
key_type VARCHAR(50),
key_value VARCHAR(256),
result JSON,
created_at TIMESTAMP,
PRIMARY KEY (key_type, key_value),
INDEX (created_at)
);
检查时:SELECT result FROM idempotency_keys WHERE key_value = ?
按用户分片:确保同用户的敞口事件顺序
partition_key = f"user_{event.user_id}"
message_queue.publish('exposure_changes', event, partition=partition_key)
消费端去重:idempotent consumer
def consume_exposure_event(event):
last_event_id = redis.get(f"last_event_{event.user_id}")
if event.event_id <= last_event_id:
return # 已处理,跳过
# 处理事件
update_exposure(event)
redis.set(f"last_event_{event.user_id}", event.event_id)
PreTradeCheck 必须 <10ms,否则影响交易体验
缓存策略
def pre_trade_check(order):
cache_key = f"ptc_{order.user_id}_{order.symbol}"
cached = cache.get(cache_key)
if cached and cached['timestamp'] > now - 100ms:
return cached['result']
try:
result = risk_service.check(order, timeout=10ms)
cache.set(cache_key, result, ttl=100ms)
return result
except TimeoutError:
# 使用上一次的结果或默认拒绝
return cached or {'approved': False}
清算是高优先级操作,必须有重试机制
def execute_liquidation(trigger):
for retry in range(3):
try:
result = liquidation_service.execute(trigger, timeout=5000ms)
if result.status == 'COMPLETED':
return result
except Exception as e:
if retry < 2:
sleep(1)
continue
else:
alert(f"Liquidation {trigger.trigger_id} failed after 3 retries", severity=CRITICAL)
# 强制进入HL_MODE,由人工处理
routing_mode.set('HL_MODE')
raise
小偏差自动修正
大偏差人工审核
def reconcile():
discrepancies = ledger_domain.export() ^ risk_domain.export()
for disc in discrepancies:
if abs(disc.amount) < 100:
auto_correct(disc)
else:
create_audit_ticket(disc, status='PENDING_REVIEW')
alert(f"Large discrepancy detected: {disc.amount}")
通过明确的域边界、单向依赖、同异混合通信,实现了:
✅ 解耦:两域独立演化,接口稳定 ✅ 可观测:异步消息全链路可追踪 ✅ 容错:清算/对冲有重试 + 人工兜底 ✅ 一致:同步事务 + 异步对账双重保障 ✅ 高效:核心路径同步<10ms,非关键路径异步不阻塞