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

聚宽平台如何对 ETF 策略进行滑点敏感性分析?(附 Python 源码与多参数对比方法)

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

问题描述

聚宽回测参数:如何进行 ETF 策略滑点敏感性分析?
如何在聚宽中对同一 ETF 策略测试不同滑点参数,并比较交易次数、收益、夏普和最大回撤?

解决方案

在量化交易中,滑点(Slippage)是影响实盘表现的关键交易成本之一,尤其是对于流动性各有差异的 ETF 标的。在聚宽(JoinQuant)平台上,我们可以通过在研究环境中使用 create_backtest API,或者在策略代码中动态调整滑点参数,来对同一策略进行滑点敏感性分析。

以下是进行 ETF 策略滑点敏感性分析的具体方案和 Python 代码实现。

一、 聚宽滑点设置 API 核心基础

在聚宽中,我们主要使用 set_slippage 函数来设定滑点:

  1. 固定值滑点FixedSlippage(0.02)(买入时在均价上加 0.01 元,卖出时减 0.01 元)。
  2. 百分比滑点PriceRelatedSlippage(0.002)(买卖时加减当时价格的 0.1%)。

二、 方案设计:研究模块批量回测法

为了比较不同滑点对同一策略的影响,最有效的方法是在**聚宽研究环境(Notebook)**中,利用 create_backtest 传入不同的 extras 参数(将滑点系数作为全局变量传入),批量启动回测,最后使用 get_backtest 获取各回测的交易次数、收益、夏普比率和最大回撤进行横向对比。

1. 编写策略代码(保存为研究根目录的策略,例如命名为 etf_ma_strategy

# -*- coding: utf-8 -*-
from jqdata import *

def initialize(context):
    set_benchmark('000300.XSHG')
    set_option('use_real_price', True)
    
    # 核心:从外部传入的 extras 中读取滑点类型和滑点值
    # 默认使用百分比滑点 0.00246
    slippage_type = g.run_params.get('extras', {}).get('slippage_type', 'percent')
    slippage_val = g.run_params.get('extras', {}).get('slippage_val', 0.00246)
    
    if slippage_type == 'fixed':
        set_slippage(FixedSlippage(slippage_val), type='fund')
    else:
        set_slippage(PriceRelatedSlippage(slippage_val), type='fund')
        
    g.security = '510300.XSHG' # 沪深300ETF
    
    # 设定手续费
    set_order_cost(OrderCost(open_commission=0.0003, close_commission=0.0003, min_commission=5), type='fund')
    
    run_daily(market_open, time='09:30')

def market_open(context):
    security = g.security
    # 简单的双均线金叉死叉策略作为测试基准
    close_data = attribute_history(security, 20, '1d', ['close'])
    ma5 = close_data['close'][-5:].mean()
    ma20 = close_data['close'][-20:].mean()
    cash = context.portfolio.available_cash
    
    if ma5 > ma20 and context.portfolio.positions[security].total_amount == 0:
        order_value(security, cash)
        log.info("买入 ETF")
    elif ma5 < ma20 and context.portfolio.positions[security].closeable_amount > 0:
        order_target(security, 0)
        log.info("卖出 ETF")

2. 在研究环境(Notebook)中运行多参数敏感性分析脚本

在 Notebook 中运行以下 Python 代码,它将自动提交 4 个不同滑点参数的回测任务,并在完成后拉取数据进行对比:

import pandas as pd
import time
from kuanke.user_space_api import * 

# 1. 定义要测试的滑点参数列表
slippage_tests = [
    {'name': '无滑点', 'type': 'percent', 'val': 0.0},
    {'name': '低滑点(0.1%)', 'type': 'percent', 'val': 0.001},
    {'name': '默认滑点(0.246%)', 'type': 'percent', 'val': 0.00246},
    {'name': '高滑点(0.5%)', 'type': 'percent', 'val': 0.005}
]

backtest_ids = {}
# 假设你的策略在聚宽编辑器的算法ID为 'your_algorithm_id_here' (从策略编辑页URL获取)
algorithm_id = "your_algorithm_id_here" 

# 2. 批量创建回测
for test in slippage_tests:
    params = {
        "algorithm_id": algorithm_id,
        "start_date": "2022-01-01",
        "end_date": "2023-12-31",
        "frequency": "day",
        "initial_cash": "1000000",
        "extras": {
            "slippage_type": test['type'],
            "slippage_val": test['val']
        },
        "name": f"ETF滑点测试_{test['name']}"
    }
    bt_id = create_backtest(**params)
    backtest_ids[test['name']] = bt_id
    print(f"已创建回测: {test['name']}, ID: {bt_id}")

# 3. 等待所有回测运行完毕并收集结果
print("等待回测完成...")
results = []

for name, bt_id in backtest_ids.items():
    gt = get_backtest(bt_id)
    while True:
        status = gt.get_status()
        if status in ['done', 'failed', 'canceled']:
            break
        time.sleep(5) # 每5秒轮询一次
        
    if status == 'done':
        # 获取风险指标
        risk = gt.get_risk()
        # 获取交易详情计算交易次数
        orders = gt.get_orders()
        trade_count = len(orders)
        
        results.append({
            '滑点参数': name,
            '交易次数': trade_count,
            '总收益率': risk.get('algorithm_return', 0),
            '年化收益率': risk.get('annual_ized_return', 0),
            '夏普比率': risk.get('sharpe', 0),
            '最大回撤': risk.get('max_drawdown', 0)
        })
        print(f"{name} 回测完成。")
    else:
        print(f"{name} 回测运行失败。")

# 4. 转换为 DataFrame 展示对比表格
df_compare = pd.DataFrame(results)
print("\n===== ETF 策略滑点敏感性分析对比表 =====")
print(df_compare.to_string(index=False))

三、 敏感性分析结果解读与实盘指导

运行上述分析后,您将获得类似下表的对比数据:

滑点参数 交易次数 总收益率 年化收益率 夏普比率 最大回撤
无滑点 48 15.2% 7.3% 0.85 -12.4%
低滑点(0.1%) 48 12.8% 6.1% 0.72 -13.1%
默认滑点(0.246%) 48 9.5% 4.6% 0.55 -14.2%
高滑点(0.5%) 48 4.1% 2.0% 0.21 -16.5%

关键结论与优化方向:

  1. 交易次数一致性:由于滑点不影响信号触发(除非策略中使用了依赖持仓市值的动态信号),交易次数通常保持一致。如果交易次数随滑点变化,说明策略存在价格边界敏感信号,需注意实盘过拟合风险。
  2. 收益衰减斜率:若从“无滑点”到“默认滑点”,夏普比率和收益率出现断崖式下跌,说明该 ETF 策略对交易成本极度敏感,属于高频/中频高敏感型策略,实盘中必须选择日内成交量极大、买卖价差极小的宽基 ETF(如 510300.XSHG)。
  3. 最大回撤放大:滑点不仅蚕食利润,还会因为每次止损时的额外摩擦,导致策略的实际最大回撤显著大于理论回测值。在实盘资金管理时,应以高滑点回测下的最大回撤作为风险控制基准。