OLS_Slope_InterceptN



  • Could you please give an example on how to use 'OLS_Slope_InterceptN' class?

    Thank you.



  • from datetime import datetime
    import backtrader as bt

    class TestStrategy(bt.Strategy):
    params = (
    ('period', 14),
    ('sma_atr', 5),
    ('ols_length',15),
    ('macd1', 12),
    ('macd2', 26),
    ('macdsig', 9),
    )

    def log(self, txt, dt=None):
        ''' Logging function fot this strategy'''
        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
    
        # To keep track of pending orders and buy price/commission
        self.order = None
        self.buyprice = None
        self.buycomm = None
    
        # Add ATR Indicator
        self.atr = bt.indicators.ATR(
            self.datas[0], period=self.params.period)
        self.sma_atr = bt.indicators.SMA(
            self.atr, period=self.params.sma_atr)
        self.my_macd = bt.indicators.MACD(
            self.datas[0], period_me1=self.p.macd1, period_me2=self.p.macd2, period_signal=self.p.macdsig)
    
        self.my_ols1, self.my_ols2 = bt.indicators.OLS_Slope_InterceptN(self.datas[0].close, self.datas[0].close)
    
    def notify_order(self, order):
        if order.status in [order.Submitted, order.Accepted]:
            # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            return
    
        # Check if an order has been completed
        # Attention: broker could reject order if not enougth cash
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm))
    
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:  # Sell
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                         (order.executed.price,
                          order.executed.value,
                          order.executed.comm))
    
            self.bar_executed = len(self)
    
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Order Canceled/Margin/Rejected')
    
        self.order = None
    
    def notify_trade(self, trade):
        if not trade.isclosed:
            return
    
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
    
    def next(self):
    
        # Simply log the closing price of the series from the reference
        self.log('Close, %.2f' % self.dataclose[0])
        self.log('ATR, %.2f' % self.atr[0])
        self.log('SMA_ATR, %.2f' % self.sma_atr[0])
        self.log('MACD, %.2f' % self.my_macd.macd[0])
        self.log('SIGNAL, %.2f' % self.my_macd.signal[0])
    
    
        # Check if an order is pending ... if yes, we cannot send a 2nd one
        if self.order:
            return
    
        # Check if we are in the market
        if not self.position:
    
            # Not yet ... we MIGHT BUY if ...
            if (self.atr[0] > self.sma_atr[0]) and (self.my_macd.macd[0] > 0) and ((self.my_macd.signal[0] > 0) and (self.my_macd.macd[0] > self.my_macd.signal[0])):
    
                # BUY, BUY, BUY!!! (with all possible default parameters)
                self.log('BUY CREATE, %.2f' % self.dataclose[0])
    
                # Keep track of the created order to avoid a 2nd order
                self.order = self.order_target_percent(target=0.9)
    
        else:
    
            if self.atr[0] < self.sma_atr[0]:
                # SELL, SELL, SELL!!! (with all possible default parameters)
                self.log('SELL CREATE, %.2f' % self.dataclose[0])
    
                # Keep track of the created order to avoid a 2nd order
                self.order = self.order_target_percent(target=0)
    

    if name == 'main':
    cerebro = bt.Cerebro()
    # Add a strategy
    cerebro.addstrategy(TestStrategy, period=14, sma_atr=3, ols_length=15)

    # Basic Setup of the trade
    cerebro.broker.setcash(1000000.0)
    # Set the commission - 0.1% ... divide by 100 to remove the %
    cerebro.broker.setcommission(commission=0.001)
    # Add a FixedSize sizer according to the stake
    cerebro.addsizer(bt.sizers.FixedSize, stake=100)
    
    #https://community.backtrader.com/topic/279/don-t-understand-buy-amount/6
    cerebro.broker.set_coc(True)
    
    data = bt.feeds.YahooFinanceData(dataname='IBM', fromdate=datetime(2017, 1, 1),
                                     todate=datetime(2017, 11, 27))
    cerebro.adddata(data)
    
    # Print out the starting conditions
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.run()
    # Print out the final result
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
    cerebro.plot()


  • C:\Users\jirath\Anaconda2\python.exe C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py
    Starting Portfolio Value: 1000000.00
    C:\Users\jirath\Anaconda2\lib\site-packages\statsmodels\compat\pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
    from pandas.core import datetools
    Traceback (most recent call last):
    File "C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py", line 133, in <module>
    cerebro.run()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1142, in run
    runstrat = self.runstrategies(iterstrat)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1229, in runstrategies
    strat = stratcls(*sargs, **skwargs)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\metabase.py", line 88, in call
    _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\metabase.py", line 78, in doinit
    _obj.init(*args, **kwargs)
    File "C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py", line 36, in init
    self.my_ols1, self.my_ols2, self.ols = bt.indicators.OLS_Slope_InterceptN(self.datas[0].close, self.datas[0].close)
    ValueError: need more than 0 values to unpack

    Process finished with exit code 1

    Please any one suggest above error.



  • @jirathh said in OLS_Slope_InterceptN:

    self.my_ols1, self.my_ols2, self.ols = bt.indicators.OLS_Slope_InterceptN(self.datas[0].close, self.datas[0].close)
    ValueError: need more than 0 values to unpack

    Obviously there is only 1 return value there.



  • I used this one:

    self.my_ols = bt.indicators.OLS_Slope_InterceptN(self.datas[0], self.datas[0], period=30)

    but still got this error

    C:\Users\jirath\Anaconda2\python.exe C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py
    Starting Portfolio Value: 1000000.00
    C:\Users\jirath\Anaconda2\lib\site-packages\statsmodels\compat\pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
    from pandas.core import datetools
    Traceback (most recent call last):
    File "C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py", line 133, in <module>
    cerebro.run()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1142, in run
    runstrat = self.runstrategies(iterstrat)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1305, in runstrategies
    self._runonce(runstrats)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1663, in _runonce
    strat._once()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\lineiterator.py", line 292, in _once
    indicator._once()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\lineiterator.py", line 313, in _once
    self.once(self._minperiod, self.buflen())
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\indicator.py", line 136, in once_via_next
    self.next()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\indicators\ols.py", line 52, in next
    slope, intercept = sm.OLS(p0, p1).fit().params
    ValueError: need more than 1 value to unpack

    Process finished with exit code 1



  • I didn't dig deeply, but looks like by default bt script requires 2 data feeds for this indicator. Maybe this is a problem. I would add 2nd data feed and call indicator as follows:

    self.my_ols = bt.indicators.OLS_Slope_InterceptN(period=whatever_period_you_want)
    

    Default period is 10.
    Otherwise you can write your own implementation.



  • thank you @ab_trader . I tried but still got this error.

    self.my_ols = bt.indicators.OLS_Slope_InterceptN(period=30)


    C:\Users\jirath\Anaconda2\python.exe C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py
    Starting Portfolio Value: 1000000.00
    C:\Users\jirath\Anaconda2\lib\site-packages\statsmodels\compat\pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
    from pandas.core import datetools
    Traceback (most recent call last):
    File "C:/Users/jirath/PycharmProjects/BackTrader.com/atr_trade.py", line 151, in <module>
    cerebro.run()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1142, in run
    runstrat = self.runstrategies(iterstrat)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1305, in runstrategies
    self._runonce(runstrats)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\cerebro.py", line 1663, in _runonce
    strat._once()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\lineiterator.py", line 292, in _once
    indicator._once()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\lineiterator.py", line 312, in _once
    self.oncestart(self._minperiod - 1, self._minperiod)
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\indicator.py", line 124, in oncestart_via_nextstart
    self.nextstart()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\lineiterator.py", line 342, in nextstart
    self.next()
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\indicators\ols.py", line 50, in next
    p1 = pd.Series(self.data1.get(size=self.p.period))
    File "C:\Users\jirath\Anaconda2\lib\site-packages\backtrader\lineseries.py", line 461, in getattr
    return getattr(self.lines, name)
    AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Indicat' object has no attribute 'data1'

    Process finished with exit code 1



  • Did you add second data feed in cerebro?



  • @jirathh said in OLS_Slope_InterceptN:

    slope, intercept = sm.OLS(p0, p1).fit().params
    ValueError: need more than 1 value to unpack
    

    This is a clear indication that the version of sm.OLS you are using is not compatible with the code in that indicator. The statsmodels API changes overtime. See this:



  • @Paska-Houso , thank you so much for your information.

    In this case, I need to modify and run ols algorithm locally.

    Could you please suggest how can I run backtrader locally?

    I think we need to set something like interpreter or structure the project correctly. I use PyCharm on Windows. Please make suggestions. Thank you.



  • I suggest you look at the many samples ... the blog is full of them. For example:



  • Thank you so much, @Paska-Houso .
    I managed to create a new indicator of OLS to be used in my strategy! :)

    Here is the code:

    class TORO_OLS_Slope_InterceptN(bt.Indicator):
    packages = (
    ('pandas', 'pd'),
    ('sklearn.linear_model', 'lm'),
    )
    lines = ('slope', 'intercept',)
    params = (
    ('period', 10),
    )
    def init(self):
    self.addminperiod(self.params.period)

    def next(self):
        p0 = pd.Series(self.data.close.get(size=self.p.period))
        p1 = np.arange(self.p.period).reshape(-1, 1)
        p1 = sm.add_constant(p1, prepend=True)
        slope, intercept = sm.OLS(p0, p1).fit().params
        self.lines.slope[0] = slope
        self.lines.intercept[0] = intercept

Log in to reply
 

Looks like your connection to Backtrader Community was lost, please wait while we try to reconnect.