1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
library(lubridate)
library(doParallel)
library(dplyr)
library(tidyr)
hostname <- system("hostname", intern=TRUE)
registerDoParallel(if(hostname=="debian") 4 else 8)
source("db.R")
source("cds_functions_generic.R")
source("yieldcurve.R")
serenitasdb <- dbConn("serenitasdb")
get.indexquotes.table <- function(indextype, series, tenors=c("3yr", "5yr", "7yr"),
onlymissing=TRUE) {
df <- serenitasdb %>%
tbl("index_quotes") %>%
filter(index == !!indextype, series == !!series, tenor %in% !!tenors) %>%
{if(onlymissing) filter(., is.null(duration)) else .} %>%
arrange(date) %>% select(date, tenor, closeprice) %>%
collect() %>%
mutate(tenor=factor(tenor, !!tenors))
if(nrow(df) == 0) {
return( df )
} else {
return( df %>% spread(tenor, closeprice) )
}
}
get.indexmaturity <- function(index, series){
index.maturity <- tbl(serenitasdb, "index_maturity")
df <- index.maturity %>%
filter(index == !!index, series == !!series) %>%
mutate(running = coupon/10000) %>%
select(maturity, running, tenor) %>%
arrange(maturity) %>%
collect()
return( df )
}
fastduration <- function(sc, cs, tradedate, maturities){
r <- rep(NA, length(maturities))
if(is.null(sc)) {
return( r )
}
startdate <- tradedate + 1
acc <- cdsAccrued(tradedate, 1)
for(i in seq_along(maturities)) {
if(startdate <= maturities[i]) {
r[i] <- couponleg(cs[cs$unadj.dates<=maturities[i],], sc,
startdate, accruedondefault=TRUE) - acc
}
}
return( r )
}
fasttheta <- function(sc, cs, recov, tradedate, maturities, quotes, fixedrate=0.05){
r <- rep(NA, length(maturities))
if(is.null(sc)) {
return(r)
}
startdate <- tradedate + 1
acc <- cdsAccrued(tradedate, 1)
newmaturities <- maturities + years(-1)
for(i in seq_along(newmaturities)){
## never extrapolate, and do not attempt to compute theta if within 1 year
if(startdate > newmaturities[i] || is.na(quotes[i])) {
next
} else {
newcs <- cs[cs$unadj.dates<=newmaturities[i],]
upfront <- defaultleg(newcs, sc, recov, startdate) -
(couponleg(newcs, sc, startdate, accruedondefault=TRUE)-acc)*fixedrate
r[i] <- quotes[i] - upfront + fixedrate
}
}
return( r )
}
sqlstr.duration <- paste("UPDATE index_quotes set duration=$1 where date=$2 and index=$3",
"and series=$4 and tenor=$5")
sqlstr.theta <- paste("UPDATE index_quotes set theta=$1 where date=$2 and index=$3",
"and series=$4 and tenor=$5")
for(index in c('IG', 'HY', 'EU', 'XO')) {
recov <- if(index %in% c('IG', 'EU')) 0.4 else 0.3
coupon <- if(index %in% c('IG', 'EU')) 0.01 else 0.05
for(series in 18:29) {
tenors <- switch(index,
IG = c("3yr", "5yr", "7yr", "10yr"),
HY = c("3yr", "5yr", "7yr"),
EU = c("3yr", "5yr", "7yr", "10yr"),
XO = c("3yr", "5yr", "7yr", "10yr"))
if( index %in% c('EU', 'XO') && series == 29) {
next
}
indexquotes <- get.indexquotes.table(index, series, tenors)
if(nrow(indexquotes) == 0) {
next
}
maturities <- get.indexmaturity(index, series)
maturities <- maturities[maturities$tenor %in% colnames(indexquotes)[-1],]
durations <- matrix(0, nrow(indexquotes), nrow(maturities))
thetas <- matrix(0, nrow(indexquotes), nrow(maturities))
last_maturity <- maturities %>% slice(n()) %>% pull(maturity)
durandthetas <- foreach(i = 1:nrow(indexquotes), .combine='rbind') %dopar% {
tradedate <- indexquotes %>% slice(i) %>% pull(date)
exportYC(tradedate, currency = if (index %in% c("IG", "HY")) "USD" else "EUR")
cs <- couponSchedule(IMMDate(tradedate, noadj=TRUE), last_maturity, "Q", "FIXED", 1,
0, tradedate, IMMDate(tradedate, "prev"))
quotes <- data.frame(upfront=(100-as.numeric(indexquotes[i,maturities$tenor]))/100,
maturities)
sc <- cdshazardrate(quotes, recov, tradedate, cs)
c(fastduration(sc, cs, tradedate, maturities$maturity),
fasttheta(sc, cs, recov, tradedate, maturities$maturity, quotes$upfront, coupon))
}
## non parallel version for easier debugging
## durandthetas <- c()
## for(i in 1:nrow(indexquotes)) {
## tradedate <- indexquotes %>% slice(i) %>% pull(date)
## exportYC(tradedate, currency = if (index %in% c("IG", "HY")) "USD" else "EUR")
## cs <- couponSchedule(IMMDate(tradedate, noadj=TRUE), last_maturity,"Q", "FIXED", 1,
## 0, tradedate, IMMDate(tradedate, "prev"))
## quotes <- data.frame(upfront=(100-as.numeric(indexquotes[i,maturities$tenor]))/100,
## maturities)
## quotes <- data.frame(upfront=(100-as.numeric(indexquotes[i,-1]))/100, maturities) %>%
## arrange(maturity)
## sc <- cdshazardrate(quotes, recov, tradedate, cs)
## durandthetas <- rbind(durandthetas, c(fastduration(sc, cs, tradedate, maturities$maturity),
## fasttheta(sc, cs, recov, tradedate, maturities$maturity, quotes$upfront, coupon)))
## }
if(is.null(dim(durandthetas))) {
dim(durandthetas) <- c(1, length(durandthetas))
}
n <- nrow(maturities)
df.durations <- data.frame(date=indexquotes$date, durandthetas[,1:n, drop=F])
df.thetas <- data.frame(date=indexquotes$date, durandthetas[,(n+1):(2*n), drop=F])
colnames(df.durations) <- c("date", maturities$tenor)
colnames(df.thetas) <- c("date", maturities$tenor)
for(i in 1:nrow(df.durations)) {
for(tenor in maturities$tenor) {
if(!is.na(df.durations[i, tenor])) {
r <- dbSendQuery(serenitasdb, sqlstr.duration,
params = list(df.durations[i, tenor],
df.durations[i,"date"], index, series, tenor))
if(dbHasCompleted(r)) {
dbClearResult(r)
}
}
if(!is.na(df.thetas[i,tenor])) {
r <- dbSendQuery(serenitasdb, sqlstr.theta,
params = list(df.thetas[i, tenor],
df.thetas[i, "date"], index, series, tenor))
if(dbHasCompleted(r)) {
dbClearResult(r)
}
}
}
}
}
}
## ## nice plot, now I'm just showing off
## library(ggplot2)
## ggplot(df.durations, aes(x=date))+geom_line(aes(y=`3yr`, colour="3yr"))+
## geom_line(aes(y=`5yr`, colour="5yr"))+
## geom_line(aes(y=`7yr`, colour="7yr"))+ylab("duration")+labs(colour="tenor")
## ggsave(filename=paste0("HY", series, " durations.png"))
## ## plot thetas
## ggplot(df.thetas, aes(x=date))+geom_line(aes(y=`3yr`, colour="3yr"))+
## geom_line(aes(y=`5yr`, colour="5yr"))+
## geom_line(aes(y=`7yr`, colour="7yr"))+ylab("theta")+labs(colour="tenor")
## ggsave(filename=paste0("HY", series, " thetas.png"))
|