I am new to R and have some questions with regard to computing VaR and CVaR with the Portfolio Analytics package.
I have historical return data in a csv file. For example as follows:
time return of stock1 return of stock2 return of stock3
2016-01-01 -0.6184181087 -0.126394629 0.2537283152
2016-01-02 -0.1738764113 -0.8100882955 -0.3162766513
2016-01-03 -0.8229430174 -0.5007778048 -0.880233143
... ... ... ...
(I) I want to compute the value at risk and conditional value at risk of this portfolio with equal weights (and later with different weights). I want to use the historical data. (I do not want to make an assumption about the probability distribution-especially not asssume a Gaussian distribution.) So e.g. for the VaR I basically want to find the percentile.
(II) I want to optimize the weights by optimizing with the CVaR. ( again by the historical method).
I have following questions:
If I use the VaR function and choose method = c("historical"), does it compute the respective percentile of my historical data?
With the help of some online tutorials, I have tried (but not completely understood) the following so far:
*Loading data into file*
testData_return <- Return.read(filename = "myTest.csv", frequency = "d",format = "%Y-%m-%d", header = TRUE)
*Create the portfolio specification object*
Wcons <- portfolio.spec(assets = colnames(testData_return))
* Add box constraints *
Wcons <- add.constraint(portfolio = Wcons, type='box', min=0, max=1)
Wcons <- add.constraint( portfolio=Wcons, type = "weight_sum", min_sum=0.99, max_sum=1.01) * why can't I put min_sum=1, max_sum=1 ? *
* Add an objective *
ObjSpec = add.objective(portfolio = Wcons, type = "risk", name = "VaR", arguments=list(p=0.95), enabled=TRUE)
* value of the objective function *
constrained_objective(w=rep(1/3,3), R=testData_return,portfolio = ObjSpec)
gives me "VaR 0.5707718".
To test this result I chose the VaR function
VaR(testData_return, p = 0.95, method = c("historical"), clean = c("none"), portfolio_method = c("single"))
this returns me as a results:
"stock1 stock2 stock3
VaR -0.8836453 -0.9002575 -0.9151286"
Hence, I do not understand why I get different results and I cannot understand why I get three results for the last line.
In order to test further, I used python as follows:
I merged the returns by adding up the returns for each day and dividing by 3, yielding a csvfile with one column.
-0.1636948075
-0.433413786
-0.7346513217
...
Then I have computed the 95th percentile (same as above) of these returns.
percentile = 0.95
* fname is the name of my file with the one column of data *
returns_values = np.loadtxt(fname, skiprows=0, usecols=[0], unpack=True)
print(np.percentile(returns_values, percentile))
This gives me -0.74321324 as a result.
So, I do not understand why this result is substantially different to my first results (-0.74 != 0.57 ).
Also, I do not understand why my second approach gives me a VaR for each individual stock.
The example code below tries to answer your questions by working through a simple example of VaR
calculations using three assets. Since your post didn't supply a complete time history of returns, the example first gets price data for three stock tickers from Yahoo finance using the quantmod
package then computes returns.
The code compares VaR
for each stock calculated by the VaR
function using portfolio_method="single"
and by the quantile
function. Since there are three stocks, each method gives three values for VaR
and the results should agree for each stock.
The constraints and objective for the portfolio calculation are specified very much as you had them. The arguments list has been expanded to include method ="historical
" to indicate that VaR
should be calculated from a cumulative distribution function directly rather than from a model and portfolio_method="component
" to indicate that the VaR
function should use input weights to calculate a portfolio VaR
. optimize.portfolio
with the given constraints and objective is used to find the optimum portfolio. The results are contained in opt
.
Finally, VaR
for the portfolio is calculated using constrained_objective
for the portfolio ObjSpec_hist
which specifies VaR
and compared with the portfolio VaR
calculated using quantile
for the portfolio formed with the optimized weights. These results should agree.
Code follows:
library(xts)
library(quantmod)
library(PerformanceAnalytics)
library(PortfolioAnalytics)
tickers <- c("AAPL", "MSFT", "AMZN")
start_date <- "2016-01-01"
percentile <- .95 # confidence level used in VaR calculations
#
# get Adjusted Close prices from Yahoo Finance
#
prices <- xts()
for( tick in tickers) {
prices <- merge(prices, getSymbols(Symbols=tick, from=start_date,
auto.assign=FALSE)[,paste(tick,"Adjusted",sep=".")])
}
colnames(prices) <- tickers
#
# transform index from POSIXct to Date class
#
index(prices) <- as.Date(index(prices))
#
# compute returns
#
testData_return <- diff(prices, arithmetic=FALSE, na.pad=FALSE) - 1
#
# Compare VaR with quantile calculations for assets
# when portfolio_method = "single" in VaR, the VaR for each column in R is calculated
#
VaR_asset_hist <- VaR(R = testData_return, p=percentile, method="historical",
portfolio_method = "single")
print(VaR_asset_hist)
quant_asset_hist <- sapply(testData_return, quantile, probs=1-percentile, type=7)
print(quant_asset_hist)
#
# Create the portfolio specification object
#
Wcons <- portfolio.spec(assets = colnames(testData_return))
#
# Add long_only and weight_sum = 1 constraints
#
Wcons <- add.constraint(portfolio = Wcons, type='box', min=0, max=1)
Wcons <- add.constraint( portfolio=Wcons, type = "weight_sum",
min_sum=0.99, max_sum=1.01)
#
# Set the objective to minimize VaR using historical returns
# portfolio_method ="component" tells VaR to use values of weights argument and calculate VaR for the portfolio
#
ObjSpec_hist = add.objective(portfolio = Wcons, type = "risk",
name = "VaR",
arguments=list(p=percentile, method="historical",
portfolio_method="component"),
enabled=TRUE)
opt <- optimize.portfolio(R =testData_return, portfolio=ObjSpec_hist,
search_size = 2000, trace = TRUE)
print(opt)
#
# compare VaR calculated using the optimization results with the quantile case.
# the VaR function calculates VaR slightly differently for historical data depending upon whether the
# portfolio_method = "single" or "component". The values for the quantile arguments probs and type used below should
# give the same results for both the constrained_objective and quantile functions
#
VaR_port_opt <-constrained_objective(w=weights(opt),
R=testData_return,portfolio = ObjSpec_hist)
quant_probs <- floor((1-percentile)*nrow(testData_return))/nrow(testData_return)
quant_port_opt <- quantile( testData_return%*%weights(opt),
probs = quant_probs, type=1)
cat(paste("VaR using opt weights =", VaR_port_opt,
"\nquantile calculation using opt weights =", quant_port_opt))
CVaR calculation
To use to CVaR rather than VaR as the objective, the optimization_method
should be changed to "ROI"
since CVaR optimization can be formulated as a quadratic programming problem. Along with this, the weight_sum
constraint can be replaced with a full_investment
constraint which set weight_sum = 1
. The code now looks like:
#
# Create the portfolio specification object
#
Wcons <- portfolio.spec(assets = colnames(testData_return))
#
# Add long_only and full investment (weight_sum = 1) constraints
#
Wcons <- add.constraint(portfolio = Wcons, type='box', min=0, max=1)
Wcons <- add.constraint(portfolio=Wcons, type = "full_investment")
#
# Set the objective to minimize CVaR using historical returns
# portfolio_method ="component" tells VaR to use values of weights argument and calculate CVaR for the portfolio
#
ObjSpec_hist = add.objective(portfolio = Wcons, type = "risk",
name = "CVaR",
arguments=list(p=percentile, method="historical",
portfolio_method="component"),
enabled=TRUE)
opt <- optimize.portfolio(R = testData_return, portfolio = ObjSpec_hist,
optimize_method="ROI")
print(opt)