深入解析 SAR 公式源码:从算法原理到代码完成

在量化交易、技术分析以及算法编程领域,抛物线转向指标(Parabolic Stop and Reverse,简称 SAR) 是一个极具影响力的工具。它由著名技术分析大师 J. Welles Wilder Jr. 在 1978 年提及,主要用于识别趋势反转点并设定动态止损位。
尽管 SAR 的数学逻辑看似简单,但其源码实现中蕴含的细节(如加速因子 AF 的更新逻辑、极值点 EP 的追踪等)决定了策略的有效性。这篇文章将深入探讨 SAR 公式,并提供高质量的 Python 源码实现,辅以数据表格说明其运行逻辑。
SAR 指标逻辑
SAR 思想是:在上升趋势中,价格每创出新高,止损位就向上移动;在下降趋势中,价格每创出新低,止损位就向下移动。 当价格突破 SAR 线时,视为趋势反转信号。
基本公式
SAR 的计算依赖于三个关键变量:- :上一周期的 SAR 值。
- (Extreme Point,极值点):趋势中的最高价(上升)或最低价(下降)。
- (Acceleration Factor,加速因子):初始值为 0.02,上限为 0.2,每次触及新极值点时增加步长(Step,为 0.02)。
计算步骤如下:
1. 确定初始 SAR:取个周期的最低价(上升趋势)或最高价(下降趋势)。
2. 计算当前 SAR:
- 若为上升趋势,且当前最高价 ,则 。
- 若为下降趋势,且当前最低价 ,则 。
- 若 发生转变,则 。
- 若 超过上限(如 0.2),则不再增加,保持为上限值。
- 上升趋势中,若 ,则趋势反转,新的 SAR 设为上一周期的 ,并重置 和 。
- 下降趋势中,若 ,则趋势反转,新的 SAR 设为上一周期的 ,并重置 和 。
SAR 公式源码实现(Python)
以下代码实现了标准的 SAR 算法,包含详细的注释,便于理解和集成到量化策略中。
```python
import numpy as np
import pandas as pd
def calculate_sar(high, low, close, step=0.02, af_limit=0.2):
"""
计算抛物线转向指标 (SAR)
参数:
high : array-like, 最高价序列
low : array-like, 最低价序列
close : array-like, 收盘价序列
step : float, 加速因子初始步长 (默认 0.02)
af_limit : float, 加速因子上限 (默认 0.2)
返回:
sar : list, SAR 值序列
ep : list, 极值点序列
af : list, 加速因子序列
"""
sar = []
ep = []
af = []
# 初始化
n = len(high)
if n == 0:
return [], [], []
# 假设初始趋势为上升
is_up = True
sar.append(low[0])
ep.append(high[0])
af.append(step)
for i in range(1, n):
prev_sar = sar[-1]
prev_ep = ep[-1]
prev_af = af[-1]
# 计算当前 SAR
current_sar = prev_sar + prev_af (prev_ep - prev_sar)
# 趋势反转逻辑
if is_up:
# 上升趋势中,若最低价低于当前SAR,则反转
if low[i] < current_sar:
is_up = False
# 反转后的SAR设为上一周期最高价
current_sar = high[i-1]
# 重置EP和AF
new_ep = low[i]
new_af = step
# 更新EP:取当前最低价和之前EP的较小值(用于后续加速)
if new_ep < prev_ep:
new_ep = prev_ep
ep.append(new_ep)
af.append(new_af)
sar.append(current_sar)
continue

else:
# 下降趋势中,若最高价高于当前SAR,则反转
if high[i] > current_sar:
is_up = True
# 反转后的SAR设为上一周期最低价
current_sar = low[i-1]
# 重置EP和AF
new_ep = high[i]
new_af = step
# 更新EP:取当前最高价和之前EP的较大值
if new_ep > prev_ep:
new_ep = prev_ep
ep.append(new_ep)
af.append(new_af)
sar.append(current_sar)
continue
# 更新EP和AF(无反转情况)
if is_up:
# 上升趋势:EP取最高价中的最大值
if high[i] > prev_ep:
new_ep = high[i]
new_af = min(prev_af + step, af_limit)
else:
new_ep = prev_ep
new_af = prev_af
else:
# 下降趋势:EP取最低价中的最小值
if low[i] < prev_ep:
new_ep = low[i]
new_af = min(prev_af + step, af_limit)
else:
new_ep = prev_ep
new_af = prev_af
ep.append(new_ep)
af.append(new_af)
sar.append(current_sar)
return sar, ep, af
示例数据生成
np.random.seed(42) days = 100 base_price = 100生成模拟股价数据(带趋势)
trend = np.linspace(0, 20, days) noise = np.random.normal(0, 2, days) high = base_price + trend + noise + 1 low = base_price + trend + noise - 1 close = base_price + trend + noise计算SAR
sar_values, ep_values, af_values = calculate_sar(high, low, close)转换为DataFrame以便展示
df = pd.DataFrame({ 'Date': pd.date_range('2023-01-01', periods=days), 'High': high, 'Low': low, 'Close': close, 'SAR': sar_values, 'EP': ep_values, 'AF': af_values }) ```数据说明与运行示例
为了更直观地理解 SAR 的计算过程,下表展示了前 10 个周期数据转变。假设初始趋势为上升,Step=0.02,AF_Limit=0.2。
| 周期 (i) | 最高价 (High) | 最低价 (Low) | 当前 SAR | EP (极值点) | AF (加速因子) | 趋势状态 | 备注 |
|---|---|---|---|---|---|---|---|
| 1 | 101.5 | 99.8 | 99.8 | 101.5 | 0.02 | 上升 | 初始值 |
| 2 | 102.3 | 100.5 | 100.08 | 102.3 | 0.02 | 上升 | 更新为 102.3,AF 不变 |
| 3 | 103.0 | 101.2 | 100.62 | 103.0 | 0.04 | 上升 | 更新,AF 增加 0.02 |
| 4 | 104.5 | 102.0 | 101.70 | 104.5 | 0.06 | 上升 | 更新,AF 增加 0.02 |
| 5 | 105.0 | 101.8 | 103.06 | 105.0 | 0.08 | 上升 | 更新,AF 增加 0.02 |
| 6 | 104.8 | 103.5 | 104.68 | 105.0 | 0.10 | 上升 | 不变,AF 增加 |
| 7 | 103.0 | 102.5 | 103.80 | 105.0 | 0.12 | 反转 | ,趋势转为下降 |
| 8 | 102.0 | 101.5 | 104.50 | 105.0 | 0.02 | 下降 | 反转后 SAR 设为上一周期 High,AF 重置 |
| 9 | 101.0 | 100.5 | 104.40 | 100.5 | 0.04 | 下降 | 更新为 100.5,AF 增加 |
| 10 | 100.0 | 99.8 | 104.24 | 99.8 | 0.06 | 下降 | 更新,AF 增加 |
注意:在实际计算中,SAR 值会跟随趋势“追赶”价格。当价格突破 SAR 线时,触发反转,SAR 值会“跳跃”到另一侧,形成抛物线形态。
SAR 源码注意事项
1. 初始趋势判断:
源码中假设个周期为上升趋势(或根据前 N 天价格变化判断)。在实际应用中,建议结合均线(如 MA20)来初始确定趋势方向,以提高准确性。
2. 加速因子 AF 的边界处理:
AF 不能超过 `af_limit`(为 0.2)。当趋势持续时,AF 会逐渐增大,使得 SAR 线更紧密地跟随价格,提高止损灵敏度;但一旦达到上限,即使价格继续创新高,SAR 的增长速度也会减缓,防止过度敏感。
3. 反转逻辑的严谨性:
在上升趋势中,判断条件是 `Low < SAR`;在下降趋势中,判断条件是 `High > SAR`。这是 SAR 指标信号,任何微小的偏差都导致错误的止损或开仓。
4. 性能优化:
对于大规模历史数据回测,建议使用向量化操作(如 NumPy)替代 Python 循环,以提升计算效率。上面这些源码为清晰易懂的循环完成,适合教学和中小规模数据。
结论
SAR 公式源码的实现虽然逻辑清晰,但其动态调整机制(EP 和 AF 的更新)是策略成功。凭借上面这些 Python 源码,交易者可以灵活地将 SAR 集成到自动化交易系统中,用于趋势跟踪和动态止损。
建议:- 将 SAR 与其他指标(如 RSI、MACD)结合利用,以减少假信号。
- 在不同市场周期中调整 `step` 和 `af_limit` 参数,以适应波动率变化。
- 在实盘前推进充分的历史回测,验证参数在不同标的上的表现。
经过深入理解 SAR 的源码逻辑,交易者不仅能更好地使用该指标,还能在此基础上进行创新,开发出更具适应性的趋势跟踪策略。
