Python for Finance Capstone - My own version

Hi All,
I have recently completed the Python for Finance course. Since I have a degree in Finance and am on my way to becoming a CFA charter holder, I didn’t feel creating a presentation for recommending a stock was going to add much value to my education.
I decided instead to create a program that will take in a user-inputted list of stocks and create mean-variance portfolio optimization output, utilizing 5 years of historical data. The program will prompt you for how many stocks you want to include - then you will input the stocks you want to include. It will show you the weights for the max-sharpe portfolio, and the weights for the minimum variance portfolio, plus their respective expected returns and risks. It will then prompt you if you want to include a dollar value for your portfolio, and it will try it’s best to tell you how many shares of each company to buy, and how much $ will be left over. At the end, it will plot a bar graph the shows the tradeoff between risk and return for the stocks in your portfolio, and also show the efficient frontier including where the max-sharpe portfolio lies.
I utilized the pyportfolioopt package for this project - so you will need to have this downloaded. There may be some other packages you need to download, so if you have any trouble you can ask me and I will point you in the right direction.
You will also need to have a Tiingo API key, which you can get for free from their website. You will ned to put in your Tiingo API key in the program where it says INPUT-API-KEY-HERE.
Hope someone gets to check this out, and please leave any feedback you may have!

from tiingo import TiingoClient
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import numpy as np
from pypfopt import EfficientFrontier, risk_models, expected_returns, plotting
from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
from datetime import date, timedelta

client = TiingoClient({‘api_key’:‘INSERT-API-KEY-HERE’})

Create an empty list to be populated by user input

list_of_stocks =

Find out how many stocks the user wants to include

number_of_stocks = int(input(‘How many stocks would you like to include?’))

Prompt user to input list of tickers, to appended to list_of_stocks above

print("Enter each ticker you’d like to include, one at a time (pressing after each ticker), below: ")

Loop through n iterations defined by user to create list of stocks

for i in range(0,number_of_stocks):
ele = input()

Define variables that hold today’s date, and the day five years ago to be used in the dataframe of historical prices

today =
yesterday = today - timedelta(days=1)
yesterday1 = yesterday.strftime(’%Y%m%d’)
five_years_ago = today - timedelta(days=(365*5))
five_years_ago1 = five_years_ago.strftime(’%Y%m%d’)

Create dataframe with user-defined list of stocks of the adjusted closes for 5 years

all_history = client.get_dataframe(list_of_stocks,

Calculate daily returns from dataframe

stocks = list(all_history.columns[0:])
daily_returns = all_history[stocks].pct_change()

find expected return of each stock and annualize them. Express as a percent

expected_return = daily_returns.mean()
annual_exp_return = expected_return * 252
annual_exp_return_pct = annual_exp_return * 100

find std dev of returns, express as a percent.

std = daily_returns.std()
std_year = std * 252**.5
std_year_pct = std_year * 100

find covariance matrix of returns

returns_cov = daily_returns.cov()

find correlation between stocks

returns_corr = daily_returns.corr()

Calculate expected returns and sample covariance

mu = expected_returns.mean_historical_return(all_history)
S = risk_models.sample_cov(all_history)

Find portfolio optimized for maximal Sharpe ratio

print(‘These are the weights of the long-only, maximum Sharpe ratio portfolio:’)
ef = EfficientFrontier(mu, S, weight_bounds=(0,1))
raw_weights = ef.max_sharpe()
cleaned_weights = ef.clean_weights()
ef.save_weights_to_file(“weights.csv”) # saves to file
ef = EfficientFrontier(mu, S, weight_bounds=(0,1))

Create a figure


Plot the efficient frontier line

ax3 = plt.subplot(1,2,2)
plotting.plot_efficient_frontier(ef, ax=ax3, show_assets=True)

find the portfolio optimized for minimum volatility

print(‘These are the weights of the long-only, minimum volatility portfolio:’)
min_vol = ef.min_volatility()
performance = ef.portfolio_performance(verbose=True)

Create side-by-side bar graph comparing volatility (annualized std dev.) vs avg annualized returns for each stock

d= number_of_stocks
x_values_one = [t * element + w * n for element in range(d)]

d= number_of_stocks
x_values_two = [t * element + w * n for element in range(d)]

ax = plt.subplot(1,2,1), annual_exp_return_pct), std_year_pct)
plt.title(‘Expected Return vs Volatility’)
plt.ylabel(‘Expected Return (annualized) vs Volatility (annualized std dev’)
plt.legend([‘Expected Return’, ‘Volatility’])

create a graph showing the efficient frontier with 5000 random portfolios

Find the tangency portfolio

ret_tangent, std_tangent, _ = ef.portfolio_performance()
plt.scatter(std_tangent, ret_tangent, marker="*", s=100, c=“r”, label=“Max Sharpe”)

Generate random portfolios and plot them

n_samples = 5000
w = np.random.dirichlet(np.ones(len(mu)), n_samples)
rets =
stds = np.sqrt(np.diag(w @ S @ w.T))
sharpes = rets / stds
plt.scatter(stds, rets, marker=".", c=sharpes, cmap=“viridis_r”)
ax1.set_title(“Efficient Frontier with Random Portfolio Weights”)
ax1.yaxis.set_major_formatter(mtick.PercentFormatter(1, decimals=1))

Print the previous day’s closing prices

print(“These are the previous day’s closing prices:”)
latest_prices = get_latest_prices(all_history)

Find out if user wants to include a $ value of their portfolio to find exact amounts of stock to buy

yes_or_no = input(‘Do you want to give a dollar value of your portfolio to find the exact amounts of stock to buy? (Answer yes or no)’)

Include portfolio value to come up with exact amount of stocks to buy

if yes_or_no == ‘yes’:
dollar_value = int(input(‘What is the dollar value of your portfolio? (Leave out the dollar sign)’))
discrete = DiscreteAllocation(cleaned_weights,
allocation, leftover = discrete.greedy_portfolio()
print('You should buy the following amounts of shares: ', allocation)
print(‘This is the amount of money you will have leftover: ${:.2f}’.format(leftover))

Show the figure[/codebyte]