robertmartin8 / PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
https://pyportfolioopt.readthedocs.io/
MIT License
4.43k stars 948 forks source link

Show-and-Tell: Applying selected consumer "demographic investing" #489

Open BradKML opened 1 year ago

BradKML commented 1 year ago

Problem: Finding the right way to create a pareto frontier for certain consumer demographics. Weirdly enough deepcopy is needed when both frontier finding and Sharpe-optimization.

Question:

  1. How does one turn this into Sortino or Treynor optimization?
  2. Are there any pie charts in this repo like riskfolio-lib's pie chart and proportional chart? https://pyportfolioopt.readthedocs.io/en/latest/Plotting.html#pypfopt.plotting.plot_weights
!pip install PyPortfolioOpt yfinance --quiet --upgrade

import numpy as np
import pandas as pd
import yfinance as yf
import warnings

warnings.filterwarnings("ignore")
pd.options.display.float_format = '{:.4%}'.format

# Date range
start = '2010-01-01'
end = '2020-12-30'

# Tickers of long-term $BECKY assets
assets = ["AAPL", "ADDYY", "AMZN", "BBBY", "BBWI", "BUD", "CHD", 
          "CMG", "CVS", "DECK", "DEO", "DIS", "EL", "F", "FIZZ", 
          "GPS", "JWN", "LRLCY", "LULU", "LVMUY", "M",  "MO", "MTCH", 
          "NFLX", "NKE", "PVH", "RL", "SBUX", "STZ", "TAP", "TGT", 
          "TJX", "TPR", "UAA", "ULTA", "VFC", "WSM", "WWW", "YUM"]

# Contemporary $BECKY companies
# "ABBV", "COTY", "CRON", "EOLS", "ETSY", "FTCH", "GOOS", "INMD", 
# "LEVI", "LYFT", "MC", "META", "OR", "PINS", "PLNT", "PTON", 
# "SFIX", "SKIN", "SNAP", "SPOT", "TLRY", "TWTR", "YETI", 

assets.sort()

# Downloading data
data = yf.download(assets, start = start, end = end)
data = data.loc[:,('Adj Close', slice(None))]
data.columns = assets

data = data.dropna()
data = data.drop(columns=['AAPL', 'AMZN', 'NFLX'])

from pypfopt.expected_returns import mean_historical_return
from pypfopt.risk_models import CovarianceShrinkage

mu = mean_historical_return(data)
S = CovarianceShrinkage(data).ledoit_wolf()

from pypfopt.efficient_frontier import EfficientFrontier

ef = EfficientFrontier(mu, S)

from copy import deepcopy
ef_frontier = deepcopy(ef)

from pypfopt.plotting import plot_efficient_frontier
plot_efficient_frontier(ef_frontier) # "BEFORE optimising an objective"
# https://pyportfolioopt.readthedocs.io/en/latest/Plotting.html

weights = ef.max_sharpe() # or min_volatility()

cleaned_weights = ef.clean_weights()
ef.save_weights_to_file("weights.txt")  # saves to file
print(cleaned_weights)

ef.portfolio_performance(verbose=True)

for i in cleaned_weights:
  if cleaned_weights[i] > 0: print(i, cleaned_weights[i])
BradKML commented 1 year ago

Also weirdly enough others have created a "point system", how do they differ from volatility? https://pythoninvest.com/long-read/practical-portfolio-optimisation