14. 交易成本与滑点分析:佣金、印花税、冲击成本、模拟滑点
做基差交易,很多人上来就研究策略、跑回测,结果实盘一跑就傻眼了——明明回测里年化收益20%,怎么实盘变成了亏损?
我告诉你,十有八九是交易成本和滑点没算清楚。说白了,基差交易的利润本身就很薄,有时候一个滑点就能把利润全吃掉。今天我们就来把这笔账算明白。
14.1 交易成本的构成
交易成本不是简单的「手续费」三个字能概括的。我个人习惯把它拆成三块:
- 显性成本:佣金、印花税、过户费。这些是交易所和券商明码标价收的。
- 隐性成本:买卖价差、冲击成本。这些看不见摸不着,但往往比显性成本更可怕。
- 机会成本:资金占用、保证金利息。做套利的人容易忽略这块。
我在项目中遇到过最典型的案例:一个做股指期货期现套利的团队,回测时只算了万分之0.23的佣金,结果实盘发现冲击成本是佣金的10倍以上。嗯,这就是典型的「捡了芝麻丢了西瓜」。
14.2 佣金与印花税
先看最基础的。A股市场的交易费用是这样的:
| 费用项目 | 费率 | 收取方 | 备注 |
|---|---|---|---|
| 佣金 | 万分之1~3 | 券商 | 可协商,最低5元 |
| 印花税 | 万分之5 | 国家 | 仅卖出时收取 |
| 过户费 | 万分之0.1 | 中登公司 | 买卖双向 |
| 期货手续费 | 按手数或比例 | 交易所+期货公司 | 可申请返还 |
你想想看,如果做一次完整的买入卖出,光印花税就是万分之5。基差套利一年可能交易几十次,这笔费用累积起来相当可观。
关键点:印花税只在卖出时收取,所以做多策略比做空策略天然多一层成本。这也是为什么很多高频套利策略更倾向于做空——不是因为他们看空,而是因为成本结构更优。
14.3 冲击成本——真正的隐形杀手
冲击成本是什么?就是你下单时,你的订单本身把价格推高了(买入时)或压低了(卖出时)。
我曾经做过一个统计:在IF主力合约上,如果一次下单50手,冲击成本大约在0.5~1个指数点。别小看这0.5个点,换算成每手就是150元。50手就是7500元——这比佣金贵多了。
冲击成本的计算公式:
冲击成本 = (成交均价 - 订单簿中间价) × 合约乘数 × 手数
举个例子:
# 假设IF合约当前买一价3800.0,卖一价3800.2
# 中间价 = (3800.0 + 3800.2) / 2 = 3800.1
# 你买入10手,成交均价为3800.4
# 冲击成本 = (3800.4 - 3800.1) × 300 × 10 = 900元
为什么会这样?因为你的大单把卖一、卖二、卖三全吃掉了,价格自然就上去了。这就是典型的「大单吃小单,价格往上窜」。
我的建议:回测时至少按0.5个指数点来估算冲击成本。如果资金量大,建议按1个点算。宁可算得保守一点,也不要实盘时被打脸。
14.4 模拟滑点的方法
滑点(Slippage)是冲击成本的另一种表现形式。在回测中,我们没法真实模拟市场深度,所以需要用一些技巧来近似。
我个人常用的三种方法:
- 固定滑点法:最简单粗暴。比如每次交易固定加1个tick的滑点。优点是快,缺点是太粗糙。
- 比例滑点法:按成交金额的万分之几来算。比如万分之1的滑点。这种方法比固定滑点更合理,因为大单的滑点比例其实更低。
- 基于成交量的滑点模型:这是最接近真实的方法。根据你的下单量占市场总成交量的比例来估算滑点。
来看一个基于成交量的滑点模型代码:
def estimate_slippage(order_volume, avg_volume, price, tick_size=0.2):
"""
基于成交量的滑点估算
:param order_volume: 你的下单量(手)
:param avg_volume: 该合约的日均成交量(手)
:param price: 当前价格
:param tick_size: 最小变动价位
:return: 滑点成本(每手)
"""
# 你的订单占市场成交量的比例
volume_ratio = order_volume / avg_volume
# 滑点系数,经验公式
slippage_coeff = 0.5 * (volume_ratio ** 0.5)
# 滑点(以tick为单位)
slippage_ticks = max(1, int(slippage_coeff * 10))
# 滑点成本
slippage_cost = slippage_ticks * tick_size
return slippage_cost
# 示例
order_vol = 50 # 下单50手
avg_vol = 100000 # IF合约日均成交约10万手
price = 3800.0
slippage = estimate_slippage(order_vol, avg_vol, price)
print(f"估算滑点: {slippage:.1f} 个指数点")
避坑指南:我曾经在回测中只用固定滑点法,结果实盘时发现滑点比回测大了3倍。后来我改用基于成交量的模型,才把回测和实盘的差距缩小到10%以内。记住:回测中的滑点设置,宁大勿小。
14.4 基差交易中的成本特殊性
基差交易和普通单边交易不一样,它涉及两个腿:一腿股票/ETF,一腿期货。所以成本是双份的。
举个例子,做期现套利:
- 现货端:买入一篮子股票或ETF,需要支付佣金+印花税(卖出时)+过户费
- 期货端:开仓和平仓各一次,每次都有手续费
- 展期成本:如果持有时间较长,期货合约到期需要移仓,又产生一次交易成本
我算过一笔账:做一次完整的期现套利(开仓+平仓),总交易成本大约在万分之8到万分之12之间。而基差套利的年化收益,很多时候也就5%~10%。你想想看,如果一年做10次,光交易成本就吃掉一半利润。
核心结论:基差交易不是不能做,但必须把交易成本算到骨子里。我个人的经验是:只有当预期收益能覆盖交易成本的3倍以上时,才值得出手。
14.5 如何优化交易成本
既然成本这么重要,那怎么降低它?我分享几个实战技巧:
- 谈佣金:资金量大的话,佣金可以谈到万分之1以下。别不好意思开口,券商也是做生意的。
- 用限价单:市价单虽然成交快,但滑点大。限价单可以控制成交价格,但可能成交不了。这是个trade-off。
- 拆单:大单拆成小单,分批进场。虽然慢一点,但冲击成本能降低不少。
- 选流动性好的合约:IF、IC、IH的主力合约流动性最好,滑点最小。远月合约虽然基差大,但流动性差,滑点也大。
- 避开开盘和收盘:这两个时间段的波动最大,滑点也最大。我一般选择在10:00~11:30和14:00~15:00之间交易。
嗯,这里要注意:优化成本不是让你一味地追求最低成本,而是在成本和成交确定性之间找到平衡。有时候多花一点成本,换来的是确定性成交,这比省了几块钱但没成交要强得多。
14.6 回测中的成本模拟
最后,我们来看看怎么在回测中模拟交易成本。我一般这样写:
def calculate_trading_cost(price, volume, is_buy, is_futures=False):
"""
计算单笔交易的总成本
"""
turnover = price * volume * 300 # IF合约乘数300
if is_futures:
# 期货端:按手数收费
commission = volume * 30 # 假设每手30元
slippage = volume * 0.5 * 300 # 0.5个指数点的滑点
else:
# 现货端:按金额收费
commission = turnover * 0.0003 # 万分之3佣金
stamp_tax = turnover * 0.0005 if not is_buy else 0 # 卖出时收印花税
slippage = turnover * 0.0001 # 万分之1的滑点
commission = max(commission, 5) # 最低5元
total_cost = commission + stamp_tax + slippage
return total_cost
这段代码虽然简单,但已经能覆盖大部分成本了。如果你要做更精细的回测,建议把逐笔成交数据也考虑进去,用真实的订单簿数据来模拟滑点。
一个小技巧:回测时把交易成本设成变量,然后做敏感性分析。看看当成本增加20%、50%、100%时,策略收益会变成什么样。这样你就能知道自己的策略对成本有多敏感。
好了,交易成本和滑点分析就讲到这里。记住一句话:在基差交易里,成本不是细节,而是核心。把成本算清楚了,你的策略才算是真正可落地的。
公众号:蓝海资料掘金营,微信deep3321