For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Extending Datafeeds GenericCSV Attribute Error



  • I have looked at extending the GenericCSV and am trying to add an additional column (pe) like in the example and am getting the error

    AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'pe'

    Hopefully i am doing something stupid but cannot seem to figure out why the GenericCSVpe isn't adding the pe parameter to the class?

    Here is my complete test code.

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    import backtrader as bt
    import pandas as pd
    from backtrader.feeds import GenericCSVData
    import backtrader.feeds as btfeeds
    import datetime as datetime
    import backtrader.indicators as btind
    import numpy as np
    
    from backtrader.feeds import GenericCSVData
    
    class GenericCSV_PE(GenericCSVData):
    
        # Add a 'pe' line to the inherited ones from the base class
        lines = ('pe',)
    
        # openinterest in GenericCSVData has index 7 ... add 1
        # add the parameter to the parameters inherited from the base class
        params = (('pe', 8),)
    
    class MyStrategy(bt.Strategy):
    
    
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = self.datas[0].datetime.date(0)
            dt_time = self.datas[0].datetime.time(0)
            dt_weekday = datetime.datetime.weekday(dt)
            print('%s, %s' % (dt.isoformat(), txt))
    
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            # init stop loss and take profit order variables
            self.sl_order, self.tp_order = None, None
            self.datavolume = self.datas[0].volume
            self.pe = self.datas[0].pe
    
    
        def next(self):
            if self.datavolume[0] / np.mean(self.datavolume.get(size=10, ago=-1)) >= 1.25:
                self.buy()
                print(self.pe[0])
    
    
    
    if __name__ == '__main__':
        # Create a cerebro entity
        cerebro = bt.Cerebro()
    
    
        data = btfeeds.GenericCSVData(
            dataname='C:\\Users\\oso\\Dropbox\\All Devices\\Datav1.csv',
    
            nullvalue=0.0,
    
            dtformat=('%m/%d/%Y'),
    
            datetime=0,
            time=-1,
            high=2,
            low=3,
            open=1,
            close=4,
            volume=5,
            openinterest=6
        )
    
        # Add the Data Feed to Cerebro
        cerebro.adddata(data)
    
        # Set our desired cash start
        cerebro.broker.setcash(100000.0)
    
        # Add a strategy
        cerebro.addstrategy(MyStrategy)
    
        # Print out the starting conditions
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
        # Run over everything
        cerebro.run()
    
        # Print out the final result
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
        cerebro.plot(style='bar')
    

    0_1507400960917_pe backtrader.PNG


  • administrators

    @Osofuego said in Extending Datafeeds GenericCSV Attribute Error:

    data = btfeeds.GenericCSVData(

    You are not using your own extended data feed.



  • @Osofuego said in Extending Datafeeds GenericCSV Attribute Error:

    dt = self.datas[0].datetime.date(0)

    Hello @Osofuego

    Hope all is well. I have a code structure remarkably similar to yours, and from what I see using the same syntax for datetime identical to you too. However, when I run it, I keep getting an error:

    ValueError: time data '"2014-12-31' does not match format '%m/%d/%Y'

    Wondering if you can quickly take a look at my code and see why mine is not running? A snapshot of the csv file format I am trying to import is shown below:

    0_1507742935812_Capture.PNG

    And my code is as following: (weird, it doesnt even show import datetime as datetime being imported at the top to beused, which could be part of the issue?)

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    
    
    import os.path  # To manage paths
    import sys  # To find out the script name (in argv[0])
    
    # Import the backtrader platform
    import backtrader as bt
    import backtrader.feeds as btfeeds
    import datetime as datetime
    
    
    # Create a Stratey
    class TestStrategy(bt.Strategy):
    
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def __init__(self):                              # upon __init__ being called the strategy already has a list of datas that are present in the platform. This is a standard Python list and datas can be accessed in the order they were inserted.
            # Keep a reference to the "close" line in the data[0] dataseries
            self.dataclose = self.datas[0].close        # self.dataclose = self.datas[0].close keeps a reference to the close line. (close price)
                                                        # the first data in the list self.datas[0] is the default data for trading operations and to keep all strategy elements synchronized (its the system clock)
    
        def next(self):                                 # 'next' method will be called on each bar of the system clock (self.datas[0]). This is true until other things come into play like indicators, which need some bars to start producing an output.
            # Simply log the closing price of the series from the reference
            self.log('Close, %.2f' % self.dataclose[0])
    
            # if the price has been falling 3 sessions in a row..... buy buy buy!
            if self.dataclose[0] < self.dataclose[-1]:
                # current close less than previous close
    
                if self.dataclose[-1] < self.dataclose[-2]:
                    # previous close less than the previous close
    
                    # BUY, BUY, BUY!!! (with all possible default parameters)
                    self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    self.buy()
    
    
    if __name__ == '__main__':
        # Create a cerebro entity
        cerebro = bt.Cerebro()
    
        # Add a strategy
        cerebro.addstrategy(TestStrategy)
    
        data = btfeeds.GenericCSVData(
            dataname='C:\\Users\\Sam\\PycharmProjects\\Test\\.ipynb_checkpoints\\orcl-1995-2014.csv',
    
            #fromdate=datetime.datetime(2000/1/1),
            #todate = datetime.datetime(2000/12/31),
    
            nullvalue=0.0, # missing values to be replaced with 0
    
            dtformat=('%m/%d/%Y'),
    
            datetime=0,
            time=-1,
            open=1,
            high=2,
            low=3,
            close=4,
            adjclose=5,
            volume=6,
            openinterest=-1,
    
    
        )
    
    
    
        # Add the Data Feed to Cerebro
        cerebro.adddata(data)
    
        # Set our desired cash start
        cerebro.broker.setcash(100000.0)
    
        # Print out the starting conditions
        print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    
        # Run over everything
        cerebro.run()
    
        # Print out the final result
        print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    


  • I noticed the last line of my csv file had a formatted date that was an integer. I would check each line of your data first.



  • nevermind got it to work. Thanks!



  • @samk

    Hi,

    What was your mistake that you corrected. You just said you got it to work. I am getting the same error.

    valueError: time data '"2016-12-31' does not match format '%m/%d/%Y'

    thanks..


  • administrators

    @samk said in Extending Datafeeds GenericCSV Attribute Error:

    ValueError: time data '"2014-12-31' does not match format '%m/%d/%Y'
    

    @michael172 said in Extending Datafeeds GenericCSV Attribute Error:

    ValueError: time data '"2016-12-31' does not match format '%m/%d/%Y'
    

    He obviously fixed it by providing the right datetime format string: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior



  • thanks.. I noticed that and made the correction. I was hoping that he ran into a problem that has puzzled me for a bit. Here is the code that reproduces the problem for me. I simply modified the above code to keep it clean. The customized datafeeder is not recognized. It's not a typo, but must be something else I am missing???

    thanks again as always,

     from __future__ import (absolute_import, division, print_function,
                             unicode_literals)
     import backtrader as bt
     import pandas as pd
     from backtrader.feeds import GenericCSVData
     import backtrader.feeds as btfeeds
     import datetime as datetime
     import backtrader.indicators as btind
     import numpy as np
     
     from backtrader.feeds import GenericCSVData
     
     class GenericCSV_PE(GenericCSVData):
     
         # Add a 'pe' line to the inherited ones from the base class
         lines = ('pe_ttm',)
     
         # openinterest in GenericCSVData has index 7 ... add 1
         # add the parameter to the parameters inherited from the base class
         params = (('pe_ttm', 8),)
     
     class MyStrategy(bt.Strategy):
     
     
         def log(self, txt, dt=None):
             ''' Logging function for this strategy'''
             dt = self.datas[0].datetime.date(0)
             dt_time = self.datas[0].datetime.time(0)
             dt_weekday = datetime.datetime.weekday(dt)
             print('%s, %s' % (dt.isoformat(), txt))
     
     
         def __init__(self):
             # Keep a reference to the "close" line in the data[0] dataseries
             # init stop loss and take profit order variables
             self.sl_order, self.tp_order = None, None
             self.datavolume = self.datas[0].volume
             self.pe = self.datas[0].pe_ttm
     
     
         def next(self):
             if self.datavolume[0] / np.mean(self.datavolume.get(size=10, ago=-1)) >= 1.25:
                 self.buy()
                 print(self.pe[0])
     
     
     
     if __name__ == '__main__':
         # Create a cerebro entity
         cerebro = bt.Cerebro()
     
     
         data = btfeeds.GenericCSV_PE(
     #    data = btfeeds.GenericCSVData(    
             dataname='E:\\Michael\\R\\Stocks\\300Index_New_Combined_Corrected\\000001.csv',
     
             nullvalue=0.0,
     
             dtformat=('%Y-%m-%d'),
     
             datetime=0,
             time=-1,
             high=2,
             low=3,
             open=1,
             close=4,
             volume=5,
             openinterest=-1,
             pe_ttm = 6
         )
     
         # Add the Data Feed to Cerebro
         cerebro.adddata(data)
     
         # Set our desired cash start
         cerebro.broker.setcash(100000.0)
     
         # Add a strategy
         cerebro.addstrategy(MyStrategy)
     
         # Print out the starting conditions
         print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
     
         # Run over everything
         cerebro.run()
     
         # Print out the final result
         print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
     
         cerebro.plot(style='bar')
    

    error output:

         AttributeError                            Traceback (most recent call last)
         <ipython-input-21-26c81b63c6dc> in <module>()
              51 
              52 
         ---> 53     data = btfeeds.GenericCSV_PE(
              54 #    data = btfeeds.GenericCSVData(
              55         dataname='E:\\Michael\\R\\Stocks\\300Index_New_Combined_Corrected\\000001.csv',
         
         AttributeError: module 'backtrader.feeds' has no attribute 'GenericCSV_PE'

  • administrators

    @michael172 said in Extending Datafeeds GenericCSV Attribute Error:

    AttributeError: module 'backtrader.feeds' has no attribute 'GenericCSV_PE'
    

    @michael172 said in Extending Datafeeds GenericCSV Attribute Error:

    if __name__ == '__main__':
         # Create a cerebro entity
         cerebro = bt.Cerebro()
     
     
         data = btfeeds.GenericCSV_PE(
     #    data = btfeeds.GenericCSVData(    
    

    @michael172 said in Extending Datafeeds GenericCSV Attribute Error:

     class GenericCSV_PE(GenericCSVData):
     
         # Add a 'pe' line to the inherited ones from the base class
         lines = ('pe_ttm',)
    

    This is something you define.

    The original answer does still apply

    @backtrader said in Extending Datafeeds GenericCSV Attribute Error:

    @Osofuego said in Extending Datafeeds GenericCSV Attribute Error:

    data = btfeeds.GenericCSVData(
    

    You are not using your own extended data feed.



  • @backtrader

    Ha! Finally figured out two things! One: why my own data feeder wasn't getting accepted and Two: who the bigger idiot is... hopefully was. Thanks for helping out.. saved a lot of my time.