RSI stock screener

Stocks screeners are effective filters when you have a specific idea of the kinds of companies in which you are looking to invest. There are tens of thousands of stocks listed on world exchanges so it’s time-consuming to browse them manually. In this post I will show you have to built your own free stock screener using Python. Most available on the Internet screeners offers a decent set of rules and filters. They have a database of equity prices updated on regular basis. However, the rules and filters are usually predefined and there is a limited possibility to extend them with more elaborate ideas. Secondly, the equity database focus usually on the most popular markets, e.g. US and West Europe stocks, and don’t cover more exotic and emerging markets like e.g. Eastern Europe. Using the same rules and applying them to the same markets as everybody else do, will give only average results. Focusing in turn on markets that are less screened by bots and algorithms (Polish, Hungarian) can give a head-to-head advantage in the pursuit for good returns. So let’s create a custom tool screening the Polish market.

To create a screener we need two things: an algorithm and data. The algorithm will be implemented in Python with the support of the pandas-ta library which leverages the Pandas library with more dozens of technical indicators and other utility functions. The data can be freely obtained from stooq where you can download a whole database of equity prices in CSV format. The database has complete coverage of all Polish equities and some Hungarian. You can also download equities from popular markets like the US, Germany, Japan or Hong Kong.

Assuming that the data files are stored offline, using the os.walk function we build a list of files. Note that we don’t filter the files according to their type so it is important to have only valid CSV files in the chosen directory which can be read by the pd.read function.

for root, dirs, files in os.walk(DB_PATH, topdown=False):
    for name in files:
        fp=os.path.join(root, name)
        df = pd.read_csv(fp)

Furthermore, we should investigate the headline of the files and write down the names of the columns. They will be needed to correctly process the data. Firstly, we must identify the column with a date that is needed to filter, index and plot the data.

#Convert data in string to date
df[COL_DATE] = df[COL_DATE].apply(pd.to_datetime,format="%Y%m%d")
#Restrict the data which is to be plotted to several months
df=df[df[COL_DATE]>='2021-01-01']
#Make a date an index of the frame
df.set_index(COL_DATE, inplace=True)

To speed up our computation, we copy the last several rows from the data to compute the single RSI value by which the quotes are filtered. Then we have the most important function of the code ta.rsi() which as the name suggests calculates RSI. Next, we check if the indicator value is below the given threshold. If not, we continue and take the next equity.

#For faster computation take only the last RSI_WINDOW+1 data points
df_test=df.iloc[-(RSI_WINDOW+1):].copy()
rsi= df_test.ta.rsi(close=COL_CLOSE)
if rsi[-1]>RSI_THRESHOLD:
    print(colored("{eq} RSI: {val}".format(eq=fp,val=round(rsi[-1])),"red"))
    continue

If the given equity passes the filter, we can compute the RSI for the whole period which is useful for plotting.

rsi= df.ta.rsi(close=COL_CLOSE)
f, axs = plt.subplots(nrows=2, ncols=1)
#Plot equity
axs[0].plot(df[COL_CLOSE])

#Plot indicator
axs[1].plot(rsi)

#Align labels on the x-axis
f.autofmt_xdate()

axs[0].grid(True)
axs[0].set_ylabel('Price')
axs[1].grid(True)
axs[1].set_ylabel('RSI value')

It is also worth to save the plots for later investigation. The plots of the filtered equities are saved as png files for later investigation.

fname, ext = os.path.splitext(name)
plt.savefig(fname)
plt.close()
Equity and its RSI
Generated plots: Equity and its RSI

Full source code

import pandas as pd
import pandas_ta as ta
from datetime import datetime
import matplotlib.pyplot as plt
import os
from termcolor import colored
import matplotlib.dates as mdates


DB_PATH = r'./eqs/'
COL_DATE='<DATE>'
COL_CLOSE='<CLOSE>'
RSI_THRESHOLD=50
RSI_WINDOW=14

#Get all files in a given directory and its directories
for root, dirs, files in os.walk(DB_PATH, topdown=False):
    print("1st for {}".format(root))
    for name in files:
        fp=os.path.join(root, name)
        df = pd.read_csv(fp)
        
        #Convert data in string to date
        df[COL_DATE] = df[COL_DATE].apply(pd.to_datetime,format="%Y%m%d")
        #Restrict the data which is to be plotted to several months
        df=df[df[COL_DATE]>='2021-01-01']
        #Make a date an index of the frame
        df.set_index(COL_DATE, inplace=True)
        #For faster computation take only the last RSI_WINDOW+1 data points
        df_test=df.iloc[-(RSI_WINDOW+1):].copy()
        
        rsi= df_test.ta.rsi(close=COL_CLOSE)

        if rsi[-1]>RSI_THRESHOLD:
            print(colored("{eq} RSI: {val}".format(eq=fp,val=round(rsi[-1])),"red"))
            continue
        
        print(colored("{eq} RSI: {val}".format(eq=fp,val=round(rsi[-1])),"green"))

        #Compute again the indicator for a positively selected equity but this time for all data points
        rsi= df.ta.rsi(close=COL_CLOSE)

        #Make plots for the filtered equities
        f, axs = plt.subplots(nrows=2, ncols=1)
        #Plot equity
        axs[0].plot(df[COL_CLOSE])
        
        #Plot indicator
        axs[1].plot(rsi)
        
        #Align labels on the x-axis
        f.autofmt_xdate()
    
        axs[0].grid(True)
        axs[0].set_ylabel('Price')
        axs[1].grid(True)
        axs[1].set_ylabel('RSI value')
        
        #Show plots
        #plt.show()
        #Save plots for later examination or show it
        fname, ext = os.path.splitext(name)
        plt.savefig(fname)
        plt.close()
Source code for RSI Stock scanner with data

Leave a Reply

Your email address will not be published. Required fields are marked *