2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 500 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!
引言
大家好,今天给大家带来一个非常有意思的量化交易策略案例 —— 基于 CCI(商品通道指标) 和 STC(沙夫趋势周期指标) 的双指标组合策略。
这个策略在纳斯达克 100 指数(QQQ)的 10 年日线数据上进行了回测,结果非常亮眼:
虽然绝对收益略低于买入持有策略(605.95%),但回撤控制得非常好,整体风险收益比更优。下面我们就用 Python 一步一步把这个策略实现出来,非常适合正在学习 Python 量化的小伙伴动手实践。
一、策略原理
这是一个动量类的双指标策略:
- • CCI(Commodity Channel Index):衡量当前价格相对于其统计均值的偏离程度。
- • STC(Schaff Trend Cycle):结合了 MACD 逻辑和随机指标平滑算法,用于识别趋势中的周期性转折点。
策略思路是:用 STC 判断大趋势方向,用 CCI 触发具体的入场和出场时机。
二、计算 CCI 指标
CCI 的计算步骤如下:
- 1. 计算典型价格 tp =(最高价 + 最低价 + 收盘价)/ 3
- 4. 套用公式:CCI =(tp - ma)/(0.015 × md)
代码实现:
import numpy as np
import pandas as pd
def CCI(data, n):
# 计算典型价格:高、低、收盘价的平均值
tp = (data["High"] + data["Low"] + data["Close"]) / 3
# 计算典型价格的 n 日滚动均值
ma = tp.rolling(n).mean()
# 计算平均绝对偏差,衡量价格的正常波动幅度
md = tp.rolling(n).apply(lambda x: np.mean(np.
abs(x - x.mean())), raw=True)
# 通过常数 0.015 缩放,使大部分值落在 -100 到 +100 之间
cci = (tp - ma) / (0.015 * md)
return cci
# 将 CCI 值添加到 DataFrame 中,使用 20 日窗口
df["CCI"] = CCI(df, 20)
三、计算 STC 指标
STC 的核心思路:先算 MACD 线,再用随机指标方法把它压缩成 0~100 的振荡指标。
代码实现:
def stc(data, n1, n2, n3):
# 计算快线 EMA
fast = data.Close.ewm(n1).mean()
# 计算慢线 EMA
slow = data.Close.ewm(n2).mean()
# MACD 线 = 快线 - 慢线,反映趋势动量
macd = fast - slow
# 计算 MACD 在 n3 周期内的最低值
lomac = macd.rolling(n3).min()
# 计算 MACD 在 n3 周期内的最高值
himac = macd.rolling(n3).max()
# 通过随机指标方式将 MACD 压缩为 0~100 的振荡器
stc = ((macd - lomac) / (himac - lomac)) * 100
return stc
# 使用参数 23、50、26 计算 STC
df["STC"] = stc(df, 23, 50, 26)
参数说明:标准参数为 23、50、10,本策略调整为 23、50、26,使指标更平滑一些。
- • 持续在 80 以上或 20 以下:表明趋势具有持续性
四、生成交易信号
策略一共定义了 3 种信号:
- • 信号 1(买入):STC > 20 且 CCI 出现向上拐点
- • 信号 2(卖空):STC < 20 且 CCI 出现向下拐点
- • 信号 3(追加买入):STC 从 20 下方向上突破 20
代码实现:
def signal(data):
# 初始化信号列表,长度与 DataFrame 相同
signal = [0] * len(df)
# 从第 3 行开始遍历(因为需要前两根 K 线的数据)
for i in range(2, len(df)):
# 信号 1:STC 在 20 上方,且 CCI 出现向上拐点
if (data.STC.iloc[i] > 20) & \
(data.CCI.iloc[i] > data.CCI.iloc[i-1]) & \
(data.CCI.iloc[i-1] < data.CCI.iloc[i-2]):
signal[i] = 1
# 信号 2:STC 在 20 下方,且 CCI 出现向下拐点
elif (data.STC.iloc[i] < 20) & \
(data.CCI.iloc[i] < data.CCI.iloc[i-1]) & \
(data.CCI.iloc[i-1] > data.CCI.iloc[i-2]):
signal[i] = 2
# 信号 3:STC 由下向上突破 20
elif (data.STC.iloc[i-1] < 20) and
(data.STC.iloc[i] > 20):
signal[i] = 3
else:
signal[i] = 0
# 将信号写入 DataFrame
df["signal"] = signal
signal(df)
五、运行回测
这里使用 backtesting.py 库进行回测,并配合不同的止盈止损参数:
代码实现:
from backtesting import Backtest, Strategy
# 定义信号函数,供 backtesting.py 调用
def SIGNAL():
return df.signal
class MyStrat(Strategy):
def init(self):
super().init()
# 初始化信号指标
self.signal = self.I(SIGNAL)
def next(self):
super().next()
# 获取最新收盘价作为止盈止损的参考
price = self.data.Close[-1]
# 信号 1:主买入信号
if self.signal == 1:
if self.position.is_short or not self.position:
self.position.close()
# 用 99% 资金买入,止盈 4.5%,止损 5%
self.buy(size=0.99, tp=1.045 * price, sl=0.95 * price)
# 信号 3:突破式买入信号
elif self.signal == 3:
if self.position.is_short or not self.position:
self.position.close()
# 用 99% 资金买入,止盈 5%,止损 2%
self.buy(size=0.99, tp=1.05 * price, sl=0.98 * price)
# 信号 2:卖空信号
elif self.signal == 2:
if self.position.is_long or not self.position:
self.position.close()
# 用 99% 资金做空,止盈 6%,止损 1%
self.sell(size=0.99, tp=0.94 * price, sl=1.01 * price)
# 创建回测:初始资金 10 万,无杠杆,单次仅持有一个仓位,手续费 0.05%
bt = Backtest(df, MyStrat, cash=100_000, margin=1, exclusive_orders=True, commission=0.0005)
stats = bt.run()
print(stats)
六、回测结果分析
完整的回测统计数据如下:
虽然胜率只有 37.45%,但盈利因子达到 1.74,说明这是一个典型的「让利润奔跑、快速止损」的趋势跟随策略。
七、策略改进方向
如果想进一步优化这个策略,可以尝试以下方向:
- 1. 参数优化:使用网格搜索或贝叶斯优化对 CCI 周期和 STC 参数进行调优。
- 2. 加入市场状态过滤:例如用 ADX 或波动率指标判断是趋势还是震荡市,避免在震荡市中做空。
- 3. 波动率自适应仓位:根据 ATR 调整仓位大小,控制单笔风险。
- 4. 多品种验证:在 SPY、IWM 等其他标的上进行验证,避免参数过拟合 QQQ。
总结
这个 CCI + STC 双指标策略给我们提供了一个非常好的量化入门案例:
- • 思路清晰:用一个指标定方向,用另一个指标定时机,逻辑层次分明。
- • 代码简洁:100 多行代码就能完成完整的策略构建和回测。
- • 结果可验证:使用
backtesting.py 加上 Monte Carlo 模拟,结果具备统计意义。
对正在学习 Python 量化的小伙伴来说,建议你亲自把代码跑一遍,再尝试调整参数或者更换标的,观察结果变化。只有动手实践,才能真正理解策略背后的逻辑。
最后提醒:本文内容仅用于技术学习和代码分享,不构成任何投资建议,实盘交易有风险,请谨慎决策。
参考文章
加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。财经数据与量化投研知识社区
2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:
- 1. 双典系统赋能:获赠《财经数据宝典》与《量化投研宝典》完整文档,凝练多年实战经验,构建系统化知识框架;
- 2. 量化因子日更教程(2026重磅新增):每日更新「量化因子专题教程」,配套完整可运行代码与实战案例,深度拆解因子构建、回测与优化全流程;
- 3. 量化文章专题教程库:500+篇星球独有高质量教程式文章,系统覆盖策略开发、因子研究、风险管理等核心领域,内容基本每日更新,并配套精选学习资料与实战参考;
- 4. 量化投研实战课程:赠送《AKQuant-入门及实战》《PyBroker-入门及实战》视频课程,手把手教学,快速掌握量化策略开发技能;
- 5. 财经数据支持:定期更新国内外财经数据,为策略研发提供精准、可靠的数据基础;
- 6. 顶尖学者与行业专家分享:年度邀请学术界博士与业界资深专家开展前沿论文精讲与实战案例分享,不少于4场,直击研究前沿与产业实践;
专家直连答疑:与核心开发者及领域专家实时互动,高效解决投研实战难题; - 7. 专业社群与专属福利:加入高质量交流社群,获取课程折扣及更多独家资源。
星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、PyBroker实战课程、专家深度分享与实时答疑服务。无论您是初探量化的学习者,还是深耕领域的从业者,这里都是助您少走弯路、高效成长的理想平台。诚邀加入,共探数据驱动的投资未来!