问题描述
解决方案
使用 SAR 指标进行自动交易
SAR(Stop and Reverse,抛物线转向指标)是一种非常经典的趋势跟踪指标。它通过在价格图表上绘制一系列点来指示潜在的趋势反转位置。
在 PTrade 中,虽然系统自带的 API 文档中没有直接提供 get_SAR 函数,但 PTrade 支持 TA-Lib 库,我们可以直接调用 talib.SAR 来计算该指标。
策略逻辑
- 买入信号:当股价收盘价 上穿 SAR 指标值时(即股价 > SAR),认为趋势转多,执行买入。
- 卖出信号:当股价收盘价 下穿 SAR 指标值时(即股价 < SAR),认为趋势转空,执行卖出(清仓)。
- 参数设置:通常 SAR 的加速因子(Acceleration Factor)初始值为 0.02,最大值为 0.2。
PTrade 策略代码实现
以下是一个完整的单只股票 SAR 策略示例。代码兼容 Python 3.5 环境。
import talib
import numpy as np
def initialize(context):
"""
初始化函数,设置股票池和全局变量
"""
# 设定要交易的股票,这里以恒生电子为例
g.security = '600570.SS'
# 设置股票池
set_universe(g.security)
# 设置滑点(可选)
set_slippage(0.002)
def handle_data(context, data):
"""
盘中运行函数,每个周期(如每日)运行一次
"""
security = g.security
# 1. 获取历史数据
# SAR 计算需要 High (最高价) 和 Low (最低价)
# 获取过去 100 天的数据以确保指标计算稳定
history_data = get_history(100, frequency='1d', field=['high', 'low', 'close'], security_list=security, fq='pre')
if history_data is None or len(history_data) < 50:
log.info("历史数据不足,跳过计算")
return
# 提取 numpy 数组,talib 需要这种格式
high_prices = history_data['high'].values
low_prices = history_data['low'].values
close_prices = history_data['close'].values
# 2. 计算 SAR 指标
# acceleration: 加速因子,默认 0.02
# maximum: 加速因子最大值,默认 0.2
try:
sar_values = talib.SAR(high_prices, low_prices, acceleration=0.02, maximum=0.2)
except Exception as e:
log.error("SAR 计算出错: %s" % e)
return
# 获取最新的 SAR 值和收盘价
current_sar = sar_values[-1]
current_close = close_prices[-1]
# 获取当前持仓
position = get_position(security).amount
cash = context.portfolio.cash
# 3. 交易逻辑
# 情况 A: 股价在 SAR 之上 (看多) 且 空仓 -> 买入
if current_close > current_sar and position == 0:
# 全仓买入
order_value(security, cash)
log.info("买入信号触发: 收盘价 %.2f > SAR %.2f" % (current_close, current_sar))
# 情况 B: 股价在 SAR 之下 (看空) 且 持仓 -> 卖出
elif current_close < current_sar and position > 0:
# 清仓卖出
order_target(security, 0)
log.info("卖出信号触发: 收盘价 %.2f < SAR %.2f" % (current_close, current_sar))
代码解析与注意事项
- 引入 TA-Lib:
代码开头使用了import talib。PTrade 环境内置了 TA-Lib 库,这是计算复杂技术指标的标准方式。 - 数据获取 (
get_history):
SAR 指标不仅需要收盘价,还需要最高价 (High) 和 最低价 (Low)。我们在get_history的field参数中指定了['high', 'low', 'close']。 - 数据长度:
SAR 是一个具有“记忆性”的递归指标,计算初期的数据可能不稳定。因此,建议获取较长的历史数据(如代码中的 100 根 K 线),以确保最新的 SAR 值是准确收敛的。 - 复权处理:
在get_history中使用了fq='pre'(前复权)。在涉及价格突破的策略中,使用复权价格可以避免因分红派息导致的价格缺口误触止损。 - Python 版本兼容性:
代码中使用了%格式化字符串(如"%.2f" % value),而不是 f-string,这是为了确保在 PTrade 可能使用的 Python 3.5 环境中也能正常运行。
Q&A: 常见问题解答
Q1: 为什么 PTrade 文档里找不到 get_SAR 函数?
A1: PTrade 的原生 API 主要提供基础数据获取(如 get_history)和部分常用指标(如 get_MACD)。对于像 SAR、布林带等其他指标,PTrade 预装了 talib 第三方库,用户应通过 talib 进行计算。
Q2: SAR 指标适合震荡市吗?
A2: 不适合。SAR 是典型的趋势跟踪指标。在单边趋势行情(大涨或大跌)中表现优异,但在横盘震荡整理期间,价格会频繁穿过 SAR 曲线,导致频繁的买卖磨损(反复止损)。建议结合 ADX(平均趋向指标)来判断当前是否处于趋势中。
Q3: 如何调整 SAR 的灵敏度?
A3: 可以通过调整 talib.SAR 函数中的 acceleration(加速因子)参数。
- 增大该值(例如 0.03):SAR 曲线会更紧贴价格,反应更灵敏,但假信号增多。
- 减小该值(例如 0.01):SAR 曲线离价格更远,更能容忍回调,但反转信号会滞后。
Q4: 回测时 SAR 计算结果为什么前几个值是 NaN?
A4: 这是正常的。TA-Lib 计算 SAR 时,前几个周期用于初始化趋势方向和极值,因此输出结果的前几项通常为 NaN。我们在取值时取 sar_values[-1](最新值)即可,前面的 NaN 不影响最新值的计算。