Background

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!

Output

Screenshot of RSI code output

Code

[sourcecode language=”python”]

import datetime
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
import csv
import os
import sys
import time

startdate = datetime.date.today()-datetime.timedelta(days=365)
today = enddate = datetime.date.today()
errorsticker=[]
LowRSI=[]
LowTickerOutput =[]
HighRSI = []
HighTickerOutput =[]
ApproachRSI=[]
ApproachTickerOutput=[]

class MyLocator(mticker.MaxNLocator):
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[0]+".L",rows[1]) for rows in reader)

for ticker in mydict:
try:
fh = finance.fetch_historical_yahoo(ticker, startdate, enddate)
r = mlab.csv2rec(fh); fh.close()
r.sort()

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]
if delta>0:
upval = delta
downval = 0.
else:
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)

return rsi

prices = r.adj_close

rsi = relative_strength(prices)

if rsi[-1] <= 30 and rsi[-1] > 0:
LowRSI.append(str(ticker)+"\t"+str(round(rsi[-1],2))+"\t"+mydict[ticker])
LowTickerOutput.append(str(ticker))

if rsi[-1] <= 40 and rsi[-1] > 30:
ApproachRSI.append(str(ticker)+"\t"+str(round(rsi[-1],2))+"\t"+mydict[ticker])
ApproachTickerOutput.append(str(ticker))

if rsi[-1] >= 70 and rsi[-1] > 0:
HighRSI.append(str(ticker)+"\t"+str(round(rsi[-1],2))+"\t"+mydict[ticker])
HighTickerOutput.append(str(ticker))

except:
errorsticker.append(ticker)
pass

print "\n*Low RSI shares*"
for shares in LowRSI:
print shares

print "\n*Consideration RSI shares*"
for shares in ApproachRSI:
print shares

print "\n*High RSI shares*"
for shares in HighRSI:
print shares
time.sleep(60)
[/sourcecode]

References

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

2 COMMENTS

  1. Hello i tried running this code , but are we sure…its not working , i am not sure what the loop” try” is trying to achieve, kindly help

I'd love to hear what your thoughts are...please feel free to leave a reply