aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cds_functions_generic.R42
-rw-r--r--cds_utils.R26
2 files changed, 47 insertions, 21 deletions
diff --git a/cds_functions_generic.R b/cds_functions_generic.R
index 57886b77..e858ffe8 100644
--- a/cds_functions_generic.R
+++ b/cds_functions_generic.R
@@ -1,5 +1,10 @@
source("cds_utils.R")
+## TODO:
+## - switch hazard rates and prepay curves to functions
+## - allow to compute forward quantities (works for couponleg and defauleg now,
+## if provide startdate
+
setClass("abstractcurve")
## flat hazard rate curve
setClass("flatcurve", contains="abstractcurve", representation(h="numeric"))
@@ -43,8 +48,11 @@ setMethod("couponleg", signature("data.frame", "defaultcurve"),
## computes the pv of the risky coupon leg based on a given coupon schedule
## and a survival curve. Also called premium leg or fixed leg.
function(cs, sc, accruedondefault=TRUE){
- dT <- diff(c(0, yearFrac(today(), cs$dates)))
- PD <- cumprod(exp(-sc@hazardrates[1:length(dT)] * dT))
+ x1T <- yearFrac(today(), sc@dates)
+ x2T <- yearFrac(today(), cs@dates)
+ dT <- diff(c(0, x2T))
+ hfun <- approxfun(x1T, sc@hazardrates, method="constant", rule=2)
+ PD <- cumprod(exp(- hfun(x2T) * dT))
if(accruedondefault){
PDadj <- 0.5 * (c(1, PD[-length(PD)]) + PD)
}else{
@@ -59,9 +67,13 @@ setMethod("couponleg", signature("data.frame", "defaultprepaycurve"),
## a hazard rate curve, and a prepay curve. We assume the poisson processes driving
## default and prepayment are independent, so the intensity of either event
## happenning is the sum of the two.
- function(cs, sc, accruedondefault=TRUE){
- dT <- diff(c(0, yearFrac(today(), cs$dates)))
- SP <- cumprod(exp( - (sc@hazardrates[1:length(dT)] + sc@prepayrates[1:length(dT)] ) * dT))
+ function(cs, sc, accruedondefault=TRUE, startdate=today()){
+ x1T <- yearFrac(today(), sc@dates)
+ x2T <- yearFrac(startdate, cs$dates)
+ dT <- diff(c(0, x2T))
+ hfun <- approxfun(x1T, sc@hazardrates, method="constant", rule=2)
+ pfun <- approxfun(x1T, sc@prepayrates, method="constant", rule=2)
+ SP <- cumprod(exp( - (hfun(x2T) + pfun(x2T)) * dT))
if(accruedondefault){
SPadj <- 0.5 * (c(1, SP[-length(SP)]) + SP)
}else{
@@ -82,8 +94,8 @@ setMethod("couponleg", signature("data.frame", "shapedcurve"),
## a hazard rate curve, and a prepay curve. We assume the poisson processes driving
## default and prepayment are independent, so the intensity of either event
## happenning is the sum of the two.
- function(cs, sc, accruedondefault=TRUE){
- return( couponleg(cs, shapedtodpc(cs, sc), accruedondefault) )
+ function(cs, sc, accruedondefault=TRUE, startdate){
+ return( couponleg(cs, shapedtodpc(cs, sc, startdate), accruedondefault, startdate) )
})
## define dcouponleg generic
@@ -172,7 +184,7 @@ setMethod("cdsduration", signature("abstractcurve", "Date"),
})
## define defaultleg generic
-setGeneric("defaultleg", function(cs, sc, recovery) {
+setGeneric("defaultleg", function(cs, sc, recovery, ...) {
standardGeneric("defaultleg")
})
@@ -204,12 +216,15 @@ setMethod("defaultleg", signature("data.frame", "defaultcurve", "numeric"),
setMethod("defaultleg", signature("data.frame", "defaultprepaycurve", "numeric"),
## Computes the pv of the default leg of a cds based on a given
## coupon schedule, hazard rates curve, prepay curves, and recovery.
- function(cs, sc, recovery){
- T <- yearFrac(today(), cs$dates)
- dT <- diff(c(0, T))
- Q <- cumprod(exp(- (sc@hazardrates[1:length(dT)]+sc@prepayrates[1:length(dT)]) * dT)) * cs$df
+ function(cs, sc, recovery, startdate=today()){
+ x2T <- yearFrac(startdate, cs$dates)
+ x1T <- yearFrac(today(), sc@dates)
+ dT <- diff(c(0, x2T))
+ hfun <- approxfun(x1T, sc@hazardrates, method = "constant", rule=2)
+ pfun <- approxfun(x1T, sc@prepayrates, method = "constant", rule=2)
+ Q <- cumprod(exp(- (hfun(x2T)+pfun(x2T)) * dT)) * cs$df
Qmid <- 1/2 * (c(1, Q[-length(Q)]) + Q)
- r <- (1 - recovery) * crossprod(sc@hazardrates[1:length(dT)] * Qmid, dT)
+ r <- (1 - recovery) * crossprod(hfun(x2T) * Qmid, dT)
return( as.numeric(r) )
})
@@ -250,7 +265,6 @@ setMethod("ddefaultleg", signature("data.frame", "defaultcurve", "numeric", "num
return( as.numeric(dr) )
})
-
setMethod("ddefaultleg", signature("data.frame", "shapedcurve", "numeric", "missing"),
function(cs, sc, recovery) {
T <- yearFrac(today(), cs$dates)
diff --git a/cds_utils.R b/cds_utils.R
index f9e6be03..f0799a8f 100644
--- a/cds_utils.R
+++ b/cds_utils.R
@@ -65,7 +65,14 @@ creditSchedule <- function(startdate, enddate) {
seq(newdate, enddate, by="3 months")
}
-couponSchedule <- function(nextpaydate=NULL, maturity, frequency, coupontype, currentcoupon, margin){
+couponSchedule <- function(nextpaydate=NULL, maturity, frequency, coupontype, currentcoupon,
+ margin, startdate=today()){
+ ## computes the coupon schedule
+ ## inputs:
+ ## nextpaydate: first payment date of the coupon schedule
+ ## maturity: last payment date of the schedule
+ ## frequency: letter specifying the frequency amon "Q", "M", "B", or "S"
+ ## if startdate is provided, this generates the forward coupon schedule starting from that date.
bystring <- switch(frequency,
Q = "3 months",
M = "1 month",
@@ -81,17 +88,22 @@ couponSchedule <- function(nextpaydate=NULL, maturity, frequency, coupontype, cu
}
dates <- dates[ dates >= today()]
DC <- switch(frequency,
- S = DiscountCurve(L6m$params, L6m$tsQuotes, yearFrac(today(), dates)),
- Q = DiscountCurve(L3m$params, L3m$tsQuotes, yearFrac(today(), dates)),
- M = DiscountCurve(L1m$params, L1m$tsQuotes, yearFrac(today(), dates)),
- B = DiscountCurve(L2m$params, L2m$tsQuotes, yearFrac(today(), dates)))
+ S = DiscountCurve(L6m$params, L6m$tsQuotes, yearFrac(L6m$params$tradeDate, dates)),
+ Q = DiscountCurve(L3m$params, L3m$tsQuotes, yearFrac(L3m$params$tradeDate, dates)),
+ M = DiscountCurve(L1m$params, L1m$tsQuotes, yearFrac(L1m$params$tradeDate, dates)),
+ B = DiscountCurve(L2m$params, L2m$tsQuotes, yearFrac(L2m$params$tradeDate, dates)))
if(coupontype=="FLOAT" && !is.na(margin)){ #if is.na(margin) probably letter of credit
coupons <- pmax(currentcoupon, DC$forwards + margin)
}else{
coupons <- rep(currentcoupon, length(dates))
}
- coupons <- diff(c(0, yearFrac(today(), dates, "act/360"))) * coupons
- return( data.frame(dates=dates, coupons=coupons, df = DC$discounts) )
+ coupons <- diff(c(0, yearFrac(startdate, dates, "act/360"))) * coupons
+ if(startdate!=DC$params$tradeDate){
+ df <- cumprod(exp(-DC$forwards * diff(c(0, yearFrac(startdate, dates)))))
+ }else{
+ df <- DC$discounts
+ }
+ return( data.frame(dates=dates, coupons=coupons, df = df) )
}
nextIMMDate <- function(date) {