问题描述
解决方案
这是一个基于布林带(Bollinger Bands)的均值回归交易策略。
策略逻辑
- 计算指标:利用过去 N 天(通常为20天)的收盘价计算移动平均线(中轨)和标准差。
- 中轨 = N日收盘价均值
- 上轨 = 中轨 + K * 标准差
- 下轨 = 中轨 - K * 标准差
- 买入信号:当当前价格跌破下轨时,认为股价超卖,执行买入。
- 卖出信号:当当前价格突破上轨时,认为股价超买,执行卖出(清仓)。
PTrade 策略代码
import numpy as np
def initialize(context):
"""
初始化函数,设置策略参数和股票池
"""
# 设置我们要操作的股票,这里以贵州茅台(600519.SS)为例
# 实际使用时可修改为其他股票代码
g.security = '600519.SS'
set_universe([g.security])
# 设置基准指数,默认为沪深300
set_benchmark('000300.SS')
# 布林带参数设置
g.n = 20 # 计算均值的周期,通常为20日
g.k = 2 # 标准差的倍数,通常为2倍
# 设置滑点和手续费(可选,根据实际情况调整)
set_commission(commission_ratio=0.0003, min_commission=5.0, type='STOCK')
set_slippage(slippage=0.002)
def handle_data(context, data):
"""
盘中运行函数,每个单位时间(如每天或每分钟)调用一次
"""
security = g.security
# 获取该股票的历史收盘价数据
# count=g.n 表示获取过去N个时间单位的数据
# include=False 表示不包含当前时间点的数据(避免未来函数)
hist = get_history(count=g.n, frequency='1d', field='close', security_list=security, include=False)
# 检查数据长度是否足够,如果是新股可能数据不足
if len(hist) < g.n:
log.info("历史数据不足,跳过计算")
return
# 提取收盘价数组
close_prices = hist['close'].values
# 计算布林带指标
# 1. 计算中轨(移动平均线)
mid_band = np.mean(close_prices)
# 2. 计算标准差
std_dev = np.std(close_prices)
# 3. 计算上轨和下轨
upper_band = mid_band + g.k * std_dev
lower_band = mid_band - g.k * std_dev
# 获取当前最新价格
current_price = data[security]['close']
# 获取当前持仓数量
position = context.portfolio.positions[security].amount
# 获取当前可用资金
cash = context.portfolio.cash
# --- 交易逻辑 ---
# 1. 买入逻辑:价格跌破下轨 且 当前无持仓
if current_price < lower_band and position == 0:
# 全仓买入
order_value(security, cash)
log.info("价格跌破下轨,买入 %s,价格: %.2f,下轨: %.2f" % (security, current_price, lower_band))
# 2. 卖出逻辑:价格突破上轨 且 当前有持仓
elif current_price > upper_band and position > 0:
# 清仓卖出
order_target(security, 0)
log.info("价格突破上轨,卖出 %s,价格: %.2f,上轨: %.2f" % (security, current_price, upper_band))
# 打印调试信息(可选)
# log.info("当前价格: %.2f, 上轨: %.2f, 中轨: %.2f, 下轨: %.2f" % (current_price, upper_band, mid_band, lower_band))
代码说明
initialize:- 使用
set_universe设置股票池。 - 定义了全局变量
g.n(周期) 和g.k(标准差倍数),方便后续调整。
- 使用
handle_data:- 使用
get_history获取过去20天的收盘价。注意include=False,这意味着我们使用昨天及之前的20天数据来计算指标,用来指导今天的交易。 - 使用
numpy(np.mean,np.std) 计算均值和标准差。 - 买入条件:
current_price < lower_band。使用order_value将所有现金买入股票。 - 卖出条件:
current_price > upper_band。使用order_target(security, 0)将持仓调整为0,即清仓。
- 使用
常见问题 (Q&A)
Q: 如何修改布林带的周期,比如改成26天?
A: 在 initialize 函数中,将 g.n = 20 修改为 g.n = 26 即可。
Q: 这个策略可以用于分钟级别回测吗?
A: 可以。代码中的 get_history 参数 frequency='1d' 是日线级别。如果需要分钟级回测,请将回测频率设置为分钟,并将代码中的 '1d' 改为 '1m' (1分钟) 或 '5m' (5分钟) 等。
Q: 为什么使用 include=False?
A: 在日线回测中,如果在盘中(比如上午10点)计算当天的均线,当天的收盘价还没确定,这会导致数据偏差。通常做法是利用截止到昨天的历史数据计算出轨道,然后观察今天的实时价格是否触碰这些轨道。
Q: 如何让策略交易多只股票?
A: 目前代码针对单只股票。如果要交易多只股票,需要在 handle_data 中使用 for 循环遍历 g.security (需将其设为列表),并对每只股票分别计算指标和下单。同时需要考虑资金分配问题(例如每只股票分配总资金的1/N)。