使用 R 计算风险价值和条件风险价值(预期短缺)
Computing Value at Risk and Conditional Value at Risk (Expected Shortfall) with R
我是 R 的新手,对使用投资组合分析包计算 VaR 和 CVaR 有一些疑问。
我在 csv 文件中有历史 return 数据。例如如下:
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) 我想计算这个投资组合的风险价值和条件风险价值,权重相等(后来权重不同)。我想使用历史数据。
(我 不想 想对概率分布做出假设——尤其是不假设高斯分布。)所以,例如对于 VaR,我基本上想找到百分位数。
(II) 我想通过 CVaR 优化权重。 (再次通过历史方法)。
我有以下问题:
如果我使用 VaR 函数并选择 method = c("historical"),它会计算我的历史数据的相应百分位数吗?
在一些在线教程的帮助下,到目前为止,我尝试了(但还没有完全理解)以下内容:
*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)
给我 "VaR 0.5707718".
为了测试这个结果,我选择了 VaR 函数
VaR(testData_return, p = 0.95, method = c("historical"), clean = c("none"), portfolio_method = c("single"))
这个 return 结果是我:
"stock1 stock2 stock3
VaR -0.8836453 -0.9002575 -0.9151286"
因此,我不明白为什么我得到不同的结果,我不明白为什么我在最后一行得到三个结果。
为了进一步测试,我使用了python如下:
我通过将每天的 return 相加并除以 3 来合并 return,得到一个包含一列的 csv 文件。
-0.1636948075
-0.433413786
-0.7346513217
...
然后我计算了这些 return 的第 95 个百分位数(同上)。
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))
结果是 -0.74321324。
所以,我不明白为什么这个结果与我的第一个结果有很大不同 (-0.74 != 0.57)。
此外,我不明白为什么我的第二种方法会为我提供每只股票的 VaR。
下面的示例代码尝试通过使用三个资产的 VaR
计算的简单示例来回答您的问题。由于您的 post 没有提供 returns 的完整时间历史记录,该示例首先使用 quantmod
包从 Yahoo finance 获取三个股票代码的价格数据,然后计算 returns .
代码比较 VaR
由 VaR
函数使用 portfolio_method="single"
和 quantile
函数计算的每只股票。由于存在三只股票,每种方法都给出了 VaR
的三个值,并且每只股票的结果应该一致。
投资组合计算的约束和 objective 与您指定的非常相似。参数列表已扩展为包括 method ="historical
" 以指示 VaR
应直接从累积分布函数而不是从模型计算,以及 portfolio_method="component
" 以指示 VaR
函数应使用输入权重来计算投资组合 VaR
。 optimize.portfolio
具有给定的约束,objective 用于查找最佳投资组合。结果包含在 opt
.
中
最后,VaR
的投资组合是使用 constrained_objective
计算的,对于指定 VaR
的投资组合 ObjSpec_hist
,并与使用 VaR
计算的投资组合进行比较quantile
对于使用优化权重形成的投资组合。这些结果应该一致。
代码如下:
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 计算
要使用 CVaR 而不是 VaR 作为 objective,optimization_method
应更改为 "ROI"
,因为 CVaR 优化可以表述为二次规划问题。与此同时,weight_sum
约束可以替换为设置 weight_sum = 1
的 full_investment
约束。代码现在看起来像:
#
# 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)
我是 R 的新手,对使用投资组合分析包计算 VaR 和 CVaR 有一些疑问。
我在 csv 文件中有历史 return 数据。例如如下:
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) 我想计算这个投资组合的风险价值和条件风险价值,权重相等(后来权重不同)。我想使用历史数据。 (我 不想 想对概率分布做出假设——尤其是不假设高斯分布。)所以,例如对于 VaR,我基本上想找到百分位数。
(II) 我想通过 CVaR 优化权重。 (再次通过历史方法)。
我有以下问题:
如果我使用 VaR 函数并选择 method = c("historical"),它会计算我的历史数据的相应百分位数吗?
在一些在线教程的帮助下,到目前为止,我尝试了(但还没有完全理解)以下内容:
*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)
给我 "VaR 0.5707718".
为了测试这个结果,我选择了 VaR 函数
VaR(testData_return, p = 0.95, method = c("historical"), clean = c("none"), portfolio_method = c("single"))
这个 return 结果是我:
"stock1 stock2 stock3
VaR -0.8836453 -0.9002575 -0.9151286"
因此,我不明白为什么我得到不同的结果,我不明白为什么我在最后一行得到三个结果。
为了进一步测试,我使用了python如下:
我通过将每天的 return 相加并除以 3 来合并 return,得到一个包含一列的 csv 文件。
-0.1636948075
-0.433413786
-0.7346513217
...
然后我计算了这些 return 的第 95 个百分位数(同上)。
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))
结果是 -0.74321324。
所以,我不明白为什么这个结果与我的第一个结果有很大不同 (-0.74 != 0.57)。
此外,我不明白为什么我的第二种方法会为我提供每只股票的 VaR。
下面的示例代码尝试通过使用三个资产的 VaR
计算的简单示例来回答您的问题。由于您的 post 没有提供 returns 的完整时间历史记录,该示例首先使用 quantmod
包从 Yahoo finance 获取三个股票代码的价格数据,然后计算 returns .
代码比较 VaR
由 VaR
函数使用 portfolio_method="single"
和 quantile
函数计算的每只股票。由于存在三只股票,每种方法都给出了 VaR
的三个值,并且每只股票的结果应该一致。
投资组合计算的约束和 objective 与您指定的非常相似。参数列表已扩展为包括 method ="historical
" 以指示 VaR
应直接从累积分布函数而不是从模型计算,以及 portfolio_method="component
" 以指示 VaR
函数应使用输入权重来计算投资组合 VaR
。 optimize.portfolio
具有给定的约束,objective 用于查找最佳投资组合。结果包含在 opt
.
最后,VaR
的投资组合是使用 constrained_objective
计算的,对于指定 VaR
的投资组合 ObjSpec_hist
,并与使用 VaR
计算的投资组合进行比较quantile
对于使用优化权重形成的投资组合。这些结果应该一致。
代码如下:
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 计算
要使用 CVaR 而不是 VaR 作为 objective,optimization_method
应更改为 "ROI"
,因为 CVaR 优化可以表述为二次规划问题。与此同时,weight_sum
约束可以替换为设置 weight_sum = 1
的 full_investment
约束。代码现在看起来像:
#
# 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)