Skip to content

Instantly share code, notes, and snippets.

@anthonymorast
Created May 18, 2022 00:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save anthonymorast/0ccd21aa70b298c331d36833b3056e80 to your computer and use it in GitHub Desktop.
Save anthonymorast/0ccd21aa70b298c331d36833b3056e80 to your computer and use it in GitHub Desktop.
import numpy as np
from scipy.sparse import rand # many 0s in our weight matrix (smaller portfolios)
from create_dataset import DatasetCreator
import pandas as pd
import matplotlib.pyplot as plt
if __name__ == '__main__':
div_cash_flow_period = 5
div_growth_period = 5 # valid values = 3, 5, 10
# takes a long time, only mark true if paramters above have changed OR the mpt_data.csv dataset is missing
create_dataset = False
data = None
if create_dataset:
creator = DatasetCreator(div_cash_flow_period, div_growth_period)
data = creator.create_dataset()
data.to_csv("./mpt_data.csv", index=False)
else:
data = pd.read_csv('./mpt_data.csv')
number_portfolios = 50000
portfolio_returns = [] # traditionally price changes
portfolio_risk = [] # traditionally volatility
portfolio_weights = []
ind_returns = data.expected_return
ind_risk = data.risk
# rather than work with percentages, this should give us ~number_stocks_in_port stocks
# in each portfolio
number_stocks_in_port = 10
weight_density = number_stocks_in_port / len(data)
print("Generating Portfolios...")
for portfolio in range(number_portfolios):
weights = rand(len(data), 1, density=weight_density) # generates a vector of mostly 0s
weights = weights.A
weights = weights / np.sum(weights) # normalize weights (sum = 1)
portfolio_weights.append(weights)
returns = np.dot(weights.T, ind_returns) # each stock weight * expected return, summed up
portfolio_returns.append(returns[0])
# since volatility isn't used, the risk is just the calculated risk (based on payout ratio
# and company solvency, i.e. dividend safety) mulitplied by the stock's weight
risk = np.dot(weights.T, ind_risk)
portfolio_risk.append(risk[0])
portfolio_data = {'return': portfolio_returns, 'risk': portfolio_risk}
for counter, symbol in enumerate(data.ticker.to_list()):
portfolio_data[symbol + ' weight'] = [w[counter][0] for w in portfolio_weights]
portfolios = pd.DataFrame(portfolio_data)
portfolios.to_csv('./portfolios.csv', index=False) # for future processing
# save lowest risk portfolios (just selected stocks)
portfolios = portfolios.sort_values(by=["risk"], ascending=True)
portfolios.head(5).to_csv("./lowest_risk.csv", index=False)
# save highest return (just selected stocks)
portfolios = portfolios.sort_values(by=["return"], ascending=False)
portfolios.head(5).to_csv("./highest_return.csv", index=False)
portfolios.plot.scatter(x="risk", y="return", marker='o', color='g', s=15, alpha=0.5, grid=True)
plt.xlabel("Risk (Dividend Safety)")
plt.ylabel(f"Return ({div_cash_flow_period} year cash flow)")
plt.title(f"{number_portfolios} Portfolios")
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment