为什么没人做macd0轴上二次金叉的策略?
看网上很多都在说macd 0轴上二次金叉是买入的黄金时期,为什么没有人做这个策略,太简单?还是这个策略不靠谱??
问题描述
解决方案
其实并不是没有人做,而是纯粹依赖“MACD 0轴上二次金叉”作为单一买入信号的量化策略,在实盘和长期回测中往往表现不佳。网上流传的“黄金买点”更多是基于人工看盘时的“幸存者偏差”(人们往往只记住成功的案例,而忽略了失败的案例)。
在量化交易中,这个策略存在以下几个致命的弱点:
1. 为什么纯 MACD 二次金叉策略“不靠谱”?
- 严重的滞后性:MACD 本质上是基于均线(EMA)的衍生指标。当“0轴上二次金叉”形成时,往往意味着价格已经经历了一波上涨(第一次金叉)、一波回调(死叉),然后再次上涨(二次金叉)。此时买入,往往买在阶段性高点,容易成为“接盘侠”。
- 震荡市的“绞肉机”:MACD 是典型的趋势跟踪指标。在明显的单边上涨行情中,它表现极好;但在震荡市中,DIF 和 DEA 会在 0 轴附近频繁交叉(假突破),导致策略频繁买卖,产生大量的滑点和手续费,造成连续亏损(俗称“来回打脸”)。
- 单因子的局限性:现代量化交易早已过了“一个技术指标打天下”的时代。纯量价指标缺乏对公司基本面、宏观环境和市场情绪的考量,胜率通常很难超过 50%。
- “二次”的定义模糊:在量化代码中,如何定义“二次”?两次金叉之间间隔多少天算有效?回调幅度多大算有效?这些参数的微调会导致策略结果天差地别(过拟合风险极高)。
2. 如何在 JoinQuant 中实现该策略?
虽然纯策略不完美,但我们可以将其作为一个基础信号进行测试。以下是在 JoinQuant 平台实现“MACD 0轴上金叉”的基础框架(为了简化,这里以0轴上金叉为例,二次金叉需要引入更复杂的状态记录):
# 导入聚宽函数库
import jqdata
import talib
import numpy as np
def initialize(context):
# 设定沪深300作为基准
set_benchmark('000300.XSHG')
# 开启动态复权模式(真实价格)
set_option('use_real_price', True)
# 股票类每笔交易时的手续费
set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
# 设定要操作的股票池(例如:平安银行)
g.security = '000001.XSHE'
# 运行函数
run_daily(market_open, time='09:30')
def market_open(context):
security = g.security
# 获取过去 40 天的收盘价数据来计算 MACD
# MACD 默认参数为 12, 26, 9,需要足够的数据预热
close_data = attribute_history(security, 60, '1d', ['close'], df=False)
close_prices = close_data['close']
if len(close_prices) < 60:
return
# 使用 talib 计算 MACD
macd, macdsignal, macdhist = talib.MACD(close_prices, fastperiod=12, slowperiod=26, signalperiod=9)
# 获取昨日和前日的 DIF (macd) 和 DEA (macdsignal)
dif_yesterday = macd[-1]
dea_yesterday = macdsignal[-1]
dif_before_yesterday = macd[-2]
dea_before_yesterday = macdsignal[-2]
# 判断条件:
# 1. 0轴之上:昨日 DIF > 0 且 DEA > 0
# 2. 金叉:前日 DIF < DEA,昨日 DIF > DEA
is_above_zero = (dif_yesterday > 0) and (dea_yesterday > 0)
is_golden_cross = (dif_before_yesterday < dea_before_yesterday) and (dif_yesterday > dea_yesterday)
# 取得当前的现金
cash = context.portfolio.available_cash
current_position = context.portfolio.positions[security].closeable_amount
# 买入逻辑
if is_above_zero and is_golden_cross and cash > 0:
order_value(security, cash)
log.info("MACD 0轴上金叉,买入 %s" % security)
# 卖出逻辑:死叉卖出
is_dead_cross = (dif_before_yesterday > dea_before_yesterday) and (dif_yesterday < dea_yesterday)
if is_dead_cross and current_position > 0:
order_target(security, 0)
log.info("MACD 死叉,卖出 %s" % security)
3. 策略优化建议
如果你想把这个思路做成一个能赚钱的策略,必须进行多因子叠加和过滤:
- 叠加基本面过滤:不要在所有股票上找金叉。先用基本面因子(如 ROE > 15%,净利润增长率 > 20%)筛选出一个优质股票池,然后再在这些好股票里找 MACD 买点。
- 结合大盘环境:只有在沪深300或中证500处于多头趋势(如指数在20日均线之上)时,才允许触发买入信号。震荡市或熊市直接空仓。
- 引入成交量确认:金叉发生时,必须伴随成交量的显著放大(如当日成交量是过去5日均量的1.5倍以上),以过滤假突破。
- 严格的止损止盈:技术指标策略必须配以严格的止损(如跌破买入价的 8% 无条件止损)和移动止盈,以控制最大回撤。