龙空技术网

学习python量化:不要迷信指标,MACD+RSI都赚不到钱

不消残酒-自在林 1023

前言:

眼前你们对“rsipython”可能比较关怀,姐妹们都想要剖析一些“rsipython”的相关内容。那么小编同时在网上汇集了一些有关“rsipython””的相关内容,希望朋友们能喜欢,小伙伴们快快来学习一下吧!

“弱水三千,只取一瓢饮。”我不贪图能吃到从行情的起涨点到最高点的全部收益,只要尝到其中的一小段就足够了。这是策略设想的最初本意。

一、最初思路

当行情位于上升趋势时,MACD的红柱会一根比一根长,而在下跌趋势时,绿柱则会一根比一根长。MACD 的红绿柱展示了多空力量强弱情况,所以,我们选择在MACD出现红柱时进场,出现绿柱时离场。

二、写出代码

今天我们选择用akshare来获取数据,用backtrader来回测。

1、导入模块

import backtrader as btimport akshare as akimport 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 btimport akshare as akimport 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的顶底背离吧。

#夏日生活打卡季#

标签: #rsipython