
Post Only 限价单被拒绝,通常不是价格格式写错,而是提交瞬间这张单会取走流动性。Coinbase Exchange 的规则是:post_only 要求订单只做 Maker;任何部分会立即与对手盘成交,整笔订单即被拒绝,零成交,也不会自动转成普通限价单继续挂着。因此,“我填的是一个挂单价”与“引擎收到时它仍处于被动一侧”是两件事。
挂单价为什么不等于 Maker 成交
普通限价单进入撮合引擎后,先看能否立即成交。买单价格大于等于卖一价,就会吃掉卖一;卖单价格小于等于买一价,就会吃掉买一。这部分成交属于 taker。Post Only 订单遇到同样的情形,平台按“只提供流动性”处理,直接拒绝整单。普通限价单则可能先完成可成交部分,剩余数量再进入订单簿。
Coinbase 文档对 post_only 的说明是:订单只应提供流动性,若有任何部分取走流动性,订单被拒绝且不执行。文档还注明,post_only 与 IOC、FOK 同时使用属于无效组合。这类参数冲突是另一种拒绝来源,与价格是否触及对手价要分开排查。
一个最小判定例子
假设卖一价为 100,数量足够,且暂不考虑手续费与最小下单量。
| 订单 | 价格 | 提交时结果 | 原因 |
|---|---|---|---|
| 普通限价买单 | 101 | 可能立即以 100 成交,成为 taker | 买价高于卖一 |
| Post Only 买单 | 101 | 被拒绝 | 会立即取走卖一流动性 |
| 普通限价买单 | 99 | 进入买盘等待 | 未立即匹配 |
| Post Only 买单 | 99 | 通常可挂入买盘 | 提交时不吃单 |
99 的买单只是“提交时未立即成交”,不保证之后成交。卖盘可能始终不降到 99,排队也可能轮不到。Post Only 约束的是成交角色,不是成交概率。
盘口变化会让“安全价”变得不安全
界面显示的参考价、最新成交价或用户输入价,都不等于撮合时的对手方最优价。提交前盘口可能已经变化:卖一从 101 降到 100,原本看似被动的买价 100 就变成可立即成交。行情刷新间隔、网络延迟、下单前最后一口流动性被撤走,也会造成“看到的价格”与“引擎收到的价格”不一致。判断依据应是对手方最优价,而不是自己填写的数字。
拒绝不一定只因为吃单
触及对手价是 Post Only 拒单的典型原因,但不是唯一原因。资金不足、价格精度不符合报价单位、数量低于最小下单量、参数组合无效,都可能让订单被拒。排查时应先看订单状态和拒绝原因字段,再区分是 Post Only 语义导致的拒单,还是余额、参数等一般性拒单。被撮合引擎拒绝的订单不会以已挂单状态留在订单簿里;把它当成“暂时没成交”会造成重复提交和仓位误判。
判定与排查
- 比较可成交方向:买单看买价是否大于等于卖一价;卖单看卖价是否小于等于买一价。满足任一条件,就存在立即成交可能,Post Only 会被拒。
- 看状态与拒绝原因:确认订单是否真的进入订单簿,并用拒绝原因字段区分 Post Only 拒单、余额不足和参数错误。
- 检查参数组合:确认没有把
post_only与IOC、FOK混用。 - 保留价格余量:若希望挂单,买单应低于当前卖一,卖单应高于当前买一;余量取决于价格跳动和盘口变化速度,无法预先保证一定不被拒。
- 区分状态:打算挂单、提交订单、订单被接受、订单成交是四个不同状态。只有进入订单簿才谈得上排队,只有后续对手方来吃才谈得上 Maker 成交。
概括来说,Post Only 被拒的核心是提交瞬间会取走流动性,而不是挂单价本身写得不对。挂单价等于某个数字,不代表它相对当前对手盘一定处于被动一侧;即使成功挂入,Post Only 也只限定成交角色,不承诺最终成交。