加密货币交易所十一:持仓管理
持仓表的主键到底是「用户 + 合约」还是「用户 + 合约 + 方向」,取决于支不支持双向持仓。这篇拆持仓数据模型、成交量涨了持仓量为什么可能不动、阶梯维持保证金的速算额是怎么来的,以及强平价怎么一步步解出来。
持仓表的主键是什么,这个问题决定了后面所有事情。
如果是「用户 + 合约」,一个用户在 BTC 永续上只能有一个仓位,下一笔反方向的单就是平仓或反手。如果是「用户 + 合约 + 方向」,同一个人可以同时持有多头和空头,反方向下单开的是新仓,两个仓位各自结算、各自有强平价。
前者叫单向持仓,后者叫双向持仓(对冲模式)。这不是一个可以事后加上去的功能 —— 它改的是主键,牵动持仓表、成交回报、强平判定、以及每一个「查一下这个用户在这个合约上有多少仓位」的地方。所以它通常是账户级的一个开关,而且要求切换时没有任何持仓和挂单。
一个仓位要存哪些字段
| 字段 | 示例值 | 存这个值要当心什么 |
|---|---|---|
| 用户 ID | user_123 |
和合约 ID、持仓方向一起构成主键 |
| 合约 ID | BTC-PERP |
同上 |
| 持仓方向 | 多头 | 单向持仓时它不进主键,双向持仓时进 —— 这一条决定表结构 |
| 持仓数量 | 1.5 | 平掉一部分要改它,方向不变 |
| 开仓均价 | 50,000 | 加仓时按数量加权重算,不是简单平均 |
| 杠杆倍数 | 10× | 逐仓下决定划多少保证金进来 |
| 保证金 | 7,500 | 1.5 × 50000 ÷ 10,和上面三个字段自洽 |
| 已实现盈亏 | 500 | 累计值,平仓时累加,不随价格变 |
| 仓位模式 | 逐仓 | 改模式要重算保证金,不能就地改这一个字段 |
| 最后更新时间 | 2026-08-14T10:03:22Z |
乐观锁靠它,并发平仓时用来判先后 |
未实现盈亏不在这张表里。 它是按标记价格算出来的派生值,标记价格每变一次它就变一次,存进数据库等于让一个每秒变几百次的量参与持久化。需要的时候现算,代价只是一次乘法。
上面那行 保证金 = 1.5 × 50000 ÷ 10 = 7500 值得留意:这几个字段之间有约束关系,任何一个被单独改动而其余没跟上,这个仓位就进入了一个不自洽的状态 —— 强平价会算错,而且不会有任何报错。所以修改持仓的入口应该只有一个,接受「成交」这一种输入,其余字段全部由它推导。
成交量涨了,持仓量可能一动不动
持仓量(Open Interest)是所有未平仓合约的总和。它不等于成交量,而且两者的关系不是单调的。
每一笔成交都有买卖两方,每一方要么在开仓要么在平仓,四种组合的结果不同:
| 买方 | 卖方 | 持仓量 |
|---|---|---|
| 开多 | 开空 | 增加 —— 市场上多了一对新仓位 |
| 平多 | 平空 | 减少 —— 一对仓位对冲掉了 |
| 开多 | 平多 | 不变 —— 仓位换了个人拿 |
| 平空 | 开空 | 不变 —— 同上 |
所以「成交量很大」和「持仓量在涨」是两件事。成交量大而持仓量不动,说明筹码在换手;持仓量涨而成交量一般,说明有新的钱在进场。这也是为什么持仓量必须由撮合结果里的开平标志累加出来,不能拿成交量去推 —— 推不出来。
维护上它是一个增量计数器:每笔成交按上表加减一次,绝不做全量扫描。代价是这个计数器一旦因为漏消息而偏了,会永远偏下去,所以要有一条低频的对账路径拿持仓表求和去校准它。
维持保证金率不是一个常数,它随仓位变大而升高
一个 100 万美元的仓位和一个 1000 美元的仓位,清算难度完全不同 —— 前者要在市场上吃掉的深度大得多,滑点也大得多。所以交易所按名义价值分档,仓位越大,要求的维持保证金率越高,允许的最高杠杆越低。
下面是 Binance USDⓈ-M BTCUSDT 永续的前五档(交易所在「杠杆和保证金」页面上公开,会随时调整,这里取的是 2025-08 那一版):
| 名义价值(USDT) | 最高杠杆 | 维持保证金率 | 速算额 |
|---|---|---|---|
| 0 – 300,000 | 150× | 0.40% | 0 |
| 300,000 – 800,000 | 100× | 0.50% | 300 |
| 800,000 – 3,000,000 | 75× | 0.65% | 1,500 |
| 3,000,000 – 12,000,000 | 50× | 1.00% | 12,000 |
| 12,000,000 – 70,000,000 | 25× | 2.00% | 132,000 |
最后一列「速算额」是这张表里唯一需要解释的东西。交易所文档给的公式是:
维持保证金 = 名义价值 × 维持保证金率 − 速算额一步就算完,没有循环。为什么能这样?拿一个 500,000 USDT 的仓位对照一下就清楚了 —— 它落在第二档:
前 300,000 那一段 300000 × 0.40% = 1200剩下 200,000 那一段 200000 × 0.50% = 1000 ─────维持保证金 2200维持保证金 = 500000 × 0.50% − 300 = 2500 − 300 = 2200两者相等,不是巧合。速算额就是为了让分段函数在档位边界上接得上而补的那个差,递推公式是「上一档的速算额 + 本档起点 × (本档费率 − 上一档费率)」。拿它把整列验一遍:
第 2 档 0 + 300000 × (0.50% − 0.40%) = 300 ✓第 3 档 300 + 800000 × (0.65% − 0.50%) = 1500 ✓第 4 档 1500 + 3000000 × (1.00% − 0.65%) = 12000 ✓第 5 档 12000 + 12000000 × (2.00% − 1.00%) = 132000 ✓四行全中。这说明公布出来的那一列不是拍脑袋定的参数,而是前两列的推论 —— 交易所真正的自由度只有「档位边界」和「维持保证金率」两列。
这条设计对代码的意义是:维持保证金的计算变成一次查表加一次乘减,没有循环,也不会因为档位数量变多而变慢。风控要在每次标记价格更新时对全量仓位跑这个计算,这个常数时间是刚需。
强平价能解出来
有了上面这些,强平价不再是一个从交易所接口读回来的神秘数字,而是一个可以自己解的方程。
强平的判定条件是:保证金余额跌到等于维持保证金。写成等式,以逐仓多头为例:
保证金余额 = 起始保证金 + (P − 开仓均价) × 数量维持保证金 = P × 数量 × 维持保证金率 − 速算额
强平时两者相等代进具体数字:10 BTC 多单,开仓均价 50,000,名义价值 500,000,落在上面那张表的第二档(0.50%,速算额 300)。逐仓 10 倍杠杆,起始保证金 50,000。
50000 + (P − 50000) × 10 = 0.005 × P × 10 − 30050000 + 10P − 500000 = 0.05P − 30010P − 450000 = 0.05P − 3009.95P = 449700P = 45195.98回代验一遍:
保证金余额 = 50000 + (45195.98 − 50000) × 10 = 1959.80维持保证金 = 0.005 × 45195.98 × 10 − 300 = 1959.80 ✓从 50,000 跌到 45,195.98,是 9.61%。10 倍杠杆听起来「跌 10% 才爆」,实际是跌 9.61% 就到了 —— 差的那 0.39% 正是维持保证金提前拿走的缓冲。杠杆倍数的倒数不是强平线,这是最常见的一处误算。
(顺带检查一下档位:强平价上的名义价值是 451,960,还在第二档里,没有跨档。如果解出来的 P 让名义价值掉进了上一档,得换那一档的参数重解一次 —— 这就是为什么强平价在代码里通常是迭代算出来的,不是一个闭式解。)
全仓的方程结构相同,但「保证金余额」是账户级的,包含其他仓位的浮盈浮亏,所以某个仓位的强平价会随着别的仓位的价格变动而移动。这就是为什么全仓下交易所显示的强平价是一个不断跳动的估算值,而逐仓下它是稳定的。
持仓限制盯的是两件不同的事
个人持仓上限防的是单个用户的信用风险 —— 他的仓位大到清算不掉,穿仓的窟窿就落到保险基金和其他用户头上。这个限制通常不是硬性的一个数,上面那张阶梯表本身就是它:仓位越大最高杠杆越低,到最后几档只剩个位数倍杠杆,实际上就开不动了。
持仓集中度盯的是另一件事:前几名用户占总持仓的比例。它防的是市场操纵 —— 一个人拿着足够大的份额,就有动机去动价格,而不只是承担价格。这两个限制的执行方式也不同,前者在下单时同步拦截,后者是事后监控加人工介入,因为它需要跨账户识别关联方,这件事没法在下单那几十微秒里做完。
这一层的代价
未实现盈亏不落库,换来的是每次读都要现算。 一个持有几千个仓位的机构账户,查一次账户总权益就是几千次乘法加一次求和。这个开销在标记价格更新时会被全量放大,是风控服务最主要的 CPU 去处。
双向持仓让资金效率变差。 同一个合约上同时持有多空,净敞口是零,但两边各自占用保证金,还各自付资金费。它的用处在策略上(比如锁仓等待税务年度切换),不在效率上,所以默认关闭是对的。
阶梯表一改,所有人的强平价都变。 上调某一档的维持保证金率,那一档里所有存量仓位的强平价立刻往不利方向移动。所以调整阶梯表要提前公告,而在极端行情里最需要调它的时候,恰恰是最不该突然调的时候 —— 这个两难没有好答案,多数交易所选择只对新开仓生效。
持仓量的增量计数器会漂。 它靠每笔成交累加,任何一次漏消息都是永久偏差。定期用持仓表求和去校准是必须的,但校准本身要扫全表,只能低频跑 —— 于是在两次校准之间,公开的持仓量数据总是可能有一点点不准。
这篇是 加密货币交易所的第 11 篇。前一篇是 加密货币交易所十:订单处理流程,后一篇是 加密货币交易所十二:安全性和风险控制。