Some trouble with tutorial algorithmic trading using Sentiment analysis
-
Hi everyone,
I'm new in backtrader and i would like to reproduce the tutorial based on these links :
https://towardsdatascience.com/https-towardsdatascience-com-algorithmic-trading-using-sentiment-analysis-on-news-articles-83db77966704
https://github.com/jasonyip184/StockSentimentTradingMoreover i have some problem when i launch the code with this error :
TypeError: 'module' object is not callable or must be real number, not LineBuffer (if i change the data i want to feed)Someone please can help me ? I think the tutorial is really interesting so i would like to run it :/
-
@Florian-Aversin said in Some trouble with tutorial algorithmic trading using Sentiment analysis:
(if i change the data i want to feed
That's probably the problem. You change something. Nobody can help you if nobody knows what you have changed.
-
Well ... sorry for the mistake. Here is my complete code :
import warnings warnings.filterwarnings('ignore') from nltk.sentiment.vader import SentimentIntensityAnalyzer # nltk.download('vader_lexicon') sia = SentimentIntensityAnalyzer() from urllib.request import urlopen from bs4 import BeautifulSoup from datetime import datetime, timedelta import time import pprint date_sentiments = {} for i in range(1,11): page = urlopen('https://www.businesstimes.com.sg/search/facebook?page='+str(i)).read() soup = BeautifulSoup(page, features="html.parser") posts = soup.findAll("div", {"class": "media-body"}) for post in posts: time.sleep(1) url = post.a['href'] date = post.time.text print(date, url) try: link_page = urlopen(url).read() except: url = url[:-2] link_page = urlopen(url).read() link_soup = BeautifulSoup(link_page) sentences = link_soup.findAll("p") passage = "" for sentence in sentences: passage += sentence.text sentiment = sia.polarity_scores(passage)['compound'] date_sentiments.setdefault(date, []).append(sentiment) date_sentiment = {} for k,v in date_sentiments.items(): date_sentiment[datetime.strptime(k, '%d %b %Y').date() + timedelta(days=1)] = round(sum(v)/float(len(v)),3) earliest_date = min(date_sentiment.keys()) print(date_sentiment) from __future__ import (absolute_import, division, print_function, unicode_literals) import backtrader as bt import backtrader.indicators as btind import datetime import os.path import sys 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) if __name__ == '__main__': cerebro = bt.Cerebro() # Strategy cerebro.addstrategy(SentimentStrat) # Data Feed data = bt.feeds.YahooFinanceData( dataname = 'FB', fromdate = earliest_date, todate = datetime.datetime(2018,11,25), reverse = False ) cerebro.adddata(data) cerebro.broker.setcash(100000.0) cerebro.addsizer(bt.sizers.FixedSize, stake=10) cerebro.broker.setcommission(commission=0.001) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot()
-
I don't know if you are expecting to read the entire code.
What did you actually change? What's the difference with the original?