# Install required packages
!pip install pandas_datareader
!pip install yfinance
!pip install numpy
!pip install matplotlib
!pip install PyPortfolioOpt
# Import necessary libraries
import pandas_datareader as pdr
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt
import numpy as np
import datetime
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
from pypfopt import black_litterman, BlackLittermanModel, objective_functions
Run to view results
# Enable Yahoo Finance source
yf.pdr_override()
# Date range: past 5 years
end_date = datetime.datetime.now()
start_date = end_date - datetime.timedelta(days=5*365)
# Selected stocks
stocks = ['CELH', 'PWR', 'FRHC', 'RWWI', 'KLAC']
# Fetch data
data = pdr.data.get_data_yahoo(stocks, start=start_date, end=end_date)['Adj Close']
# Calculate daily returns
daily_returns = data.pct_change().dropna()
# Statistical Exploration
print("Mean Returns:")
print(daily_returns.mean())
print("\nStandard Deviation:")
print(daily_returns.std())
# Visualization
for stock in stocks:
plt.hist(daily_returns[stock], bins=50, alpha=0.5, label=f'{stock}')
plt.xlabel('Daily Return')
plt.ylabel('Frequency')
plt.title('Distribution of Daily Returns in the Past 5 Years')
plt.legend()
plt.show()
Run to view results
# Enable Yahoo Finance source
yf.pdr_override()
# Date range: past 5 years
end_date = datetime.datetime.now()
start_date = end_date - datetime.timedelta(days=5*365)
# Selected stocks
stocks = ['CELH', 'PWR', 'FRHC', 'RWWI', 'KLAC']
# Calculate daily returns
data = pdr.data.get_data_yahoo(stocks, start=start_date, end=end_date)['Adj Close']
daily_returns = data.pct_change().dropna()
# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(data)
S = risk_models.sample_cov(data)
# Optimize the portfolio for equal weighting
ef = EfficientFrontier(mu, S)
weights = ef.max_sharpe() # Maximize the Sharpe ratio
ef.portfolio_performance(verbose=True)
# Re-calculate the daily portfolio returns based on optimized weights
optimized_weights = np.array(list(weights.values()))
daily_portfolio_returns = daily_returns.dot(optimized_weights)
# Basic Portfolio Statistics
annualized_return = ((1 + daily_portfolio_returns.mean()) ** 252) - 1
annualized_volatility = daily_portfolio_returns.std() * np.sqrt(252)
# Assuming a risk-free rate of 1% for the Sharpe ratio
risk_free_rate = 0.01
sharpe_ratio = (annualized_return - risk_free_rate) / annualized_volatility
print(f"\nAdditional Portfolio Statistics:")
print(f"Annualized Portfolio Return: {annualized_return}")
print(f"Annualized Portfolio Volatility: {annualized_volatility}")
print(f"Portfolio Sharpe Ratio: {sharpe_ratio}")
# Cumulative Returns Plot
cumulative_returns = (1 + daily_portfolio_returns).cumprod()
plt.plot(cumulative_returns.index, cumulative_returns)
plt.xlabel('Date')
plt.ylabel('Cumulative Returns')
plt.title('5-Year Cumulative Returns of the Portfolio')
plt.show()
Run to view results
# Enable Yahoo Finance source
yf.pdr_override()
# Date range: past 5 years
end_date = datetime.datetime.now()
start_date = end_date - datetime.timedelta(days=5*365)
# Selected stocks
stocks = ['CELH', 'PWR', 'FRHC', 'RWWI', 'KLAC']
# Calculate daily returns
data = pdr.data.get_data_yahoo(stocks, start=start_date, end=end_date)['Adj Close']
daily_returns = data.pct_change().dropna()
# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(data)
S = risk_models.sample_cov(data)
# Portfolio with Maximum Sharpe Ratio
ef = EfficientFrontier(mu, S)
max_sharpe_weights = ef.max_sharpe() # Maximize the Sharpe ratio
ef.portfolio_performance(verbose=True)
daily_max_sharpe_returns = daily_returns.dot(np.array(list(max_sharpe_weights.values())))
# Portfolio with Minimum Volatility
ef = EfficientFrontier(mu, S)
min_volatility_weights = ef.min_volatility()
ef.portfolio_performance(verbose=True)
daily_min_volatility_returns = daily_returns.dot(np.array(list(min_volatility_weights.values())))
# Function to calculate statistics
def calculate_statistics(daily_portfolio_returns):
annualized_return = ((1 + daily_portfolio_returns.mean()) ** 252) - 1
annualized_volatility = daily_portfolio_returns.std() * np.sqrt(252)
risk_free_rate = 0.01
sharpe_ratio = (annualized_return - risk_free_rate) / annualized_volatility
print(f"Annualized Portfolio Return: {annualized_return}")
print(f"Annualized Portfolio Volatility: {annualized_volatility}")
print(f"Portfolio Sharpe Ratio: {sharpe_ratio}")
print("\nMaximum Sharpe Portfolio Statistics:")
calculate_statistics(daily_max_sharpe_returns)
print("\nMinimum Volatility Portfolio Statistics:")
calculate_statistics(daily_min_volatility_returns)
# Cumulative Returns Plot
cumulative_max_sharpe_returns = (1 + daily_max_sharpe_returns).cumprod()
cumulative_min_volatility_returns = (1 + daily_min_volatility_returns).cumprod()
plt.figure(figsize=(14, 7))
plt.plot(cumulative_max_sharpe_returns.index, cumulative_max_sharpe_returns, label="Max Sharpe Portfolio")
plt.plot(cumulative_min_volatility_returns.index, cumulative_min_volatility_returns, label="Min Volatility Portfolio")
plt.xlabel('Date')
plt.ylabel('Cumulative Returns')
plt.title('5-Year Cumulative Returns')
plt.legend()
plt.show()
print(min_volatility_weights)
print(max_sharpe_weights)
Run to view results
# Download stock data
tickers = ['CELH', 'PWR', 'FRHC', 'RWWI', 'KLAC']
end_date = datetime.datetime.now()
start_date = end_date - datetime.timedelta(days=5*365)
prices = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
# Calculate expected returns and sample covariance
mu = expected_returns.mean_historical_return(prices)
S = risk_models.sample_cov(prices)
# Black-Litterman model
market_caps = {"CELH": 15404388417.18, "PWR": 30359653682.75, "FRHC": 5684924310.39, "RWWI": 805874400, "KLAC": 70201656396.78}
viewdict = {"CELH": 100, "KLAC": 0}
market_prior = black_litterman.market_implied_prior_returns(market_caps, risk_aversion=1000.0, risk_free_rate=0.01, cov_matrix=S)
bl = BlackLittermanModel(S, pi=market_prior, absolute_views=viewdict)
ret_bl, S_bl = bl.bl_returns(), bl.bl_cov()
# Efficient Frontier with L2 Regularization
ef = EfficientFrontier(ret_bl, S_bl, weight_bounds=(0, 1))
ef.add_objective(objective_functions.L2_reg, gamma=0.1) # gamma is the tuning parameter for L2 regularization
ef.max_sharpe()
weights = ef.clean_weights()
print(weights)
# Calculate and show the portfolio performance
ef.portfolio_performance(verbose=True)
# Plotting the portfolio
pd.Series(weights).plot.pie(autopct="%.2f%%")
plt.show()
Run to view results