问题描述
解决方案
这是一个基于 CCI (Commodity Channel Index,顺势指标) 的量化交易策略。
策略逻辑
CCI 指标主要用于衡量股价是否超出常态分布范围。本策略采用经典的 超买超卖反转逻辑:
- 买入信号:当 CCI 指标从下方上穿 -100 线时,视为股价脱离超卖区,开始反弹,执行买入。
- 卖出信号:当 CCI 指标从上方下穿 +100 线时,视为股价脱离超买区,趋势转弱,执行卖出。
- 参数设置:CCI 计算周期默认为 14。
PTrade 策略代码
def initialize(context):
"""
初始化函数,设置股票池和全局变量
"""
# 设置我们要操作的股票,这里以恒生电子为例
g.security = '600570.SS'
# 设置股票池
set_universe(g.security)
# CCI指标的计算周期,通常为14
g.n = 14
# 设置回测频率为日线
# 注意:实际运行时请在回测界面选择"日线"频率
def handle_data(context, data):
"""
盘中运行函数,每个单位时间(如每天)运行一次
"""
security = g.security
# 1. 过滤停牌股票
# 如果股票停牌(is_open为0),则跳过不处理
if data[security].is_open == 0:
return
# 2. 获取历史行情数据
# 获取过去 100 天的数据,确保有足够的数据计算 CCI
# 需要 high, low, close 三个字段
h = get_history(100, '1d', ['high', 'low', 'close'], security_list=security)
# 提取数据为 numpy 数组
high_data = h['high'].values
low_data = h['low'].values
close_data = h['close'].values
# 3. 计算 CCI 指标
# PTrade 内置了 get_CCI 函数,直接调用即可
# 注意:虽然文档有时简写,但 get_CCI 标准调用需要 high, low, close, n
cci_values = get_CCI(high_data, low_data, close_data, g.n)
# 确保计算结果有效
if cci_values is None or len(cci_values) < 2:
return
# 获取当前周期和上一周期的 CCI 值
curr_cci = cci_values[-1]
prev_cci = cci_values[-2]
# 4. 获取当前持仓和资金情况
position = get_position(security)
cash = context.portfolio.cash
current_price = data[security].close
# 5. 交易逻辑
# 买入逻辑:CCI 上穿 -100 (前值 < -100 且 当前值 > -100)
# 且当前没有持仓
if prev_cci < -100 and curr_cci > -100:
if position.amount == 0:
# 全仓买入
order_value(security, cash)
log.info("买入信号触发: CCI上穿-100 (前值: %.2f, 现值: %.2f)" % (prev_cci, curr_cci))
# 卖出逻辑:CCI 下穿 +100 (前值 > 100 且 当前值 < 100)
# 且当前持有股票
elif prev_cci > 100 and curr_cci < 100:
if position.amount > 0:
# 清仓卖出
order_target(security, 0)
log.info("卖出信号触发: CCI下穿+100 (前值: %.2f, 现值: %.2f)" % (prev_cci, curr_cci))
代码解析
-
数据获取 (
get_history):- CCI 计算需要最高价 (
high)、最低价 (low) 和收盘价 (close)。 - 我们获取过去 100 根 K 线的数据,这是为了确保指标计算初期有足够的“预热”数据,使结果更准确。
- CCI 计算需要最高价 (
-
指标计算 (
get_CCI):- 使用了 PTrade 内置的
get_CCI(high, low, close, n)函数。这是最高效的方法,无需手动编写公式。 g.n设置为 14,这是 CCI 的标准参数。
- 使用了 PTrade 内置的
-
信号判断:
- 上穿 -100:
prev_cci < -100 and curr_cci > -100。这通常意味着市场处于超卖状态后的修复阶段,是一个潜在的买点。 - 下穿 +100:
prev_cci > 100 and curr_cci < 100。这通常意味着市场处于超买状态后的回调阶段,是一个潜在的卖点。
- 上穿 -100:
-
交易执行:
- 使用
order_value进行按金额买入(示例中为全仓)。 - 使用
order_target进行卖出(目标仓位设为 0 即为清仓)。 - 加入了
data[security].is_open判断,避免在停牌日下单导致废单。
- 使用
注意事项
- Python 版本:代码兼容 Python 3.5 及以上版本(未使用 f-string 等新特性)。
- 回测设置:建议在回测界面将频率设置为“日线”,并设置适当的初始资金。
- 风险提示:CCI 是一个敏感指标,在震荡市中表现较好,但在单边趋势行情中可能会出现过早卖出(牛市中 CCI 长期大于 100)或过早抄底(熊市中 CCI 长期小于 -100)的情况。实际使用时建议结合均线或其他趋势指标进行过滤。
Q&A
Q: 如何修改 CCI 的计算周期?
A: 在 initialize 函数中,修改 g.n = 14 这一行,将 14 改为您想要的数字(例如 20 或 9)。
Q: 这个策略可以用于分钟级别回测吗?
A: 可以。代码逻辑是通用的。您只需要在 PTrade 回测界面的配置中,将运行频率从“日线”改为“分钟”即可。get_history 会自动获取分钟级别的 K 线数据。
Q: 为什么使用 get_history 获取 100 条数据而不是 14 条?
A: 虽然 CCI 周期是 14,但技术指标通常需要更多的数据来平滑计算结果(特别是涉及移动平均的计算)。获取更多数据(如 100 条)可以确保计算出的当前 CCI 值与看盘软件上的数值一致。