Backtrader Community

    • 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/

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

    General Code/Help
    3
    4
    1498
    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.
    • Kevin Fu
      Kevin Fu last edited by

      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)
      B 2 Replies Last reply Reply Quote 0
      • J
        jeff lee last edited by

          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])

        1 Reply Last reply Reply Quote 0
        • B
          backtrader administrators @Kevin Fu last edited by

          @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 ...

          1 Reply Last reply Reply Quote 0
          • B
            backtrader administrators @Kevin Fu last edited by

            @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
            1 Reply Last reply Reply Quote 0
            • 1 / 1
            • First post
              Last post
            Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors