怎样指定backtrader库自定义MACD指标红绿柱颜色?

我在学习backtrader库的时候,自定义的一个全新的MACD指标,指标需要的参数是提前算好写在CSV文件里的。新建指标的时候直接从CSV里读取。

class MacdNew(bt.Indicator):  #自定义全新MACD指标
    lines = ('diff', 'dea','macd')
    #colors_bar = np.where(data.macd_bar.values > 0, 'red', 'green')
    setcolor = None
    plotinfo = dict(plot=True,plotname='MACD',plotabove=False,subplot=True)
    plotlines = dict(macd=dict(_method='bar', alpha=0.50, width=0.8,color=setcolor),
                                    diff=dict(color='black',linewidth=0.8),
                                    dea=dict(color='blue',linewidth=0.8))
    def __init__(self):
        self.lines.diff = self.data.diff
        self.lines.dea = self.data.dea
        self.lines.macd = self.data.macd_bar
        MacdNew.setcolor = 'red'

该指标里有三根线,diff,dea,macd。macd就是指MACD指标的红绿柱bar。我想让红绿柱根据bar值的正负,显示对应的红与绿。不知道应该怎么写简单:
(已经扩展了class PandasData_macd(PandasData)库 #扩展PandasData线

class PandasData_macd(PandasData):  #扩展PandasData线
    lines = ('diff','dea','macd_bar',)
    params = (('diff',8),('dea',9),('macd_bar',10))

在尝试解决这个问题的时候,我在从bt.Indicator继承的MacdNew类(自定义的指标)里面,先写上类属性:
setcolor=None
然后在class MacdNew(bt.Indicator)类的init初始化里面给这个类属性赋值'red':

class MacdNew(bt.Indicator):  #自定义MACD指标
    lines = ('diff', 'dea','macd')
    #colors_bar = np.where(data.macd_bar.values > 0, 'red', 'green')
    setcolor = None
    plotinfo = dict(plot=True,plotname='MACD',plotabove=False,subplot=True)
    plotlines = dict(macd=dict(_method='bar', alpha=0.50, width=0.8,color=setcolor),diff=dict(color='black',linewidth=0.8),dea=dict(color='blue',linewidth=0.8))
    def __init__(self):
        self.lines.diff = self.data.diff
        self.lines.dea = self.data.dea
        self.lines.macd = self.data.macd_bar
        MacdNew.setcolor = 'red'

在策略库运行的时候,

class MyStrategy(bt.Strategy):
    params = (('myparam', 27), ('exitbars', 5),('maperiod',[5,20,30]),('fast_period',6),('slow_period',10))
    def log(self,txt,dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print('%s %s' % (dt.isoformat(),txt))

    def __init__(self):

        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.macd = MacdNew()

并没有将:MacdNew.setcolor = 'red',赋值给自定义指标中: plotlines = dict(macd=dict(_method='bar', alpha=0.50, width=0.8,color=setcolor)的setcolor。
请指教:在backtrader的全新自定义MACD指标(指标提前算好在CSV文件)里,如何根据bar柱值的正负,显示相对应的红绿色?

这样,把柱子分成两部分,即水上部分与水下部分。

class MacdNew(bt.ind.MACD):  #自定义全新MACD指标

    lines = ('histo_up', 'histo_down')
    plotlines = dict(histo_up=dict(_method='bar', alpha=0.80, width=0.5, color='tomato'),
                    histo_down=dict(_method='bar', alpha=0.80, width=0.5, color='limegreen'))

    def __init__(self):
        super(MacdNew, self).__init__()

    def next(self):
        histo = (self.lines.macd - self.lines.signal) * 2
        if histo > 0:
            self.l.histo_up[0] = histo
        else:
            self.l.histo_down[0] = histo

该回答引用GPTᴼᴾᴱᴺᴬᴵ
你可以在 next() 方法里动态设置 setcolor 属性,以便根据 macd_bar 值的正负来设置颜色。可以参考下面的代码:

class MacdNew(bt.Indicator):  #自定义全新MACD指标
    lines = ('diff', 'dea','macd')
    plotinfo = dict(plot=True,plotname='MACD',plotabove=False,subplot=True)
    plotlines = dict(macd=dict(_method='bar', alpha=0.50, width=0.8,color=None),
                     diff=dict(color='black',linewidth=0.8),
                     dea=dict(color='blue',linewidth=0.8))

    def __init__(self):
        self.lines.diff = self.data.diff
        self.lines.dea = self.data.dea
        self.lines.macd = self.data.macd_bar
        self.setcolor = None

    def next(self):
        if self.data.macd_bar[0] > 0:
            self.plotlines.macd.color = 'red'
        else:
            self.plotlines.macd.color = 'green'

在这个例子中,在 init() 方法里初始化了 setcolor 属性,并将其赋值为 None,因为要在 next() 方法中动态设置它的值。然后,在 next() 方法中,检查 macd_bar 的值,并设置 plotlines.macd.color 的值来指定红或绿颜色。

你可以根据需要更改颜色设置的逻辑。还要注意,在这个例子中,使用 plotlines.macd.color 来设置颜色,而不是 self.setcolor,因为 plotlines 是用于绘制指标的参数,而 self.setcolor 是一个不同的属性,没有用于绘图。

你好,上面的代码我测试了,还是不能达到我的要求,我把全部的代码贴在下面:

import backtrader as bt
import pandas as pd
from datetime import datetime
from backtrader.feeds import PandasData
import numpy as np

class PandasData_macd(PandasData):  #扩展PandasData线
    lines = ('diff','dea','macd_bar',)
    params = (('diff',8),('dea',9),('macd_bar',10))



class MacdNew(bt.Indicator):  #自定义MACD指标
    lines = ('diff', 'dea','macd')
    params = (('period',1),)
    plotinfo = dict(plot=True,plotname='MACD',plotabove=False,subplot=True)
    plotlines = dict(macd=dict(_method='bar', alpha=0.50, width=0.8,color=None),
                     diff=dict(color='grey',linewidth=0.8),
                     dea=dict(color='blue',linewidth=0.8))
    def __init__(self):
        self.addminperiod(self.params.period)
        self.lines.diff = self.data.diff
        self.lines.dea = self.data.dea
        self.lines.macd = self.data.macd_bar
        #self.setcolor = None

    def next(self):
        if self.data.macd_bar[0] < 0:  #if self.data.macd_bar[0] < 0 整体显示红色;if self.data.macd_bar[0] > 0 整体显示绿色
            print('red')   #能正常显示对应的颜色
            self.plotlines.macd.color = 'red'
        else:
            print('green')  #能正常显示对应的颜色
            self.plotlines.macd.color = 'green'




class MyStrategy(bt.Strategy):
    params = (('myparam', 27), ('exitbars', 5),('maperiod',[5,20,30]),('fast_period',6),('slow_period',10))
    def log(self,txt,dt=None):
        dt = dt or self.datas[0].datetime.date(0)
        print('%s %s' % (dt.isoformat(),txt))

    def __init__(self):

        self.order = None
        self.buyprice = None
        self.buycomm = None
        self.macd = MacdNew()



    def notify_order(self, order):
        if order.status in [order.Submitted,order.Accepted]:        #如果指令在指令集合[提交的指令、接受的指令]集合里面
            #self.log('标记')
            return                                                  #不处理这个指令
        if order.status in  [order.Completed]:
            if order.isbuy():
                self.log('买入指令已执行 执行价格: %.2f 交易手数:%.2f 交易金额: %.2f  手续费: %.2f ' %( order.executed.price ,
                                                                                                        order.executed.size,
                                                                                                        order.executed.value ,
                                                                                                        order.executed.comm))
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm                #self.buysize = order.executed.size

            else:
                if order.issell():
                    self.log('卖出指令已执行 执行价格: %.2f 交易手数:%.2f 交易金额: %.2f  手续费: %.2f ' %( order.executed.price,
                                                                                                            order.executed.size ,
                                                                                                            order.executed.value ,
                                                                                                            order.executed.comm))
            self.bar_executed = len(self)
        elif order.status in [order.Canceled,order.Margin,order.Rejected]:
            self.log('Canceled,margin,rejected')
        self.order = None

    def notify_trade(self, trade):
        if not trade.isclosed:
            return
        else:
            self.log('本次交易已完成 毛利:%.2f 净利:%.2f' %(trade.pnl,trade.pnlcomm))

    def next(self):
        pass

cerebro = bt.Cerebro()
cerebro.addstrategy(MyStrategy)
ts_code = '600425.SH'
startdate = '20200101'
enddate = '20230223'
file_path_csv = 'G:\\pycharm\\CSV\\'  #CSV文件存放目录注意'\\'
df_new = pd.read_csv(file_path_csv+ts_code+'-'+startdate+'-'+enddate+'.csv',index_col='trade_date',parse_dates=['trade_date'])
df_new.rename(columns={'vol':'volume'},inplace=True) #因为tushare数据里成交量用的列名:vol,而backtrader里面需要的列名:volume,需要重命名tushare的成交量列名
#rint(df_new)
start_date = datetime(2020,1,1)
end_date = datetime(2023,2,20)
data = PandasData_macd(dataname=df_new,
                           datetime=None,
                           open = 2,
                           high = 3,
                           low = 4,
                           close = 5,
                           volume = 9,
                           diff = 23,
                           dea = 24,
                           macd_bar = 25,
                           fromdate= start_date,todate= end_date)
#print(data)
cerebro.adddata(data)
cerebro.broker.setcash(20000)
cerebro.addsizer(bt.sizers.FixedSize,stake= 1000)
cerebro.broker.setcommission(commission=0.0003)

print('大脑运行前的金额:%.2f' % cerebro.broker.getvalue())
cerebro.run()
print('大脑运行后的金额:%.2f' % cerebro.broker.getvalue())
cerebro.plot(volume=True,style='candle',barup='red',bardown='green',barupfill= False,bardownfill= True,volup='red',voldown='green')

当我把改动if self.data.macd_bar[0] < 0 或者if self.data.macd_bar[0] > 0时,MACD柱的颜色整体要么变称red,或者green


    def next(self):
        if self.data.macd_bar[0] < 0:  #if self.data.macd_bar[0] < 0 整体显示红色;if self.data.macd_bar[0] > 0 整体显示绿色
            print('red')   #能正常显示对应的颜色
            self.plotlines.macd.color = 'red'
        else:
            print('green')  #能正常显示对应的颜色
            self.plotlines.macd.color = 'green'

不知道哪里出了问题

不知道你这个问题是否已经解决, 如果还没有解决的话:

如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^