I was helping out with a little PhD analysis this evening and whilst taking a break, stumbled across some old code for sourcing share prices and then computing their Relative Strength Index (RSI) in Python. If I recall, the original version also used Matplotlib to draw charts showing performance, OHLC and some regression analysis but this version was used to produce a concise list of shares with RSI’s indicating either Buy or Sell, or, those which were approaching a level to consider which I would then read on the way into the office.
Putting aside efficient market arguments over whether the RSI is a valid measure or not – since when did stop a good opportunity to get deep into some code?! – the source code presented here is relatively straightforward and could be improved by threading the RSI calculation, storing the share tickers in a database and linking this to an automated process for when companies enter and exit the index.
Set up and configuration
There is very little to actually consider when setting up. The pre-requisites are to have Python installed along with NumPy and MatplotLib libraries and an active internet connection. Additionally, I had created a text file containing a list of all of the companies, tickers and FTSE tier (100, 250 etc) which this script reads. I’ve posted this file here and invite you to download it but caveat emptor, it was created a few years ago and I’ve not updated it since – I can see that Autonomy are still within it’s electronic pages for instance.
Once this is file is downloaded (and you can change the location where it is read from) then the script will run, read the csv file and sequentially source and calculate the RSI with a 14 day window based upon the last 365 days of data. It will then present you with a list of shares which are classically thought to be indicating a price drop (RSI >= 70 or rally (RSI<=30) and I also included an RSI of between 30 and 40 for those shares which might be worth considering. Obviously, you can change this how you like and might like to also include a list of your own portfolio. Additionally, the RSI function could easily be deployed to accept any time-series data.
The code is presented as is below and you’re welcome to use it as you wish. Hopefully it might safe you a bit of time writing such from scratch, although please attribute back to this page and share a small slice of any profits you make!
import numpy as np
import matplotlib.finance as finance
import matplotlib.dates as mdates
import matplotlib.ticker as mticker
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
import matplotlib.font_manager as font_manager
startdate = datetime.date.today()-datetime.timedelta(days=365)
today = enddate = datetime.date.today()
HighRSI = 
def __init__(self, *args, **kwargs):
mticker.MaxNLocator.__init__(self, *args, **kwargs)
def __call__(self, *args, **kwargs):
return mticker.MaxNLocator.__call__(self, *args, **kwargs)
with open(r"C:\Test\AllSharesOrdered.csv", mode=’r’) as infile:
reader = csv.reader(infile)
for rows in reader:
mydict = dict((rows+".L",rows) for rows in reader)
for ticker in mydict:
fh = finance.fetch_historical_yahoo(ticker, startdate, enddate)
r = mlab.csv2rec(fh); fh.close()
def relative_strength(prices, n=14):
deltas = np.diff(prices)
seed = deltas[:n+1]
up = seed[seed>=0].sum()+0.000001/n
down = -seed[seed<0].sum()+0.000001/n
rs = up/down
rsi = np.zeros_like(prices)
rsi[:n] = 100. – 100./(1.+rs)
for i in range(n, len(prices)):
delta = deltas[i-1]
upval = delta
downval = 0.
upval = 0.
downval = -delta
up = (up*(n-1) + upval)/n
down = (down*(n-1) + downval)/n
rs = up/down
rsi[i] = 100. – 100./(1.+rs)
prices = r.adj_close
rsi = relative_strength(prices)
if rsi[-1] <= 30 and rsi[-1] > 0:
if rsi[-1] <= 40 and rsi[-1] > 30:
if rsi[-1] >= 70 and rsi[-1] > 0:
print "\n*Low RSI shares*"
for shares in LowRSI:
print "\n*Consideration RSI shares*"
for shares in ApproachRSI:
print "\n*High RSI shares*"
for shares in HighRSI:
I’d like to attribute credit for the original RSI function and code stem but I am unable to locate the primary source. Should this change I will post a link to the original code base