<jupyter_start><jupyter_text>Portfolios Construction  Q1.2.1 visualize the estimated dynamic volatilities from 2016 to 2020<jupyter_code># Compute daily volatility for each stock
daily_volatilty = pd.DataFrame(Volatility, columns=[asset for asset in df_test.columns])
daily_volatilty.index = date_df
# Q1.2.1 Plot daily volatility on one single plot
daily_volatilty.plot.line(figsize=(20,10))<jupyter_output><empty_output><jupyter_text>Q1.2.2 visualize the correlation matrices on 4 January 2016 and 25 March 2020<jupyter_code># Define function to convert covariance matrix to correlation matrix
def cov_to_corr(M):
    Res = np.zeros(M.shape)
    for i in range(0, M.shape[0]):
        for j in range(0, M.shape[1]):
            Res[i][j] = M[i][j]/((M[i][i]*M[j][j])**0.5)
    return Res
# Correlation matrix on 4-Jan-2016
date = '2016-01-04'
V_jan = V_all[date_df[date_df==date].index[0]]
V_jan = cov_to_corr(V_jan)
ax = sns.heatmap(V_jan, linewidth=0.8, xticklabels=df_test.columns, yticklabels=df_test.columns,annot=True)
ax.xaxis.tick_top() # x axis on top
plt.show()
# Correlation matrix on 25-Mar-2020
date = '2020-03-25'
V_mar = V_all[date_df[date_df==date].index[0]]
V_mar = cov_to_corr(V_mar)
ax = sns.heatmap(V_mar, linewidth=0.8, xticklabels=df_test.columns, yticklabels=df_test.columns,annot=True)
ax.xaxis.tick_top() # x axis on top
plt.show()<jupyter_output><empty_output><jupyter_text>Q1.2.3 report and visualize the three portfolio weights<jupyter_code>def Vshrink_calculator(V,CORR,delta):
    
    corr_n=np.shape(CORR)[0]
    aver_cov= (np.sum(CORR)-corr_n)/(corr_n**2-corr_n)
    VCC=V.copy()
    for i in range(corr_n):
        for j in range(corr_n):
            if i!=j:
                VCC[i][j]= (V[i][j]/CORR[i][j])*aver_cov
                
    Vshrink= delta*VCC+(1-delta)*V
    
    return Vshrink

# Define delta
delta = 0.3

# Compute w_static
V_corr = (df_train/100).corr().values
V_cap = (df_train/100).cov().values
# V-shrink
V_shrink = Vshrink_calculator(V_cap, V_corr,delta)
# Compute w_static
w_static = np.linalg.inv(V_shrink) @ np.ones((10,1))
w_static /= np.sum(w_static)
np.round(w_static,2)
# Compute w_dynamic for 2016-01-04
date = '2016-01-04'
V = V_all[date_df[date_df==date].index[0]]
w_dynamic = np.linalg.inv(V) @ np.ones((10,1))
w_dynamic /= np.sum(w_dynamic)
w_dyn=w_dynamic
np.round(w_dyn,2)
# Compute w_dynamic for 2020-03-25
date = '2020-03-25'
V = V_all[date_df[date_df==date].index[0]]
w_dynamic = np.linalg.inv(V) @ np.ones((10,1))
w_dynamic /= np.sum(w_dynamic)
np.round(w_dynamic,2)
C = df_test.columns
x1=w_dynamic.reshape(1,-1)[0]
x2=w_dyn.reshape(1,-1)[0]
x3=w_static.reshape(1,-1)[0]

dfplot = pd.DataFrame(np.c_[x1,x2,x3], columns=['2020-03-25','2016-01-04','w_static'], index=C)
# plt.figure(figsize=(3, 3))
plt.figure(figsize=(30,20))
dfplot.plot.bar()
plt.title('Visualize three portfolio weights')
plt.gcf().set_size_inches(15, 8)
plt.show()<jupyter_output><empty_output><jupyter_text>Q1.2.4 visualize the total portfolio value under the three portfolio strategies<jupyter_code>data2 =df_test/100
data2.head()<jupyter_output><empty_output><jupyter_text>I. Equally Weighted Portfolio<jupyter_code>r_validate=data2.copy()
w_e= np.array([0.1 for i in range(10)])
w_e= np.reshape(w_e,(-1,1))
w_e
position_init=w_e*1000000
df_ew=data2+1
for j in range(10):
        df_ew.iloc[0,j]= position_init[j] * (df_ew.iloc[0, j])
df_ew['Portfolio Value']=np.sum(df_ew.values, axis = 1)
for i in range(1,len(df_ew)):
    position=w_e*df_ew['Portfolio Value'][i-1]
    for j in range(10):
        df_ew.iloc[i,j]= position[j] * (r_validate.iloc[i, j]+1)
        df_ew['Portfolio Value'][i]=np.sum(df_ew.iloc[i,:10])

df_ew.head()
986480.000000-987752.559200<jupyter_output><empty_output><jupyter_text>II. Static GMV<jupyter_code># Compute w_static
w_static = np.linalg.inv(V_shrink) @ np.ones((10,1))
w_static /= np.sum(w_static)
w_static
position_init=w_static*1000000
df_static=data2+1
for j in range(10):
        df_static.iloc[0,j]= position_init[j] * (df_static.iloc[0, j])
df_static['Portfolio Value']=np.sum(df_static.values, axis = 1)
for i in range(1,len(df_static)):
    position=w_static*df_static['Portfolio Value'][i-1]
    for j in range(10):
        df_static.iloc[i,j]= position[j] * (r_validate.iloc[i, j]+1)
        df_static['Portfolio Value'][i]=np.sum(df_static.iloc[i,:10])

df_static.head()<jupyter_output><empty_output><jupyter_text>III. Dynamic GMV<jupyter_code>def weight_GMV(V,n):
    w_G = np.linalg.inv(V) @ np.ones((n,1))
    w_G /= np.sum(w_G)
    np.round(w_G,5)
    return w_G 
w_dynamic=np.zeros_like(r_validate)
for t in range(len(r_validate)):
    w_dynamic[t]=weight_GMV(V_all[t],10).flatten()
        
print(w_dynamic)        
position_init=w_dynamic[0]*1000000
df_dynamic=data2+1
for j in range(10):
        df_dynamic.iloc[0,j]= position_init[j] * (df_dynamic.iloc[0, j])
df_dynamic['Portfolio Value']=np.sum(df_dynamic.values, axis = 1)
for i in range(1,len(df_dynamic)):
    position=w_dynamic[i]*df_dynamic['Portfolio Value'][i-1]
    for j in range(10):
        df_dynamic.iloc[i,j]= position[j] * (r_validate.iloc[i, j]+1)
        df_dynamic['Portfolio Value'][i]=np.sum(df_dynamic.iloc[i,:10])

df_dynamic.head()
# Q1.2.4 Visualize the dynamics of the total portfolio value under the three portfolio strategies
portfolio_value = pd.concat([df_static['Portfolio Value'], df_dynamic['Portfolio Value'], df_ew['Portfolio Value']],axis=1)
portfolio_value.columns=['static_portfolio','dynamic_portfolio','equal_weight_portfolio']
portfolio_value.plot.line(figsize=(20,10))<jupyter_output><empty_output><jupyter_text>Q1.3 Risk Evaluation  I. Equally Weighted Portfolio<jupyter_code>#  VaR and ES for equal weighted portfolio
df_loss=- df_ew['Portfolio Value'] + df_ew['Portfolio Value'].shift(periods=1)
df_loss[0]=1000000-df_ew['Portfolio Value'][0]
df_loss

alpha=0.99

losses = df_loss.sort_values(ascending = False).values

VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
ES = np.mean(losses [losses >= VaR])

print('VaR: ', VaR)
print('ES ', ES)
# Stressed VaR and stressed ES for equal weighted portfolio
stressed_VaR=0
VaR_start=0
stressed_ES=0
ES_start=0
for i in range(1010):
    df_loss_250 = df_loss[i:i+250]
    losses = df_loss_250.sort_values(ascending = False).values
    VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
    ES = np.mean(losses [losses >= VaR])
    
    if VaR>stressed_VaR:
        stressed_VaR=VaR
        VaR_start=i
    if ES>stressed_ES:
        stressed_ES=ES
        ES_start=i
        
print('one-day 99% stressed VaR:',stressed_VaR,'250-day period:',df_loss.index[VaR_start],df_loss.index[VaR_start+249])
print('one-day 99% stressed ES:',stressed_ES,'250-day period:',df_loss.index[ES_start],df_loss.index[ES_start+249])<jupyter_output>one-day 99% stressed VaR: 123287.88130546943 250-day period: 2019-03-20 2020-03-16
one-day 99% stressed ES: 132618.59086014275 250-day period: 2019-03-20 2020-03-16<jupyter_text>II. Static GMV<jupyter_code>#  VaR and ES for Static GMV portfolio
df_loss=- df_static['Portfolio Value'] + df_static['Portfolio Value'].shift(periods=1)
df_loss[0]=1000000-df_static['Portfolio Value'][0]
# df_loss
alpha=0.99

losses = df_loss.sort_values(ascending = False).values

VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
ES = np.mean(losses [losses >= VaR])

print('VaR: ', VaR)
print('ES ', ES)
# Stressed VaR and stressed ES for Static GMV portfolio
stressed_VaR=0
VaR_start=0
stressed_ES=0
ES_start=0
for i in range(1010):
    df_loss_250 = df_loss[i:i+250]
    losses = df_loss_250.sort_values(ascending = False).values
    VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
    ES = np.mean(losses [losses >= VaR])
    if VaR>stressed_VaR:
        stressed_VaR=VaR
        VaR_start=i
    if ES>stressed_ES:
        stressed_ES=ES
        ES_start=i
        
print('Static GMV: one-day 99% stressed VaR:',stressed_VaR,'250-day period:',df_loss.index[VaR_start],df_loss.index[VaR_start+249])
print('Static GMV: one-day 99% stressed ES:',stressed_ES,'250-day period:',df_loss.index[ES_start],df_loss.index[ES_start+249])<jupyter_output>Static GMV: one-day 99% stressed VaR: 100632.12607033807 250-day period: 2019-03-26 2020-03-20
Static GMV: one-day 99% stressed ES: 110281.88921095578 250-day period: 2019-03-26 2020-03-20<jupyter_text>III. Dynamic GMV<jupyter_code>df_loss=- df_dynamic['Portfolio Value'] + df_dynamic['Portfolio Value'].shift(periods=1)
df_loss[0]=1000000-df_dynamic['Portfolio Value'][0]

alpha=0.99

losses = df_loss.sort_values(ascending = False).values

VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
ES = np.mean(losses [losses >= VaR])

print('VaR: ', VaR)
print('ES ', ES)
stressed_VaR=0
VaR_start=0
stressed_ES=0
ES_start=0
for i in range(1010):
    df_loss_250 = df_loss[i:i+250]
    losses = df_loss_250.sort_values(ascending = False).values
    VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
    ES = np.mean(losses [losses >= VaR])
    
    if VaR>stressed_VaR:
        stressed_VaR=VaR
        VaR_start=i
    if ES>stressed_ES:
        stressed_ES=ES
        ES_start=i
        
print('one-day 99% stressed VaR:',stressed_VaR,'250-day period:',df_loss.index[VaR_start],df_loss.index[VaR_start+249])
print('one-day 99% stressed ES:',stressed_ES,'250-day period:',df_loss.index[ES_start],df_loss.index[ES_start+249])<jupyter_output>one-day 99% stressed VaR: 58281.95146253612 250-day period: 2019-06-17 2020-06-11
one-day 99% stressed ES: 78131.73823996757 250-day period: 2019-06-17 2020-06-11<jupyter_text>Q1.4 Further Thoughts Construction of EWMA model - V 1(i, j) = Vˆ (i, j). That is, the initial value is the sample covariance matrix obtained from the pre-2006 data; - Fort≥2,Vt(i,j)=lambda* VL(i,j)+(1-lambda) × r_validate(t−1,i)×r_validate(t−1,j).<jupyter_code>ewma_V_all = []
ewma_V_all.append(V_1)
ewma_Volatility = []
ewma_Volatility.append([V_1[i,i] for i in range(0, 10)])
Lambda = 0.95
V_L = V_1
V_prev = V_1
r_validate_prev = df_test.iloc[0].values[np.newaxis]/100
for k in range(1, df_test.shape[0]):
    V_t = Lambda*V_prev + (1-Lambda)*(r_validate_prev.T @ r_validate_prev)
    ewma_V_all.append(V_t)
    ewma_Volatility.append([V_t[i,i] for i in range(0, df_test.shape[1])])
    V_prev = V_t 
    r_validate_prev = df_test.iloc[k].values[np.newaxis]/100
ewma_w_dynamic=np.zeros_like(r_validate)
for t in range(len(r_validate)):
    ewma_w_dynamic[t]=weight_GMV(ewma_V_all[t],10).flatten()      
position_init=ewma_w_dynamic[0]*1000000
df_ewma=data2+1
for j in range(10):
        df_ewma.iloc[0,j]= position_init[j] * (df_ewma.iloc[0, j])
df_ewma['Portfolio Value']=np.sum(df_ewma.values, axis = 1)
for i in range(1,len(df_ewma)):
    position=ewma_w_dynamic[i]*df_ewma['Portfolio Value'][i-1]
    for j in range(10):
        df_ewma.iloc[i,j]= position[j] * (r_validate.iloc[i, j]+1)
        df_ewma['Portfolio Value'][i]=np.sum(df_ewma.iloc[i,:10])
portfolio_return = pd.concat([df_static['Portfolio Value'], df_dynamic['Portfolio Value'], df_ew['Portfolio Value'],df_ewma['Portfolio Value']],axis=1)
portfolio_return.columns=['static_portfolio','dynamic_portfolio','equal_weight_portfolio','ewma_portfolio']
portfolio_return.plot.line(figsize=(20,10))
df_loss=- df_ewma['Portfolio Value'] + df_ewma['Portfolio Value'].shift(periods=1)
df_loss[0]=1000000-df_ewma['Portfolio Value'][0]

alpha=0.99

losses = df_loss.sort_values(ascending = False).values

VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
ES = np.mean(losses [losses >= VaR])

print('VaR: ', VaR)
print('ES ', ES)
stressed_VaR=0
VaR_start=0
stressed_ES=0
ES_start=0
for i in range(1010):
    df_loss_250 = df_loss[i:i+250]
    losses = df_loss_250.sort_values(ascending = False).values
    VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
    ES = np.mean(losses [losses >= VaR])
    
    if VaR>stressed_VaR:
        stressed_VaR=VaR
        VaR_start=i
    if ES>stressed_ES:
        stressed_ES=ES
        ES_start=i
        
print('one-day 99% stressed VaR:',stressed_VaR,'250-day period:',df_loss.index[VaR_start],df_loss.index[VaR_start+249])
print('one-day 99% stressed ES:',stressed_ES,'250-day period:',df_loss.index[ES_start],df_loss.index[ES_start+249])<jupyter_output>one-day 99% stressed VaR: 75869.39405767038 250-day period: 2019-04-26 2020-04-22
one-day 99% stressed ES: 82179.32018127968 250-day period: 2019-04-26 2020-04-22<jupyter_text>Second Approach - GARCH GMV<jupyter_code>#### Second Approach - GARCH GMVGARCH_w_dynamic=np.zeros_like(r_validate)
for t in range(len(r_validate)):
    GARCH_w_dynamic[t]=weight_GMV(Vall_new[t],10).flatten() def getVall(a,b,c):
    Vall = []
    Vall.append(V_1)
    gamma = a
    alpha = b
    beta =  c
    V_L = V_1
    V_prev = V_1
    r_validate_prev = df_test.iloc[0].values[np.newaxis]/100
    volatility = []
    for k in range(1, df_test.shape[0]):
        V_t = gamma*V_L + alpha*(r_validate_prev.T @ r_validate_prev) + beta * V_prev
        Vall.append(V_t)
        Volatility.append([V_t[i,i] for i in range(0, df_test.shape[1])])
        V_prev = V_t 
        r_validate_prev = df_test.iloc[k].values[np.newaxis]/100
    return Vall
data2 =df_test/100
r_validate=data2.copy()
def weight_GMV(V,n):
    w_G = np.linalg.inv(V) @ np.ones((n,1))
    w_G /= np.sum(w_G)
    np.round(w_G,5)
    return w_G 

Vall_new=getVall(0.05,0.05,0.9)
GARCH_w_dynamic=np.zeros_like(r_validate)
for t in range(len(r_validate)):
    GARCH_w_dynamic[t]=weight_GMV(Vall_new[t],10).flatten() 
df_loss=- df_GARCH['Portfolio Value'] + df_GARCH['Portfolio Value'].shift(periods=1)
df_loss[0]=1000000-df_GARCH['Portfolio Value'][0]

alpha=0.99

losses = df_loss.sort_values(ascending = False).values

VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
ES = np.mean(losses [losses >= VaR])

print('VaR: ', VaR)
print('ES ', ES)
df_loss=- df_GARCH['Portfolio Value'] + df_GARCH['Portfolio Value'].shift(periods=1)
df_loss[0]=1000000-df_GARCH['Portfolio Value'][0]

alpha=0.99

losses = df_loss.sort_values(ascending = False).values

VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
ES = np.mean(losses [losses >= VaR])

print('VaR: ', VaR)
print('ES ', ES)stressed_VaR=0
VaR_start=0
stressed_ES=0
ES_start=0
for i in range(1010):
    df_loss_250 = df_loss[i:i+250]
    losses = df_loss_250.sort_values(ascending = False).values
    VaR  = np.percentile(losses, alpha * 100, interpolation = 'higher') 
    ES = np.mean(losses [losses >= VaR])
    
    if VaR>stressed_VaR:
        stressed_VaR=VaR
        VaR_start=i
    if ES>stressed_ES:
        stressed_ES=ES
        ES_start=i
        
print('one-day 99% stressed VaR:',stressed_VaR,'250-day period:',df_loss.index[VaR_start],df_loss.index[VaR_start+249])
print('one-day 99% stressed ES:',stressed_ES,'250-day period:',df_loss.index[ES_start],df_loss.index[ES_start+249])<jupyter_output>one-day 99% stressed VaR: 59424.14065993251 250-day period: 2019-06-17 2020-06-11
one-day 99% stressed ES: 76664.44501475834 250-day period: 2019-06-17 2020-06-11
{'fraction_non_alphanumeric': 0.15083983600052903, 'fraction_numerical': 0.06850945642110833, 'mean_word_length': 5.003572846367606, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 65, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '12', 'dir': 'jupyter-structured-clean-dedup', 'id': '564656', 'license': 'MIT', 'n_tokens_mistral': 6933, 'n_tokens_neox': 6171, 'n_words': 1061, 'path': 'Project 2/GP2_G10.ipynb', 'repo_name': 'nusstu-dz/DBA5109-Quantitative-Risk-Management', 'size': '15122'}