-
-
Save anthonymorast/0ccd21aa70b298c331d36833b3056e80 to your computer and use it in GitHub Desktop.
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
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