【问题标题】:backtrader how to use analyzer to access data?backtrader 如何使用分析器访问数据?
【发布时间】:2021-07-18 05:57:32
【问题描述】:

我对此很陌生。 backtrader有一个addwriter可以写一些数据,
cerebro.addwriter(bt.WriterFile, csv=True, out='outputfiles3\{}cerebro.csv'.format(ticker)) 但买卖价格总是与执行价格不匹配。

另外:

我在cerebro.run() 之前做过cerebro.addanalyzer(WritingAnalyzer)

所以我正在尝试使用 'datetime'、'open'、'close'、'cash'、'value'、'position size' 构建 csv 文件 但我不知道如何访问这些数据。我只能用self.data[0]指出当天收盘价

我不知道该怎么做。我希望有人能给我一些指导。

import backtrader as bt
from backtrader import Analyzer
import csv

class WritingAnalyzer(Analyzer):

    def __init__(self):

    def create_analysis(self):
        self.counter = 0
        print(self.counter)
        with open('demo1.csv',mode='w') as csv_file:
            fieldnames=['datetime','open','close','cash','value','position size']
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
            writer.writeheader()

    def next(self):
        self.counter += 1
        print('close price:',self.data[0], "counter:",self.counter,)
        #  the following line suppose to write into csv file but i dont know how to get most of the data.
        bt.writer.writerow({'datetime': '??', 'open': '??', 'close': self.data[0],'cash':'??','value':'??','position size':'??'})

    def stop(self):
        print("SSSSSSSSSSSSSTTTTTTOOOOOOOOOOOOPPPPPPPPPP")

        self.rets._close()

【问题讨论】:

    标签: csv analyzer writer backtrader


    【解决方案1】:

    您需要以不同的方式处理您的分析仪。您可以从字面上抓取每个条形图上的数据,然后在最后将其提供给您。

    创建一个新的分析器,以我为例:

    class BarAnalysis(bt.analyzers.Analyzer):
    

    在开始的分析器中,您将创建一个新列表。

    def start(self):
        self.rets = list()
    

    接下来,您将为每个条形添加一个数据列表。我使用 try 语句以防万一出现任何数据问题,但可能没有必要。 Strategy 作为子类包含在内,您可以通过调用 self.strategy.getvalue() 作为示例来使用它的方法。

    def next(self):
        try:
            self.rets.append(
                [
                    self.datas[0].datetime.datetime(),
                    self.datas[0].open[0],
                    self.datas[0].high[0],
                    self.datas[0].low[0],
                    self.datas[0].close[0],
                    self.datas[0].volume[0],
                    self.strategy.getposition().size,
                    self.strategy.broker.getvalue(),
                    self.strategy.broker.getcash(),
                ]
            )
        except:
            pass
    

    最后创建一个get_analysis 方法,您可以使用它来获得最后的结果。

    def get_analysis(self):
        return self.rets
    

    在运行 cerebro 之前添加您的分析仪。您可以随意命名,我们需要名称来调用结果。

    cerebro.addanalyzer(BarAnalysis, _name="bar_data")
    

    确保为 cerebro.run() 方法的结果提供变量,以便收集回测结果。

    strat = cerebro.run()
    

    最后,从strat 中取出数据并按照您的意愿使用它。在这种情况下,我正在创建一个数据框并进行打印。

    bar_data_res = strat[0].analyzers.bar_data.get_analysis()
    df = pd.DataFrame(bar_data_res)
    print(df)
    

    打印输出如下:

    /home/runout/projects/rb_master/venv/bin/python /home/runout/projects/scratch/20210424_analyzer.py
                                 0       1       2  ...  6         7         8
    0   2020-01-02 23:59:59.999989  212.70  213.36  ...  0  10000.00  10000.00
    1   2020-01-03 23:59:59.999989  210.81  213.28  ...  0  10000.00  10000.00
    2   2020-01-06 23:59:59.999989  210.18  213.59  ...  0  10000.00  10000.00
    3   2020-01-07 23:59:59.999989  213.11  214.13  ...  0  10000.00  10000.00
    4   2020-01-08 23:59:59.999989  212.43  216.47  ...  0  10000.00  10000.00
    ..                         ...     ...     ...  ... ..       ...       ...
    247 2020-12-23 23:59:59.999989  268.38  269.31  ...  1  10015.38   9747.25
    248 2020-12-24 23:59:59.999989  267.76  269.67  ...  1  10016.48   9747.25
    249 2020-12-28 23:59:59.999989  270.48  270.55  ...  1  10014.82   9747.25
    250 2020-12-29 23:59:59.999989  268.30  268.78  ...  1  10011.78   9747.25
    251 2020-12-30 23:59:59.999989  264.45  265.64  ...  1  10010.86   9747.25
    
    [252 rows x 9 columns]
    
    Process finished with exit code 0
    

    整个代码如下所示:

    import datetime
    import backtrader as bt
    import pandas as pd
    
    class BarAnalysis(bt.analyzers.Analyzer):
    
        def start(self):
            self.rets = list()
    
        def next(self):
            try:
                self.rets.append(
                    [
                        self.datas[0].datetime.datetime(),
                        self.datas[0].open[0],
                        self.datas[0].high[0],
                        self.datas[0].low[0],
                        self.datas[0].close[0],
                        self.datas[0].volume[0],
                        self.strategy.getposition().size,
                        self.strategy.broker.getvalue(),
                        self.strategy.broker.getcash(),
                    ]
                )
            except:
                pass
    
        def get_analysis(self):
            return self.rets
    
    
    class Strategy(bt.Strategy):
    
        params = (
            ("lowerband", 30),
            ("upperband", 70),
        )
    
        def __init__(self):
            self.rsi = bt.ind.RSI(period=10)
    
        def next(self):
            if not self.position:
                if self.rsi <= self.p.lowerband:
                    self.buy()
            elif self.rsi >= self.p.upperband:
                self.close()
    
    if __name__ == "__main__":
    
        cerebro = bt.Cerebro()
    
        ticker = "HD"
        data = bt.feeds.YahooFinanceData(
            dataname=ticker,
            timeframe=bt.TimeFrame.Days,
            fromdate=datetime.datetime(2020, 1, 1),
            todate=datetime.datetime(2020, 12, 31),
            reverse=False,
        )
    
        cerebro.adddata(data, name=ticker)
    
        cerebro.addanalyzer(BarAnalysis, _name="bar_data")
        cerebro.addstrategy(Strategy)
    
        # Execute
        strat = cerebro.run()
    
        bar_data_res = strat[0].analyzers.bar_data.get_analysis()
        df = pd.DataFrame(bar_data_res)
        print(df)
    
    
    

    【讨论】:

    • 非常感谢您的宝贵时间。 @用完。你解释得很好。有没有办法在try: self.rets.append() 中提取成本基础?
    • 将此行添加到您的分析器:` self.strategy.getposition().adjbase, `
    • 谢谢。你能告诉我你是怎么发现的吗?您发布答案后,我很容易搜索和验证。但如果你不回答我,我就找不到它。
    • getposition 主要用于大小和价格,但如果您将其打印出来,您会看到还有更多字段跟踪数据。尝试下一个:print(self.getposition()) 你会得到类似的东西: --- Position Begin - Size: 1 - Price: 267.01 - Price orig: 0.0 - Closed: 0 - Opened: 1 - Adjbase: 264.53 --- Position End
    • self.strategy.getposition().adjbase,为持仓当日收盘价。无仓时(0仓)返回持仓最后一天的收盘价。如果没有持仓,我正在寻找 0,即持仓当天的(购买价格 * 持仓数量)(实际成本)。有人建议 self.broker.getcommissioninfo(data),但无法将“数据”传递给课堂。
    猜你喜欢
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 2015-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    相关资源
    最近更新 更多