Mining Stocktwits Retail Sentiments for Momentum Trading
TLDR: Using python to perform Natural Language Processing (NLP) Sentiment Analysis on Tesla & Apple retail traders’ tweets mined from StockTwits, and use these sentiments as long / short signals for a trading algorithm. Trading Performance Dashboard on Heroku: Link | Github Repo

Image by Mayofi on Unsplash

During a year of worldwide pandemic and economic crisis, 2020 has been a roller coaster ride for the stock market. After the huge market dip in February and March, the S&P 500, Nasdaq and Dow all rose and closed the year at an all-time high.

Markets in 2020

There has also been an atomic rise in the number of retail traders on popular retail trading platforms. Interestingly, a study by JP Morgan concluded that the most popular Robinhood stocks outperformed their less-traded peers in the short term. Many hilarious memes came about saying how successful retail traders on Robinhood, WallStreetBets or StockTwits have been with their *Yolo* bets.

Inspiration

Would it be possible to predict market movements from retail traders’ sentiments? After picking up programming in the later part of 2020 and being curious by such a thesis, I decided to create an algorithm using python which trades on sentiments mined from StockTwits (a popular twitter-like social platform for retail traders to discuss market speculation, boast about their newly purchased Lambos because their stock went “to the moon”, or moan about selling their houses because their all-in call options just expired worthless.)

The inspiration for this project came from SwaggyStocks, a website that mines Reddit’s r/WallStreetBets stock sentiments, which some people relies on for trade confirmations.

I decided to run the experiment on two extremely popular stocks amongst retail traders $AAPL (Apple) and $TSLA (Tesla).

Overview

This project involves the following steps and respective python libraries:

Web Scraping: Collecting tweets on StockTwits for sentiment analysis through web scraping using Requests and BeautifulSoup Data Cleaning and Preprocessing: Cleaning the unstructured tweets to feed them into a supervised learning classifier model using Pandas and Regex Machine Learning and NLP: Training and optimizing different models to classify tweets into their respective sentiments using Sklearn and NLTK Visualization Dashboard and Wordcloud: Creating interactive visualizations using Plotly and Dash Backtesting: Testing a short term momentum trading strategy based on sentiments mined and classified using the best model

Results: If you would like to skip the technical stuff and go straight to the charts and backtesting results, you can view the interactive dashboard hosted on Heroku here!

Interactive dashboard coded using Plotly Dash

1. Web Scraping StockTwits for Data

StockTwits has a page for every ticker where users frequently post their speculations regarding the company. Every user has an option to tag either “Bullish” or “Bearish” for their tweets. Here’s an example of a very bullish tweet from a retail trader:

On 01/01/2021, aka “AAPL to the moon 🚀🚀🚀”

The first step was to scrape 1 year worth of tweets from both tickers, which will be used for sentiment analysis in the next step. There are a few key informative data that I aimed to scrape from each comment — The tweet itself, the date/time of the tweet and the sentiment that the user tagged (if any). All these data will be very useful to generate some insights in the later parts of the project.

Through accessing StockTwits backend API using Python’s Requests library, I was able to scrape roughly 500k — 1 million tweets from both tickers and put them into a Python Pandas table as such:

2. Data Cleaning and Preprocessing

This step is arguably the most important. The aim here is to clean and standardize each tweet to feed them into an NLP model. Leveraging on Python’s Regular Expression for data cleaning, each tweet will undergo the following steps:

Removing all Tickers in the comments — These are not proper words that the NLP model can score (E.g. $AAPL, $TSLA, $SPY) Converting all characters into small letters Removing all username mentions (E.g. “@IamABear”) Removing all numbers, emojis and hyperlinks Removing all commonly used words (Stopwords) — These words are often insignificant to the NLP model, hence doing so will reduce memory load (e.g: is, are, have) Vectorization — Transforming string data to numerical values to feed it to a machine learning algorithm in the next step

Result of preprocessing (Original Message Vs Cleaned Message):

Initial tweets vs cleaned tweets

3. Training an NLP Classifier Model to Derive Tweets Sentiments

This step aims to tag all the tweets that do not have a pre-defined sentiment. It will be done through training a classifier model using supervised learning.

For Apple, about 237k tweets (~50% of total) do not have a pre-defined sentiment tagged by the respective StockTwits user (“N/A” Sentiment referencing from the image above). It will be a hassle to manually read and tag 237k tweets, but it will also be a big waste of valuable data if I were to just discard them.

There are a couple of deep learning neural network algorithms for NLP such as the BERT model. However, since this is a proof of concept experiment, I decided to go ahead with using traditional machine learning classification models such as the Multinomial Naive Bayes and Logistic Regression models for the NLP classification.

The models will be trained using tweets that already have a bullish/ bearish tag as the training data set. 80% of the training data set was used for training the model while 20% was used to validate the trained model.

Using the sklearn library, I tested between a Multinomial Naïve Bayes Classification model and a logistic regression model, and iterated through a few unique parameters using the Gridsearch function to find the model with the highest accuracy, recall and f1-score.

Definitions Precision: The percentage of bullish/bearish comments that were predicted correctly out of the total predictions for that class. Recall: The percentage of correct predictions out of true labels for the bullish/bearish class. F1-Score: This is the weighted average of precision and recall for that class. It generally gives the bigger picture of how the model is performing for that label and obviously the higher this number is the better.

The logistic regression model came up with a 78% accuracy and a 79% weighted average f1-score:

Logistic Regression Classification Report

Comparing with the Multinomial Naive Bayes model which had a 74% accuracy and 74% weighted average f1-score:

Multinomial Naive Bayes Classification Report

Let’s see how the logistic regression model classified a sample of the untagged tweets:

The model seems to be able to pick up positive and negative tonalities well and classified them into Bullish and Bearish respectively.

There are some comments such as “next leg minutes” which doesn’t make much sense, but yet is rated as Bullish by the model. Hence, there is still room for improvements for the model in the future. However, with quite a decent accuracy and f1-score I decided to go ahead with implementing the Log Regression model.

4. Data Visualization

With the data available, there are a couple of interesting insights that could be drawn

1. AAPL Sentiment Across 2020 vs AAPL Performance

Pre-Market and After Hour sentiments were consolidated and mapped against the stocks’ performance during their next trading day. Holidays and Weekends’ sentiments were also consolidated and mapped against the next trading day.

(Unfortunately, Plotly’s charts aren’t fully optimized to be displayed beautifully on mobile, hence I have attached a screenshot of the chart to be viewed on mobile. You may view the interactive version on the Heroku Dashboard!)
['Jay Lin']
['Investing', 'Sentiment Analysis', 'NLP', 'Stock Market', 'Data Science']