Skip to contents

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, where X has distribution specified by dist, see Details.

tol

tollerance

x

deprecated and will soon be removed. x was renamed to p_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\).

See also

ES for ES,

predict for examples with fitted models

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