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

Building Sentiment Indicator class: TypeError: must be real number, not LineBuffer



  • Hi,

    First time posting here and I am a beginner in python. I am trying to build a new Sentiment strategy that executes buy/sell based on changes in sentiment scores analyzed from tweets about certain companies. I first run a twitter text search and use NLTK on the tweets to get sentiment scores. I then store the sentiment data as a dict (date_sentiment) with keys = date and values = score. Everything works until here but after building the sentiment Indicator and run cerebro, I keep getting the error message "TypeError: must be real number, not LineBuffer". I suspect the problem lies somewhere in the Sentiment class, but I couldn't figure out what went wrong. Could someone please help me with this problem?

    Any input would be greatly appreciated!```
    code_text

    class Sentiment(bt.Indicator):
        lines = ('sentiment',)
        plotinfo = dict(
            plotymargin=0.15,
            plothlines=[0],
            plotyticks=[1.0, 0, -1.0])
        
        def next(self):
            self.date = self.data.datetime
            date = bt.num2date(self.date[0]).date()
            prev_sentiment = self.sentiment
            if date in date_sentiment:
                self.sentiment = date_sentiment[date]
            self.lines.sentiment[0] = self.sentiment
    
    
    class SentimentStrat(bt.Strategy):
        params = (
            ('period', 15),
            ('printlog', True),
        )
    
        def log(self, txt, dt=None, doprint=False):
            ''' Logging function for this strategy'''
            if self.params.printlog or doprint:
                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
            # Keep track of pending orders
            self.order = None
            self.buyprice = None
            self.buycomm = None
            self.sma = bt.indicators.SimpleMovingAverage(
                self.datas[0], period=self.params.period)
            self.date = self.data.datetime
            self.sentiment = None
            Sentiment(self.data)
            
        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 enough 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')
                
            # Write down: no pending order
            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))
        
        ### Main Strat ###
        def next(self):
            # log closing price of the series from the reference
            self.log('Close, %.2f' % self.dataclose[0])
            
            date = bt.num2date(self.date[0]).date()
            prev_sentiment = self.sentiment
            if date in date_sentiment:
                self.sentiment = date_sentiment[date]
            
            # Check if an order is pending. if yes, we cannot send a 2nd one
            if self.order:
                return
            print(self.sentiment)
            # If not in the market and previous sentiment not none
            if not self.position and prev_sentiment:
                # buy if current close more than sma AND sentiment increased by >= 0.5
                if self.dataclose[0] > self.sma[0] and self.sentiment - prev_sentiment >= 0.5:
                    self.log('BUY CREATE, %.2f' % self.dataclose[0])
                    self.order = self.buy()
                    
            # Already in the market and previous sentiment not none
            elif prev_sentiment:
                # sell if current close less than sma AND sentiment decreased by >= 0.5
                if self.dataclose[0] < self.sma[0] and self.sentiment - prev_sentiment <= -0.5:
                    self.log('SELL CREATE, %.2f' % self.dataclose[0])
                    self.order = self.sell()
    
        def stop(self):
            self.log('(MA Period %2d) Ending Value %.2f' %
                     (self.params.period, self.broker.getvalue()), doprint=True)


  •   self.sentiment = None
       Sentiment(self.data)
    
    
    
    

    seems the variable is always none?
    but anyway, when you see "TypeError: must be real number, not LineBuffer", that means, you should add 3 characters "[0]" after your variable, such as:
    print(self.sentiment) # ---change to ---> print(self.sentiment[0])


  • administrators

    @Kevin-Fu said in Building Sentiment Indicator class: TypeError: must be real number, not LineBuffer:

    Any input would be greatly appreciated

    But you provide no input with regards to the error. Only

    TypeError: must be real number, not LineBuffer
    

    Python exceptions provided a stacktrace which points to the different line numbers in the stack ... allowing to trace the error to the origin point (and showing any potential intermediate conflict)

    The error is only telling us that you are passing an object (a LineBuffer) there where a float should have been passed by you. But not where you are doing it ... which is in the stacktrace ...


  • administrators

    @Kevin-Fu said in Building Sentiment Indicator class: TypeError: must be real number, not LineBuffer:

        def next(self):
            self.date = self.data.datetime
            date = bt.num2date(self.date[0]).date()
            prev_sentiment = self.sentiment
            if date in date_sentiment:
                self.sentiment = date_sentiment[date]
            self.lines.sentiment[0] = self.sentiment
    

    In any case that's probably where the error happens. There is no definition of self.sentiment and the indicator understands you are looking for the line named sentiment. The problems

    • Lack of variable initialization
    • Conflicting naming

Log in to reply
 

});