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

在 JoinQuant 中如何计算与通达信一致的 SAR 指标?

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

问题描述

请教SAR指标的计算(接近国内主流即可)

如何计算的得到和主流厂家相等或接近的指标。

我尝试了talib库的SAR函数,
talib.SAR(df.high.values,df.low.values,acceleration=0.02, maximum=0.2)

虽然知道传入high,low序列的长度不一样得到的结果不一样。
但无论传10天, 20天, 30天, 100天,似乎都和通达信的都不太一样。

SRA这个指标一般你们都怎么算? 参数如何设定?

解决方案

为什么 talib 计算的 SAR 和通达信不一样?

在使用 talib.SAR 计算抛物线转向(SAR)指标时,很多量化开发者会发现结果与国内主流炒股软件(如通达信、同花顺)存在差异。这主要由以下两个原因导致:

1. SAR 指标的“递归”特性(最核心原因)

SAR 是一个典型的路径依赖(递归)指标。今天的 SAR 值是由昨天的 SAR 值、昨天的极值(EP)以及加速因子(AF)共同决定的。这意味着,计算的起点不同,得到的结果就会完全不同

通达信等主流软件在展示 SAR 时,通常是从该股票上市的第一天(或者软件本地缓存的极长历史数据,如几年甚至十几年)开始计算的。而你在策略中如果只传入 10天、30天 甚至 100天的数据,talib 只能以这短短几十天的数据作为起点进行初始化,这必然导致当前的 SAR 值与通达信产生巨大偏差。

2. 初始值的设定逻辑

talib 和通达信在第一天的 SAR 初始值设定上可能存在微小的逻辑差异,但只要经过足够长时间的迭代,这种初始误差会被逐渐抹平(收敛)。


如何解决?(参数设定与计算方法)

要得到与通达信高度接近的 SAR 指标,核心秘诀是:利用长周期数据进行“预热”

参数设定

通达信 SAR 的默认参数通常是 (10, 2, 20),对应的含义是:

  • 加速因子步长 (Step):2% -> 对应 talib 中的 acceleration=0.02
  • 加速因子最大值 (Max):20% -> 对应 talib 中的 maximum=0.2

正确的计算姿势

不要只传 30 天或 100 天的数据。建议至少传入过去 300 天到 500 天的数据talib.SAR,让指标有足够的时间进行递归收敛。然后,你只需要取计算结果的最后几个值即可。经过 300 天以上的迭代,talib 的结果通常会与通达信精确到小数点后两位。

JoinQuant 代码示例

以下是在 JoinQuant 平台中获取与通达信一致的 SAR 指标的代码示例:

import talib
import numpy as np
from jqdata import *

def initialize(context):
    g.security = '000001.XSHE'
    set_benchmark('000300.XSHG')
    # 必须使用真实价格(前复权),因为通达信默认也是前复权
    set_option('use_real_price', True)
    
    run_daily(market_open, time='09:30')

def market_open(context):
    # 秘诀:获取过去 400 天的最高价和最低价数据进行“预热”
    # 数据量越大,越接近通达信,但为了性能,400天通常足够收敛了
    df = attribute_history(g.security, 400, '1d', ['high', 'low'], skip_paused=True)
    
    if len(df) < 400:
        log.warn("数据不足 400 天,SAR 可能存在误差")
        
    high_prices = df['high'].values
    low_prices = df['low'].values
    
    # 使用 talib 计算 SAR
    # acceleration=0.02, maximum=0.2 对应通达信默认参数
    sar_values = talib.SAR(high_prices, low_prices, acceleration=0.02, maximum=0.2)
    
    # 我们只需要最新的那一个 SAR 值
    current_sar = sar_values[-1]
    previous_sar = sar_values[-2]
    
    current_close = attribute_history(g.security, 1, '1d', ['close'])['close'][-1]
    
    log.info(f"昨日 SAR: {previous_sar:.2f}, 今日 SAR: {current_sar:.2f}, 当前收盘价: {current_close:.2f}")
    
    # 简单的 SAR 策略逻辑:价格向上突破 SAR 买入,向下突破 SAR 卖出
    if current_close > current_sar and context.portfolio.positions[g.security].closeable_amount == 0:
        order_value(g.security, context.portfolio.available_cash)
        log.info("价格突破 SAR,买入")
    elif current_close < current_sar and context.portfolio.positions[g.security].closeable_amount > 0:
        order_target(g.security, 0)
        log.info("价格跌破 SAR,卖出")

总结

  1. 参数acceleration=0.02, maximum=0.2 是正确的。
  2. 数据长度:将传入 talib.SAR 的数据长度增加到 300~500天
  3. 复权方式:确保你获取的数据是前复权数据(JoinQuant 默认即为前复权,开启 use_real_price=True 即可),因为通达信的指标通常也是基于前复权 K 线计算的。如果不复权,遇到分红派息时 SAR 会出现严重失真。