“弱水三千,只取一瓢饮。”我不贪图能吃到从行情的起涨点到最高点的全部收益,只要尝到其中的一小段就足够了。这是策略设想的最初本意。
一、最初思路
当行情位于上升趋势时,MACD的红柱会一根比一根长,而在下跌趋势时,绿柱则会一根比一根长。MACD 的红绿柱展示了多空力量强弱情况,所以,我们选择在MACD出现红柱时进场,出现绿柱时离场。
二、写出代码
今天我们选择用akshare来获取数据,用backtrader来回测。
1、导入模块
import backtrader as bt
import akshare as ak
import pandas as pd
2、获取行情数据、转换为Backtrader 数据格式
# 获取股票数据
df = ak.stock_zh_a_hist('600863', start_date='20200101', end_date='20240601')
# 确保 '日期' 列被转换为 'datetime' 列,并且是 pandas 的 Timestamp 类型
df['datetime'] = pd.to_datetime(df['日期'])
# 需要将 akshare 返回的列名映射为 backtrader 能够识别的列名
data_columns = {
'开盘': 'open',
'收盘': 'close',
'最高': 'high',
'最低': 'low',
'成交量': 'volume'
}
# 映射列名
for ak_name, bt_name in data_columns.items():
df[bt_name] = df[ak_name]
# 转换为 Backtrader 数据格式
data = bt.feeds.PandasData(
dataname=df,
datetime='datetime', # 确保 datetime 列名正确
open='开盘', # 列名映射
high='最高',
low='最低',
close='收盘',
volume='成交量'
)
3、编写策略:
class MACDStrategy(bt.Strategy):
# 定义策略参数
params = (
('fast_period', 12),
('slow_period', 26),
('signal_period', 9),
)
def __init__(self):
# 初始化MACD指标
self.macd = bt.indicators.MACD(self.data.close,
period_me1=self.params.fast_period,
period_me2=self.params.slow_period,
period_signal=self.params.signal_period)
# 获取MACD直方图
self.macd_hist = self.macd.macd - self.macd.signal
def next(self):
# 获取当前和前一个周期的MACD直方图值
current_hist = self.macd_hist[0]
previous_hist = self.macd_hist[-1]
# MACD柱子由绿变红时买入
if current_hist > previous_hist and previous_hist <= 0 and current_hist > 0:
if self.position.size == 0:
self.buy()
# MACD柱子缩短且由正变负时卖出
elif current_hist < previous_hist and previous_hist > 0 and current_hist <= 0:
if self.position:
self.close()
4、将数据及策略导入backtrader中进行回策
# 创建Cerebro引擎
cerebro = bt.Cerebro()
# 将数据添加到Cerebro引擎
cerebro.adddata(data)
# 添加策略
cerebro.addstrategy(MACDStrategy)
# 设置初始资金
initial_capital= 100000
# 设置交易费用和滑点
cerebro.broker.setcash(initial_capital)
cerebro.broker.setcommission(commission=0.001)
# 运行回测
cerebro.run()
# 打印结果
print(f"Final Portfolio Value: {cerebro.broker.getvalue()}")
print(f"Total Return: {(cerebro.broker.getvalue() - initial_capital) / initial_capital * 100:.2f}%")
cerebro.plot()
三、运行程序,查看回测结果


结果怎么样?辛辛苦苦四年半,最后还没赚到1元钱。难道是等出现绿柱时抛,有点儿卖完了,那等红柱一开如缩短就开始逃跑吧。修改一下卖出条件:
elif current_hist < previous_hist:
if self.position:
self.close()
但是结果反而亏了几毛:

四、优化策略:MACD+RSI
macd的红绿柱虽能表示多空力量,但单独使用它来进行交易还是有局限性的。下面来改进优化策略,加上RSI强弱指标,在超卖区买入,超买区卖出。完整代码如下:
# MACD红柱买入策略:MACD柱子绿翻红,全仓买入,当MACD红柱翻绿,全仓卖出。
# 本策略仅用于学习,不支持实盘
import backtrader as bt
import akshare as ak
import pandas as pd
# 获取股票数据
df = ak.stock_zh_a_hist('600863', start_date='20200101', end_date='20230101')
# 确保 '日期' 列被转换为 'datetime' 列,并且是 pandas 的 Timestamp 类型
df['datetime'] = pd.to_datetime(df['日期'])
# 需要将 akshare 返回的列名映射为 backtrader 能够识别的列名
data_columns = {
'开盘': 'open',
'收盘': 'close',
'最高': 'high',
'最低': 'low',
'成交量': 'volume'
}
# 映射列名
for ak_name, bt_name in data_columns.items():
df[bt_name] = df[ak_name]
# 转换为 Backtrader 数据格式
data = bt.feeds.PandasData(
dataname=df,
datetime='datetime',
open='开盘',
high='最高',
low='最低',
close='收盘',
volume='成交量'
)
# 定义MACD策略
class MACDStrategy(bt.Strategy):
# 定义策略参数
params = (
('fast_period', 12),
('slow_period', 26),
('signal_period', 9),
('rsi_period', 14),
('rsi_upper', 70),
('rsi_lower', 30),
)
def __init__(self):
# 初始化MACD指标
self.macd = bt.indicators.MACD(self.data.close,
period_me1=self.params.fast_period,
period_me2=self.params.slow_period,
period_signal=self.params.signal_period)
# 获取MACD直方图
self.macd_hist = self.macd.macd - self.macd.signal
self.rsi = bt.indicators.RSI(self.data.close, period=self.params.rsi_period)
def next(self):
# 获取当前和前一个周期的MACD直方图值
current_hist = self.macd_hist[0]
previous_hist = self.macd_hist[-1]
current_rsi = self.rsi[0]
# MACD柱子由绿变红时买入
if current_hist > previous_hist and previous_hist <= 0 and current_hist > 0 and current_rsi < self.params.rsi_lower:
if self.position.size == 0:
self.buy()
# MACD柱子缩短且由正变负时卖出
elif current_hist < previous_hist and previous_hist > 0 and current_hist <= 0 and current_rsi > self.params.rsi_upper:
if self.position:
self.close()
# 创建Cerebro引擎
cerebro = bt.Cerebro()
# 将数据添加到Cerebro引擎
cerebro.adddata(data)
# 添加策略
cerebro.addstrategy(MACDStrategy)
# 设置初始资金
initial_capital= 100000
# 设置交易费用和滑点
cerebro.broker.setcash(initial_capital)
cerebro.broker.setcommission(commission=0.001)
# 运行回测
cerebro.run()
# 打印结果
print(f"Final Portfolio Value: {cerebro.broker.getvalue()}")
print(f"Total Return: {(cerebro.broker.getvalue() - initial_capital) / initial_capital * 100:.2f}%")
cerebro.plot()

结果依然没有赚到钱,又适当修改了一下参数,还是没有什么用。
五、总结
在股市中,仅仅依据某个指标很难保证一定能赚到钱的。指标通常是基于价格和成交量等数据计算得出的,而影响价格的因素实在太多、例如各种消息、投资者的情绪、各种政策的出台、资金的流向等等,所以指标常常在某个时间段有效,过了一段时间又会失效。
以后有机会,再回测一下MACD的顶底背离吧。
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/73454
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!