12、冲击成本回测框架:回测环境搭建、冲击成本模拟、绩效评估指标

做量化交易的朋友都知道,策略在纸上跑得再漂亮,一上实盘就变脸。为什么?说白了,就是冲击成本在作祟。我这些年踩过的坑,十有八九都跟这个有关。今天咱们就来聊聊,怎么搭建一个靠谱的冲击成本回测框架。

12.1 回测环境搭建:别让基础设施拖后腿

回测环境这东西,看着简单,其实门道不少。我个人习惯用 Python + Pandas + NumPy 这套组合,够用且灵活。但要注意几个关键点:

  • 数据精度:至少要用 tick 级数据,分钟级数据做冲击成本分析,误差会大到离谱。我见过有人用日线数据算冲击成本,结果回测收益翻倍,实盘直接亏光。
  • 订单簿重建:你得能模拟出真实的订单簿状态。光有成交价不够,还得有买卖盘口的深度信息。
  • 撮合引擎:要支持限价单、市价单、冰山订单等多种订单类型。别小看这个,不同订单类型的冲击成本差异很大。

核心要点:回测环境的核心是「尽可能接近真实市场」。做不到100%,但至少要覆盖90%的微观结构特征。

这里给个简单的环境搭建示例:

import pandas as pd
import numpy as np
from collections import deque

class OrderBook:
    def __init__(self, depth=10):
        self.bids = deque(maxlen=depth)  # 买单队列
        self.asks = deque(maxlen=depth)  # 卖单队列
        
    def update(self, bid_prices, bid_volumes, ask_prices, ask_volumes):
        self.bids = list(zip(bid_prices, bid_volumes))
        self.asks = list(zip(ask_prices, ask_volumes))
    
    def simulate_market_order(self, side, volume):
        """模拟市价单的冲击成本"""
        if side == 'buy':
            book = self.asks
        else:
            book = self.bids
            
        remaining = volume
        total_cost = 0
        for price, qty in book:
            if remaining <= 0:
                break
            trade_qty = min(remaining, qty)
            total_cost += trade_qty * price
            remaining -= trade_qty
        
        return total_cost, volume - remaining

12.2 冲击成本模拟:从理论到实战

冲击成本模拟,说白了就是算一笔账:你要吃掉多少流动性,得付出多少代价。我常用的模型有这么几种:

模型名称 核心逻辑 适用场景
线性冲击模型 冲击成本与成交量成正比 流动性较好的股票、期货
平方根冲击模型 冲击成本与成交量的平方根成正比 流动性一般的品种
Almgren-Chriss模型 考虑时间因素,动态优化拆单 大单交易、算法交易

嗯,这里要注意一点:没有万能模型。我在做A股策略时,发现线性模型在茅台这种股票上表现不错,但换到小盘股就完全失灵。后来我改用平方根模型,效果好了不少。

个人经验:建议先用历史数据做一次「冲击成本曲线拟合」,看看你的品种到底适合哪种模型。别直接套用别人的参数,会出大问题。

来看一个实际的冲击成本模拟代码:

def calculate_impact_cost(order_book, side, volume, model='linear'):
    """计算冲击成本"""
    if model == 'linear':
        # 线性模型:cost = alpha * volume
        alpha = 0.0001  # 冲击系数,需要根据历史数据拟合
        return alpha * volume * order_book.mid_price()
    
    elif model == 'sqrt':
        # 平方根模型:cost = beta * sqrt(volume)
        beta = 0.001
        return beta * np.sqrt(volume) * order_book.mid_price()
    
    elif model == 'almgren_chriss':
        # Almgren-Chriss模型
        # 这里简化处理,实际需要更多参数
        sigma = 0.02  # 波动率
        gamma = 0.01  # 永久冲击系数
        eta = 0.005   # 临时冲击系数
        
        T = 1.0  # 交易时间
        N = 10   # 拆单次数
        
        x = volume / N  # 每单成交量
        impact = (gamma * volume + eta * x) * order_book.mid_price()
        return impact

12.3 绩效评估指标:别只看收益率

冲击成本回测做完,怎么评价效果?我建议从三个维度来看:

  • 成本维度:冲击成本占总交易金额的比例,这个最直观。我一般要求控制在0.1%以内,超过0.5%的策略基本没法实盘。
  • 执行维度:滑点率、成交率、订单完成时间。这些指标能反映你的订单执行质量。
  • 风险维度:冲击成本波动率、极端情况下的最大冲击成本。别只看平均值,尾部的风险往往更致命。

避坑指南:我曾经犯过一个错误——只看平均冲击成本,忽略了极端行情。结果在2015年股灾时,策略的冲击成本直接翻了10倍,回撤惨不忍睹。所以一定要做压力测试。

下面是我常用的绩效评估指标表:

指标名称 计算公式 理想范围
冲击成本率 冲击成本 / 交易金额 < 0.1%
滑点率 (实际成交价 - 预期价格) / 预期价格 < 0.05%
成交率 实际成交量 / 委托量 > 95%
成本波动率 冲击成本的标准差 越低越好
极端冲击成本 99%分位数的冲击成本 < 0.5%

最后,我习惯把回测结果可视化,这样一眼就能看出问题。下面这张图展示了冲击成本回测的整体框架:

冲击成本回测框架 数据输入层 Tick数据 / 订单簿 回测引擎 订单撮合 / 冲击模拟 绩效评估 成本/执行/风险 冲击成本模型 订单执行算法 风险控制模块 核心逻辑:数据驱动 → 模型模拟 → 绩效评估 → 策略优化 关键输出指标 冲击成本率 | 滑点率 | 成交率 | 成本波动率 | 极端冲击成本

这张图把整个框架串起来了。从数据输入开始,经过回测引擎的模拟,最后输出绩效指标。每个环节都有对应的模型和算法支撑。

我的建议:刚开始做冲击成本回测时,别追求太复杂的模型。先用线性模型跑通流程,再逐步优化。我见过太多人一上来就搞Almgren-Chriss,结果参数调了三个月还没跑通。

好了,冲击成本回测框架的核心内容就这些。记住:回测不是目的,实盘才是。框架搭好了,后面就是不断迭代优化的事。

交易系统化学习资料 微信Strategy888888