Final Project 4930

Daniel Tafmizi

Dr. Friedman

Lis 4930

July 19, 2024 

Warren Buffett Stock Screener

“The number one rule of investing is don’t lose money and the number two rule of investing is don’t forget rule number one.” - Warren Buffett

GitHub - lis4930/finalProjectBuffetModel.py at master · DanielDataGit/lis4930 (github.com)   

Precursor: I have been investing in the stock market since the age of 16 (about 4 years). I began to truly use the markets at 18. Since, in about one and a half years, I have grown my portfolio by 15%. I hold a diversified portfolio that is mainly in tech and energy. About 50% stable, and 50% that might file bankruptcy yesterday. While this is a fine mix of risk for a 19-year-old, I have become wise about my future. At some point I will need to lay back on the high-risk tech stocks and focus on slow yet tangible growth. Thus, I am making a program that allows users to screen stocks like Warren Buffett. Many stock screeners are locked behind payed accounts. By using what I have learned about python I am able to design my own screener that is free.   

    Warren Buffetts golden goose is finding and investing into undervalued companies, also known as value investing. This is usually a long-term investment strategy that was founded by Ben Graham in his 1935 manuscript, "Security Analysis". The goal is to purchase stock when its price is lower than its intrinsic value. Warren Buffett analyses companies by their expected future cashflow using the discounted cashflow (DCF) valuation method. The DCF is a type of intrinsic value method. He uses this to calculate the margin of safety (percent difference), and only invests if the difference is above 30%.

    Buffetts second popular form of investing is known as shorting puts. This is when a person offers an "insurance" for someone's short bet. The insurer is paid a premium. If that stock stays above the strike price, the insurer walks away with the premium. If it falls below the strike price, the insurer is liable to purchase the stock at the strike price which may be above market value at the time of expiration. For this reason, a put shorter should use a strike price at which they would be willing to buy the stock at regardless. My program calculates this at Buffett's 30% rule, but the user can adjust it to their own risk tolerances. Another important tid-bit is that Buffett's options tend to expire 10+ years out. This takes advantage of the black Scholes (methods put shorts are valued) inaccuracies. 

    To calculate this in python I sourced an API that provided up to date stock data. I used Financial Modeling Prep. They offer hundreds of stocks Api's for different purposes. Initially, I had planned on having to do the math to calculate the discounted cashflow. However, my free account only allows access to their precalculated DCF API. 

This code was provided by the API provider. It allows me to receive the JSON data over a secure line.

def get_jsonparsed_data(url):
"""Code from FMP to get/parse data from their JSON"""
context = ssl.create_default_context(cafile=certifi.where())
response = urlopen(url, context=context)
data = response.read().decode("utf-8")
return json.loads(data)

This function is the heart of my program. It takes in a stock ticker symbol then pushes it to the API. The API returns the JSON data. It checks that JSON data was retrieved, if not it presents an error message. If data is received, it turns the JSON data to a Data Frame. Next, the DCF and Stock Price is used to algebraically calculate the margin of safety. If the margin of safety is above the determined value it receives Buffett's Approval. It then algebraically calculates the short put strike price based off margin of safety and DCF. The newfound data is then appended to the empty data frame and is presented in the GUI.

# Display all column and initialize empty dataframe
pd.set_option('display.max_columns', None)
x = pd.DataFrame()
def stockVal():
"""function that calculates and appends valuation data to dataframe"""
ticker = entry1.get()
url = (f"https://financialmodelingprep.com/api/v3/discounted-cash-flow/{ticker}?apikey"
f"=wcwrVLVMhYICGRP7RXBx0fVE1Gi8oC0y")
# retrieves API data as dictionary
response_data = get_jsonparsed_data(url)
# Checks data is present
if response_data:
# Converts to dataframe
data = pd.DataFrame(response_data)
# Calculate Margin of Safety and rounds to 2 places
data['Margin of Safety'] = round((data['dcf'] - data['Stock Price']) / abs(data['dcf']) * 100, 2)

# Sets Buffett's Approval based on Margin of Safety
y = int(entry2.get())
if data['Margin of Safety'].iloc[0] >= y:
data["Buffett Approves"] = "Yes"
else:
data["Buffett Approves"] = "No"

# Calculates strike price and rounds to 2 places
z = symbols('z')
equation = Eq((data["dcf"].iloc[0] - z) / abs(data["dcf"].iloc[0]) * 100, int(entry2.get()))
answer = solve(equation, z)
rounded_answer = [round(float(a), 2) for a in answer]
data["Strike Price"] = rounded_answer

# concatenates data to dataframe
global x
x = pd.concat([x, data], ignore_index=True)

stockResult.insert("1.0", data.to_string(index=False) + "\n")
entry1.delete(0, tkinter.END)

return data
else:
stockResult.insert("1.0", "No data returned from the API or out of API requests." + "\n")

I have not done GUI programming since freshman year of high school, which I believe was done using HTML (not fun from what I remember). So, I thought to give it a go in python. I reviewed the GUI module and watched a few videos. I ended up using the customtkinter and tkinter library since it seemed easy and offered modern styling. I am very happy with what I achieved. Here is my GUI code.

# initialize customtkinter window
customtkinter.set_appearance_mode("system")
root = customtkinter.CTk()
root.geometry("900 x450")

# creates frame to hold widgets
frame = customtkinter.CTkFrame(master=root)
frame.pack(pady=10, padx=10, fill="both", expand=True)
# creates title label
label = customtkinter.CTkLabel(master=frame, text="Warren Buffett Stock Screener")
label.pack(pady=10, padx=10)
# creates frame to hold entry widgets
entry_frame = customtkinter.CTkFrame(master=frame)
entry_frame.pack(pady=10, padx=10)
# entry widget for ticker symbol
entry1 = customtkinter.CTkEntry(master=entry_frame, placeholder_text="Ticker Symbol", justify="center")
entry1.pack(side=tkinter.LEFT, padx=5, pady=10)
# entry widget for margin of safety value, set at 30
entry2 = customtkinter.CTkEntry(master=entry_frame, placeholder_text="Margin of Safety", justify="center")
entry2.pack(side=tkinter.LEFT, padx=5, pady=10)
entry2.insert(0, "30")
# triggers stockVal function
button = customtkinter.CTkButton(master=frame, text="Search", command=stockVal)
button.pack(pady=10, padx=10)
# text display for results
stockResult = tkinter.Text(master=frame, height=15, width=100, background="gray")
stockResult.pack(pady=10, padx=10)
# label to display description
description_label = customtkinter.CTkLabel(master=frame,
text="This widget is a stock screener inspired by Warren Buffett's "
"principles.\n"
"Enter a ticker symbol to see the margin of safety at 30% (Or modify "
"to your likeness)"
" and recommended short put strike price.\n"
"Data is sourced from Financial Modeling Prep. The creator of this "
"program is not liable for any financial losses incurred by its use")
description_label.pack(pady=10, padx=10)
# tkinter loop
root.mainloop()
Further work can be done to automate the system. It would be more useful if I had a database of stock tickers that the program could iterate through. I could then rank them based off of their margin of safety. Unfortunately, my free subscription only allows 250 API requests each day. It would take months to get all the data.

Comments

Popular posts from this blog

First Day Assignment

Module 10 Assignment