source("cds_functions_generic.R") buildSC <- function(quote, cs, cdsdates){ SC <- new("creditcurve", recovery=quote$recovery, startdate=tradedate, issuer=quote$ticker) quotes <- data.frame(maturity=cdsdates, upfront = quote$upfront, running=quote$running) SC@curve <- cdshazardrate(quotes, SC@recovery, tradedate, cs) return( SC ) } get.cdsSchedule <- function(tradedate){ cdsdates <- as.Date(character(0)) for(tenor in paste0(c(1:5, 7), "y")){ newdate <- cdsMaturity(tenor, date=tradedate) cdsdates <- c(cdsdates, newdate) } return( list(cs=couponSchedule(IMMDate(tradedate, noadj=TRUE), cdsdates[length(cdsdates)], "Q", "FIXED", 1, tradedate, IMMDate(tradedate, "prev")), cdsdates=cdsdates) ) } set.singlenamesdata <- function(index, tradedate){ cds.cs <- get.cdsSchedule(tradedate) quotes <- get.indexquotes(index$name, tradedate) tenor <- names(cds.cs$cdsdates) index$portfolio <- list() for(i in seq_along(quotes$tickers)){ if(quotes$ticker[i] %in% c("IACI", "TITANC", "ESPSAN", "CBRY")){ quotes$spread_curve[i,] <- rep(0.001,8) quotes$upfront_curve[i,] <- rep(0,8) quotes$recovery[i,] <- rep(0.4,8) } quotes$upfront_curve[i, tenor] <- pmax(-yearFrac(tradedate+2,cds.cs$cdsdates)* quotes$spread_curve[i, tenor]*1e-2, quotes$upfront_curve[i, tenor]) quote <- list(ticker = quotes$ticker[i], running = quotes$spread_curve[i, tenor] * 1e-4, upfront = quotes$upfront_curve[i, tenor] * 0.01, recovery = as.double(quotes$recovery[i,tenor][1])) if(all(is.na(quote$upfront))){ loginfo(paste("no quotes available for", quote$ticker, "on day", as.character(tradedate))) return( NULL ) } index$portfolio <- c(index$portfolio, buildSC(quote, cds.cs$cs, cds.cs$cdsdates)) } if(index$name == "EU9"){ index$issuerweights <- rep(0.08, 123) index$issuerweights[quotes$ticker=="GDFS"] <- 0.08*2 index$issuerweights[quotes$ticker=="GASSM"] <- 0.08*2 } index$issuerweights <- rep(1/length(index$portfolio), length(index$portfolio)) index$recov <- sapply(index$portfolio, attr, "recovery") return( index ) } set.tranchedata <- function(index, tradedate){ if(is.null(index)){ return( NULL ) } temp <- get.tranchequotes(index$name, index$tenor, tradedate) if(is.null(temp)){ loginfo(paste(index$name, "no quote for day", as.character(tradedate))) return(NULL) } index$quotes <- data.frame(maturity=index$maturity, refspread=temp$indexrefspread[1], refprice=temp$indexrefprice[1]) index$quotes$spread <- couponfromindex(index$name, index$tenor)*1e-4 index$cs <- couponSchedule(IMMDate(tradedate, noadj=TRUE), index$maturity,"Q", "FIXED", 1, 0, tradedate, IMMDate(tradedate, "prev")) if(!is.na(index$quotes$refprice) && index$quotes$refprice != 0){ index$quotes$price <- index$quotes$refprice/100 }else{ index$quotes$price <- snacpv(index$cs, index$quotes$refspread[1]*1e-4, index$quotes$spread, 0.4, tradedate) } if(length(indexpv(index, tradedate=tradedate, check=TRUE))==1){ return(NULL) } tweak <- tweakcurves(index, tradedate) index$portfolio <- NULL index <- c(index, tweak) index$defaultprob <- 1 - SPmatrix(index$portfolio, length(index$cs$dates)) negprob <- which(index$defaultprob<0, arr.ind=T) if(nrow(negprob) > 0){ stop(paste(index$portfolio[[negprob[1,1]]]@issuer, "has negative probability, check single names data")) } K <- c(0, temp$detach/100) index$K.orig <- K index$K <- adjust.attachments(K, index$loss, index$factor) ## convert snac prices to proper upfront if(index$type == "XO"){ coupon <- 500 temp$trancheupfrontmid[4] <- 100 * ( 1 - snacpv(index$cs, temp$trancherunningmid[4]*1e-4, coupon*1e-4, 0.4, tradedate)) temp$trancherunningmid[4] <- coupon } if(index$type =="EU"){ if(index$series>=21){ coupon <- 100 temp$trancheupfrontmid[3] <- 100 * ( 1 - snacpv(index$cs, temp$trancherunningmid[3]*1e-4, coupon*1e-4, 0, tradedate)) temp$trancheupfrontmid[4] <- 100 * ( 1 - snacpv(index$cs, temp$trancherunningmid[4]*1e-4, coupon*1e-4, 0.4, tradedate)) temp$trancherunningmid[3:4] <- coupon }else if(index$series == 9){ for(i in 4:5){ coupon <- 100 temp$trancheupfrontmid[i] <- 100 * ( 1 - snacpv(index$cs, temp$trancherunningmid[i]*1e-4, coupon*1e-4, 0, tradedate)) temp$trancherunningmid[i] <- coupon } coupon <- 25 temp$trancheupfrontmid[6] <- 100 * ( 1 - snacpv(index$cs, temp$trancherunningmid[6]*1e-4, coupon*1e-4, 0.4, tradedate)) temp$trancherunningmid[6] <- coupon } } ## compute dirty protection price accrued <- cdsAccrued(tradedate, temp$trancherunningmid*1e-4) if(index$type == "HY"){ dirtyquotes <- 1 - temp$trancheupfrontmid/100 - accrued }else{ dirtyquotes <- temp$trancheupfrontmid/100 - accrued } index$tranches <- data.frame(upfront=temp$trancheupfrontmid, running=temp$trancherunningmid * 1e-4, quotes=dirtyquotes, mkt.delta=temp$tranchedelta, row.names=paste(index$K.orig[-length(index$K.orig)]*100, index$K.orig[-1]*100, sep="-")) return( index ) } build.skew <- function(index, type="bottomup"){ require(lossdistrib) aux <- function(rho, index, K, quote, spread, complement){ temp <- BCtranche.legs(index, K, rho, complement) return(abs(temp$pl+temp$cl*spread + quote)) } rhovec <- rep(NA, length(index$K)) dK <- diff(index$K) if(type=="bottomup"){ for(j in 1:(length(dK)-1)){ ##use the current tranche coupon ## we compute the 0-index$K[j+1] equivalent quote using the coupon of the jth quote tranchepv <- BCtranche.legs(index, index$K[j], rhovec[j]) q <- index$tranches$quotes[j] * dK[j] - tranchepv$pl - tranchepv$cl*index$tranches$running[j] rho <- optimize(aux, interval=c(0,1), index=index, K=index$K[j+1], quote=q, spread=index$tranches$running[j], complement=FALSE)$minimum rhovec[j+1] <- rho } }else if(type=="topdown"){ for(j in length(dK):2){ tranchepv <- BCtranche.legs(index, index$K[j+1], rhovec[j+1], complement=TRUE) q <- index$tranche.quotes[j] * dK[j] - tranchepv$pl - tranchepv$cl * index$tranches$running[j] rho <- optimize(aux, interval=c(0,1), index=index, K=index$K[j], quote=q, spread=index$tranches$running[j], complement=TRUE)$minimum rhovec[j] <- rho } } return( rhovec ) } build.MFdist <- function(index, type="bottomup", tol=1e-2){ index$w.mod <- index$w p <- index$defaultprob n.credit <- length(index$issuerweights) rho <- rep(0.45, n.credit) result <- matrix(0, 4, n.int) n.tranches <- length(index$K)-1 err <- Inf if(type=="bottomup"){ select <- 1:(n.tranches-1) }else if(type=="topdown"){ select <- 2:n.tranches } while(err > tol){ Rstoch <- MFrecovery(index, p) L <- array(0, dim=c(index$N, n.int, ncol(index$defaultprob))) R <- array(0, dim=c(index$N, n.int, ncol(index$defaultprob))) for(t in 1:ncol(index$defaultprob)){ S <- 1 - Rstoch[,,t] L[,,t] <- lossdistCZ(p[,t], index$issuerweights, S, index$N, 0, rho, index$Z) R[,,t] <- lossdistCZ(p[,t], index$issuerweights, 1-S, index$N, 0, rho, index$Z) } for(i in 1:n.int){ dist <- list(L=L[,i,], R=R[,i,]) result[,i] <- MFtranche.pv(index, dist, protection=TRUE)$bp } ## solve the optimization problem program <- KLfit(result[select,], index$w, index$tranches$quotes[select]) err <- 0 for(i in 1:n.credit){ for(j in 1:ncol(p)){ err <- err + abs(crossprod(shockprob(p[i,j], rho[i], index$Z), program$weight) - index$defaultprob[i,j]) } } ## update the new probabilities p <- MFupdate.prob(index$Z, program$weight, rho, index$defaultprob) index$w.mod <- program$weight cat("=") } cat("\n") return(index$w.mod) }