# consulted Chatgpt for the use of function, the codes of merging factors, and the section related to illustration; codes includes works done by chatgpt and modified by myself.
!pip install yfinance numpy pandas
!pip install pandas_datareader
import yfinance as yf
import numpy as np
import pandas as pd
from scipy.optimize import minimize
import pandas_datareader.data as web
stocks = ['AAPL', 'TSLA', 'PDD', 'XPEV', 'ASML']
start_date = '2018-09-07'
end_date = '2023-09-07'
data = yf.download(stocks, start=start_date, end=end_date)
returns = data['Adj Close'].pct_change().dropna()
def negative_sharpe_ratio(weights):
portfolio_return = np.dot(returns.mean(), weights)
portfolio_std = np.sqrt(np.dot(weights.T, np.dot(returns.cov(), weights)))
return -portfolio_return / portfolio_std
constraints = ({'type': 'eq', 'fun': lambda weights: np.sum(weights) - 1})
stock_bounds = tuple((0, 1) for stock in range(len(stocks)))
solution_sharpe = minimize(negative_sharpe_ratio, [1./len(stocks)]*len(stocks), method='SLSQP', bounds=stock_bounds, constraints=constraints)
weights_sharpe = solution_sharpe.x
returns_sharpe = (returns * weights_sharpe).sum(axis=1)
fama_french = web.DataReader('F-F_Research_Data_5_Factors_2x3_daily', 'famafrench', start=start_date, end=end_date)[0]
fama_french = fama_french.div(100) # Convert to percentage
fama_french.index = pd.to_datetime(fama_french.index, format='%Y%m%d')
merged_data = pd.merge(pd.DataFrame(returns_sharpe, columns=['Max Sharpe Daily']), fama_french, left_index=True, right_index=True, how='inner')
print(merged_data)
!pip install seaborn
import seaborn as sns
import matplotlib.pyplot as plt
correlation_matrix = merged_data.corr()
factors = ['Mkt-RF', 'SMB', 'HML', 'RMW', 'CMA']
for factor in factors:
plt.figure(figsize=(8, 6))
sns.scatterplot(x='Max Sharpe Daily', y=factor, data=merged_data)
plt.title(f'Scatter Plot of Max Sharpe Daily Returns vs. {factor} Returns')
plt.xlabel('Max Sharpe Daily Returns')
plt.ylabel(f'{factor} Returns')
plt.grid(True)
plt.show()
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', vmin=-1, vmax=1)
plt.title('Correlation Heatmap')
plt.show()
!pip install statsmodels
import statsmodels.api as sm
results = {}
for factor in factors:
X = merged_data[factor]
y = merged_data['Max Sharpe Daily'] - merged_data['RF'] # deducting risk-free rate from portfolio returns
X = sm.add_constant(X)
model = sm.OLS(y, X).fit()
coefficient = model.params[factor]
t_value_alpha = model.tvalues['const']
results[factor] = {'Coefficient': coefficient, 'T-Value (Alpha)': t_value_alpha}
results_df = pd.DataFrame(results).T
print(results_df)
alpha_significance = results_df['T-Value (Alpha)'].apply(lambda x: "Significant" if abs(x) > 1.96 else "Not Significant")
print("\nIntercept (Alpha) Significance at 5% level:")
print(alpha_significance)
X = merged_data[factors]
y = merged_data['Max Sharpe Daily'] - merged_data['RF'] # deducting risk-free rate from portfolio returns
X = sm.add_constant(X)
model = sm.OLS(y, X).fit()
coefficients = model.params
t_value_alpha = model.tvalues['const']
print("Portfolio's Sensitivity to Factors:")
print(coefficients)
alpha_significance = "Significant" if abs(t_value_alpha) > 1.96 else "Not Significant"
print("\nIntercept (Alpha) Significance at 5% level:", alpha_significance)