In
a previous blogpost (Marginal and Component Value-at-Risk: A Python Example http://elenamarinova.blogspot.com/2015/05/marginal-and-component-value-at-risk.html) the Python way for calculating marginal, component and
portfolio VaR was introduced. However, it left the portfolio management task a
little bit incomplete as the important stage of extracting the risk-minimizing
weights of the shares in the portfolio was missing.
Here
is again an example of calculating VaR of a simple model portfolio with added a
code for extracting weights that minimize the portfolio VaR. A change in the
codes introduced in the previous post was made (we worked with annualized numbers in the previous post) to be more precise in the VaR we
want, namely 99% confidence interval, 1-day VaR. (Implemented on Python 3.4)
import
pandas as pd
import
numpy as np
import
pandas.io.data as web
import
scipy.optimize as scopt
from
scipy.stats import norm
Value=1e5
# $100,000
CI=0.99
# set the
confidence interval
tickers
=['AAPL', 'MSFT', 'YHOO']
numbers=len(tickers)
data=pd.DataFrame()
for
share in tickers:
data[share]=web.DataReader(share,
data_source='yahoo', start='2011-01-01', end='2015-06-08')['Adj Close']
data.columns=tickers
ret=data/data.shift(1)-1 # calculate
the simple returns
covariances=ret.cov()
#gives the
covariance of returns
variances=np.diag(covariances)
#extracts
variances of the individual shares from covariance matrix
volatility=np.sqrt(variances) #gives standard
deviation
weights =
np.ones(data.columns.size)/data.columns.size
weights
Out: array([
0.33333333, 0.33333333, 0.33333333])
Pf_variance=np.dot(weights.T,np.dot(ret.cov(),weights))
#Portfolio
variance
Pf_volatility=np.sqrt(Pf_variance)
#Portfolio
standard deviation
USDvariance=np.square(Value)*Pf_variance
USDvolatility=np.sqrt(USDvariance)
covariance_asset_portfolio=np.dot(weights.T,covariances)
covUSD=np.multiply(covariance_asset_portfolio,Value)
beta=np.divide(covariance_asset_portfolio,Pf_variance)
def VaR():
# this code calculates Portfolio
Value-at-risk (Pf_VaR) in USD-terms and Individual Value-at-risk
(IndividualVaR) of shares in portfolio.
Pf_VaR=norm.ppf(CI)*USDvolatility
IndividualVaR=np.multiply(volatility,Value*weights)*norm.ppf(CI)
IndividualVaR = [ '$%.2f' % elem for elem
in IndividualVaR ]
print ('Portfolio VaR: ', '$%0.2f' %Pf_VaR)
print ('Individual VaR: ',[[tickers[i],
IndividualVaR[i]] for i in range (min(len(tickers), len(IndividualVaR)))])
VaR() # call the
function
Out: Portfolio
VaR: $2830.87
Individual
VaR: [['AAPL', '$1289.91'], ['MSFT',
'$1123.15'], ['YHOO', '$1493.15']]
def
marginal_component_VaR():
# this code calculates Marginal
Value-at-risk in USD-terms and Component Value-at-risk of shares in portfolio.
marginalVaR=np.divide(covUSD,USDvolatility)*norm.ppf(CI)
componentVaR=np.multiply(weights,beta)*USDvolatility*norm.ppf(CI)
marginalVaR = [ '%.3f' % elem for elem in
marginalVaR ]
componentVaR=[ '$%.2f' % elem for elem in
componentVaR ]
print ('Marginal VaR:', [[tickers[i],
marginalVaR[i]] for i in range (min(len(tickers), len(marginalVaR)))])
print ('Component VaR: ', [[tickers[i],
componentVaR[i]] for i in range (min(len(tickers), len(componentVaR)))])
marginal_component_VaR()# call the
function
Out: Marginal VaR: [['AAPL', '0.027'], ['MSFT',
'0.023'], ['YHOO', '0.034']]
Component VaR:
[['AAPL', '$908.03'], ['MSFT', '$783.18'], ['YHOO', '$1139.65']]
# Risk-minimizing approach;
first, we set the objective function and then we minimize it by changing
weights
def VaR(weights):
return
norm.ppf(CI)*np.sqrt(np.square(Value)*(np.dot(weights.T,np.dot(ret.cov(),weights))))
def minVaR(VaR):
nstocks = data.columns.size
bounds = [(0.,1.) for i in np.arange(nstocks)] #non-negative weights
constraints = ({'type': 'eq',
'fun': lambda weights: np.sum(weights) - 1}) #sum of weights to equal 100%
results = scopt.minimize(VaR, weights,
method='SLSQP',
constraints = constraints,
bounds = bounds)
result_weights=np.round(results.x, 4)
result_weights= [ '%.8f' % elem for elem in result_weights ]
new_VaR=VaR(results['x'])
print ('Optimal VaR: ', new_VaR)
print ('Optimal Weights: ', [[tickers[i], result_weights[i]] for i in range (len(tickers))])
nstocks = data.columns.size
bounds = [(0.,1.) for i in np.arange(nstocks)] #non-negative weights
constraints = ({'type': 'eq',
'fun': lambda weights: np.sum(weights) - 1}) #sum of weights to equal 100%
results = scopt.minimize(VaR, weights,
method='SLSQP',
constraints = constraints,
bounds = bounds)
result_weights=np.round(results.x, 4)
result_weights= [ '%.8f' % elem for elem in result_weights ]
new_VaR=VaR(results['x'])
print ('Optimal VaR: ', new_VaR)
print ('Optimal Weights: ', [[tickers[i], result_weights[i]] for i in range (len(tickers))])
minVaR(VaR) # call the function
Out: Optimal VaR: 2756.04924565
Optimal Weights: [['AAPL', '0.328'], ['MSFT', '0.475'],
['YHOO', '0.197']]
No comments:
Post a Comment