Technical Analysis is the process of using charts and indicators based on the price and volume to predict the future movements of financial assets.
It bears similarities with Sentiment Analysis as Technical Indicators are used to guess the opinions of other investors. For example, a large volume with increasing price could signify that investors are largely positive and bullish about the asset.
As such, Technical Indicators is a proxy for Sentiment Analysis.
This post will hope to show that incorporating Sentiment Analysis into a simple Technical Strategy can improve its performance.
Strategies to be Compared
The following 2 strategies will be compared.
If (5-day SMA > 10-day SMA): Long Asset
Else: Short Asset
If (5-day SMA > 10-day SMA) and (2-day Average Sentiment > A1): Long Asset
Else if (5-day SMA > 10-day SMA) and (2-day Average Sentiment < A2): Close Position
Else if (5-day SMA <= 10-day SMA) and (2-day Average Sentiment < B1): Short Asset
Else if (5-day SMA <= 10-day SMA) and (2-day Average Sentiment > B2): Close Position
The basis of both strategies is when the short-term moving average is above the long-term moving average, the asset price is in an upward path. Hence, we want to follow the trend and long the asset. Conversely, we want to short the asset in the other case.
The difference between the strategies is that B has additional entry and exit conditions for when the sentiment data does not agree with the moving average condition. A 2-day average is used here to smooth out noise which could cause the strategy to change positions constantly.
It is obvious that Strategy A will always have open positions whereas Strategy B will occasionally have no positions, instead holding cash until another opportunity arises.
Sentiment data from the FinSentS API will be used for the comparison of the 2 strategies. A1, A2, B1, B2 are selected to be 5, 4, 6, 7 respectively for Strategy B.
For the asset, Apple Inc. (AAPL) is used.
When either Strategy enters a position, the position size will be equal to 90% of the portfolio’s value. This is to simulate the leaving of some cash holdings to prevent for margin calls.
The FinSentS News Sentiment database offers daily media sentiment indicators for 23,000+ global equities, calculated by applying sophisticated real-time machine-learning algorithms to the content of thousands of news websites and media sources from around the world.
Each stock has 5 indicators:
- Sentiment Score: a numeric measure of the bullishness / bearishness of news coverage of the stock.
- Sentiment High / Low: highest and lowest intra-day sentiment scores.
- News Volume: the absolute number of news articles covering the stock.
- News Buzz: a numeric measure of the change in coverage volume for the stock.
|Returns||1 Month||3 Month||6 Month||12 Month|
|Alpha||1 Month||3 Month||6 Month||12 Month|
|Beta||1 Month||3 Month||6 Month||12 Month|
|Sharpe||1 Month||3 Month||6 Month||12 Month|
|Sortino||1 Month||3 Month||6 Month||12 Month|
|Volatility||1 Month||3 Month||6 Month||12 Month|
|Max Drawdown||1 Month||3 Month||6 Month||12 Month|
import numpy def initialize(context): context.stock = sid(24) context.count = 0 context.s = 0 context.sHist = [5.5,5.5] fetch_csv('https://dl.dropboxusercontent.com/s/iaksknc5ipql24d/AAPL.csv?dl=0', date_column = 'date', date_format = '%y-%m-%d') schedule_function( myfunc, date_rules.every_day(), time_rules.market_open(minutes=15) ) def myfunc(context,data): #Setting this to True will execute Strategy B and False will execute Strategy A sentiment = True if sentiment == True: prices = data.history(context.stock,'close',20,'1d').iloc[::-1] sma5 = numpy.mean(prices[0:5]) sma10 = numpy.mean(prices[0:10]) sma = numpy.mean(context.sHist) if sma5 > sma10: #Market is Bullish if sma > 5: #Positive sentiment order_target_percent(sid(24),0.9) elif sma < 4: #Reversal Signal order_target_percent(sid(24),0) elif sma5 < sma10: #Market is Bearish if sma < 6: #Negative sentiment order_target_percent(sid(24),-0.9) elif sma > 7: #Reversal Signal order_target_percent(sid(24),0) #Updates the data for use in the next trading day sent = data.current(context.stock,("sVol","s","sHigh","sLow",'sBuzz')) context.sVol = sent['sVol'] #If sentiment is 0 (No News) we assume that the previous sentiment will continue as there is nothing that changes it. Hence we will use the previous sentiment if int(sent['s']) > 0: context.s = sent['s'] context.sHist[context.count % 2] = context.s context.count += 1 record(sma5 = sma5, sma10 = sma10, Sentiment = sma) elif sentiment == False: prices = data.history(context.stock,'close',20,'1d').iloc[::-1] sma5 = numpy.mean(prices[0:5]) sma10 = numpy.mean(prices[0:10]) if sma5 > sma10: #Market is Bullish order_target_percent(sid(24),0.9) elif sma5 < sma10: #Market is Bearish order_target_percent(sid(24),-0.9)