问题描述
请帮我编写一个 MACD 交易策略,当 DIF 线上穿 DEA 线时买入,下穿时卖出。
解决方案
这是一个基于 PTrade 平台的 MACD 交易策略。
策略逻辑
- 指标计算:使用 PTrade 内置的
get_MACD函数计算 MACD 指标(默认参数:快线12,慢线26,信号线9)。 - 买入信号(金叉):当 DIF 线由下向上穿过 DEA 线时(即上一周期 DIF < DEA,当前周期 DIF > DEA),全仓买入。
- 卖出信号(死叉):当 DIF 线由上向下穿过 DEA 线时(即上一周期 DIF > DEA,当前周期 DIF < DEA),清仓卖出。
策略代码
def initialize(context):
"""
初始化函数,设置股票池和全局变量
"""
# 设置要操作的股票,这里以恒生电子为例
g.security = '600570.SS'
# 设置股票池
set_universe(g.security)
# 设置滑点(可选,这里设为0以便观察逻辑)
set_slippage(0.0)
# 设置佣金(可选,这里设为万三)
set_commission(commission_ratio=0.0003, min_commission=5.0)
def handle_data(context, data):
"""
盘中运行函数,每个周期(如每天或每分钟)运行一次
"""
security = g.security
# 1. 获取历史收盘价数据
# 为了保证MACD计算的准确性,建议获取较长的数据,这里取100根K线
# fq='pre' 表示使用前复权数据,这在回测中很重要
history_data = get_history(100, '1d', 'close', security, fq='pre')
# 如果数据不足,直接返回,避免报错
if len(history_data) < 50:
return
close_prices = history_data['close'].values
# 2. 计算 MACD 指标
# get_MACD 返回三个数组:dif, dea, macd
# 参数说明:close_prices(收盘价序列), short=12(快线), long=26(慢线), m=9(移动平均)
dif, dea, macd = get_MACD(close_prices, 12, 26, 9)
# 3. 获取当前和上一周期的指标值
# [-1] 代表当前周期,[-2] 代表上一周期
curr_dif = dif[-1]
curr_dea = dea[-1]
prev_dif = dif[-2]
prev_dea = dea[-2]
# 获取当前持仓和可用资金
position = get_position(security).amount
cash = context.portfolio.cash
# 4. 交易逻辑判断
# 判断金叉:上一周期 DIF < DEA 且 当前周期 DIF > DEA
if prev_dif < prev_dea and curr_dif > curr_dea:
# 如果有资金,则全仓买入
if cash > 0:
# 使用 order_value 按金额下单
order_value(security, cash)
log.info("MACD金叉买入: %s, 价格: %.2f" % (security, data[security]['close']))
# 判断死叉:上一周期 DIF > DEA 且 当前周期 DIF < DEA
elif prev_dif > prev_dea and curr_dif < curr_dea:
# 如果有持仓,则清仓卖出
if position > 0:
# 使用 order_target 将持仓调整为 0
order_target(security, 0)
log.info("MACD死叉卖出: %s, 价格: %.2f" % (security, data[security]['close']))
注意事项
- 数据长度:代码中
get_history获取了 100 条数据。MACD 是基于移动平均线的指标,如果获取的历史数据太短,计算出的初始值可能不稳定,导致信号不准确。 - 复权处理:在
get_history中使用了fq='pre'(前复权)。在股票回测中,为了避免分红派息导致的价格跳空影响技术指标计算,通常推荐使用前复权数据。 - 频率:此代码默认在日线级别(
1d)运行。如果您在回测设置中选择了“分钟”级别,该策略会在每分钟结束时运行,逻辑依然适用,但交易频率会变高。 - Python 版本兼容性:代码使用了兼容 Python 3.5 的字符串格式化方式(
%s),确保在 PTrade 的旧版环境中也能正常运行。