成交与费用
一张限价单分几次成交,手续费该怎么算?
限价单部分成交时,按每笔成交价、数量、maker/taker 身份和扣费资产核算,再处理撤单余量、BNB 抵扣与导出去重。
订单页显示“一张限价单”,成交明细却有三行,手续费也跟着出现三笔。核账时应以每一笔实际成交为起点:成交多少、按什么价格成交、这一笔是 maker 还是 taker、实际扣了哪种资产,逐行记录后再按订单汇总。订单总额适合核数量,不能替代成交明细计算手续费。
本文只讨论中心化交易所的现货订单簿,不延伸到 DEX 的 Gas、链上路由,也不套用股票券商的最低佣金。文中的币种、价格和费率都是教学假设,不代表真实交易或平台当前收费。平台费率、优惠和取整规则会调整,最终应以账户在成交时留下的手续费记录为准。
先把订单与成交分成两层
限价委托表达的是“最多买到什么价格”或“最低卖到什么价格”,订单簿撮合后才形成成交。一张买入 10 枚 XCOIN 的委托,可能先成交 2 枚,几分钟后成交 3 枚,最后再成交 5 枚;也可能只成交 4 枚,余下 6 枚被用户取消。手续费跟着已发生的成交产生,不跟着未成交的委托数量产生。
因此,核账要同时保留两层记录:
| 层级 | 主要回答的问题 | 适合核对的内容 | 不宜单独据此判断 |
|---|---|---|---|
| 订单 | 这次委托想买卖多少,当前状态是什么 | 委托数量、累计成交数量、未成交余量、取消状态 | 每一笔的实际费率、扣费资产和逐笔取整 |
| 成交 | 订单具体怎样被撮合 | 成交价、成交量、maker/taker、手续费、扣费资产、成交时间 | 原订单还剩多少未成交 |
限价单也不等于 maker 单。若限价买单进入市场时,价格足以与卖盘中的现有挂单立即成交,立即成交的部分拿走了流动性,可能按 taker 计费;剩余部分进入订单簿后,日后被别的订单成交,才可能按 maker 计费。币安的官方说明也明确举出一张 GTC 订单同时产生 taker 与 maker 成交的情况。若产品提供 Post Only,它可以用于避免订单立即作为 taker 成交,但对账仍应读取实际成交标记,而不是根据下单意图猜测。
同一订单号只是把成交归在一起的线索,不能把几笔成交压成一个虚构的“统一费率”。
逐笔手续费如何计算
教学核算可以写成:
单笔理论手续费 = 该笔计费基数 × 该笔适用费率
难点在三个“该笔”。计费基数要取这一笔实际成交的数量或金额;费率要取成交当时针对该交易对、账户等级和流动性身份适用的费率;扣费资产及换算要以实际记录为准。买入与卖出时默认收到的资产不同,启用 BNB 抵扣后扣费资产还可能改变,所以不能永远假设手续费用 USDT 表示。
账表应同时放“理论手续费”和“实际手续费”。理论列用于解释费率,实际列用于财务汇总。若平台逐笔按其精度规则处理,先把多笔未取整理论值相加再取整,可能与每笔实际扣费相加不同;不能为了让总数好看而改写原始 commission。
三笔 0.84 示例
先看成交价格相同、流动性身份不同的教学数据。假设某 XCOIN/USDT 买单分三次成交,第一笔为 taker,假设费率 0.10%;后两笔为 maker,假设费率 0.08%。为单独说明 maker/taker 混合,三笔成交价都设为 100 USDT。表中的手续费暂以 USDT 作为教学记账单位,不代表真实平台一定这样扣费。
下表价格、成交额和费用的单位为 USDT。吃单对应 taker,挂单对应 maker。
| 成交 | 数量 × 价格 | 费用计算 |
|---|---|---|
| A 吃单 | 2 × 100 | 200 × 0.10% = 0.20 |
| B 挂单 | 3 × 100 | 300 × 0.08% = 0.24 |
| C 挂单 | 5 × 100 | 500 × 0.08% = 0.40 |
三笔共成交 10 枚,成交额为 200 + 300 + 500 = 1,000 USDT;手续费为 0.20 + 0.24 + 0.40 = 0.84 USDT。以教学记账单位计算的综合费率为 0.84 ÷ 1,000 = 0.084%。0.084% 是三笔结果的加权值,不是平台另设的一档费率。若用 0.08% 套整单,会少算第一笔;若用 0.10% 套整单,又会多算后两笔。
成交价格也变化的示例
再看更接近日常导出的情况。假设一张买入 5 枚 YCOIN 的限价单设为 101 USDT,进入订单簿时立即吃掉 98.00 和 99.20 两档卖单,因此 D、E 两笔是 taker;剩余数量以 101.00 挂在订单簿,后来成交的 F 是 maker。费率仍是纯教学参数,手续费继续用统一记账单位展示,以便先练习逐行计算。
价格、成交额和费用继续用 USDT 表示。
| 成交 | 数量 × 价格 | 费用计算 |
|---|---|---|
| D 吃单 | 1.50 × 98.00 | 147.00 × 0.10% = 0.14700 |
| E 吃单 | 2.25 × 99.20 | 223.20 × 0.10% = 0.22320 |
| F 挂单 | 1.25 × 101.00 | 126.25 × 0.08% = 0.10100 |
总成交额是 147.00 + 223.20 + 126.25 = 496.45,总手续费是 0.14700 + 0.22320 + 0.10100 = 0.47120。数量加权平均成交价是 496.45 ÷ 5 = 99.29,但不能再用 99.29 乘一个统一费率倒推出原手续费,因为三笔的流动性身份不同。按总成交额观察,教学综合费率约为 0.47120 ÷ 496.45 = 0.09491%;这个结果仍只是复核指标。
核对成交数量与净到账
前面的两个例子把手续费暂时放在统一记账单位中,适合练习 maker/taker 加权。真正核钱包余额时,还要处理“成交数量”和“净收到数量”的差别。币安官方现货资料说明,常规情况下手续费通常从交易中收到的资产收取:买入时收到基础资产,卖出时收到报价资产。启用且满足 BNB 抵扣条件时,扣费资产可能改为 BNB。无论采用哪一种,都应以成交明细的 commissionAsset 为准。
假设某买单以 25.00 USDT 限价委托买入 8 枚 ACOIN,进入订单簿时先吃掉 24.80 和 24.90 两档卖单,剩余数量挂在 25.00;最后成交 6 枚,余下 2 枚取消。三笔教学记录如下;费率不是平台当前费率,并假设都从买入后收到的 ACOIN 中扣除。
下表数量为 ACOIN,价格为 USDT;费用从 ACOIN 数量中计算扣除。
| 成交 | 数量 × 价格 | 扣费计算(ACOIN) |
|---|---|---|
| T101 吃单 | 2 × 24.80 | 2 × 0.10% = 0.0020 |
| T102 吃单 | 3 × 24.90 | 3 × 0.10% = 0.0030 |
| T103 挂单 | 1 × 25.00 | 1 × 0.08% = 0.0008 |
成交数量合计为 2 + 3 + 1 = 6 ACOIN,报价成交额为 49.60 + 74.70 + 25.00 = 149.30 USDT,ACOIN 手续费为 0.0020 + 0.0030 + 0.0008 = 0.0058 ACOIN。在这个假设里,净收到数量是 6 - 0.0058 = 5.9942 ACOIN。订单的未成交余量仍是 8 - 6 = 2 ACOIN,它不会进入成交额,也不会产生这一订单的现货成交手续费。
这组数量核对可以解释一种常见误会:订单页显示买到 6 枚,钱包可用余额却只增加 5.9942 枚,并不自动意味着少成交了 0.0058 枚。先查看实际手续费是否正好以 ACOIN 扣除。若明细显示手续费资产是 BNB,理论上的净到账数量应重新按 BNB 路径核对,不能继续从 6 枚 ACOIN 中减费。
卖出时也按成交额核对净到账。若成交明细显示卖出 6 ACOIN、报价成交额 149.30 USDT、手续费 0.1493 USDT,那么教学条件下净收到报价资产是 149.30 - 0.1493 = 149.1507 USDT。这只是说明账表关系;实际费用数量、资产和精度全部取成交记录。
为了避免把仓位成本算乱,可在账表中把“成交数量”“手续费资产”“手续费数量”“净入账数量”分开。以后计算平均持仓成本时,选择用成交前数量还是扣费后的净数量,必须在整本账中采用同一规则并写进说明,不能只在出现差异的订单上临时换算法。
部分成交后撤单如何核对
订单状态为“已取消”不代表整张订单没有成交,也不代表此前手续费应退回。应先核累计成交量,再算未成交余量:
未成交余量 = 委托数量 - 累计成交数量
假设限价买入 10 枚 ZCOIN,其中 4 枚以 50 USDT 成交,余下 6 枚随后取消。已成交金额是 4 × 50 = 200 USDT。若为了教学假设这一笔的记账费率为 0.10%,理论手续费为 200 × 0.10% = 0.20 USDT。取消的 6 枚没有形成现货成交,不能把 10 × 50 = 500 USDT 当手续费基数,也不能因为最终状态是取消就把已成交的 0.20 抹掉。
核对这类订单,可使用下面的数量关系:
| 项目 | 教学数量 |
|---|---|
| 原始委托数量 | 10 |
| 成交明细数量合计 | 4 |
| 取消时未成交余量 | 6 |
| 数量恒等式 | 4 + 6 = 10 |
若订单页的累计成交为 4,而导出里只找到 3,首先怀疑成交导出缺行或筛选范围不完整;若导出合计为 5,则检查是否重复导入。不要通过新增一行“平衡数”强行对平,因为那会失去成交编号、扣费资产和时间证据。
扣费资产不同怎么汇总
币安现货资料说明,常规现货手续费通常按交易中收到的资产收取;启用 BNB 手续费抵扣后,符合条件的费用会换算成 BNB。真正对账时仍以每笔 commissionAsset 为准,因为买卖方向、功能开关、余额和具体活动都可能让扣费资产不同。
例如,同一订单的三笔实际记录分别为 0.00012 BNB、0.00011 BNB 和 0.08 USDT。正确的原币汇总是:
- BNB 手续费:
0.00012 + 0.00011 = 0.00023 BNB - USDT 手续费:
0.08 USDT
不能写成“总手续费 0.08023”,因为 BNB 与 USDT 不是同一计量单位。如果管理账需要统一折成 USDT,应新增估值价格、估值时点和折算值三列,同时保留原始手续费数量。这样才能区分“平台实际扣了多少币”和“这笔币在某个时点值多少 USDT”。
BNB 抵扣余额不足
打开 BNB 抵扣开关也不等于每笔一定按 BNB 折扣扣费。币安官方说明写明,现货账户需要持有足够 BNB;余额不足时,会按费用与交易概览页列示的原始手续费收取。官方页面同时提醒,下单界面的预计手续费只供参考,最终费用取决于实际成交。
因此,若前两笔扣 BNB、后一笔突然改扣收到的资产,不要先把它认定为重复收费,也不要自行假设系统会把剩余 BNB 用完后仅补差额。更稳妥的处理是逐笔检查:成交时间、BNB 可用余额、抵扣开关状态、commission、commissionAsset,以及当时的实际费率记录。账表只记录已发生的扣费;对余额不足原因没有账户证据时,标成“待核”,不要把推测写成结论。
导出缺行与重复如何排查
合并网页导出、分月 CSV 和 API 结果时,最容易出现两类错误:筛选窗口漏掉一段,以及同一笔成交被导入两次。处理顺序应先保全原文件,再在工作副本中标准化。
查缺行
- 先按账户范围、现货市场和交易对固定范围,记录导出的开始时间、结束时间与时区。
- 用订单页的累计成交数量,对比同一
orderId下所有qty之和;再用订单成交额对比quoteQty之和。 - 检查时间边界。按月导出时,UTC 月末与本地月初可能落在不同文件;毫秒时间戳应保留到原始精度。
- 若使用 API,记录每次查询参数和返回条数,按文档允许的时间或成交编号方式连续取数。一次返回达到上限或仍有后续记录时,继续分页,不能把单次响应当作完整历史。
- 若订单数量能对上而手续费对不上,检查是否遗漏
commissionAsset列,或表格软件把很小的数显示为 0。
查重复
建议用“账户范围 + 市场 + 交易对 + 成交编号”作为账表中的复合去重键,订单编号作为复核列。同一个订单号对应多笔不同成交编号是正常情况,不能按 orderId 去重;相同时间、价格和数量也可能是两笔真实成交,不能仅凭这三列删除。
若同一复合键在网页导出和 API 文件中各出现一次,保留一笔,并在“来源文件”列同时记录两个来源。若关键字段不一致,先保留两行、标记冲突,再回到官方成交历史核对;不要任意选择手续费较小的一行。
可复制的逐笔账表
每笔成交应该保留哪些字段
网页、CSV 和 API 的中文列名可能不同,先把字段含义统一,后续才能合并。币安现货账户成交接口返回的核心字段包括 symbol、id、orderId、price、qty、quoteQty、commission、commissionAsset、time 和 isMaker。其中 id 是成交编号,orderId 是订单编号;两者不能互换。
| 账表列与接口字段 | 用来核对什么 |
|---|---|
| 账户范围(自行记录) | 区分主账户、子账户或其他账本,不同账户的数字编号不能混着去重 |
| 市场(自行记录) | 本文固定为现货,不把杠杆、合约流水混入 |
交易对 symbol |
确定基础资产与报价资产,不跨交易对仅凭数字编号去重 |
成交编号 id |
定位一笔成交,连同账户范围、市场和交易对使用 |
订单编号 orderId |
汇总一张委托,一个订单号出现多行通常是分批成交 |
成交时间 time |
排序、分账期、核对费率时点,统一时区并保留原始毫秒时间戳 |
成交价 price |
计算实际成交金额,不用订单限价代替 |
成交数量 qty |
这一笔实际成交的基础资产数量,不用原始委托数量代替 |
报价成交额 quoteQty |
可用价格乘数量复核,实际返回值优先 |
成交身份 isMaker |
区分挂单或吃单,同一订单可以有两种身份 |
手续费数量 commission |
保留实际原值,不先折算或四舍五入 |
扣费资产 commissionAsset |
确认费用以什么资产收取,不同资产分组汇总 |
如果只做手工对账,最少也要留下交易对、成交编号、订单编号、时间、成交价、数量、成交额、maker/taker、手续费和扣费资产。缺少成交编号时,先回到更完整的原始导出补字段;用“同一分钟、同价格、同数量”拼成替代编号,容易误删两笔真实成交。
原始字段旁边可以增加解释列,但不要覆盖原值。比如网页把 isMaker=true 显示为“挂单方”,工作表可另建“身份中文”列;时间戳可另建“本地时间”列;quoteQty 可另建“计算成交额”列进行交叉检查。若两列不一致,保留差异并回查精度,而不是把接口返回值改成手算值。价格和数量也应按文本或足够的小数位导入,避免表格软件自动转成科学计数法或截断末尾精度。对账文件一旦交给别人复核,原始列、转换列与汇总列分开,才看得出差异是在交易记录里,还是在导入和计算过程中产生。
下面这组表头可以直接粘贴到表格软件。金额列不要预先设置成两位小数,以免小额手续费被显示精度掩盖。
账户范围,市场,交易对,成交编号,订单编号,成交时间UTC,成交价,成交数量,报价成交额,isMaker,实际手续费,扣费资产,成交时费率依据,理论手续费,估值时点,估值价格,统一计价成本,来源文件,去重键,核对状态,备注
汇总表则保持简单:
订单编号,交易对,委托数量,成交数量合计,未成交余量,成交额合计,maker成交额,taker成交额,手续费资产,该资产手续费合计,统一计价成本,差异状态
同一订单有两种扣费资产时,在汇总表中写两行,不要把资产名称塞进一个单元格后直接求和。推荐的公式关系是:
- 成交数量合计等于该订单所有唯一成交编号的
qty之和; - 未成交余量等于委托数量减成交数量合计;
- 成交额合计等于所有唯一成交编号的
quoteQty之和; - 某资产手续费合计只汇总
commissionAsset等于该资产的commission; - 统一计价成本等于各原币手续费乘各自明确记录的估值价格,不能反推覆盖原币数据。
这张表也能与资金费用对账分开:现货逐笔手续费用成交编号归集,永续合约资金费用则围绕结算事件和资金流水核对。把两类成本放在同一个总账没有问题,但来源键和计算公式不能混用。
账期与估值规则怎样固定
逐笔数据对上后,月度报表仍可能因为账期和估值方式不同而出现差异。先在工作簿首页写明账期时区、起止时间是否包含、手续费原币的估值时点和价格来源。比如采用 UTC 月度账期时,可以把 9 月定义为 2026-09-01 00:00:00 UTC(含)至 2026-10-01 00:00:00 UTC(不含)。这样,一笔发生在新加坡时间 10 月 1 日清晨的成交仍可能属于 UTC 9 月,分类依据清楚可复查。
估值也要与原币汇总分开。假设 9 月手续费合计为 0.004 BNB,月报选择每笔成交时的换算价,就逐笔折算后再汇总;若管理报表选择月末价,则整月统一用月末价。两种方法可能得到不同的 USDT 估值,但原始成本始终是 0.004 BNB。账表应标注所选方法,不能用某个更接近订单页显示值的价格反复试算,直到数字“看起来对了”。
需要重跑报表时,从未改动的原始导出重新生成工作表,并保存导入文件名、生成时间和筛选条件。手工修正应放在单独的调整表,写清原成交编号、调整原因和证据链接;不要直接覆盖 commission、commissionAsset 或成交时间。这样,即使平台后来改变显示格式,也能从原始字段还原当时的计算。
年度或跨平台汇总时,先在各平台内部完成去重,再转成统一列名。不同平台的成交编号规则未必相同,不能把某个平台的数字 ID 当成全局 ID。平台名称、账户范围和市场类型都应成为复合键的一部分;这也能防止现货成交与同名合约成交被错误合并。
差异仍未消失时查什么
完成逐笔加总后仍有差异,按下面的证据顺序排查:
- 范围:账户、现货市场、交易对、起止时间和时区是否一致。
- 完整性:成交数量合计能否与订单累计成交量对应,API 是否取完全部页。
- 重复:是否将网页、CSV 和 API 中的同一成交编号重复导入。
- 费率身份:每笔
isMaker是否与所用费率一致,是否误把整张限价单都当 maker。 - 扣费资产:是否把 BNB、基础资产和报价资产直接相加,或漏掉余额不足后的非 BNB 扣费。
- 历史条件:是否拿今天的费率等级、促销或开关状态重算过去的成交。
- 精度:是否用显示值代替原始精度,或先汇总理论值再统一取整。
向平台客服提交问题时,准备订单编号、成交编号、交易对、UTC 时间、实际手续费和扣费资产即可形成可定位的证据包。API 密钥、密码、2FA 恢复信息都不属于对账材料。
资料来源与核验日期
本文于 2026-09-11 核验。下列官方资料用于核对流动性身份、成交字段和 BNB 抵扣情况,实际费率仍以账户成交时记录为准。
作者:Tradecost 编辑部