Python Tutorial: RSI

Download the accompanying IPython Notebook for this Tutorial from Github. 

Python streamlines tasks requiring multiple steps in a single block of code. For this reason, it is a great tool for querying and performing analysis on data.

Last Tutorial, we outlined steps for calculating Price Channels.

In this Tutorial, we introduce a new technical indicator, the Relative Strenght Index (RSI).

The Relative Strength Index (RSI) is a momentum indicator developed by noted technical analyst Welles Wilder, that compares the magnitude of recent gains and losses over a specified time period to measure speed and change of price movements of a security. It is primarily used to identify overbought or oversold conditions in the trading of an asset.

The Relative Strength Index (RSI) is calculated as follows:

RSI = 100 - 100 / (1 + RS)

RS = Average gain of last 14 trading days / Average loss of last 14 trading days

RSI values range from 0 to 100.

Traditional interpretation and usage of the RSI is that RSI values of 70 or above indicate that a security is becoming overbought or overvalued, and therefore may be primed for a trend reversal or corrective pullback in price. On the other side, an RSI reading of 30 or below is commonly interpreted as indicating an oversold or undervalued condition that may signal a trend change or corrective price reversal to the upside.

Let’s use Python to compute the Relative Strenght Index (RSI).

1.) Import modules (numpy included).

import pandas as pd
import numpy as np
from pandas_datareader import data as web
import matplotlib.pyplot as plt
%matplotlib inline

2.) Define function for querying daily close.

def get_stock(stock,start,end):
 return web.DataReader(stock,'google',start,end)['Close']

3.) Define function for RSI.

def RSI(series, period):
 delta = series.diff().dropna()
 u = delta * 0
 d = u.copy()
 u[delta > 0] = delta[delta > 0]
 d[delta < 0] = -delta[delta < 0]
 u[u.index[period-1]] = np.mean( u[:period] ) #first value is sum of avg gains
 u = u.drop(u.index[:(period-1)])
 d[d.index[period-1]] = np.mean( d[:period] ) #first value is sum of avg losses
 d = d.drop(d.index[:(period-1)])
 rs = pd.stats.moments.ewma(u, com=period-1, adjust=False) / \
 pd.stats.moments.ewma(d, com=period-1, adjust=False)
 return 100 - 100 / (1 + rs)

How does the RSI function work?

– 3.a.) Function creates two series of daily differences.

– 3.b.) One series is daily positive differences, i.e. gains.

– 3.c.) One series is daily negative difference, i.e. losses.

– 3.d.) Average daily positive differences for the period specified.

– 3.e.) Average daily negative difference for the period specified.

– 3.f.) RS is set equal to Exponential Moving Average of daily positive differences for the period sepcified / Exponential Moving Average of daily positive differences for the period sepcified.

– 3.g) Return 100 – 100 / (1 + RS)

 4.) Query daily close for ‘FB’ during 2016.

df = pd.DataFrame(get_stock('FB', '1/1/2016', '12/31/2016'))

5.) Run daily close through RSI function. Save series to new column in dataframe.

df['RSI'] = RSI(df['Close'], 14)
df.tail()

6.) Plot daily close and RSI.

df.plot(y=['Close'])
df.plot(y=['RSI'])

There you have it! We created our RSI indicator. Here’s the full code:

import pandas as pd
import numpy as np
from pandas_datareader import data as web
import matplotlib.pyplot as plt
%matplotlib inline

def get_stock(stock,start,end):
 return web.DataReader(stock,'google',start,end)['Close']
 
def RSI(series, period):
 delta = series.diff().dropna()
 u = delta * 0
 d = u.copy()
 u[delta > 0] = delta[delta > 0]
 d[delta < 0] = -delta[delta < 0]
 u[u.index[period-1]] = np.mean( u[:period] ) #first value is sum of avg gains
 u = u.drop(u.index[:(period-1)])
 d[d.index[period-1]] = np.mean( d[:period] ) #first value is sum of avg losses
 d = d.drop(d.index[:(period-1)])
 rs = pd.stats.moments.ewma(u, com=period-1, adjust=False) / \
 pd.stats.moments.ewma(d, com=period-1, adjust=False)
 return 100 - 100 / (1 + rs)
 
df = pd.DataFrame(get_stock('FB', '1/1/2016', '12/31/2016'))
df['RSI'] = RSI(df['Close'], 14)
df.tail()

If they Google You, Do you Win?

In a way, this election is a referendum on “do actions speak louder than words”, is what people do in the privacy of their internet browsing more reflective of their future behavior than what they tell pollsters? And while I have focused on twitter as a barometer of public opinion, there are other data sources that could signal the private thoughts and future actions of voters. The linked NYT article, “If they Google you, Do you Win?”, mentions using the Google queries “Trump Clinton” vs. “Clinton Trump” as signals of voter interest, with the respective queries reflecting bias towards the candidate listed first, i.e. “Clinton Trump” would reflect bias towards Clinton. Using this methodology, I researched Google trends for Battleground states to see where public opinion may be. The data are displayed below.

screen-shot-2016-11-03-at-5-49-10-pm

For the month of October 2016, “Trump Clinton” leads “Clinton Trump” in every state with the exception of Nevada.

You might say Trump is a polarizing celebrity, and for that reason he may be top of mind even if the individual plans to vote for Clinton. Okay, well then let’s penalize Trump 10%. Even in that case, ‘Factored “Trump Clinton”‘ indicates that, with the exception of Nevada, the three states that are in play are Virginia, Iowa, and Florida.

So while it is unclear in which direction the election will result, I believe we may be surprised at how close the results turn out to be, and that one thing we may remember is the discrepancy between what was reported in the polls leading up to the election and what actually happened online. We only have 4 days left to see which source provides a clearer signal of truth, and until then….Good luck to both candidates!

Up to +0.9 Correlation between Twitterwonk Scores and National Polls

455906_2bf3212686734defb5f3b366a29c3c86 I have found, on average, a +0.6 correlation between Twitterwonk Scores and national polls. Of the four leading candidates, Bernie Sanders (displayed) shows the highest correlation, +0.9. The national poll data used in the analysis is from fivethirtyeight. The findings suggest Twitterwonk can be used as a substitute to traditional national polling methods, which are resource intensive and delayed in reporting. While national polls are not always predictive of state primary results, they play a big role in media coverage. 

Hillary: Age Perception Problem?

“I come from the ‘60s, a long time ago,” Hillary Clinton said at Saturday’s Democratic Presidential debate, in response to a question about student activism. The gaffe has mostly fallen on deaf ears.

Hillary Clinton is 68 years old. She was born October 26, 1947. Here is a visualization showing the age distribution of US Presidents upon assuming the Oval Office.

Screen Shot 2015-11-19 at 12.53.10 PM (2)

To date, only three US Presidents between the ages 65-69 have assumed the Oval Office. Once again, Hillary Clinton is 68 years old. She “come(s) from the ‘60s, a long time ago.”

Granted, the US population is aging. However, when selecting Presidents, this aging US population has trended towards younger Presidents.

Age upon assuming Oval Office: Barack Obama, 47 years old; George W. Bush, 54 years old; Bill Clinton, 46 years old.

Hillary wishes to dispel the age perception. HFA recently posted the SnapChat logo wearing a most recognizable pantsuit.

Screen Shot 2015-11-19 at 12.55.00 PM (2)

Of all the social networks, Snapchat skews youngest. According to Business Insider, 45% of Snapchat users are between the ages 18-24.Screen Shot 2015-11-19 at 12.44.44 PM (2)

Thus, a strategy has emerged: capture the young mind. Win the unspoiled voter, who is excited by the prospect of casting her first vote. Btw, Hillary uses Snapchat.

Further evidence of the strategy:

Twitter Banner displaying young prospective voters

Screen Shot 2015-11-19 at 12.53.58 PM (2)

HFA blog post appealing to youth and “a new age”

Screen Shot 2015-11-19 at 1.43.10 PM (2)

We should expect age to become a louder issue as the campaigns unfold. For reference, here are the ages of all the candidates, both Democrats and Republicans. Those between the ages 44- 60 are in bold.

Hilary Clinton, 68 years old

Bernie Sanders, 74 yeards old

Martin O’Malley, 52 years old

Donald Trump, 69 years old

Ben Carson, 64 years old

Marco Rubio, 44 years old

Ted Cruz, 44 years old

Jeb Bush, 62 years old

Carly Fiorina, 61 years old

John Kasich, 63 years old

Rand Paul, 52 years old