import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import scipy.stats
from sklearn.linear_model import LinearRegression
from scipy.interpolate import UnivariateSpline
from sympy import symbols, solve
# Load data
df = pd.read_csv('StockData.txt', delimiter = ",")
# Convert to one date column
df['Date'] = pd.to_datetime(df[['Year', 'Month', 'Day']])
df = df.drop(columns = ['Year', 'Month', 'Day'])
# Extract sub df with only stock values in USD and EUR
df_stocks_USD = df.iloc[:,:5]
df_stocks_EUR = df_stocks_USD*df['USDEUR'][:,np.newaxis]
# Define portfolio
#alpha = 2000*np.ones(5)
/shared-libs/python3.7/py-core/lib/python3.7/site-packages/ipykernel_launcher.py:10: FutureWarning: Support for multi-dimensional indexing (e.g. `obj[:, None]`) is deprecated and will be removed in a future version. Convert to a numpy array before indexing instead.
# Remove the CWD from sys.path while we load stuff.
alpha = 2000*np.ones(5)
# VaR on the final day
def simple_method(data, alpha, CI = 0.99):
#Percentage change between the current and a prior element.
return_data = data.pct_change()
# Standard deviation of portfolio
portfolio_std = (alpha@return_data.cov(ddof = 0)@alpha.T)**(1/2)
# Quantile of CI
Q = scipy.stats.norm.ppf(CI)
# Calculate
VaR = portfolio_std * Q
return VaR
print(f'VaR = {simple_method(df_stocks_EUR, alpha):.2f}€')
VaR = 252.34€
def fx_method(data_fx, alpha, CI = 0.99):
# Add sum og portfolio
alpha_comb = np.append(alpha,sum(alpha))
#Percentage change between the current and a prior element.
return_data = data_fx.pct_change()
portfolio_std = (alpha_comb@return_data.cov(ddof = 0)@alpha_comb.T)**(1/2)
Q = scipy.stats.norm.ppf(CI)
# Calculate VaR
VaR = portfolio_std * Q
return VaR
print(f"VaR = {fx_method(df[['Stock 1','Stock 2','Stock 3','Stock 4','Stock 5','USDEUR']], alpha):.2f}€")
VaR = 252.19€
def CAPM(data, fx, index, alpha, CI = 0.99):
# Merge the stock dataframe with indicies
comb_df = pd.concat((data,index), axis=1)
# Get covariance matrix
cov_mat = comb_df.pct_change().cov(ddof = 0)
# Get variance of market (index) and exchange rate
r_m = cov_mat.loc['Index','Index']
r_fx = fx.pct_change().var()
# Calculate beta from the formula
beta = np.array([cov_mat.loc[stock,'Index']/r_m for stock in data.columns])
# Exposure is the dotproduct of alpha and beta and the investment in foreign currency (all)
omega = np.append(sum(alpha*beta),sum(alpha))
# Get variance as sum of both risk facots
ret_std = np.sqrt(omega@np.diag(np.append(r_m,r_fx))@omega.T)
# Calculate VaR as ususal
VaR = ret_std * scipy.stats.norm.ppf(CI)
return VaR
print(f"VaR = {CAPM(df[['Stock 1','Stock 2','Stock 3','Stock 4','Stock 5']], df['USDEUR'], df['Index'], alpha, CI = 0.99):.2f}€")
VaR = 229.78€
def Reg_method(df_stock, fx, index, alpha, CI = 0.99):
# Change in fortfolio
PF_change = (df_stocks_EUR.pct_change()@alpha)[1:]
# Get variance of market (index) and exchange rate
r_m = index.pct_change().var()
r_fx = fx.pct_change().var()
# Get regressors
X = np.vstack((index.pct_change(), fx.pct_change())).T[1:]
# Get risk factors from a linear regression
reg = LinearRegression().fit(X, PF_change)
omega = reg.coef_
# Get variance as sum of both risk factors
ret_std = np.sqrt(omega@np.diag(np.append(r_m,r_fx))@omega.T)
# Calculate VaR as ususal
VaR = ret_std * scipy.stats.norm.ppf(CI)
return VaR
print(f"VaR = {Reg_method(df[['Stock 1','Stock 2','Stock 3','Stock 4','Stock 5']], df['USDEUR'], df['Index'], alpha, CI = 0.99):.2f}€")
VaR = 231.08€
df_bond = pd.read_csv('BondPrices.txt', delimiter = ",")
df_yield = pd.read_csv('Yields.txt', delimiter = ",")
Delta_bond = df_bond.pct_change() #return of bond
cov_mat = Delta_bond.cov() #covariance
Vol = Delta_bond.std()
corr_mat = Delta_bond.corr() #correlation
plt.figure(figsize = (12,8))
sns.heatmap(corr_mat, xticklabels=corr_mat.columns, yticklabels=corr_mat.columns)
plt.tight_layout()
plt.show()
plt.figure(figsize = (14,8))
Vol.plot()
plt.show()
def bond_mapping(df_yields, Vols, w, corr, cov, n, N):
# Helper function that can linear interpolate
def interpolate(x,y,z):
return y[0]+((z-x[0]) / (x[1]-x[0]))*(y[1]-y[0])
# Find interpolate exchange rate
Rate1 = interpolate([float(x) for x in df_yields.columns[:2]],df_yields.iloc[-1,:2].values,w[0])
Rate2 = interpolate([float(x) for x in df_yields.columns[2:4]],df_yields.iloc[-1,2:4].values,w[1])
# Value of cash flows
PV1 = n/(1+Rate1)**w[0]
PV2 = (n+N)/(1+Rate2)**w[1]
#Interpolate volatility to yields
Vol1 = interpolate([float(x) for x in df_yields.columns[:2]],Vols[:2].values,w[0])
Vol2 = interpolate([float(x) for x in df_yields.columns[2:4]],Vols[2:4].values,w[1])
#Find alpha to allocate value to different bonds
a_0 = symbols('a_0')
eoq_1 = a_0**2*Vols[0]**2 + (1-a_0)**2*Vols[1]**2+2*corr.loc[str(0.25),str(0.5)]*Vols[0]*Vols[1]*a_0*(1-a_0) - Vol1**2
sol1 = solve(eoq_1)
sol1 = [i for i in sol1 if i<1][0]
a_1 = symbols('a_1')
eoq_2 = a_1**2*Vols[2]**2 + (1-a_1)**2*Vols[3]**2+2*corr.loc[str(0.75),str(1)]*Vols[2]*Vols[3]*a_1*(1-a_1) - Vol2**2
sol2 = solve(eoq_2)
sol2 = [i for i in sol2 if i<1][0]
#Calculate amounts placed in bonds
Amount = [sol1*PV1, (1-sol1)*PV1, sol2*PV2, (1-sol2)*PV2]
#Caluclate std
PF_std = (Amount@cov.iloc[:4,:4]@Amount)**0.5
#Caluclate VaR
VaR = scipy.stats.norm.ppf(0.99)*PF_std
return VaR
print(f"VaR = {bond_mapping(df_yield, Vol, [0.3, 0.8], corr_mat, cov_mat, 50000, 1000000):.2f}€")
VaR = 2555.32€
# 10-day var is calculated in the usual fashion using the fact it scales with the square root
bond_VaR = bond_mapping(df_yield, Vol, [0.3, 0.8], corr_mat, cov_mat, 50000, 1000000)
print(f"VaR = {np.sqrt(10)*bond_VaR:.2f}€")
VaR = 8080.62€