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
# Necessary Libraries | |
import yfinance as yf, pandas as pd, shutil, os, time, glob, smtplib, ssl | |
from get_all_tickers import get_tickers as gt |
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
# These two lines remove the Stocks folder and then recreate it in order to remove old stocks. | |
shutil.rmtree("<Your Path>\\Daily_Stock_Report\\Stocks\\") | |
os.mkdir("<Your Path>\\Daily_Stock_Report\\Stocks\\") | |
# Holds the amount of API calls we executed | |
Amount_of_API_Calls = 0 | |
# This while loop is reponsible for storing the historical data for each ticker in our list. Note that yahoo finance sometimes incurs json.decode errors and because of this we are sleeping for 2 seconds after each iteration, also if a call fails we are going to try to execute it again. Also, do not make more than 2,000 calls per hour or 48,000 calls per day or Yahoo Finance may block your IP. The clause "(Amount_of_API_Calls < 1800)" below will stop the loop from making too many calls to the yfinance API.Prepare for this loop to take some time. It is pausing for 2 seconds after importing each stock. | |
Stock_Failure = 0 # Used to make sure we don't waste too many API calls on one Stock ticker that could be having issues | |
Stocks_Not_Imported |
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
# List of the stocks we are interested in analyzing. At the time of writing this, it narrows the list of stocks down to 44. If you have a list of your own you would like to use just create a new list instead of using this, for example: tickers = ["FB", "AMZN", ...] | |
tickers = gt.get_tickers_filtered(mktcap_min=150000, mktcap_max=10000000) | |
# Check that the amount of tickers isn't more than 1800 | |
print("The amount of stocks chosen to observe: " + str(len(tickers))) |
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
# OBV Analysis, feel free to replace this section with your own analysis ------------------------------------------------------------------------- | |
list_files = (glob.glob("<Your Path>\\Daily_Stock_Report\\Stocks\\*.csv")) # Creates a list of all csv filenames in the stocks folder | |
new_data = [] # This will be a 2D array to hold our stock name and OBV score | |
interval = 0 # Used for iteration | |
while interval < len(list_files): | |
Data = pd.read_csv(list_files[interval]).tail(10) # Gets the last 10 days of trading for the current stock in iteration | |
pos_move = [] # List of days that the stock price increased | |
neg_move = [] # List of days that the stock price increased | |
OBV_Value = 0 # Sets the initial OBV_Value to zero | |
count = 0 |
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
Analysis = pd.read_csv("<Your Path>\\Daily_Stock_Report\\OBV_Ranked.csv") # Read in the ranked stocks | |
top10 = Analysis.head(10) # I want to see the 10 stocks in my analysis with the highest OBV values | |
bottom10 = Analysis.tail(10) # I also want to see the 10 stocks in my analysis with the lowest OBV values | |
# This is where we write the body of our email. Add the top 10 and bottom 10 dataframes to include the results of your analysis | |
Body_of_Email = """\ | |
Subject: Daily Stock Report | |
Your highest ranked OBV stocks of the day: | |
""" + top10.to_string(index=False) + """\ |
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
# Necessary Libraries | |
import yfinance as yf, pandas as pd, shutil, os, time, glob | |
import numpy as np | |
import requests | |
from get_all_tickers import get_tickers as gt | |
from statistics import mean |
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
# If you have a list of your own you would like to use just create a new list instead of using this, for example: tickers = ["FB", "AMZN", ...] | |
tickers = gt.get_tickers_filtered(mktcap_min=5000, mktcap_max=10000000) | |
# Check that the amount of tickers isn't more than 2000 | |
print("The amount of stocks chosen to observe: " + str(len(tickers))) | |
# These two lines remove the Stocks folder and then recreate it in order to remove old stocks. Make sure you have created a Stocks Folder the first time you run this. | |
shutil.rmtree("<Your Path>\\SMA_Analysis\\Stocks\\") | |
os.mkdir("<Your Path>\\SMA_Analysis\\Stocks\\") | |
# Holds the amount of API calls we executed | |
Amount_of_API_Calls = 0 | |
# This while loop is reponsible for storing the historical data for each ticker in our list. Note that yahoo finance sometimes incurs json.decode errors and because of this we are sleeping for 2 |
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
# Get the path for each stock file in a list | |
list_files = (glob.glob("<Your Path>\\SMA_Analysis\\Stocks\\*.csv")) | |
# You can use this line to limit the analysis to a portion of the stocks in the "stocks folder" | |
# list_files = list_files[:100] | |
# Create the dataframe that we will be adding the final analysis of each stock to | |
Compare_Stocks = pd.DataFrame(columns=["Company", "Days_Observed", "Crosses", "True_Positive", "False_Positive", "True_Negative", "False_Negative", "Sensitivity", | |
"Specificity", "Accuracy", "TPR", "FPR"]) | |
# While loop to cycle through the stock paths | |
count = 0 | |
for stock in list_files: |
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
Compare_Stocks = pd.read_csv("<Your Path>\\SMA_Analysis\\All_Stocks.csv") # Read in the All_Stocks data to a dataframe | |
# Delete companies that don't have enough crosses observed. I am using 50 crosses as my cuttoff: | |
Not_Enough_Records = [] | |
Row = 0 | |
while Row < (len(Compare_Stocks)): | |
if Compare_Stocks.iloc[Row, 2] < 50: | |
Not_Enough_Records.append(Row) | |
Row += 1 | |
Compare_Stocks = Compare_Stocks.drop(Not_Enough_Records) # Remove records that do not have enough crosses for us to observe | |
Avg_Accuracy = [] # List to hold the accuracy of each stock |
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
list_files = (glob.glob("<Your path>\\Stocks\\*.csv")) # Creates a list of all csv filenames in the stocks folder | |
new_data = [] # This will be a 2D array to hold our stock name and OBV score |
OlderNewer