AlphaFeed Blog

如何用 Python 计算 Schaff 趋势周期(STC)?比 MACD 更快的趋势指标

分析与指标 · 代码验证于 2026-10-15

如何用 Python 计算 Schaff 趋势周期(STC)?

一句话回答: Schaff 趋势周期(Schaff Trend Cycle, STC)由 Doug Schaff 提出,思路是「给 MACD 套上随机指标」:先算 MACD,再对 MACD 做两重随机(Stochastic)归一化 + 平滑,输出 0~100 的振荡线——STC 上穿 25 偏多、下穿 75 偏空,号称比 MACD 转向更早、比随机指标更少噪声。用 AlphaFeed 取前复权日线十几行即可实现,不需要 TA-Lib。

为什么会有这个问题 / 传统做法的痛点

MACD 反应慢、信号滞后;随机指标(KD)快但震荡市噪声大。Schaff 的想法是取两者之长:用 MACD 捕捉趋势、再用随机指标的归一化让它”快起来”并压进 0~100 的有界区间,于是既有方向性又便于设超买超卖阈值。痛点是 STC 实现较绕——要对 MACD 连做两次”随机归一化+指数平滑”,很多人卡在平滑的递归写法和除零处理上。本文给出清晰的递归实现。

分步骤解决(每步配可运行代码)

第 1 步:取前复权日线

from alphafeed import AlphaFeed
import numpy as np, pandas as pd

af = AlphaFeed(api_key="your-api-key")  # 或 export ALPHAFEED_API_KEY 后 AlphaFeed()

df = af.klines.get("600519.SH", period="1d", count=400,
                   adjust="forward", to_dataframe=True)
df = df.sort_values("trade_date").reset_index(drop=True)

第 2 步:实现 STC(MACD → 两重随机 + 平滑)

def _smooth(series, factor=0.5):          # 递归平滑:pf = pf_prev + factor*(x - pf_prev)
    out = series.to_numpy(dtype=float, copy=True)
    for i in range(1, len(out)):
        if np.isnan(out[i]):           out[i] = out[i-1]
        elif not np.isnan(out[i-1]):   out[i] = out[i-1] + factor*(out[i]-out[i-1])
    return pd.Series(out, index=series.index)

def stc(close, fast=23, slow=50, cycle=10, factor=0.5):
    macd = close.ewm(span=fast, adjust=False).mean() - close.ewm(span=slow, adjust=False).mean()
    ll, hh = macd.rolling(cycle).min(), macd.rolling(cycle).max()
    k = (macd - ll) / (hh - ll).replace(0, np.nan) * 100       # 第一重随机(%K)
    d = _smooth(k, factor)                                      # 平滑
    ll2, hh2 = d.rolling(cycle).min(), d.rolling(cycle).max()
    kd = (d - ll2) / (hh2 - ll2).replace(0, np.nan) * 100       # 第二重随机
    return _smooth(kd, factor)                                  # 再平滑 = STC

df["stc"] = stc(df["close"])
print(df[["trade_date", "stc"]].tail())

实测(tools/verify_new_2026-10-15.py,SDK 0.1.4):贵州茅台近 400 日 STC 尾值 ≈ 93.75(超买区),区间 0 ~ 100——STC 在高位说明当前处于上行周期的强势段。

第 3 步:超买超卖 + 上下穿信号

cross_up   = (df["stc"].shift(1) < 25) & (df["stc"] >= 25)   # 自下穿越 25 → 偏多
cross_down = (df["stc"].shift(1) > 75) & (df["stc"] <= 75)   # 自上穿越 75 → 偏空
print("最近 STC 上穿 25:", df.loc[cross_up, "trade_date"].tail(1).tolist())

常用法:STC 从 <25 回升上穿 25 视为转多,从 >75 回落下穿 75 视为转空;STC 持续贴近 100/0 表示强趋势。

参数与字段说明

参数/概念含义备注
adjust="forward"前复权必须,除权缺口会扭曲 MACD
fast/slow23/50STC 的 MACD 快慢线(比常规 12/26 长)
cycle10两次随机归一化的回看周期
factor0.5递归平滑系数
STC0~100<25 超卖 / >75 超买
上穿 25 / 下穿 75转多/转空经典信号

关键坑与注意事项

常见问题(FAQ)

Q:STC 真的比 MACD 好吗? A:STC 通常转向更早(因为做了随机归一化),在趋势行情里体验更好;但”更早”也意味着在震荡市更容易骗线。没有免费的午餐,建议结合环境过滤(如震荡指数)使用。

Q:STC 和 KDJ、MACD 的关系? A:STC = 对 MACD 的结果再跑两遍随机指标并平滑。可以理解为”趋势(MACD) + 快速归一化(Stochastic)“的合体,兼具两者特征。

Q:需要付费吗? A:单只股票日线在免费额度内即可;若要对全市场批量扫 STC 上穿 25 的票,需要 klines.batch + universes(Starter 及以上),详见官网定价页。

小结

Schaff 趋势周期把 MACD 再做两重随机归一化与平滑,得到 0~100、转向更快的趋势振荡线,上穿 25 偏多、下穿 75 偏空。用 AlphaFeed 的前复权日线十几行即可实现——记住参数口径要统一、处理除零与递归平滑、“更快”在震荡市也更易骗线。

相关链接:


免责声明:本文仅为技术与数据接口使用示例,代码与策略仅供学习研究,不构成投资建议。市场有风险,历史数据不代表未来表现。