OptiNod 学院
滑点、手续费与流动性——回测隐藏的交易成本
按相同的名义金额口径计算手续费和成交成本,并检查买卖价差的重复计算、交易频率的分母,以及实际下单规模与盘口深度。
即使知道手续费率,最终的交易成本仍然未知。要确认与下单规模相匹配的成交成本,才能把回测的期望值与实盘联系起来。
看交易成本时,要区分向交易所支付的手续费(Fees)、买卖盘口报价之差的买卖价差(Spread),以及基准价格与实际成交价格之差的滑点(Slippage)。流动性(Liquidity)是影响这些成交成本的市场条件,并不是另外收取的手续费项目。手续费率也因交易所、产品、下单方式和账户等级而不同,因此要确认实际适用的费率。
例如,假设单边手续费为0.04%,那么入场、出场名义金额相同的往返手续费率就是0.08%。这个数值以及下面的绩效、盘口示例,都是为了说明计算而做的假设,并不代表某个交易所当前的费率,也不是实测的订单簿。实际成本要把相应费率乘以每笔成交金额后加总。
要确认的是,成本消耗了策略多少平均盈利空间。市价单吃掉多档报价,或者下单过程中价格发生移动,成交价格就可能变得不利。滑点并不总是大于手续费,同一个品种也会因时间段和下单规模而不同。如果以中间价为基准计算的滑点已经包含了买卖价差,就不要再重复加上价差。

手续费与成交价格差异要分开计算,流动性影响的是成交价格差异。
确认手续费率后,单独测量成交价格差异
手续费只要知道适用费率和成交金额就可以计算。它可能因挂单方与吃单方的区分、产品、账户等级以及是否有折扣、返佣而不同。单边0.04%、相同名义金额往返0.08%,是本文的示例值。要使用交易所最新的实际费率和成交明细。
滑点首先要确定比较基准。如果是市价买入,可以把下单前的最优卖价与实际平均买入价比较,也可以使用中间价或信号产生时的价格。基准不同,买卖价差和下单延迟被包含的范围也不同。大额买单一直吃到更高的卖价,平均买入价格会上升,而即使全部在最优价成交,相对于中间价的买卖价差成本依然存在。
假设一个虚构的短线策略,成本前的平均盈亏相当于每个往返占交易名义金额的0.15%。减去同一口径的往返手续费0.08%,剩下0.07%。如果在没有重复计算买卖价差的情况下,测得额外的往返成交成本为0.10%,期望值的估计就是0.15% − 0.08% − 0.10% = −0.03%。1bp为0.01%,计算时必须统一单边、往返的单位。
市价单入场会消耗盘口深度
订单簿是按价位累积的买卖挂单的列表。市价买入从最低的卖价开始向上逐档填满所需数量。如果最上面一档的量小于下单规模,就会转到更上面一档,平均成交价格是在显示价格之上确定的。
假设虚构资产A的最优卖价是100美元,这个价格上有2,000个。如果报价没有变化,也没有其他订单抢先成交,那么500个市价买单会全部以100美元成交,成交金额为5万美元。相对于最优卖价的价格差为0,但这并不意味着买卖价差和手续费也是0。
假设虚构资产B在100美元有100个,在101美元有900个。在同样的静态条件下买入500个,平均成交价为 (100 × 100 + 400 × 101) ÷ 500 = 100.80美元,成交金额为50,400美元。比最初的卖价100美元高出0.80%,即80bp。实际上还有撤单、新挂单以及与其他订单的竞争,所以这种盘口合计只是某一时点的估计,并不保证成交。

除了成交额,还要确认当前的买卖价差和盘口深度
买卖价差是最优卖价与最优买价之差。盘口稀薄与价差较宽可能同时出现,但不能仅凭日成交额就确定当前的买卖价差。如果在同一盘口以市价买入后立即卖出相同数量,且没有价格移动和市场冲击,那么由价格差造成的亏损就是整个价差一次。
假设买价为99.95美元,卖价为100.05美元,则中间价为100美元,价差为0.10美元,相对中间价为10bp。在卖价买入、立即在买价卖出,每个亏损0.10美元。相对于入场金额100.05美元,约为9.995bp,而不是20bp。如果在不同时点入场和出场,就要把各时点相对中间价的半个价差加总,再单独评估额外的市场冲击、延迟和手续费。还要确认所用的滑点估计值是否已经包含了这些因素。
成交量是成交的数量,成交额是每笔成交的价格与数量相乘之后的合计。假设1亿个全部以0.004美元成交,成交额就是40万美元。比较不同品种的规模时,用统一货币计价的成交额很有用,但过去24小时的成交额并不保证当前有足够的挂单量接下订单。要用预定入场数量直接确认盘口深度和预期平均成交价。

累计成本由交易次数和每笔交易的名义金额来计算
要得出累计成本,需要比率的分母。在相同规模的往返交易适用相同成本率的简单模型中,累计成本 = 交易次数 × 每笔名义金额 × 往返成本率。规模不同时,逐笔把统一口径的名义金额与成本率相乘,再加总。实际手续费是用费率乘以成交金额,而买入的滑点金额是数量 ×(成交价 − 基准价)。上面的资产B是基准名义金额5万美元 × 0.8% = 400美元,而不是用成交金额50,400美元乘以0.8%。在杠杆交易中,手续费的计算基准也不是保证金,而是该产品的交易金额。
假设初始资金1万美元,每次往返交易的名义金额固定为1万美元,往返成本率为0.1%。省略价格变动带来的平仓金额差异和复利,每笔交易的成本是10美元。每天10次 × 22天 = 220次,所以每月成本2,200美元,相当于初始资金的22%。如果每笔交易的名义金额是初始资金10%的1,000美元,同样的计算是220美元,即2.2%。用相同规模每月只交易两次,就是20美元,占初始资金的0.2%,220次与2次的成本差是110倍。22%并不是适用于所有账户的月亏损率。
这个模型是为观察成本累积而设的计算,并不是对策略净利润的预测。交易盈亏、余额变化、仓位规模和成本率不同,实际账户的变化也会不同。把滑点设为0的结果与加入实际成交成本的结果,在同一份交易清单上比较,就能看出遗漏的成本有多少。并没有“遗漏的滑点总是占总成本一半以上”这样的规则。

优势小于成本时,期望值为负
把成本前的平均盈亏与往返成本,统一到相同的名义金额和单位后做比较。这个差为正,则该假设下的期望值为正,但并不保证实际盈利。样本估计存在误差,市场也会变化,交易规模改变时,还要重新按金额口径汇总盈亏。
假设所有交易的名义金额相同,胜率60%,盈利交易和亏损交易的平均收益率分别为 +0.3%和 −0.3%,那么成本前的期望值是0.6 × 0.3% − 0.4 × 0.3% = 0.06%。减去往返手续费0.08%后是 −0.02%,再减去单独的往返成交成本0.05%,则是 −0.07%。如果同样条件下计入手续费的结果为正,那就不可能是因为滑点为0。要先确认胜率、平均盈亏、手续费的适用单位、仓位规模以及成本是否重复,是否与示例条件相同。
上面示例中成本前的期望值0.06%,是简单模型的盈亏平衡往返成本。仅凭某个品种的名称,不能断定实际成本比它小。假设往返成本是50bp,即0.5%,则期望值为0.06% − 0.5% = −0.44%。如果是成本前期望值为3%的另一个策略,在同样的成本假设之后还剩2.5%,但仅凭这一点并不能解决流动性低的市场中的成交可能性或风险问题。
在剧烈波动区间,要重新检查平时的成交成本假设
即使是平时盘口很厚的品种,在波动率剧烈变化的区间,订单簿上的挂单量也会迅速减少。价格朝一个方向快速运动时,预先挂在盘口的限价单被成交或撤销,而新挂单补充的速度赶不上挂单撤走的速度。此时相同规模的市价单会吃到比平时深得多的档位,滑点变大。
仅凭某个特定日期的K线,无法计算滑点和盘口消耗量。在假设的压力情形下,即使成交额大幅增加,如果订单快速成交、撤销,而新订单进来得慢,瞬时盘口也可能变得稀薄。这时市价止损的成交价可能比触发价格更不利,但要知道不利的幅度,需要当时的盘口、订单和成交记录。不能仅凭成交额增加,就断定价格下跌是由市价卖出造成的。
要分别测量平时与剧烈波动区间的成交差异,并比较成本敏感性。如果没有实测数据,可以用明确列出各种成本假设的情景来测试,但不要把这些当作观测到的值来使用。跳空、交易暂停和订单延迟,可能无法仅靠一个固定的滑点来充分重现。不同时间段的流动性差异,也要通过交易所和品种的记录来确认。
用交易成本过滤器,提前筛掉候选品种和策略
对候选品种,要同时应用成交额、当前买卖价差与盘口深度、下单规模和成本空间。某一天的成交额或买卖价差数字,并不是适合所有策略的安全线。要预先确定可接受的成本预算和暂停交易的条件,在下单前的估计超出这个范围时重新评估。
- 成交额与盘口:用统一货币计价的成交额比较市场规模,并确认当前盘口能否承接预定的下单数量。仅凭日成交额下限不能保证成交。
- 价差预算:按下单规模和策略的成本空间评估当前价差。不要把10bp的价差自动换算成往返20bp。
- 成本单位:记录实际的单边手续费率、入场与出场名义金额,以及滑点的基准价格。确认是否包含价差,避免重复计算。
- 盈亏平衡与敏感性:把成本前的平均盈亏与相同单位的成本做比较,并检查成本进一步增大的情景下的结果。
- 下单规模与失效:如果因盘口变动导致预期成本超出设定预算,就暂缓入场或重新计算规模。限价单和分批下单同样存在未成交和价格变动的风险。
交易越频繁,即使是遗漏的小成本,也可能对累计金额产生很大影响。不过,频率本身并不决定每笔交易的滑点大小。要使用与下单规模和市场状态相符的实测分布,并同时计算相对于资金的累计成交金额。即使每次的平均盈利很大,盘口深度和止损成交风险也要另外确认。
用符合现实的成本假设重新跑回测
通过成本过滤器之后,还要确认回测的成交模型是否与现实相符。比较遗漏成本的结果与采用保守成交假设的结果,并记录结果对成本变化有多敏感。TradingView的固定滑点是以最小跳动点为单位的模型,并不是能精确重现实际订单簿和部分成交的机制。
如果结果是把订单处理成恰好以信号K线的收盘价成交,就要确认订单生成时点与成交时点。没有证据表明那个价格上有所需的数量,就要另外检查成交的可能性。根据交易所和引擎设置,会有下一个逐笔成交、下一根K线、收盘价处理等差异,所以不要假定所有回测都是收盘价成交。预定下单规模越大,除了价格之外,可成交的数量也越重要。
在前面固定名义金额的示例中,如果往返成本率从0.10%增加到0.15%,220次交易的成本就从初始资金的22%增加到33%。如果每笔交易的名义金额是初始资金的10%,则从2.2%变为3.3%。这是额外往返成本0.05个百分点的效果,并不是对实际账户月收益率的预测。在回测结果中要同时留下适用费率、基准价格、下单规模和成本情景,以便与之后的实测成交记录比较。