python backtrader打板回测代码无结果

我尝试用python的backtrader编写A股主板股票打板回测的程序,并参考了网上的多种代码,最后完成了整个代码的编写且运行时无error,但无结果生成,其中也可以确定数据已经导入cerebro中,不明白为什么跑不出内容。

######我在resset网站上下载了2020年1月的A股主板股票日数据Excel表,是这样的

img

######附上我的回测代码


```python


import backtrader as bt
import backtrader.feeds as btfeeds # 导入数据模块
import pandas as pd
import datetime
import warnings
warnings.filterwarnings("ignore")

# 实例化 cerebro
cerebro = bt.Cerebro()

# 导入daily_price
dtype={'code':str,}
data= pd.read_excel(r'C:\Users\Administrator\Desktop\data\2020-1.xls',dtype={'code':str,})
daily_price = data[["date", "code", "open", "high", "low", "close", "volume","openinterest"]]
daily_price.set_index('date', inplace=True)


# 按股票代码,依次循环传入数据
for stock in daily_price['code'].unique():
    # 日期对齐
    data = pd.DataFrame(index=daily_price.index.unique()) # 获取回测区间内所有交易日
    df = daily_price.query(f"code=='{stock}'")[['open','high','low','close','volume','openinterest']]
    data_ = pd.merge(data, df, left_index=True, right_index=True, how='left')
    # 缺失值处理:日期对齐时会使得有些交易日的数据为空,所以需要对缺失数据进行填充
    data_.loc[:,['volume',]] = data_.loc[:,['volume']].fillna(0)
    data_.loc[:,['open','high','low','close']] = data_.loc[:,['open','high','low','close']].fillna(method='pad')
    data_.loc[:,['open','high','low','close']] = data_.loc[:,['open','high','low','close']].fillna(0)
    # 导入数据
    datafeed = btfeeds.PandasData(dataname=data_, fromdate=datetime.datetime(2020,1,1), todate=datetime.datetime(2020,1,31))
    cerebro.adddata(datafeed, name=stock) # 通过 name 实现数据集与股票的一一对应
print("Done !")




class MyStrategy(bt.Strategy):
    # 策略参数
    params = dict(
        look_back_days=2,
        printlog=False
    )
    def __init__(self):
        self.order = None

    def next(self):
        #计算今日涨幅,并得出股票池
        long_list=[]
        for data in self.datas:
            if len(data)>self.p.look_back_days:
                p0=data.close[0]
                pn=data.close[-1]
                if pn !=0:
                    rate = (p0-pn)/pn
                else:
                    rate = 0
                if rate>0.097:
                    long_list.append([data._name])  
        # 得到当前的账户价值
        total_value = self.broker.getvalue()
        p_value = total_value*0.9/10
        for data in self.datas:
            #获取仓位
            pos = self.getposition(data).size
            if not pos and data._name in long_list:
                size=int(p_value/100/data.close[0])*100
                price = self.data.lines.high[0]
                self.buy(data = data, size = size,price = price) 
            if pos!=0:
                if (self.data.lines.high[0]-self.data.lines.close[0])/self.data.lines.high[0]>0.05:
                    price = self.data.lines.close[0]
                    self.sell(data = data,size = pos,price = price)                        
    def log(self, txt, dt=None,doprint=False):
        if self.params.printlog or doprint:
            dt = dt or self.datas[0].datetime.date(0)
            print(f'{dt.isoformat()},{txt}')
    #记录交易执行情况
    def notify_order(self, order):
        # 如果order为submitted/accepted,返回空
        if order.status in [order.Submitted, order.Accepted]:
            return
        # 如果order为buy/sell executed,报告价格结果
        if order.status in [order.Completed]: 
            if order.isbuy():
                self.log(f'买入:\n价格:{order.executed.price:.2f},\
                成本:{order.executed.value:.2f},\
                手续费:{order.executed.comm:.2f}')
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:
                self.log(f'卖出:\n价格:{order.executed.price:.2f},\
                成本: {order.executed.value:.2f},\
                手续费{order.executed.comm:.2f}')
            self.bar_executed = len(self) 
        # 如果指令取消/交易失败, 报告结果
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('交易失败')
        self.order = None
    #记录交易收益情况(可省略,默认不输出结果)
    def notify_trade(self,trade):
        if not trade.isclosed:
            return
        self.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}')
 

# 初始资金 10,000
startcash = 10000.0
cerebro.broker.setcash(startcash)

# 佣金,双边各 0.0002
cerebro.broker.setcommission(commission=0.0002)

# 滑点:双边各 0.0001
cerebro.broker.set_slippage_perc(perc=0.0001)

# 将编写的策略添加给大脑
cerebro.addstrategy(MyStrategy,printlog=True)

# 添加策略分析指标
cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='pnl') # 返回收益率时序数据
cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='_AnnualReturn') # 年化收益率
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='_SharpeRatio') # 夏普比率
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='_DrawDown') # 回撤

# 添加观测器
#cerebro.addobserver(...)

# 启动回测
result = cerebro.run()

#打印结果
portvalue = cerebro.broker.getvalue()
pnl = portvalue - startcash
print(f'总资金: {round(portvalue,2)}')
print(f'净收益: {round(pnl,2)}')

# 从返回的 result 中提取回测结果
strat = result[0]

# 返回日度收益率序列
daily_return = pd.Series(strat.analyzers.pnl.get_analysis())

# 打印评价指标
print("--------------- AnnualReturn -----------------")
print(strat.analyzers._AnnualReturn.get_analysis())
print("--------------- SharpeRatio -----------------")
print(strat.analyzers._SharpeRatio.get_analysis())
print("--------------- DrawDown -----------------")
print(strat.analyzers._DrawDown.get_analysis())

对于运行后的结果,

img

我原本怀疑过data导入时的问题,但print过后发现导入是可以的,然后考虑过strategy的问题,但改了两三次最后都没有结果,实在是不清楚问题出在什么地方了,希望可以帮助我,谢谢了!