<jupyter_start><jupyter_text>Question 1  1.1 False, mean varience optimization will balance the assets based on their covariance to each other, not based on their Sharpe Ratio  1.2 False, investing in a leveraged ETF long-term will not produce the same results as investing in the multiple of the amount. This is due to the fact that the tracking error in the ETF daily can compound over time which results in a massive difference.  1.3 I would suggest not including an intercept. With an intercept, you are trying to replicate trend and variance. Without, there is no trend. Since the data is only a year long, there shoudln't be need to replicate the trend as well  1.4 HDG is tracking the MLFM-ES model, which does track the HFRI fairly well overall. So HDG is pretty effective in tracking HFRI in-sample and out-of-sample.  1.5 There are many hedge funds out there. It is entirely possible that the merrill-lynch factor model does not capture what the overperforming hedge fund is invested in. This would result in a bad approximation of trying to replicate the hedge fund returns, leading to a bad alpha.  Question 2<jupyter_code>df = pd.read_excel("proshares_analysis_data.xlsx", sheet_name="merrill_factors").set_index("date")
df
risk_free = df["USGG3M Index"]
df_excess = df.drop(columns = ["USGG3M Index"])
for x in df_excess.columns:
    df_excess[x] -= risk_free
df_excess<jupyter_output><empty_output><jupyter_text>2.1<jupyter_code>def calculate_mv_frontier(df,diagonalized=False):
    mu = df.mean() * 12
    sigma = df.cov()
    if diagonalized:
        sigma.loc[:,:] = np.diag(np.diag(sigma))
    sigma_inv = np.linalg.inv(sigma)
    weights = sigma_inv @ mu / (np.ones(sigma.shape[0]) @ sigma_inv @ mu)
    return weights, mu, sigma
def display_weights(weights,columns):
    print(pd.DataFrame(weights,index = columns,columns=['position']).sort_values(by=['position']))
weights, mu, sigma = calculate_mv_frontier(df_excess)
display_weights(weights, df_excess.columns)<jupyter_output>position
EFA US Equity -0.754759
IWM US Equity -0.448540
EEM US Equity -0.152124
EUO US Equity  0.181807
SPY US Equity  2.173616<jupyter_text>2.2<jupyter_code>def calculate_portfolio_weights_w_target(df,target,diagonalized = False):
    weights, mu, sigma = calculate_mv_froniter(df, diagonalized)
    if diagonalized:
        sigma.loc[:,:] = np.diag(np.diag(sigma))
    sigma_inv =  np.linalg.inv(sigma)
    delta = ((np.ones(sigma.shape[0]) @ sigma_inv @ mu) / (mu @ sigma_inv @ mu )) * target
    weights_t = delta * weights
    return weights_t, mu, sigma
weights, mu, sigma = calculate_portfolio_weights_w_target(df_excess, 0.02*12)
display_weights(weights, df_excess.columns)<jupyter_output>position
EFA US Equity -0.873680
IWM US Equity -0.519212
EEM US Equity -0.176092
EUO US Equity  0.210452
SPY US Equity  2.516093<jupyter_text>2.3<jupyter_code>def calculate_performance(weights, mu, sigma):
    mean = mu @ weights 
    vol = np.sqrt(weights @ sigma @ weights) * np.sqrt(12)
    sharpe_ratio = mean / vol
    return pd.DataFrame({"mean":[mean],"volatility":[vol] ,"sharpe":[sharpe_ratio]})
calculate_performance(weights, mu, sigma)<jupyter_output><empty_output><jupyter_text>2.4<jupyter_code>df_excess_2018 = df_excess[:"2018"]
weights, mu, sigma = calculate_portfolio_weights_w_target(df_excess_2018, 0.02*12)
df_excess_2019 = df_excess["2019":]
mu_2019 = df_excess_2019.mean()*12
sigma_2019 = df_excess_2019.cov()
calculate_performance(weights, mu_2019, sigma_2019)<jupyter_output><empty_output><jupyter_text>2.5 By using these less risky commodities, the oos fragility problem should be reduced. As these assets are viewed as less risky, there will be less variance involved, so the oos should be better.  Question 3<jupyter_code>y = df_excess["EEM US Equity"]
x = df_excess["SPY US Equity"]

no_intercept_EEM = sm.OLS(y, x, missing="drop").fit()
print(no_intercept_EEM.summary())<jupyter_output>OLS Regression Results                                
=======================================================================================
Dep. Variable:          EEM US Equity   R-squared (uncentered):                   0.509
Model:                            OLS   Adj. R-squared (uncentered):              0.505
Method:                 Least Squares   F-statistic:                              125.5
Date:                Mon, 18 Oct 2021   Prob (F-statistic):                    2.00e-20
Time:                        19:27:44   Log-Likelihood:                          229.11
No. Observations:                 122   AIC:                                     -456.2
Df Residuals:                     121   BIC:                                     -453.4
Df Model:                           1                                                  
Covariance Type:            nonrobust                                                  
================================[...]<jupyter_text>3.1<jupyter_code>beta = no_intercept_EEM.params[0]
print("Optimal hedge ratio is just the beta, " + str(round(beta, 4)))<jupyter_output>Optimal hedge ratio is just the beta, 0.9257<jupyter_text>3.2<jupyter_code>hedge_spy = df_excess["SPY US Equity"]*beta
hedge_mean = hedge_spy.mean()*12
hedge_vol = hedge_spy.std()*np.sqrt(12)
hedge_sharpe = hedge_mean/hedge_vol
table3_2 = pd.DataFrame({"Mean": hedge_mean, "Vol": hedge_vol, "Sharpe": hedge_sharpe}, ["Hedge"])
table3_2<jupyter_output><empty_output><jupyter_text>3.3<jupyter_code>mean = df_excess["EEM US Equity"].mean() * 12
mean<jupyter_output><empty_output><jupyter_text>No they do not have the same mean. Hedge is supposed to reduce the variance of the position.   3.4<jupyter_code>df_excess.corr()<jupyter_output><empty_output><jupyter_text>As we can see, SPY and IWM are highly correlated, this will not help in hedging out the position if we already have SPY used as a hedge  Question 4  4.1<jupyter_code>def p(h, tilde_mu, tilde_sigma):
    x = -np.sqrt(h) * tilde_mu / tilde_sigma
    val =  scipy.stats.norm.cdf(x)
    return val

spy = df["SPY US Equity"]
efa = df["EFA US Equity"]

spy_mu_log = np.log(spy+1).mean()*12
efa_mu_log = np.log(efa+1).mean()*12
tilde_sigma = np.log(spy+1).std()*np.sqrt(12)
tilde_mu = efa_mu_log - spy_mu_log
prob = p(10, tilde_mu, tilde_sigma)
print("Probaility that spy will continue to outperform is " + str(round(prob, 4)))<jupyter_output>Probaility that spy will continue to outperform is 0.9711<jupyter_text>4.2<jupyter_code>rolling_vol = efa.rolling(60).std()*np.sqrt(12)
rolling_vol
var = rolling_vol[-1] * -2.33
print("VaR is " + str(round(var, 4)))<jupyter_output>VaR is -0.3365
{'fraction_non_alphanumeric': 0.11948920644572819, 'fraction_numerical': 0.040589844937671024, 'mean_word_length': 3.629838142153413, 'pattern_counts': {'":': 7, '<': 43, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '462891', 'license': 'MIT', 'n_tokens_mistral': 2425, 'n_tokens_neox': 2200, 'n_words': 593, 'path': 'solutions/mid1/submissions/tonggabriel_169514_6241657_Midterm_1_soln.ipynb', 'repo_name': 'tulyu96/finm-portfolio-2021', 'size': '6578'}