Last active
January 4, 2024 05:28
-
-
Save shashankvemuri/50ed514a0ed41599ac29cc297efc3c05 to your computer and use it in GitHub Desktop.
the entire stock screener code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Imports | |
from pandas_datareader import data as pdr | |
from pandas import ExcelWriter | |
import yfinance as yf | |
import pandas as pd | |
import datetime | |
import time | |
import requests | |
yf.pdr_override() | |
# Get tickers for all S&P 500 stocks from Wikipedia | |
def tickers_sp500(): | |
url = 'https://en.wikipedia.org/wiki/List_of_S%26P_500_companies' | |
html = requests.get(url).text | |
df = pd.read_html(html, header=0)[0] | |
tickers = df['Symbol'].tolist() | |
return tickers | |
# Variables | |
tickers = tickers_sp500() | |
tickers = [item.replace(".", "-") for item in tickers] # Yahoo Finance uses dashes instead of dots | |
index_name = '^GSPC' # S&P 500 | |
start_date = datetime.datetime.now() - datetime.timedelta(days=365) | |
end_date = datetime.date.today() | |
exportList = pd.DataFrame(columns=['Stock', "RS_Rating", "50 Day MA", "150 Day Ma", "200 Day MA", "52 Week Low", "52 week High"]) | |
returns_multiples = [] | |
# Index Returns | |
index_df = pdr.get_data_yahoo(index_name, start_date, end_date) | |
index_df['Percent Change'] = index_df['Adj Close'].pct_change() | |
index_return = (index_df['Percent Change'] + 1).cumprod()[-1] | |
# Find top 30% performing stocks (relative to the S&P 500) | |
for ticker in tickers: | |
# Download historical data as CSV for each stock (makes the process faster) | |
df = pdr.get_data_yahoo(ticker, start_date, end_date) | |
df.to_csv(f'{ticker}.csv') | |
# Calculating returns relative to the market (returns multiple) | |
df['Percent Change'] = df['Adj Close'].pct_change() | |
stock_return = (df['Percent Change'] + 1).cumprod()[-1] | |
returns_multiple = round((stock_return / index_return), 2) | |
returns_multiples.extend([returns_multiple]) | |
print (f'Ticker: {ticker}; Returns Multiple against S&P 500: {returns_multiple}\n') | |
time.sleep(1) | |
# Creating dataframe of only top 30% | |
rs_df = pd.DataFrame(list(zip(tickers, returns_multiples)), columns=['Ticker', 'Returns_multiple']) | |
rs_df['RS_Rating'] = rs_df.Returns_multiple.rank(pct=True) * 100 | |
rs_df = rs_df[rs_df.RS_Rating >= rs_df.RS_Rating.quantile(.70)] | |
# Checking Minervini conditions of top 30% of stocks in given list | |
rs_stocks = rs_df['Ticker'] | |
for stock in rs_stocks: | |
try: | |
df = pd.read_csv(f'{stock}.csv', index_col=0) | |
sma = [50, 150, 200] | |
for x in sma: | |
df["SMA_"+str(x)] = round(df['Adj Close'].rolling(window=x).mean(), 2) | |
# Storing required values | |
currentClose = df["Adj Close"][-1] | |
moving_average_50 = df["SMA_50"][-1] | |
moving_average_150 = df["SMA_150"][-1] | |
moving_average_200 = df["SMA_200"][-1] | |
low_of_52week = round(min(df["Low"][-260:]), 2) | |
high_of_52week = round(max(df["High"][-260:]), 2) | |
RS_Rating = round(rs_df[rs_df['Ticker']==stock].RS_Rating.tolist()[0]) | |
try: | |
moving_average_200_20 = df["SMA_200"][-20] | |
except Exception: | |
moving_average_200_20 = 0 | |
# Condition 1: Current Price > 150 SMA and > 200 SMA | |
condition_1 = currentClose > moving_average_150 > moving_average_200 | |
# Condition 2: 150 SMA and > 200 SMA | |
condition_2 = moving_average_150 > moving_average_200 | |
# Condition 3: 200 SMA trending up for at least 1 month | |
condition_3 = moving_average_200 > moving_average_200_20 | |
# Condition 4: 50 SMA> 150 SMA and 50 SMA> 200 SMA | |
condition_4 = moving_average_50 > moving_average_150 > moving_average_200 | |
# Condition 5: Current Price > 50 SMA | |
condition_5 = currentClose > moving_average_50 | |
# Condition 6: Current Price is at least 30% above 52 week low | |
condition_6 = currentClose >= (1.3*low_of_52week) | |
# Condition 7: Current Price is within 25% of 52 week high | |
condition_7 = currentClose >= (.75*high_of_52week) | |
# If all conditions above are true, add stock to exportList | |
if(condition_1 and condition_2 and condition_3 and condition_4 and condition_5 and condition_6 and condition_7): | |
exportList = exportList.append({'Stock': stock, "RS_Rating": RS_Rating ,"50 Day MA": moving_average_50, "150 Day Ma": moving_average_150, "200 Day MA": moving_average_200, "52 Week Low": low_of_52week, "52 week High": high_of_52week}, ignore_index=True) | |
print (stock + " made the Minervini requirements") | |
except Exception as e: | |
print (e) | |
print(f"Could not gather data on {stock}") | |
exportList = exportList.sort_values(by='RS_Rating', ascending=False) | |
print('\n', exportList) | |
writer = ExcelWriter("ScreenOutput.xlsx") | |
exportList.to_excel(writer, "Sheet1") | |
writer.save() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I get below error when in run in AWS EC2 instance
File "/root/test.py", line 1, in
from pandas_datareader import data as pdr
File "/usr/local/lib/python3.9/site-packages/pandas_datareader/init.py", line 5, in
from .data import (
File "/usr/local/lib/python3.9/site-packages/pandas_datareader/data.py", line 9, in
from pandas.util._decorators import deprecate_kwarg
ModuleNotFoundError: No module named 'pandas.util'; 'pandas' is not a package
Please advise how to fix it ?