在 JoinQuant 平台上使用 Python 实现 MACD 金叉与死叉交易策略
本文将详细介绍如何基于 JoinQuant(聚宽)量化平台,利用 Python 编程语言实现经典的 MACD 技术指标策略。通过识别 MACD 的“金叉”和“死叉”信号,自动触发买入与卖出操作。文中包含完整可运行的代码示例,帮助您快速掌握策略开发流程。
策略核心逻辑说明
技术指标设置
采用标准 MACD 参数配置:快线周期为 12,慢线周期为 26,信号线周期为 9。
交易信号定义
- 金叉(买入信号):当 DIF 线(差离值)从下方穿越 DEA 线(讯号线)时,判定为买入时机,执行全仓买入操作。
- 死叉(卖出信号):当 DIF 线从上方穿过 DEA 线向下时,视为卖出信号,立即清空持仓。
数据处理方式
每个交易日获取目标股票过去 100 个交易日的收盘价数据,确保有足够的历史信息用于稳定计算 MACD 指标值。
计算工具支持
借助高效的第三方技术分析库进行指标运算,提升计算性能与准确性。
talib
完整策略代码实现
# -*- coding: utf-8 -*-
# 导入所需函数库
from jqdata import *
import talib
import numpy as np
def initialize(context):
"""
初始化函数,配置基准、复权模式、标的股票及交易成本等参数
"""
# 设定沪深300指数作为业绩基准
set_benchmark('000300.XSHG')
# 启用真实价格的动态复权模式
set_option('use_real_price', True)
# 指定操作的个股,此处以平安银行为例
g.security = '000001.XSHE'
# 定义MACD参数
g.fast_period = 12 # 快线周期
g.slow_period = 26 # 慢线周期
g.signal_period = 9 # 信号线周期
# 设置股票类交易的手续费与印花税
set_order_cost(
OrderCost(
close_tax=0.001, # 卖出印花税千分之一
open_commission=0.0003, # 买入佣金万分之三
close_commission=0.0003, # 卖出佣金万分之三
min_commission=5 # 每笔最低5元
),
type='stock'
)
# 每日开盘时执行 market_open 函数
run_daily(market_open, time='every_bar')
def market_open(context):
"""
日内交易逻辑主函数
"""
security = g.security
# 获取最近100天的日线收盘价数据
close_data = attribute_history(security, 100, '1d', ['close'])
# 转换为 numpy 数组格式以适配 talib 输入要求
close_array = close_data['close'].values
# 利用 talib 计算 MACD 三项输出:DIF, DEA, 柱状图
macd_dif, macd_dea, macd_hist = talib.MACD(
close_array,
fastperiod=g.fast_period,
slowperiod=g.slow_period,
signalperiod=g.signal_period
)
# 提取当前及前一时刻的 DIF 与 DEA 值
current_dif = macd_dif[-1]
current_dea = macd_dea[-1]
prev_dif = macd_dif[-2]
prev_dea = macd_dea[-2]
# 查询当前是否持有该股票
current_position = context.portfolio.positions[security].closeable_amount
# 获取账户可用现金
cash = context.portfolio.available_cash
# 判断交易条件并执行相应操作
# 金叉判断:前一期 DIF 小于 DEA,当前期 DIF 大于 DEA
if prev_dif < prev_dea and current_dif > current_dea:
if cash > 0:
order_value(security, cash) # 使用全部可用资金买入
log.info("MACD金叉,买入 %s" % security)
# 死叉判断:前一期 DIF 大于 DEA,当前期 DIF 小于 DEA
elif prev_dif > prev_dea and current_dif < current_dea:
if current_position > 0:
order_target(security, 0) # 清仓卖出所有持股
log.info("MACD死叉,卖出 %s" % security)
# 代码关键点解析
talib.MACD
该函数是一个高效的技术分析工具,能够返回三个数组:DIF(快线)、DEA(慢线)以及MACD柱状图。这些数据是判断买卖信号的核心依据。
attribute_history
在调用历史数据时,我们选取了过去100天的数据长度。尽管MACD的标准参数为12和26,但为了确保EMA(指数移动平均)计算的稳定性和准确性,通常需要提供比最长周期多出2-3倍的数据量,以便让指标充分收敛。
# 交叉判断逻辑
通过对比前一日与当日的DIF和DEA值,可以识别金叉或死叉信号:
- 若昨日 DIF < DEA,而今日 DIF > DEA,则形成**金叉**,视为买入信号。
- 若昨日 DIF > DEA,而今日 DIF < DEA,则形成**死叉**,视为卖出信号。
elif prev_dif > prev_dea and current_dif < current_dea:
# 当出现死叉信号时执行清仓操作
if current_position > 0:
order_target(security, 0)
log.info("MACD死叉,卖出 %s" % security)
[-1]
[-2]
# 核心交易指令说明
order_value(security, cash)
此命令表示使用当前账户中全部可用现金买入指定证券,实现满仓操作。
order_target(security, 0)
该指令将目标证券的持仓调整为零,即执行彻底的清仓卖出动作,不留余股。
order_value
order_target
# 常见问题解答(Q&A)
Q: 为什么获取历史数据时不采用26天,而是选择100天?
A: 因为MACD依赖EMA进行计算,而EMA具有递归特性,初始值对后续结果影响较大。若仅取26天数据,前期EMA尚未收敛,会导致指标失真。获取更长时间段(如100天以上)的数据可使EMA趋于稳定,从而保证回测中指标值与实际行情软件显示一致。
Q: 如何将此策略扩展为多只股票轮动模式?
A: 可将g.security
替换为一个股票代码列表,例如g.stocks = ['000001.XSHE', '600519.XSHG']
。随后在market_open
函数中,利用for security in g.stocks:
循环逐一处理每只股票,分别完成数据提取、指标计算与下单操作。同时需考虑资金分配策略,比如将总资金均分为N份,每只股票使用1/N的资金量进行交易。
Q: 策略中的set_option('use_real_price', True)
有何作用?
A: 此行启用了动态复权模式(即真实价格处理)。在实际市场中,股票会因分红、配股、拆合股等事件导致价格跳变。启用该选项后,聚宽平台会在回测过程中自动进行复权处理,确保所使用的股价序列连续无断点,避免因价格异常波动造成技术指标误判(例如股价除权后骤降被误认为死叉触发条件)。