🚀 AI 一键生成 joinquant 策略代码

JoinQuant 平台如何实现抛物线转向(SAR)交易策略?(附源码)

joinquant | 发布时间: 2025/12/31
以下内容由 EasyQuant 生成。

问题描述

请帮我编写一个基于抛物线转向指标(SAR)的量化策略

解决方案

这是一个基于抛物线转向指标(SAR, Stop and Reverse)的量化交易策略。

策略原理

SAR指标(Parabolic SAR)是一种趋势跟踪指标。

  1. 买入信号:当股价向上突破SAR曲线时,认为趋势转多,执行买入。
  2. 卖出信号:当股价向下突破SAR曲线时,认为趋势转空,执行卖出(清仓)。
  3. 参数设置:通常加速因子(Acceleration Factor, AF)初始值为0.02,每次递增0.02,最大值为0.2。

策略实现

以下是完整的策略代码,可以直接在聚宽(JoinQuant)的回测环境中运行。

# -*- coding: utf-8 -*-
# 导入聚宽函数库
import jqdata
import talib
import numpy as np

def initialize(context):
    """
    初始化函数,设定基准、股票池、费用等
    """
    # 设定沪深300作为基准
    set_benchmark('000300.XSHG')
    
    # 开启动态复权模式(真实价格)
    set_option('use_real_price', True)
    
    # 过滤掉order系列API产生的比error级别低的log
    log.set_level('order', 'error')
    
    # 设定要操作的股票,这里以平安银行为例
    g.security = '000001.XSHE'
    
    # SAR指标参数
    g.sar_acceleration = 0.02  # 加速因子初始值
    g.sar_maximum = 0.2        # 加速因子最大值
    
    # 设定手续费:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    # 每天开盘时运行
    run_daily(market_open, time='09:30')

def market_open(context):
    """
    每日开盘运行的策略逻辑
    """
    security = g.security
    
    # 获取过去100天的最高价、最低价、收盘价数据
    # SAR计算需要High和Low,Close用于判断信号
    # 获取较长的数据以确保SAR指标计算稳定
    data = attribute_history(security, 100, '1d', ['high', 'low', 'close'], skip_paused=True)
    
    # 如果数据不足(例如新股),则跳过
    if len(data) < 50:
        return
        
    # 将数据转换为numpy数组,talib需要float类型的numpy数组
    high_prices = data['high'].values
    low_prices = data['low'].values
    close_prices = data['close'].values
    
    # 使用talib库计算SAR
    # real = SAR(high, low, acceleration=0, maximum=0)
    try:
        sar_values = talib.SAR(high_prices, low_prices, 
                               acceleration=g.sar_acceleration, 
                               maximum=g.sar_maximum)
    except Exception as e:
        log.error("计算SAR指标出错: %s" % e)
        return

    # 获取最新的SAR值和收盘价(这里的“最新”指的是前一交易日的收盘数据,用于指导今日交易)
    current_sar = sar_values[-1]
    current_close = close_prices[-1]
    
    # 获取之前的SAR值和收盘价,用于判断交叉
    prev_sar = sar_values[-2]
    prev_close = close_prices[-2]
    
    # 获取当前账户资金和持仓
    cash = context.portfolio.available_cash
    position = context.portfolio.positions[security]
    
    # 交易逻辑
    # 1. 买入信号:收盘价站上SAR曲线 (金叉)
    # 为了避免频繁震荡,这里判断前一天在下方,最新一天在上方,或者持续在上方
    if current_close > current_sar:
        # 如果当前没有持仓,则全仓买入
        if position.closeable_amount == 0:
            log.info("买入信号触发:收盘价(%.2f) > SAR(%.2f)" % (current_close, current_sar))
            order_value(security, cash)
            
    # 2. 卖出信号:收盘价跌破SAR曲线 (死叉)
    elif current_close < current_sar:
        # 如果当前有持仓,则清仓卖出
        if position.closeable_amount > 0:
            log.info("卖出信号触发:收盘价(%.2f) < SAR(%.2f)" % (current_close, current_sar))
            order_target(security, 0)
            
    # 记录数据以便在回测图中查看
    record(Price=current_close, SAR=current_sar)

常见问答 (Q&A)

Q1: 为什么代码中使用了 talib 库?
A1: talib (Technical Analysis Library) 是量化领域最常用的技术分析库,计算效率高且标准。聚宽平台内置了该库,可以直接调用 talib.SAR 来计算指标,避免手动编写公式可能出现的错误。

Q2: attribute_history 获取的是什么时间的数据?
A2:run_daily 设置为 09:30 运行时,attribute_history 获取的是截止到前一个交易日收盘的数据。这是为了避免使用当天的未来数据(即在收盘前就预知了收盘价)。策略逻辑是基于昨日收盘价与SAR的关系来决定今日开盘的操作。

Q3: 如何调整SAR指标的灵敏度?
A3: 可以通过修改 initialize 函数中的 g.sar_acceleration (加速因子) 和 g.sar_maximum (最大值) 来调整。

  • 增大加速因子(如0.03):SAR曲线会更紧贴价格,灵敏度提高,但可能导致频繁交易(假信号增加)。
  • 减小加速因子(如0.01):SAR曲线会更平滑,对趋势反应较慢,但能过滤掉部分震荡。

Q4: 这个策略适合什么市场环境?
A4: SAR是典型的趋势跟踪指标,在单边趋势行情(持续上涨或下跌)中表现较好,能吃到大部分波段。但在横盘震荡行情中,价格会频繁穿梭于SAR曲线上下,导致策略频繁止损,产生磨损成本。建议结合其他指标(如ADX)来过滤震荡行情。