diff options
| author | Guillaume Horel <guillaume.horel@gmail.com> | 2017-12-18 13:10:26 -0500 |
|---|---|---|
| committer | Guillaume Horel <guillaume.horel@gmail.com> | 2017-12-18 13:10:26 -0500 |
| commit | 72549cc50059c32291a33c8933ee4a767438df61 (patch) | |
| tree | 6dbb14f231d461625bee9e6c873f6a280fe29960 | |
| parent | f76f4068da836f1e7baee1fc5965354b8666096f (diff) | |
| download | lossdistrib-72549cc50059c32291a33c8933ee4a767438df61.tar.gz | |
use Roxygen more
| -rw-r--r-- | DESCRIPTION | 4 | ||||
| -rw-r--r-- | NAMESPACE | 36 | ||||
| -rw-r--r-- | R/distrib.R | 63 |
3 files changed, 84 insertions, 19 deletions
diff --git a/DESCRIPTION b/DESCRIPTION index c19cdcd..f4eb62a 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -6,6 +6,8 @@ Date: 2014-10-03 Author: Guillaume Horel Maintainer: Guillaume Horel <guillaume.horel@serenitascapital.com> Description: Utility functions for generating the loss and recovery - distributions of a portfolio of obligations + distributions of a portfolio of obligations. License: GPL-3 Suggests: testthat +RoxygenNote: 6.0.1 +Imports: distr @@ -1,2 +1,34 @@ -exportPattern("^[[:alpha:]]+") -useDynLib("lossdistrib", .registration=TRUE, .fixes = "C_") +# Generated by roxygen2: do not edit by hand + +export(BCER) +export(BClossdist) +export(BClossdistC) +export(GHquad) +export(dist.transform) +export(dqnorm) +export(dshockprob) +export(exp_trunc) +export(fit.prob) +export(fit.probC) +export(lossdist.joint) +export(lossdist.prepay.joint) +export(lossdistC) +export(lossdistC.prepay.joint) +export(lossdistC.prepay.jointZ) +export(lossdistC.truncated) +export(lossdistCZ) +export(lossdistrib) +export(lossdistrib.fft) +export(lossdistrib2) +export(lossdistrib2.truncated) +export(lossrecovdist) +export(lossrecovdist.joint.term) +export(lossrecovdist.term) +export(rec.trunc) +export(recovdist) +export(recovdistC) +export(shockprob) +export(shockseverity) +export(stochasticrecov) +export(stochasticrecovC) +useDynLib(lossdistrib, .registration=TRUE, .fixes = "C_") diff --git a/R/distrib.R b/R/distrib.R index 59fba37..ae5e51f 100644 --- a/R/distrib.R +++ b/R/distrib.R @@ -9,7 +9,8 @@ ## recovery with 0.1-1 support, so it's not clear that there is a big gain. ## - do the correlation adjustments when computing the deltas since it seems to be ## the market standard - +#' @useDynLib lossdistrib, .registration=TRUE, .fixes = "C_" +NULL #' Gauss-Hermite quadrature weights #' #' \code{GHquad} computes the quadrature weights for integrating against a @@ -21,8 +22,8 @@ #' @return A list with two components: #' \item{Z}{the list of nodes} #' \item{w}{the corresponding weights} -#' -GHquad <- function(n){ +#' @export +GHquad <- function(n) { n <- as.integer(n) Z <- double(n) w <- double(n) @@ -42,6 +43,7 @@ GHquad <- function(n){ #' algorithm of Andersen, Sidenius and Basu #' @param p Numeric vector, the vector of success probabilities #' @return A vector q such that \eqn{q_k=\Pr(S=k)} +#' @export lossdistrib <- function(p){ ## basic recursive algorithm of Andersen, Sidenius and Basu n <- length(p) @@ -81,6 +83,7 @@ convolve <- function(dist1, dist2) { #' compared to \eqn{O(n^2)} for the recursive algorithm. #' @param p Numeric vector, the vector of success probabilities #' @return A vector such that \eqn{q_k=\Pr(S=k)} +#' @export lossdistrib.fft <- function(p) { ## haven't tested when p is not a power of 2. if(length(p) == 1){ @@ -109,7 +112,8 @@ lossdistrib.fft <- function(p) { #' (instead of the loss distribution). #' @return a Numeric vector of size \code{N} computing the loss (resp. #' default) distribution if \code{defaultflag} is FALSE (resp. TRUE). -lossdistrib2 <- function(p, w, S, N, defaultflag=FALSE){ +#' @export +lossdistrib2 <- function(p, w, S, N, defaultflag = FALSE){ n <- length(p) lu <- 1/(N-1) q <- rep(0, N) @@ -147,7 +151,8 @@ lossdistrib2 <- function(p, w, S, N, defaultflag=FALSE){ #' @param N Integer, number of ticks in the grid #' @param cutoff Integer, where to stop computing the exact probabilities #' @return a Numeric vector of size \code{N} computing the loss distribution -lossdistrib2.truncated <- function(p, w, S, N, cutoff=N){ +#' @export +lossdistrib2.truncated <- function(p, w, S, N, cutoff = N){ n <- length(p) lu <- 1/(N-1) q <- rep(0, cutoff) @@ -188,6 +193,7 @@ lossdistrib2.truncated <- function(p, w, S, N, cutoff=N){ #' @param S Numeric, vector of severities #' @param N Integer, number of ticks in the grid #' @return a Numeric vector of size \code{N} computing the recovery distribution +#' @export recovdist <- function(dp, pp, w, S, N){ n <- length(dp) q <- rep(0, N) @@ -226,7 +232,8 @@ recovdist <- function(dp, pp, w, S, N){ #' @return q Matrix of joint loss, recovery probability distribution #' colSums(q) is the recovery distribution marginal #' rowSums(q) is the loss distribution marginal -lossdist.joint <- function(p, w, S, N, defaultflag=FALSE){ +#' @export +lossdist.joint <- function(p, w, S, N, defaultflag = FALSE){ n <- length(p) lu <- 1/(N-1) q <- matrix(0, N, N) @@ -249,11 +256,12 @@ lossdist.joint <- function(p, w, S, N, defaultflag=FALSE){ qtemp[(i+2):N, (j+1):N] <- qtemp[(i+2):N, (j+1):N] + psplit[4] * q[1:(N-i-1), 1:(N-j)] q <- qtemp + (1-p[k])*q } - q[length(q)] <- q[length(q)]+1-sum(q) + q[length(q)] <- q[length(q)] + 1 - sum(q) return(q) } -lossdist.prepay.joint <- function(dp, pp, w, S, N, defaultflag=FALSE){ +#' @export +lossdist.prepay.joint <- function(dp, pp, w, S, N, defaultflag = FALSE){ ## recursive algorithm with first order correction ## to compute the joint probability distribition of the loss and recovery ## inputs: @@ -314,6 +322,7 @@ lossdist.prepay.joint <- function(dp, pp, w, S, N, defaultflag=FALSE){ return(q) } +#' @export lossdistC <- function(p, w, S, N, defaultflag=FALSE){ ## C version of lossdistrib2, roughly 50 times faster .C(C_lossdistrib, as.double(p), as.integer(length(p)), @@ -321,6 +330,7 @@ lossdistC <- function(p, w, S, N, defaultflag=FALSE){ as.logical(defaultflag), q = double(N))$q } +#' @export lossdistCZ <- function(p, w, S, N, defaultflag=FALSE, rho, Z){ ##S is of size (length(p), length(Z)) stopifnot(length(rho) == length(p), @@ -332,6 +342,7 @@ lossdistCZ <- function(p, w, S, N, defaultflag=FALSE, rho, Z){ as.double(Z), as.integer(length(Z)), q = matrix(0, N, length(Z)))$q } +#' @export lossdistC.truncated <- function(p, w, S, N, T=N, defaultflag=FALSE){ ## truncated version of lossdistrib ## q[i] is 0 for i>=T @@ -340,13 +351,15 @@ lossdistC.truncated <- function(p, w, S, N, T=N, defaultflag=FALSE){ as.logical(defaultflag), q = double(N))$q } -exp.trunc <- function(p, w, S, N, K){ +#' @export +exp_trunc <- function(p, w, S, N, K){ ## computes E[(K-L)^+] r <- 0 .C(C_exp_trunc, as.double(p), as.integer(length(p)), as.double(w), as.double(S), as.integer(N), as.double(K), res = r)$res } +#' @export rec.trunc <- function(p, w, S, N, K){ ## computes E[(K-(1-R))^+] = E[(\tilde K- \bar R)] ## where \tilde K = K-sum_i w_i S_i and \bar R=\sum_i w_i R_i (1-X_i) @@ -358,12 +371,14 @@ rec.trunc <- function(p, w, S, N, K){ } } +#' @export recovdistC <- function(dp, pp, w, S, N){ ## C version of recovdist .C(C_recovdist, as.double(dp), as.double(pp), as.integer(length(dp)), as.double(w), as.double(S), as.integer(N), q = double(N))$q } +#' @export lossdistC.prepay.joint <- function(dp, pp, w, S, N, defaultflag=FALSE){ ## C version of lossdist.prepay.joint r <- .C(C_lossdistrib_joint, as.double(dp), as.double(pp), as.integer(length(dp)), @@ -371,6 +386,7 @@ lossdistC.prepay.joint <- function(dp, pp, w, S, N, defaultflag=FALSE){ return(r) } +#' @export lossdistC.prepay.jointZ <- function(dp, pp, w, S, N, defaultflag = FALSE, rho, Z, wZ){ ## N is the size of the grid ## dp is of size n.credits @@ -387,6 +403,7 @@ lossdistC.prepay.jointZ <- function(dp, pp, w, S, N, defaultflag = FALSE, rho, Z return(r$output) } +#' @export lossrecovdist <- function(defaultprob, prepayprob, w, S, N, defaultflag=FALSE, useC=TRUE){ lossdistrib2 <- if(useC) lossdistC recovdist <- if(useC) recovdistC @@ -400,6 +417,7 @@ lossrecovdist <- function(defaultprob, prepayprob, w, S, N, defaultflag=FALSE, u return(list(L=L, R=R)) } +#' @export lossrecovdist.term <- function(defaultprob, prepayprob, w, S, N, defaultflag=FALSE, useC=TRUE){ ## computes the loss and recovery distribution over time L <- array(0, dim=c(N, ncol(defaultprob))) @@ -420,6 +438,7 @@ lossrecovdist.term <- function(defaultprob, prepayprob, w, S, N, defaultflag=FAL return(list(L=L, R=R)) } +#' @export lossrecovdist.joint.term <- function(defaultprob, prepayprob, w, S, N, defaultflag=FALSE, useC=TRUE){ ## computes the joint loss and recovery distribution over time Q <- array(0, dim=c(ncol(defaultprob), N, N)) @@ -437,7 +456,8 @@ lossrecovdist.joint.term <- function(defaultprob, prepayprob, w, S, N, defaultfl return(Q) } -dist.transform <- function(dist.joint){ +#' @export +dist.transform <- function(dist.joint) { ## compute the joint (D, R) distribution ## from the (L, R) distribution using D = L+R distDR <- array(0, dim=dim(dist.joint)) @@ -459,7 +479,8 @@ dist.transform <- function(dist.joint){ return( distDR ) } -shockprob <- function(p, rho, Z, log.p=F){ +#' @export +shockprob <- function(p, rho, Z, log.p=F) { ## computes the shocked default probability as a function of the copula factor ## function is vectorized provided the below caveats: ## p and rho are vectors of same length n, Z is a scalar, returns vector of length n @@ -478,7 +499,8 @@ shockprob <- function(p, rho, Z, log.p=F){ } } -shockseverity <- function(S, Stilde=1, Z, rho, p){ +#' @export +shockseverity <- function(S, Stilde=1, Z, rho, p) { ## computes the severity as a function of the copula factor Z result <- double(length(S)) result[p==0] <- 0 @@ -487,15 +509,18 @@ shockseverity <- function(S, Stilde=1, Z, rho, p){ return(result) } -dshockprob <- function(p,rho,Z){ +#' @export +dshockprob <- function(p,rho,Z) { dnorm((qnorm(p)-sqrt(rho)*Z)/sqrt(1-rho))*dqnorm(p)/sqrt(1-rho) } +#' @export dqnorm <- function(x){ 1/dnorm(qnorm(x)) } -fit.prob <- function(Z, w, rho, p0){ +#' @export +fit.prob <- function(Z, w, rho, p0) { ## if the weights are not perfectly gaussian, find the probability p such ## E_w(shockprob(p, rho, Z)) = p0 if(p0==0){ @@ -519,14 +544,16 @@ fit.prob <- function(Z, w, rho, p0){ return(p) } -fit.probC <- function(Z, w, rho, p0){ +#' @export +fit.probC <- function(Z, w, rho, p0) { stopifnot(length(Z)==length(w)) r <- .C(C_fitprob, as.double(Z), as.double(w), as.integer(length(Z)), as.double(rho), as.double(p0), q = double(1)) return(r$q) } -stochasticrecov <- function(R, Rtilde, Z, w, rho, porig, pmod){ +#' @export +stochasticrecov <- function(R, Rtilde, Z, w, rho, porig, pmod) { ## if porig == 0 (probably matured asset) then return orginal recovery ## it shouldn't matter anyway since we never default that asset if(porig == 0){ @@ -537,6 +564,7 @@ stochasticrecov <- function(R, Rtilde, Z, w, rho, porig, pmod){ } } +#' @export stochasticrecovC <- function(R, Rtilde, Z, w, rho, porig, pmod){ r <- .C(C_stochasticrecov, as.double(R), as.double(Rtilde), as.double(Z), as.double(w), as.integer(length(Z)), as.double(rho), as.double(porig), @@ -544,6 +572,7 @@ stochasticrecovC <- function(R, Rtilde, Z, w, rho, porig, pmod){ return(r$q) } +#' @export BClossdist <- function(defaultprob, issuerweights, recov, rho, Z, w, N=length(recov)+1, defaultflag=FALSE, n.int=500){ @@ -575,6 +604,7 @@ BClossdist <- function(defaultprob, issuerweights, recov, rho, Z, w, list(L=L, R=R) } +#' @export BClossdistC <- function(defaultprob, issuerweights, recov, rho, Z, w, N=length(issuerweights)+1, defaultflag=FALSE){ if(is.null(dim(defaultprob))){ @@ -593,6 +623,7 @@ BClossdistC <- function(defaultprob, issuerweights, recov, rho, Z, w, return(list(L=r$L,R=r$R)) } +#' @export BCER <- function(defaultprob, issuerweights, recov, K, rho, Z, w, N=length(issuerweights)+1, defaultflag=FALSE){ stopifnot(length(Z)==length(w), |
