VaR
computes the Value-at-Risk of the distribution specified by the
arguments. The meaning of the parameters is the same as in ES
, including
the recycling rules.
Usage
VaR(dist, p_loss = 0.05, ...)
VaR_qf(
dist,
p_loss = 0.05,
...,
intercept = 0,
slope = 1,
tol = .Machine$double.eps^0.5,
x
)
VaR_cdf(
dist,
p_loss = 0.05,
...,
intercept = 0,
slope = 1,
tol = .Machine$double.eps^0.5,
x
)
# S3 method for default
VaR(
dist,
p_loss = 0.05,
dist.type = "qf",
...,
intercept = 0,
slope = 1,
tol = .Machine$double.eps^0.5,
x
)
# S3 method for numeric
VaR(dist, p_loss = 0.05, ..., intercept = 0, slope = 1, x)
Arguments
- dist
specifies the distribution whose ES is computed, usually a function or a name of a function computing quantiles, cdf, pdf, or a random number generator, see Details.
- p_loss
level, default is 0.05.
- ...
passed on to
dist
.- intercept, slope
compute VaR for the linear transformation
intercept + slope*X
, whereX
has distribution specified bydist
, see Details.- tol
tollerance
- x
deprecated and will soon be removed.
x
was renamed top_loss
, please use the latter.- dist.type
a character string specifying what is computed by
dist
, such as "qf" or "cdf".
Details
VaR
is S3 generic. The meaning of the parameters for its default method is the
same as in ES
, including the recycling rules.
VaR_qf
and VaR_cdf
are streamlined, non-generic, variants for the common
case when the "..."
parameters are scalar. The parameters x
,
intercept
, and slope
can be vectors, as for VaR
.
Argument dist
can also be a numeric vector. In that case the ES is computed,
effectively, for the empirical cumulative distribution function (ecdf) of the
vector. The ecdf is not created explicitly and the quantile
function is used instead for the computation of VaR. Arguments in "..."
are
passed eventually to quantile()
and can be used, for example, to select a
non-defult method for the computation of quantiles.
In practice, we may need to compute VaR associated with data. The distribution comes from fitting a model. In the simplest case, we fit a distribution to the data, assuming that the sample is i.i.d. For example, a normal distribution \(N(\mu, \sigma^2)\) can be fitted using the sample mean and sample variance as estimates of the unknown parameters \(\mu\) and \(\sigma^2\), see section ‘Examples’. For other common distributions there are specialised functions to fit their parameters and if not, general optimisation routines can be used. More soffisticated models may be used, even time series models such as GARCH and mixture autoregressive models.
Note
We use the traditional definition of VaR as the negated lower quantile. For example, if \(X\) are returns on an asset, VAR\({}_\alpha\) = \(-q_\alpha\), where \(q_\alpha\) is the lower \(\alpha\) quantile of \(X\). Equivalently, VAR\({}_\alpha\) is equal to the lower \(1-\alpha\) quantile of \(-X\).
Examples
cvar::VaR(qnorm, c(0.01, 0.05), dist.type = "qf")
#> [1] 2.326348 1.644854
## the following examples use these values, obtained by fitting a normal distribution to
## some data:
muA <- 0.006408553
sigma2A <- 0.0004018977
## with quantile function, giving the parameters directly in the call:
res1 <- cvar::VaR(qnorm, 0.05, mean = muA, sd = sqrt(sigma2A))
res2 <- cvar::VaR(qnorm, 0.05, intercept = muA, slope = sqrt(sigma2A))
abs((res2 - res1)) # 0, intercept/slope equivalent to mean/sd
#> [1] 0
## with quantile function, which already knows the parameters:
my_qnorm <- function(p) qnorm(p, mean = muA, sd = sqrt(sigma2A))
res1_alt <- cvar::VaR(my_qnorm, 0.05)
abs((res1_alt - res1))
#> [1] 0
## with cdf the precision depends on solving an equation
res1a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", mean = muA, sd = sqrt(sigma2A))
res2a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", intercept = muA, slope = sqrt(sigma2A))
abs((res1a - res2)) # 3.287939e-09
#> [1] 3.287939e-09
abs((res2a - res2)) # 5.331195e-11, intercept/slope better numerically
#> [1] 5.331195e-11
## as above, but increase the precision, this is probably excessive
res1b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf",
mean = muA, sd = sqrt(sigma2A), tol = .Machine$double.eps^0.75)
res2b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf",
intercept = muA, slope = sqrt(sigma2A), tol = .Machine$double.eps^0.75)
abs((res1b - res2)) # 6.938894e-18 # both within machine precision
#> [1] 6.938894e-18
abs((res2b - res2)) # 1.040834e-16
#> [1] 1.040834e-16
## relative precision is also good
abs((res1b - res2)/res2) # 2.6119e-16 # both within machine precision
#> [1] 2.6119e-16
abs((res2b - res2)/res2) # 3.91785e-15
#> [1] 3.91785e-15
## an extended example with vector args, if "PerformanceAnalytics" is present
if (requireNamespace("PerformanceAnalytics", quietly = TRUE)) withAutoprint({
data(edhec, package = "PerformanceAnalytics")
mu <- apply(edhec, 2, mean)
sigma2 <- apply(edhec, 2, var)
musigma2 <- cbind(mu, sigma2)
## compute in 2 ways with cvar::VaR
vAz1 <- cvar::VaR(qnorm, 0.05, mean = mu, sd = sqrt(sigma2))
vAz2 <- cvar::VaR(qnorm, 0.05, intercept = mu, slope = sqrt(sigma2))
vAz1a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf",
mean = mu, sd = sqrt(sigma2))
vAz2a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf",
intercept = mu, slope = sqrt(sigma2))
vAz1b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf",
mean = mu, sd = sqrt(sigma2),
tol = .Machine$double.eps^0.75)
vAz2b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf",
intercept = mu, slope = sqrt(sigma2),
tol = .Machine$double.eps^0.75)
## analogous calc. with PerformanceAnalytics::VaR
vPA <- apply(musigma2, 1, function(x)
PerformanceAnalytics::VaR(p = .95, method = "gaussian", invert = FALSE,
mu = x[1], sigma = x[2], weights = 1))
## the results are numerically the same
max(abs((vPA - vAz1))) # 5.551115e-17
max(abs((vPA - vAz2))) # ""
max(abs((vPA - vAz1a))) # 3.287941e-09
max(abs((vPA - vAz2a))) # 1.465251e-10, intercept/slope better
max(abs((vPA - vAz1b))) # 4.374869e-13
max(abs((vPA - vAz2b))) # 3.330669e-16
})
#> > data(edhec, package = "PerformanceAnalytics")
#> > mu <- apply(edhec, 2, mean)
#> > sigma2 <- apply(edhec, 2, var)
#> > musigma2 <- cbind(mu, sigma2)
#> > vAz1 <- cvar::VaR(qnorm, 0.05, mean = mu, sd = sqrt(sigma2))
#> > vAz2 <- cvar::VaR(qnorm, 0.05, intercept = mu, slope = sqrt(sigma2))
#> > vAz1a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2))
#> > vAz2a <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2))
#> > vAz1b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", mean = mu, sd = sqrt(sigma2),
#> + tol = .Machine$double.eps^0.75)
#> > vAz2b <- cvar::VaR(pnorm, 0.05, dist.type = "cdf", intercept = mu, slope = sqrt(sigma2),
#> + tol = .Machine$double.eps^0.75)
#> > vPA <- apply(musigma2, 1, function(x) PerformanceAnalytics::VaR(p = 0.95,
#> + method = "gaussian", invert = FALSE, mu = x[1], sigma = x[2], weights = 1))
#> > max(abs((vPA - vAz1)))
#> [1] 4.163336e-17
#> > max(abs((vPA - vAz2)))
#> [1] 4.163336e-17
#> > max(abs((vPA - vAz1a)))
#> [1] 1.953409e-09
#> > max(abs((vPA - vAz2a)))
#> [1] 1.242979e-10
#> > max(abs((vPA - vAz1b)))
#> [1] 4.831205e-14
#> > max(abs((vPA - vAz2b)))
#> [1] 2.914335e-16