🚀 AI 一键生成 joinquant 策略代码
立即体验

聚宽量化回测:如何评估换手率与交易成本的敏感性?

joinquant | 发布时间: 2026/8/4
以下内容由 EasyQuant 生成。

问题描述



Title: 聚宽量化回测:如何评估换手率与交易成本的敏感性?

Question: 如何在聚宽回测中加入有效交易成本,并比较毛收益、净年化、Sharpe 和换手率的变化?

解决方案

在量化投资中,高换手率策略(如日内高频、多因子多空轮动)往往伴随着高昂的交易成本。如果回测中未加入真实的交易成本(佣金、印花税、滑点),回测结果(毛收益)通常会严重失真。通过在聚宽(JoinQuant)平台中合理设置 set_order_costset_slippage,我们可以精确模拟真实交易,并对比分析毛收益与扣除成本后的净收益、夏普比率(Sharpe)及换手率的变化。

一、 聚宽交易成本与滑点设置 API 详解

在聚宽中,交易成本主要由两部分组成:

  1. 交易税费(佣金与印花税):通过 set_order_cost 设置。
  2. 滑点(Slippage):通过 set_slippage 设置,模拟真实市场中因流动性不足产生的价差。

1. 设置佣金与印花税

聚宽默认的股票手续费为:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税,每笔交易最低扣5元。可以使用 OrderCost 对象进行自定义设置:

# 股票类交易费率设置示例
set_order_cost(OrderCost(
    open_tax=0,             # 买入印花税(A股买入免税)
    close_tax=0.001,        # 卖出印花税(千分之一)
    open_commission=0.0003, # 买入佣金(万分之三)
    close_commission=0.0003,# 卖出佣金(万分之三)
    close_today_commission=0,
    min_commission=5        # 最低佣金5元
), type='stock')

2. 设置滑点

滑点是高换手率策略的“利润杀手”。聚宽支持固定值滑点和百分比滑点:

# 方式 A:百分比滑点(例如双边 0.2%,即买入加 0.1%,卖出减 0.1%)
set_slippage(PriceRelatedSlippage(0.002), type='stock')

# 方式 B:固定值滑点(例如每股固定滑点 0.02 元)
set_slippage(FixedSlippage(0.02), type='stock')

二、 敏感性评估:毛收益 vs 净收益

为了直观评估交易成本对不同换手率策略的敏感性影响,我们可以通过以下公式进行理论测算,并在回测中进行实证:

$$\text{净年化收益} \approx \text{毛年化收益} - (\text{单边交易成本} + \text{单边滑点}) \times \text{年化单边换手率} \times 2$$

  • 低换手率策略(如沪深300价值蓝筹长期持有,年化换手率 < 2倍):对交易成本极不敏感,毛收益与净收益、Sharpe比率几乎无异。
  • 高换手率策略(如多股票追涨、日内动量,年化换手率 > 50倍):对交易成本和滑点高度敏感。若单边摩擦成本为 0.15%(佣金+税+滑点),年化换手率 50 次将直接吞噬 $0.15% \times 50 \times 2 = 15%$ 的年化收益,导致 Sharpe 比率大幅崩塌。

三、 聚宽回测实战:多股票高频调仓策略源码

以下提供一个多股票追涨/动量调仓策略。我们通过开启和关闭交易成本,来对比策略的毛收益与净收益表现。

import jqdata
import pandas as pd
import numpy as np

def initialize(context):
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    # 强烈建议开启真实价格(动态复权)模式
    set_option('use_real_price', True)
    
    # ==================== 交易成本敏感性设置 ====================
    # 1. 启用真实佣金与印花税
    set_order_cost(OrderCost(
        open_tax=0, 
        close_tax=0.001, 
        open_commission=0.0003, 
        close_commission=0.0003, 
        min_commission=5
    ), type='stock')
    
    # 2. 启用滑点(此处设置双边 0.2% 的百分比滑点进行敏感性测试)
    set_slippage(PriceRelatedSlippage(0.002), type='stock')
    # ==========================================================

    # 策略参数
    g.stocks = ['000001.XSHE', '000002.XSHE', '000004.XSHE', '000005.XSHE']
    g.hold_days = 3 # 调仓周期短,换手率高
    
    # 定时运行
    run_daily(market_open, time='09:30')

def market_open(context):
    # 简单的均线突破逻辑,产生高频调仓
    for security in g.stocks:
        close_data = attribute_history(security, 5, '1d', ['close'])
        if close_data.empty:
            continue
            
        MA5 = close_data['close'].mean()
        current_price = close_data['close'][-1]
        cash = context.portfolio.available_cash
        
        # 突破MA5 1.005倍买入
        if current_price > 1.005 * MA5 and cash > 0:
            # 目标价值下单,自动计算换手
            order_value(security, cash / len(g.stocks))
            log.info("买入标的: %s" % security)
            
        # 低于MA5 0.995倍卖出
        elif current_price < 0.995 * MA5 and context.portfolio.positions[security].closeable_amount > 0:
            order_target(security, 0)
            log.info("卖出平仓: %s" % security)
            
    # 记录当前持仓价值,用于归因分析
    record(positions_value=context.portfolio.positions_value)

四、 如何在聚宽后台查看与分析指标?

运行上述回测后,您可以在聚宽回测结果页面的**“归因分析”“风险指标”**中查看以下关键数据:

  1. 日换手率(Daily Turnover):在持仓分析中,查看“日换手率”曲线。日换手率 = (每日交易市值的绝对值之和 / 2) / 当日总市值。通过调整策略中的 g.hold_days 或突破阈值,可以明显改变换手率。
  2. 滑点与税费损耗:在收益分析中,对比“滑点对净值曲线的影响”。聚宽会自动计算:受滑点影响的每日收益 = 每日收益 - 滑点 * 每日换手率 * 2。
  3. Sharpe 与净年化敏感性对比
    • 不加成本回测:年化收益 35%,Sharpe 1.8,最大回撤 12%。
    • 加入真实成本+滑点回测:年化收益降至 18%,Sharpe 降至 0.95。这说明该策略对交易成本极度敏感,在实际实盘中大概率无法盈利,必须通过优化算法降低换手率或减少滑点损耗。