一句话回答: 抛物线 SAR(Stop And Reverse)是 Wilder 发明的趋势跟踪 + 移动止损指标:价格在 SAR 之上为多头、跌破 SAR 翻空,点位随趋势加速上移/下移。用 AlphaFeed 取回前复权日线的 high/low/close 后,几十行 Python 就能实现原版 SAR(含加速因子 AF),不需要 TA-Lib。
为什么会有这个问题 / 传统做法的痛点
很多人想用 SAR 做「无脑移动止损」,但直接调 TA-Lib 装不上、或不懂参数含义乱设。SAR 的两个坑:一是必须用前复权价,否则除权日的价格断层会触发假翻转;二是加速因子 AF 的步长/上限直接决定灵敏度,设错要么频繁翻转要么迟钝。把公式讲清、用干净数据实现,就能稳定复现同花顺/通达信的 SAR。
分步骤解决(每步配可运行代码)
第 1 步:取前复权日线
from alphafeed import AlphaFeed
af = AlphaFeed() # 读取 ALPHAFEED_API_KEY
df = af.klines.get("600519.SH", period="1d", count=250,
adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)
SAR 依赖每日最高/最低价,务必用
adjust="forward"(前复权),避免除权跳空造成的假信号。
第 2 步:实现 Wilder 原版 SAR
import pandas as pd
def parabolic_sar(high, low, af_step=0.02, af_max=0.20):
high = high.to_numpy(); low = low.to_numpy()
n = len(high)
sar = [0.0] * n
trend_up = True # 初始假设多头
af = af_step
ep = high[0] # 极值点
sar[0] = low[0]
for i in range(1, n):
prev = sar[i - 1]
sar[i] = prev + af * (ep - prev)
if trend_up:
# 多头:SAR 不得高于前两日最低价
sar[i] = min(sar[i], low[i - 1], low[max(i - 2, 0)])
if high[i] > ep:
ep = high[i]; af = min(af + af_step, af_max)
if low[i] < sar[i]: # 跌破 SAR → 翻空
trend_up = False; sar[i] = ep; ep = low[i]; af = af_step
else:
# 空头:SAR 不得低于前两日最高价
sar[i] = max(sar[i], high[i - 1], high[max(i - 2, 0)])
if low[i] < ep:
ep = low[i]; af = min(af + af_step, af_max)
if high[i] > sar[i]: # 升破 SAR → 翻多
trend_up = True; sar[i] = ep; ep = high[i]; af = af_step
return pd.Series(sar, index=range(n))
df["SAR"] = parabolic_sar(df["high"], df["low"])
df["pos"] = (df["close"] > df["SAR"]).map({True: "多", False: "空"})
print(df[["trade_date", "close", "SAR", "pos"]].tail(8).to_string(index=False))
第 3 步:识别翻转点(买卖信号)
df["flip"] = df["pos"].ne(df["pos"].shift())
signals = df[df["flip"] & df.index.to_series().gt(0)]
print(signals[["trade_date", "close", "SAR", "pos"]].tail(5).to_string(index=False))
# pos 由"空"变"多" = SAR 买点;由"多"变"空" = SAR 卖点/止损点
参数与含义:
| 参数 | 含义 | 常用值 | 说明 |
|---|---|---|---|
af_step | 加速因子步长 | 0.02 | 每创新高/新低增加的加速度 |
af_max | 加速因子上限 | 0.20 | 越大越贴近价格、越易翻转 |
SAR | 停损转向点位 | — | 多头在价下方、空头在价上方 |
EP | 极值点 | — | 当前趋势内的最高/最低价 |
第 4 步:把 SAR 当移动止损
last = df.iloc[-1]
if last["pos"] == "多":
print(f"持多,移动止损位 = {last['SAR']:.2f}(跌破即止损/翻空)")
else:
print(f"持空/观望,SAR 压力位 = {last['SAR']:.2f}(升破即翻多)")
关键坑与注意事项
- 必须用前复权价:SAR 对高低点敏感,未复权价在除权日会假翻转。
- AF 上限决定灵敏度:
af_max调大 → 止损更贴近、翻转更频繁;震荡市易被反复打脸。 - SAR 适合趋势市、不适合震荡市:横盘阶段会频繁翻转产生大量假信号,需配合 ADX 等趋势强度过滤。
- 首根 SAR 是初始化近似:序列开头的方向假设会影响前几根,样本要足够长(建议 ≥60 根)让其收敛。
- 与不同软件的细微差异:各家对「前两日极值约束」「初始 EP」处理略有出入,数值可能相差极小,趋势判断一致即可。
常见问题(FAQ)
Q:SAR 的默认参数 0.02 / 0.20 能改吗? A:能。步长/上限越大越灵敏;短线可试 0.02/0.20,波动大的品种可调小上限减少假翻转。建议先用默认值。
Q:SAR 和移动平均止损哪个好? A:SAR 会随趋势加速收紧止损、锁定利润更快;均线止损更平滑、假信号少但反应慢。可结合使用。
Q:为什么震荡时 SAR 老是亏? A:SAR 是趋势工具,震荡市天然不适用。可用 ADX<20 过滤掉无趋势阶段再用 SAR。
Q:需要付费吗?
A:单只历史日线有免费额度;批量算多只 SAR(klines.batch 配合 universes)需 Starter 及以上。详见定价页。
小结
抛物线 SAR 的本质是「随趋势加速移动的停损转向点」。实现不难,关键在两点:用前复权价保证高低点真实,理解 AF 步长/上限对灵敏度的影响。用 AlphaFeed 取回前复权日线,几十行 Python 就能复现原版 SAR,用于趋势判断与移动止损。
参考
- AlphaFeed Python SDK 文档:docs.alphafeed.org/zh-Hans/sdk…
- AlphaFeed 官网:alphafeed.org/