Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Can get backtrader to buy on the 1st of the month

    General Code/Help
    6
    12
    1207
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      Christopher Xu last edited by

      I am trying to implement the BuyAndHold_More strategy listed here:
      https://www.backtrader.com/blog/2019-06-13-buy-and-hold/buy-and-hold/

      I am using the exact same code. I then try to run it via this:

      if __name__ == '__main__':
          cerebro = bt.Cerebro()
          cerebro.addstrategy(BuyAndHold_More)
      
          class PandasData(bt.feeds.DataBase):
            params = (
                ('datetime', 'Date'),
                ('open','Open'),
                ('high','High'),
                ('low','Low'),
                ('close','Close'),
                ('volume','Volume'),
                ('openinterest',None),
                #('adj_close','Adj Close'),
              )
              
          adj_data = bt.feeds.PandasData(dataname=df3)
          cerebro.adddata(adj_data)
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
          cerebro.run()
          print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      

      But the staring and ending portfolio values are unchanged. What am I missing please? I feel like it should be something simple but I am lost. Thanks in advance.

      1 Reply Last reply Reply Quote 0
      • Ajay Nainani
        Ajay Nainani last edited by

        Having the same problem! Sharing whole code snippet below.

        import datetime
        import backtrader as bt
        
        class BuyAndHold_More(bt.Strategy):
            params = dict(
                monthly_cash=1000.0,  # amount of cash to buy every month
            )
        
            def start(self):
                self.cash_start = self.broker.get_cash()
                self.val_start = 100.0
        
                # Add a timer which will be called on the 1st trading day of the month
                self.add_timer(
                    bt.timer.SESSION_END,  # when it will be called
                    monthdays=[1],  # called on the 1st day of the month
                    monthcarry=True,  # called on the 2nd day if the 1st is holiday
                )
        
            def notify_timer(self, timer, when, *args, **kwargs):
                # Add the influx of monthly cash to the broker
                self.broker.add_cash(self.p.monthly_cash)
                print('Cash Added!')
                # buy available cash
                target_value = self.broker.get_value() + self.p.monthly_cash
                self.order_target_value(target=target_value)
        
            def stop(self):
                # calculate the actual returns
                self.roi = (self.broker.get_value() / self.cash_start) - 1.0
                print('ROI:        {:.2f}%'.format(self.roi))
        
        
        if __name__ == '__main__':
            cerebro = bt.Cerebro()
        
           # Get a pandas dataframe
        
            class PandasData(bt.feeds.DataBase):
              #lines = ('adj_close')
              params = (
                  ('datetime', 'Date'),
                  ('open','Open'),
                  ('high','High'),
                  ('low','Low'),
                  ('close','Close'),
                  ('volume','Volume'),
                  ('openinterest',None),
                  #('adj_close','Adj Close'),
                )
                
            # import data
            print(df_new)
            adj_data = bt.feeds.PandasData(dataname=df_new)
            
            #add data to cerebro
            cerebro.adddata(adj_data)
        
            cerebro.addstrategy(BuyAndHold_More)
        
            # Execute
            cerebro.run()
        
        

        Output when run. Note that my "Cash Added!" never prints, so it looks like the timer is never getting run.

                    Open      High       Low       Close     Volume
        

        Date
        2000-01-03 101.3166 101.3166 98.3267 99.394493 8164300
        2000-01-04 98.0917 98.4548 95.4328 95.507530 8089800
        2000-01-05 95.6357 96.7249 93.7990 95.678391 12177900
        2000-01-06 95.4221 96.7035 94.1407 94.140717 6227200
        2000-01-07 95.8920 99.6081 95.7211 99.608055 8066500
        ... ... ... ... ... ...
        2020-04-20 282.6100 286.7900 281.3500 281.589996 100109300
        2020-04-21 276.7300 278.0400 272.0200 273.040009 126385700
        2020-04-22 278.3500 281.0000 276.9100 279.100006 93524600
        2020-04-23 280.4900 283.9400 278.7500 279.079987 104709700
        2020-04-24 280.7300 283.7000 278.5000 282.970001 85063200

        [5110 rows x 5 columns]
        ROI: 0.00%

        1 Reply Last reply Reply Quote 0
        • Ajay Nainani
          Ajay Nainani last edited by

          Is it possible that this is due to the date format of the pandas date? i.e. there is no time in my data source, vs in the examples on

          https://www.backtrader.com/docu/timers/timers/

          they all have times attached to their dates.

          A 1 Reply Last reply Reply Quote 0
          • Ajay Nainani
            Ajay Nainani last edited by

            Modified data to have EOD time stamp attached. Still doesn't work. Output:

                                 Open      High       Low       Close     Volume
            

            Date
            2000-01-03 17:30:00 101.3166 101.3166 98.3267 99.394493 8164300
            2000-01-04 17:30:00 98.0917 98.4548 95.4328 95.507530 8089800
            2000-01-05 17:30:00 95.6357 96.7249 93.7990 95.678391 12177900
            2000-01-06 17:30:00 95.4221 96.7035 94.1407 94.140717 6227200
            2000-01-07 17:30:00 95.8920 99.6081 95.7211 99.608055 8066500
            ... ... ... ... ... ...
            2020-04-20 17:30:00 282.6100 286.7900 281.3500 281.589996 100109300
            2020-04-21 17:30:00 276.7300 278.0400 272.0200 273.040009 126385700
            2020-04-22 17:30:00 278.3500 281.0000 276.9100 279.100006 93524600
            2020-04-23 17:30:00 280.4900 283.9400 278.7500 279.079987 104709700
            2020-04-24 17:30:00 280.7300 283.7000 278.5000 282.970001 85063200

            [5110 rows x 5 columns]
            ROI: 0.00%

            1 Reply Last reply Reply Quote 0
            • A
              ab_trader @Ajay Nainani last edited by

              @Ajay-Nainani said in Can get backtrader to buy on the 1st of the month:

              s it possible that this is due to the date format of the pandas date?

              Looks like this is correct guess. Possibly the date is not in the datetime format, but is imported as text.

              • If my answer helped, hit reputation up arrow at lower right corner of the post.
              • Python Debugging With Pdb
              • New to python and bt - check this out
              Sabir Jana 1 Reply Last reply Reply Quote 0
              • Sabir Jana
                Sabir Jana @ab_trader last edited by

                @ab_trader
                Hello, I too facing the timer issue, it doesn't trigger not only for this simple buy and hold but anywhere I tried. The pandas feed I am using has datetime index, I also tried tz_localize('UTC')

                prices.index = prices.index.tz_localize('UTC')
                prices.info()
                DatetimeIndex: 2792 entries, 2009-01-02 00:00:00+00:00 to 2020-05-19 00:00:00+00:00
                Data columns (total 5 columns):
                 #   Column  Non-Null Count  Dtype  
                ---  ------  --------------  -----  
                 0   open    2792 non-null   float64
                 1   high    2792 non-null   float64
                 2   low     2792 non-null   float64
                 3   close   2792 non-null   float64
                 4   volume  2792 non-null   float64
                
                prices.head()
                	open	high	low	close	volume
                date					
                2009-01-02 00:00:00+00:00	145.625000	145.625000	140.475006	50.516472	9012080.0
                2009-01-05 00:00:00+00:00	142.500000	148.087006	142.462006	52.332775	11241232.0
                2009-01-06 00:00:00+00:00	147.500000	148.750000	143.169006	52.143211	11563864.0
                2009-01-07 00:00:00+00:00	146.393997	149.694000	143.199997	52.991051	22538352.0
                2009-01-09 00:00:00+00:00	148.261993	158.324997	146.250000	53.698215	40182160.0
                
                

                I appreciate any help!!

                1 Reply Last reply Reply Quote 0
                • run-out
                  run-out last edited by

                  You have the notify_timer, but you didn't initiate the timer. You also need to add in a monthdays parameter.

                  I've simplified your example just to get the cash added.

                  class BuyAndHold_More(bt.Strategy):
                      params = dict(
                          monthly_cash=1000.0,  # amount of cash to buy every month
                          when=bt.timer.SESSION_START,
                          timer=True,
                          monthdays=[1],
                      )
                  
                      def __init__(self):
                          self.add_timer(
                              when=self.p.when,
                              monthdays=self.p.monthdays,
                          )
                  
                      def log(self, txt, dt=None):
                          """ Logging function fot this strategy"""
                          dt = dt or self.data.datetime[0]
                          if isinstance(dt, float):
                              dt = bt.num2date(dt)
                          print("%s, %s" % (dt.isoformat(), txt))
                  
                      def start(self):
                          self.cash_start = self.broker.get_cash()
                          self.val_start = 100.0
                  
                          # Add a timer which will be called on the 1st trading day of the month
                          self.add_timer(
                              bt.timer.SESSION_END,  # when it will be called
                              monthdays=[1],  # called on the 1st day of the month
                              monthcarry=True,  # called on the 2nd day if the 1st is holiday
                          )
                  
                      def notify_timer(self, timer, when, *args, **kwargs):
                          # Add the influx of monthly cash to the broker
                          self.broker.add_cash(self.p.monthly_cash)
                          print("Cash Added!")
                          
                      def next(self):
                          self.log("Cash {} Value {}".format(self.broker.cash, self.broker.get_value()))
                  
                      def stop(self):
                          # calculate the actual returns
                          self.roi = (self.broker.get_value() / self.cash_start) - 1.0
                          print("ROI:        {:.2f}%".format(self.roi))
                  

                  This yields:

                  2005-01-03T00:00:00, Cash 10000.0 Value 10000.0
                  2005-01-04T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-05T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-06T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-07T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-10T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-11T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-12T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-13T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-14T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-18T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-19T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-20T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-21T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-24T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-25T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-26T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-27T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-28T00:00:00, Cash 11000.0 Value 11000.0
                  2005-01-31T00:00:00, Cash 11000.0 Value 11000.0
                  Cash Added!
                  2005-02-01T00:00:00, Cash 11000.0 Value 11000.0
                  2005-02-02T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-03T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-04T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-07T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-08T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-09T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-10T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-11T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-14T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-15T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-16T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-17T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-18T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-22T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-23T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-24T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-25T00:00:00, Cash 12000.0 Value 12000.0
                  2005-02-28T00:00:00, Cash 12000.0 Value 12000.0
                  Cash Added!
                  2005-03-01T00:00:00, Cash 12000.0 Value 12000.0
                  2005-03-02T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-03T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-04T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-07T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-08T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-09T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-10T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-11T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-14T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-15T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-16T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-17T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-18T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-21T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-22T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-23T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-24T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-28T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-29T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-30T00:00:00, Cash 13000.0 Value 13000.0
                  2005-03-31T00:00:00, Cash 13000.0 Value 13000.0
                  Cash Added!
                  2005-04-01T00:00:00, Cash 13000.0 Value 13000.0
                  2005-04-04T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-05T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-06T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-07T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-08T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-11T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-12T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-13T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-14T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-15T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-18T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-19T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-20T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-21T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-22T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-25T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-26T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-27T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-28T00:00:00, Cash 14000.0 Value 14000.0
                  2005-04-29T00:00:00, Cash 14000.0 Value 14000.0
                  Cash Added!
                  2005-05-02T00:00:00, Cash 14000.0 Value 14000.0
                  2005-05-03T00:00:00, Cash 15000.0 Value 15000.0
                  2005-05-04T00:00:00, Cash 15000.0 Value 15000.0
                  2005-05-05T00:00:00, Cash 15000.0 Value 15000.0
                  

                  RunBacktest.com

                  Sabir Jana 1 Reply Last reply Reply Quote 0
                  • Sabir Jana
                    Sabir Jana @run-out last edited by

                    @run-out Thank you!!! understood the mistake at my end and got it now. I highly appreciate your on-time help. Many thanks again.
                    -SJ

                    1 Reply Last reply Reply Quote 1
                    • A
                      ab_trader last edited by

                      If you want to operate only at the end of the month, you can resample to monthly bars, add cash in the next(), and remove timers from the script. Might be simpler.

                      • If my answer helped, hit reputation up arrow at lower right corner of the post.
                      • Python Debugging With Pdb
                      • New to python and bt - check this out
                      Sabir Jana 1 Reply Last reply Reply Quote 1
                      • Sabir Jana
                        Sabir Jana @ab_trader last edited by

                        @ab_trader Yes, Thank you!!

                        1 Reply Last reply Reply Quote 1
                        • K
                          kljfevw last edited by

                          Hey everyone,

                          I am also trying out this sample code from https://www.backtrader.com/blog/2019-06-13-buy-and-hold/buy-and-hold/ , however I don't understand what fundmode/fundstartval means. Documentation also doesn't have alot of information either. How does the example code track "tax lots"? Can someone please explain this to me?

                          Thanks!

                          1 Reply Last reply Reply Quote 0
                          • A
                            ab_trader last edited by

                            Blog - Fund tracking

                            • If my answer helped, hit reputation up arrow at lower right corner of the post.
                            • Python Debugging With Pdb
                            • New to python and bt - check this out
                            1 Reply Last reply Reply Quote 1
                            • 1 / 1
                            • First post
                              Last post
                            Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors