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

Numeric average value of past 10 days



  • Hello,

    I've been trying to get the actual numeric average value of the "low" field for the past 10 days to use in a calculation in Strategy, example: self.lowF = bt.indicators.SMA(self.data.low, period=10)

    So far everything I've tried resulted in TypeError: %d format: a number is required, not LinesOperation, or TypeError: must be real number, not SMA, or similar.

    What do I have to use to actually be able to calculate on past data fields ? Been scrolling through the documentation but so far I haven't found what I'm looking for.

    Hopefully someone's gonna point me in the right direction.



  • Make sure your line of code is in the init section.



  • Actually, can you include your code and we can better answer your questions.



  • @run-out said in Numeric average value of past 10 days:

    Make sure your line of code is in the init section.

    The idea is to generate these values on each day.
    I'll try to attach the code after 10-20 minutes.



  • main.py:

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    import pandas as pd
    import backtrader as bt
    from Strategy import TestStrategy
    
    if __name__ == '__main__':
        # Create a cerebro entity
        cerebro = bt.Cerebro()
        # Set our desired cash start
        cerebro.broker.setcash(1000.0)
        spy_prices = pd.read_csv('data/SPY-2019-2020.csv', index_col='Date', parse_dates=True)
        data_feed = bt.feeds.PandasData(dataname=spy_prices)
    
        # Add the Data Feed to Cerebro
        cerebro.adddata(data_feed)
        # Add a strategy
        cerebro.addstrategy(TestStrategy)
    
        # 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())
        # Plot the result
        cerebro.plot()
    

    Strategy.py

    import math
    import backtrader as bt
    
    
    class TestStrategy(bt.Strategy):
        params = (
            ('fast', 5),   # 5 days avg
            ('slow', 90),  # 90 days avg
            ('ticker', 'SPY')
        )
    
        def log(self, txt, dt=None):
            dt = dt or self.datas[0].datetime.date(0)
            print('%s, %s' % (dt.isoformat(), txt))
    
        def __init__(self):
            # Keep a reference to the "close" line in the data[0] dataseries
            self.dataclose = self.datas[0].close
            self.lowF = 0
            self.highF = 0
    
            # Calculate these on each new day
            self.lowF = bt.indicators.MovingAverageSimple(self.data.low, period=self.params.fast)
            self.highF = bt.indicators.MovingAverageSimple(self.data.high, period=self.params.fast)
    
            # Test print the average of last 5 days for low and high
            self.log('Low, %.2f | High: %.2f' % (self.lowF, self.highF))
    
        def notify_order(self, order):
            pass
    
        def notify_trade(self, trade):
            pass
    
        def next(self):
            pass
    

    Data located in "data/SPY-2019-2020.csv"
    Result: TypeError: must be real number, not MovingAverageSimple



  • @chewbacca said in Numeric average value of past 10 days:

    Test print the average of last 5 days for low and high
    self.log('Low, %.2f | High: %.2f' % (self.lowF, self.highF))

    This section of code needs to be in next. The indicator is calculated as a line at the outset of the program. So something line this:

    bt.indicators.MovingAverageSimple(self.data.high, period=20)
    

    Returns an object with all of the data for the whole backtest for that line.

    In order to print for each data, you have to call it in next and use square brackets around zero.

    self.log('Low, %.2f | High: %.2f' % (self.lowF[0], self.highF[0]))
    

    This should hopefully get what you are looking for.



  • @run-out

    I've placed the indicators in strategy's init(self)
    # Calculate these on each run
    self.lowF = bt.indicators.MovingAverageSimple(self.data.low, period=15)
    self.highF = bt.indicators.MovingAverageSimple(self.data.high, period=15)

    If I try to place the indicators in next(self), I'm unable to use the results (self.lowF: IndexError: array index out of range) or (self.lowF[0]: <backtrader.indicators.sma.MovingAverageSimple object at 0x7f9153a59c70>)

    What is the difference when calling the data with self.lowF[0] and self.lowF[1] in next(self) ?
    I'm comparing the exact same algorithm in Backtrader and Quantopian (with the exception that in Q the indicators are generated on every run of the rebalance function).

    If I use [0] to get the indicators values in next(), I get quite different results.
    If I set [1] and then do the algo calculations - the end result is ... extremely similar to the one I see in Quantopian.

    Absolutely every other parameter is 1:1... I'm hitting my head for a week now trying to figure out where this enormous difference comes from.

    And something else, say I set a fromdate 2010-08-01 and todate 2010-09-01.
    If the SMA period is 20 days, that makes the strategy start working at 2010-08-21 which is ... weird comparing to Quantopian where data.history can get values outside of the backtest period.

    How do you approach this? If I leave the fromdate value out of the dataset load - most indicators / observers start from the very beginning of the dataset, which makes graphing them extremely ugly, and some of my indicators are for 1 year back.

    Hopefully you'll help me out cause my head starting to hurt a lot :)

    Regards,
    C


Log in to reply
 

});