Skip to content

Instantly share code, notes, and snippets.

@wilsonfreitas
Last active May 4, 2018 16:56
Show Gist options
  • Save wilsonfreitas/80ff2bd8800732969a4f71e6f77d3846 to your computer and use it in GitHub Desktop.
Save wilsonfreitas/80ff2bd8800732969a4f71e6f77d3846 to your computer and use it in GitHub Desktop.
#' @export
next_anniversary = function(x, ...) UseMethod("next_anniversary")
#' @export
next_anniversary.bond = function(x, ...) {
refdate = crf.options$get("REFDATE")
start_year = year(refdate)
start_month = month(refdate)
anniversary = as.Date(ISOdate(start_year, start_month, x$anniversary))
if (refdate <= anniversary) anniversary else anniversary %m+% months(1)
}
#' @export
last_anniversary = function(x, ...) UseMethod("last_anniversary")
#' @export
last_anniversary.bond = function(x, ...) {
refdate = crf.options$get("REFDATE")
start_year = year(refdate)
start_month = month(refdate)
anniversary = as.Date(ISOdate(start_year, start_month, x$anniversary))
if (refdate < anniversary) anniversary %m-% months(1) else anniversary
}
# bond functions ----
amortization_cashflow = function(cashflow, maturity_date, calendar) {
cashFlow = cashflow %>%
rename(Dates = date) %>%
mutate(Dates = following(as.Date(Dates), calendar))
## amortization cash flow
amortization_cashflow = cashFlow %>%
filter(eventType != "J") %>%
rename(Amortization_p = yield) %>%
mutate(Amortization_p = Amortization_p/100) %>%
select(Dates, Amortization_p)
# create cash flow if it is empty
if (nrow(amortization_cashflow) == 0) {
amortization_cashflow = data.frame(Dates = maturity_date,
Amortization_p = 1)
}
# add maturity date as the last cash flow
if (max(amortization_cashflow$Dates) < maturity_date) {
res = 1 - sum(amortization_cashflow$Amortization_p)
amortization_cashflow = rbind(
amortization_cashflow,
data.frame(Dates = maturity_date, Amortization_p = res)
)
}
if (sum(amortization_cashflow$Amortization_p) < 1) {
mx = which.max(amortization_cashflow$Dates)
res = 1 - sum(amortization_cashflow$Amortization_p)
amortization_cashflow$Amortization_p[mx] = amortization_cashflow$Amortization_p[mx] + res
}
amortization_cashflow
}
coupon_cashflow = function(cashflow, calendar) {
coupon_cashflow = cashflow %>%
rename(Dates = date) %>%
mutate(Dates = following(as.Date(Dates), calendar)) %>%
filter(eventType == "J") %>%
mutate(Coupon_p = 0) %>%
select(Dates, Coupon_p)
coupon_cashflow
}
cashflow = function(raw_cashflow, start_date, maturity_date, calendar) {
amortization_cashflow = amortization_cashflow(raw_cashflow, maturity_date, calendar)
coupon_cashflow = coupon_cashflow(raw_cashflow, calendar)
cashflow = merge(amortization_cashflow, coupon_cashflow,
by = "Dates", all = TRUE) %>%
arrange(Dates) %>%
mutate(
Amortization_p = ifelse(is.na(Amortization_p), 0, Amortization_p),
Fixings = following(Dates, calendar),
DaysBetween = bizdiff(c(start_date, Fixings), calendar)
) %>%
mutate(c_amt_l = cumsum(Amortization_p), VNR_p = 1-c_amt_l) %>%
select(-c_amt_l)
cashflow
}
# bond ----
#' @export
bond_from_legacy = function(bond_details) {
that = list()
## set attributes
that$issuer = bond_details$issuer
that$issuer_ticker = bond_details$codbond
that$issue_date = ymd(bond_details$issuedate)
that$start_date = ymd(bond_details$startingdate)
that$maturity_date = ymd(bond_details$expiredate)
that$anniversary = bond_details$anniversaryday
## anniversary
anniversary = as.Date(ISOdate(year(that$start_date), month(that$start_date), that$anniversary))
that$zero_anniversary = if (that$start_date < anniversary) anniversary %m-% months(1) else anniversary
that$first_anniversary = if (that$start_date < anniversary) anniversary else anniversary %m+% months(1)
that$calendar = "Brazil/ANBIMA"
### type dependent attributes
that$type = type(bond_details$method)
that$perc = perc(that$type, as.numeric(bond_details$yield)/100)
that$coupon_rate = coupon_rate(that$type, as.numeric(bond_details$yield)/100)
that$..notional = bond_details$vne
## cash flow calculations
that$cashflow = cashflow(bond_details$events, that$start_date, that$maturity_date, that$calendar)
structure(that, class = "bond")
}
#' @export
bond_from_cetip_data = function(deb_data, deb_cashflow) {
that = list()
## set attributes
that$issuer = deb_data$ISSUER
that$issuer_ticker = deb_data$CODBOND
that$anniversary = as.integer(deb_data$ANNIVERSARYDAY)
that$issue_date = dmy(deb_data$ISSUEDATE)
that$start_date = dmy(deb_data$STARTINGDATE)
that$maturity_date = dmy(deb_data$EXPIREDATE)
## anniversary
anniversary = as.Date(ISOdate(year(that$start_date), month(that$start_date), that$anniversary))
that$zero_anniversary = if (that$start_date < anniversary) anniversary %m-% months(1) else anniversary
that$first_anniversary = if (that$start_date < anniversary) anniversary else anniversary %m+% months(1)
that$calendar = "Brazil/ANBIMA"
### type dependent attributes
that$type = type(deb_data$METHOD)
that$perc = perc(that$type, as.numeric(deb_data$YIELD)/100)
that$coupon_rate = coupon_rate(that$type, as.numeric(deb_data$YIELD)/100)
that$..notional = deb_data$VNE
## cash flow calculations
that$cashflow = cashflow(deb_cashflow, that$start_date, that$maturity_date, that$calendar)
structure(that, class = "bond")
}
#' @export
print.bond = function(x, ...) {
cat(x$issuer_ticker, "\n")
cat(as.character(x$type), "\n")
print(market_cashflow(x))
invisible(x)
}
#' @name calculadorarendafixa
#' @author wilson
#' @docType package
#'
NULL
# coupon rate ----
#' @export
coupon_rate = function(x, ...) UseMethod("coupon_rate")
#' @export
`coupon_rate.DI-SPREAD` = function(x, value, ...) value
#' @export
`coupon_rate.DI-PERC` = function(x, value, ...) 0
#' @export
`coupon_rate.IPCA` = function(x, value, ...) value
#' @export
`coupon_rate.IPCA-N15` = function(x, value, ...) value
#' @export
`coupon_rate.IPCA-I` = function(x, value, ...) value
#' @export
`coupon_rate.PRE` = function(x, value, ...) value
#' @export
`coupon_rate.DI-SSU` = function(x, value, ...) value
# set_config(use_proxy(url="10.0.0.24",port=8080, username="wfreitas", password="A1manaque"))
#' @export
crf_auth_token <- function() {
site_url = "https://api.calculadorarendafixa.com.br"
token = "8f3d4610-9938-4ec2-a01b-cb95de5c8ede"
url <- parse_url(site_url)
r <- POST(url, body = list(token = token), verbose())
if (status_code(r) != 200)
stop("Unable to request www.calculadorarendafixa.com.br")
m <- str_match(content(r, as = "text"), "authorization = '([\\d\\w]*)'")
auth_code <- if (! any(is.na(m[1, 2]))) m[1,2] else NULL
m <- str_match(content(r, as = "text"), "apiurl = '(.*)'")
api_url <- if (! any(is.na(m[1, 2]))) m[1,2] else NULL
auth_token = list(
auth_code = auth_code,
api_url = api_url,
site_url = site_url
)
structure(auth_token, class = "crf_auth_token")
}
crf_build_url = function(token, code = c("bonds", "calc", "details"), ...) {
code = match.arg(code)
switch (code,
"bonds" = {
modify_url(token$site_url, path = c(token$api_url, "listBondCodes"))
},
"calc" = {
parms = list(...)
modify_url(token$site_url, path = c(token$api_url, "calcPU",
parms$bond_code, parms$refdate, parms$yield))
},
"details" = {
parms = list(...)
modify_url(token$site_url, path = c(token$api_url, "getBondDetails",
parms$bond_code))
}
)
}
connect_calculadora <- function(x, auth_code) {
VERB(
verb = "GET", url = x,
add_headers(
`Accept-Encoding` = "gzip, deflate, sdch, br",
`Accept-Language` = "pt-BR,pt;q=0.8,en-US;q=0.6,en;q=0.4",
`Accept` = "text/javascript, text/html, application/xml, text/xml, */*",
`Authorization` = auth_code,
`Auth-Code` = auth_code,
`X-Requested-With` = "XMLHttpRequest",
`Connection` = "keep-alive",
`Referer` = "https://calculadorarendafixa.com.br/",
`User-Agent` = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"
)
)
}
#' @export
list_bond_codes <- function(token) {
r <- connect_calculadora(crf_build_url(token, "bonds"), token$auth_code)
if (status_code(r) == 200) {
x <- fromJSON(content(r, as = "text", encoding = "UTF-8"))
if (is.list(x) && exists("err", x) && x$err)
stop("Problems downloading bond codes. API HTTP status code = ", x$httpStatusCode,
"; API Message = ", x$message)
else
x
} else
stop("Unable to download bond codes. status = ", status_code(r))
}
#' @export
get_bond_details <- function(token, bond_code, as = c("json", "text")) {
as <- match.arg(as)
url_ = crf_build_url(token, "details", bond_code = bond_code)
r <- connect_calculadora(url_, token$auth_code)
if (status_code(r) == 200) {
text <- content(r, as = "text", encoding = "UTF-8")
if (as == "text")
return(text)
x <- fromJSON(text)
if (is.list(x) && exists("err", x) && x$err)
stop("Problems downloading bond details. API HTTP status code = ", x$httpStatusCode,
"; API Message = ", x$message)
else
x
} else
stop("Unable to download bond details. status = ", status_code(r))
}
#' @export
calc_bond <- function(token, bond_code, refdate, yield) {
url_ = crf_build_url(token, "calc", bond_code = bond_code,
refdate = format(refdate),
yield = format(yield))
r <- connect_calculadora(url_, token$auth_code)
if (status_code(r) == 200) {
x <- fromJSON(content(r, as = "text", encoding = "UTF-8"))
if (is.list(x) && exists("err", x) && x$err)
stop("Problems downloading bond results. API HTTP status code = ", x$httpStatusCode,
"; API Message = ", x$message)
else
x
} else
stop("Unable to download bond results. status = ", status_code(r))
}
# merge elements of y into x with the same names
merge_list = function(x, y) {
x[names(y)] = y
x
}
# new_defaults - creates a settings object
new_defaults <- function(value=list()) {
defaults <- value
get <- function(name, default=FALSE, drop=TRUE) {
if (default)
defaults <- value # this is only a local version
if (missing(name))
defaults
else {
if (drop && length(name) == 1) {
if (!exists(name, defaults))
stop("Name (", name, ") not found in options.")
defaults[[name]]
} else
defaults[name]
}
}
set <- function(...) {
dots <- list(...)
if (length(dots) == 0) return()
if (is.null(names(dots)) && length(dots) == 1 && is.list(dots[[1]]))
if (length(dots <- dots[[1]]) == 0) return()
defaults <<- merge(dots)
invisible(NULL)
}
merge <- function(values) merge_list(defaults, values)
restore <- function(target = value) defaults <<- target
list(get=get, set=set, merge=merge, restore=restore)
}
#' @export
crf.options <- new_defaults()
# equivalent coupon rate ----
equivalent_coupon_rate = function(x, ...) UseMethod("equivalent_coupon_rate")
equivalent_coupon_rate.bond = function(x, business_days, days_between, ...) {
get(.Generic)(x$type, x, business_days, days_between, ...)
}
`equivalent_coupon_rate.DI-PERC` = function(x, bond, business_days, days_between, ...) {
# z_rate = curve$value
curve = crf.options$get("IRBRL_CURVE")
z_rate = curve[business_days]
comp1 = (1 + z_rate)^(business_days/252)
comp2 = lag(comp1)
du1 = business_days
du2 = lag(du1)
f_rate = (comp1/comp2)^(252/(du1 - du2)) - 1
c_rate = c(z_rate[1], tail(f_rate, -1))
du_ = c(business_days[1], tail(days_between, -1))
fc1 = (((1 + c_rate)^(1/252) - 1)*bond$perc + 1)^du_
c_rate = fc1^(252/du_) - 1
data.frame(CouponDays = du_, CouponRate = c_rate)
}
`equivalent_coupon_rate.DI-SPREAD` = function(x, bond, business_days, days_between, ...) {
# z_rate = curve$value
curve = crf.options$get("IRBRL_CURVE")
z_rate = curve[business_days]
comp1 = (1 + z_rate)^(business_days/252)
comp2 = lag(comp1)
du1 = business_days
du2 = lag(du1)
f_rate = (comp1/comp2)^(252/(du1 - du2)) - 1
c_rate = c(z_rate[1], tail(f_rate, -1))
du_ = c(business_days[1], tail(days_between, -1))
fc1 = (1 + c_rate)^(du_/252)
fc2 = (1 + bond$coupon_rate)^(du_/252)
c_rate = (fc1 * fc2)^(252/du_) - 1
data.frame(CouponDays = du_, CouponRate = c_rate)
}
`equivalent_coupon_rate.PRE` = function(x, bond, business_days, days_between, ...) {
du_ = c(business_days[1], tail(days_between, -1))
data.frame(CouponDays = du_, CouponRate = bond$coupon_rate)
}
`equivalent_coupon_rate.IPCA-N15` = function(x, bond, business_days, days_between, ...) {
du_ = c(business_days[1], tail(days_between, -1))
data.frame(CouponDays = du_, CouponRate = bond$coupon_rate)
}
`equivalent_coupon_rate.IPCA-I` = function(x, bond, business_days, days_between, ...) {
du_ = c(business_days[1], tail(days_between, -1))
data.frame(CouponDays = du_, CouponRate = bond$coupon_rate)
}
`equivalent_coupon_rate.IPCA` = function(x, bond, business_days, days_between, ...) {
du_ = c(business_days[1], tail(days_between, -1))
data.frame(CouponDays = du_, CouponRate = bond$coupon_rate)
}
extract_curve = function(calc_details) {
curv_df = calc_details$cashFlowList %>% filter(eventType == "J") %>% select(workingDays, yield)
curve_d = curv_df[!duplicated(curv_df),] %>%
rename(terms = workingDays, value = yield) %>%
mutate(value = value/100) %>%
filter(value > 1e-100)
curve_d
}
# first vna ----
#' @export
first_vna = function(x, ...) UseMethod("first_vna")
#' @export
first_vna.bond = function(x, ...) get(.Generic)(x$type, x, ...)
#' @export
`first_vna.DI-SPREAD` = function(x, bond, ...) vna(bond)
#' @export
`first_vna.DI-PERC` = function(x, bond, ...) vna(bond)
#' @export
`first_vna.PRE` = function(x, bond, ...) vna(bond)
#' @export
`first_vna.IPCA` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
last_event = last_coupon_date(bond)
vnr(bond) * (1 + bond$coupon_rate)^(bizdays(last_event, refdate, bond$calendar)/252)
}
#' @export
`first_vna.IPCA-N15` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
last_event = last_coupon_date(bond)
vnr(bond) * (1 + bond$coupon_rate)^(bizdays(last_event, refdate, bond$calendar)/252)
}
#' @export
`first_vna.IPCA-I` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
last_event = last_coupon_date(bond)
vnr(bond) * (1 + bond$coupon_rate)^(bizdays(last_event, refdate, bond$calendar)/252)
}
#' @export
load_historical_data = function(fname) {
# locale = Sys.getlocale("LC_ALL")
# Sys.setlocale("LC_ALL", "C")
calc_data = read_csv(fname)
.data = calc_data %>%
mutate(DATEINDEX = dmy(DATEINDEX)) %>%
arrange(desc(DATEINDEX)) %>%
rename(Date = DATEINDEX, Type = TYPE, Value = VALUE)
# Sys.setlocale("LC_ALL", locale)
.data
}
#' @export
historical_index = function(.data, index_name) {
hdata = .data %>% filter(Type == index_name) %>% select(Date, Value)
that = list(data = hdata)
structure(that, class = "historical_index")
}
#' @export
`[.historical_index` = function(x, ix) {
ix = as.Date(ix)
N1 = x$data %>% filter(Date <= ix) %>% pull(Value)
N1[1]
}
# index ----
#' @export
index = function(x) UseMethod("index")
#' @export
`index.DI-SPREAD` = function(x) "HISTORICAL_CDI"
#' @export
`index.DI-PERC` = function(x) "HISTORICAL_CDI"
#' @export
`index.PRE` = function(x) NULL
#' @export
irc = function(curv) {
that = list()
that$fc_interp = flat_forward(curv$terms, curv$value)
that$data = curv
structure(that, class = "irc")
}
#' @export
`[.irc` = function(x, ix) {
x$fc_interp(ix)
}
#' @export
`[[.irc` = function(x, ix) {
x$fc_interp(ix)
}
# issue spread ----
#' @export
issue_spread = function(x, ...) UseMethod("issue_spread")
#' @export
issue_spread.bond = function(x, ...) get(.Generic)(x$type, x, ...)
#' @export
`issue_spread.DI-PERC` = function(x, bond, ...) bond$perc
#' @export
`issue_spread.DI-SPREAD` = function(x, bond, ...) bond$coupon_rate
#' @export
`issue_spread.PRE` = function(x, bond, ...) bond$coupon_rate
#' @export
`issue_spread.IPCA-N15` = function(x, bond, ...) bond$coupon_rate
#' @export
`issue_spread.IPCA-I` = function(x, bond, ...) bond$coupon_rate
#' @export
`issue_spread.IPCA` = function(x, bond, ...) bond$coupon_rate
#' @export
last_coupon_date = function(x, ...) UseMethod("last_coupon_date")
#' @export
last_coupon_date.bond = function(x, ...) {
refdate = crf.options$get("REFDATE")
dts = x$cashflow %>% filter(Dates <= refdate) %>% pull(Dates)
if (length(dts) == 0) x$start_date else last(dts)
}
#' @export
market_cashflow = function(x, ...) UseMethod("market_cashflow")
#' @export
market_cashflow.bond = function(x, ...) {
refdate = crf.options$get("REFDATE")
mcf = x$cashflow %>%
filter(Dates > refdate) %>%
mutate(
BusinessDays = bizdays(refdate, Fixings, x$calendar)
)
df = equivalent_coupon_rate(x, mcf$BusinessDays, mcf$DaysBetween)
mcf$Coupon_p = df$CouponRate
mcf$CouponDays = df$CouponDays
# payments
mcf = mcf %>% mutate(
VNR = notional(x)*VNR_p,
Amortizations = notional(x)*Amortization_p
)
f_vna = first_vna(x)
mcf %>%
mutate(N_ = lag(VNR, default = as.numeric(f_vna)),
NN_ = lag(VNR, default = as.numeric(vnr(x)))) %>%
mutate(
Coupons = N_*(1 + Coupon_p)^(CouponDays/252) - NN_,
Payments = Coupons + Amortizations) %>%
select(-N_, -NN_)
}
# notional ----
#' @export
notional = function(x, ...) UseMethod("notional")
#' @export
notional.bond = function(x, ...) get(.Generic)(x$type, x, ...)
#' @export
`notional.DI-SPREAD` = function(x, bond, ...) bond$..notional
#' @export
`notional.DI-PERC` = function(x, bond, ...) bond$..notional
#' @export
`notional.PRE` = function(x, bond, ...) bond$..notional
#' @export
`notional.IPCA` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
index_ = crf.options$get("HISTORICAL_INDEX_IPCA")
rate_ = crf.options$get("HISTORICAL_RATES_IPCA")
N1 = index_[bond$zero_anniversary]
N2 = index_[bond$first_anniversary]
dt1 = bizdays(bond$start_date, bond$first_anniversary, bond$calendar)
dn1 = bizdays(bond$zero_anniversary, bond$first_anniversary, bond$calendar)
N3 = index_[refdate]
proj = rate_[refdate]
dt2 = bizdays(last_anniversary(bond), refdate, bond$calendar)
dn2 = bizdays(last_anniversary(bond), next_anniversary(bond), bond$calendar)
if (dn2 == 0)
bond$..notional * (N2/N1)^(dt1/dn1) * (N3/N2)
else
bond$..notional * (N2/N1)^(dt1/dn1) * (N3/N2) * (1 + proj/100)^(dt2/dn2)
}
#' @export
`notional.IPCA-N15` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
index_ = crf.options$get("HISTORICAL_INDEX_IPCA")
rate_ = crf.options$get("HISTORICAL_RATES_IPCA")
N1 = index_[bond$zero_anniversary]
N2 = index_[bond$first_anniversary]
dt1 = bizdays(bond$start_date, bond$first_anniversary, bond$calendar)
dn1 = bizdays(bond$zero_anniversary, bond$first_anniversary, bond$calendar)
N3 = index_[refdate]
proj = rate_[refdate]
dt2 = bizdays(last_anniversary(bond), refdate, bond$calendar)
dn2 = bizdays(last_anniversary(bond), next_anniversary(bond), bond$calendar)
bond$..notional * (N2/N1)^(dt1/dn1) * (N3/N2) * (1 + proj/100)^(dt2/dn2)
}
#' @export
`notional.IPCA-I` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
index_ = crf.options$get("HISTORICAL_INDEX_IPCA")
rate_ = crf.options$get("HISTORICAL_RATES_IPCA")
N1 = index_[bond$zero_anniversary]
N2 = index_[bond$first_anniversary]
dt1 = bizdays(bond$start_date, bond$first_anniversary, bond$calendar)
dn1 = bizdays(bond$zero_anniversary, bond$first_anniversary, bond$calendar)
N3 = index_[refdate]
proj = rate_[refdate]
dt2 = bizdays(last_anniversary(bond), refdate, bond$calendar)
dn2 = bizdays(last_anniversary(bond), next_anniversary(bond), bond$calendar)
bond$..notional * (N2/N1)^(dt1/dn1) * (N3/N2) * (1 + proj/100)^(dt2/dn2)
}
# perc ----
#' @export
perc = function(x, ...) UseMethod("perc")
#' @export
`perc.DI-SPREAD` = function(x, value, ...) 1
#' @export
`perc.DI-PERC` = function(x, value, ...) value
#' @export
`perc.IPCA` = function(x, value, ...) 1
#' @export
`perc.IPCA-N15` = function(x, value, ...) 1
#' @export
`perc.IPCA-I` = function(x, value, ...) 1
#' @export
`perc.PRE` = function(x, value, ...) 1
#' @export
`perc.DI-SSU` = function(x, value, ...) 1
# reference vna ----
#' @export
reference_vna = function(x, ...) UseMethod("reference_vna")
#' @export
`reference_vna.DI-SPREAD` = function(x, calc_details, ...) calc_details$PUPar
#' @export
`reference_vna.DI-PERC` = function(x, calc_details, ...) calc_details$PUPar
#' @export
`reference_vna.PRE` = function(x, calc_details, ...) calc_details$PUPar
#' @export
`reference_vna.IPCA` = function(x, calc_details, ...) calc_details$VNA
#' @export
`reference_vna.IPCA-N15` = function(x, calc_details, ...) calc_details$VNA
#' @export
`reference_vna.IPCA-I` = function(x, calc_details, ...) calc_details$VNA
# risk_spread ----
#' @export
risk_spread = function(x, ...) UseMethod("risk_spread")
#' @export
risk_spread.bond = function(x, ...) get(.Generic)(x$type, x, ...)
#' @export
`risk_spread.DI-SPREAD` = function(x, bond, ...) bond$coupon_rate
#' @export
`risk_spread.DI-PERC` = function(x, bond, ...) bond$perc
#' @export
`risk_spread.IPCA` = function(x, bond, ...) bond$coupon_rate
#' @export
`risk_spread.IPCA-N15` = function(x, bond, ...) bond$coupon_rate
#' @export
`risk_spread.PRE` = function(x, bond, ...) bond$coupon_rate
#' @export
`risk_spread.IPCA-I` = function(x, bond, ...) bond$coupon_rate
#' @export
`risk_spread.DI-SSU` = function(x, bond, ...) bond$coupon_rate
# theoretical value ----
#' @export
theoretical_price = function(x, ...) UseMethod("theoretical_price")
#' @export
theoretical_price.bond = function(x, spread, ...) get(.Generic)(x$type, x, spread, ...)
#' @export
`theoretical_price.DI-PERC` = function(x, bond, spread, ...) {
curve = crf.options$get("IRBRL_CURVE")
mcf = market_cashflow(bond)
.terms = mcf$BusinessDays
z_rate = curve[.terms]
discount = 1 / (( ((1 + z_rate)^(1/252) - 1)*spread + 1 )^.terms)
sum(mcf$Payments*discount)
}
#' @export
`theoretical_price.DI-SPREAD` = function(x, bond, spread, ...) {
curve = crf.options$get("IRBRL_CURVE")
mcf = market_cashflow(bond)
.terms = mcf$BusinessDays
z_rate = curve[.terms]
discount = 1 / ( (1+z_rate)^(.terms/252)*(1+spread)^(.terms/252) )
sum(mcf$Payments*discount)
}
#' @export
`theoretical_price.PRE` = function(x, bond, spread, ...) {
mcf = market_cashflow(bond)
.terms = mcf$BusinessDays
discount = 1 / ( (1+spread)^(.terms/252) )
sum(mcf$Payments*discount)
}
#' @export
`theoretical_price.IPCA-N15` = function(x, bond, spread, ...) {
mcf = market_cashflow(bond)
.terms = mcf$BusinessDays
compound = (1+spread)^(.terms/252)
sum(mcf$Payments/compound)
}
#' @export
`theoretical_price.IPCA-I` = function(x, bond, spread, ...) {
mcf = market_cashflow(bond)
.terms = mcf$BusinessDays
compound = (1+spread)^(.terms/252)
sum(mcf$Payments/compound)
}
#' @export
`theoretical_price.IPCA` = function(x, bond, spread, ...) {
mcf = market_cashflow(bond)
.terms = mcf$BusinessDays
compound = (1+spread)^(.terms/252)
sum(mcf$Payments/compound)
}
theoretical_price_2 = function(bond, curve, spread, premium = 1, ...) {
compound = (1+curve$value)^(curve$terms/252) * (1+spread$value*premium)^(curve$terms/252)
mcf = market_cashflow(bond, curve)
sum(mcf$Payments/compound)
}
theoretical_price_3 = function(bond, curve, spread, ...) {
compound = (1+curve$value)^(curve$terms/252) * (1+spread)^(curve$terms/252)
mcf = market_cashflow(bond, curve)
sum(mcf$Payments/compound)
}
theoretical_price_4 = function(x, bond, curve, spread, ...) {
compound = (1+curve$value)^(curve$terms/252) * (1+spread$value)^(curve$terms/252)
mcf = market_cashflow(bond, curve)
sum(mcf$Payments/compound)
}
# type ----
#' @export
type = function(x, ...) {
structure(x, class = x)
}
# vna ----
#' @export
vna = function(x, ...) UseMethod("vna")
#' @export
vna.bond = function(x, ...) get(.Generic)(x$type, x, ...)
#' @export
`vna.DI-SPREAD` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
date_range = paste0(
format(last_coupon_date(bond), "%Y-%m-%d"), "/",
format(offset(refdate, -1, "Brazil/ANBIMA"), "%Y-%m-%d")
)
cdi_series = crf.options$get(index(x))
cdi = as.numeric( cdi_series[date_range] )/100
c_cdi = prod( (1 + cdi)^(1/252) * (1 + bond$coupon_rate)^(1/252) )
vnr(bond) * c_cdi
}
#' @export
`vna.DI-PERC` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
date_range = paste0(
format(last_coupon_date(bond), "%Y-%m-%d"), "/",
format(offset(refdate, -1, "Brazil/ANBIMA"), "%Y-%m-%d")
)
cdi_series = crf.options$get(index(x))
cdi = as.numeric( cdi_series[date_range] )/100
c_cdi = prod( (((1 + cdi)^(1/252) - 1)*bond$perc + 1) )
vnr(bond) * c_cdi
}
#' @export
`vna.PRE` = function(x, bond, ...) {
refdate = crf.options$get("REFDATE")
du = bizdays(last_coupon_date(bond), refdate, bond$calendar)
c_cdi = (1 + bond$coupon_rate)^(du/252)
vnr(bond) * c_cdi
}
#' @export
`vna.IPCA-N15` = function(x, bond, ...) {
vnr(bond)
}
#' @export
`vna.IPCA` = function(x, bond, ...) {
vnr(bond)
}
#' @export
`vna.IPCA-I` = function(x, bond, ...) {
vnr(bond)
}
# vnr ----
#' @export
vnr = function(x, ...) UseMethod("vnr")
#' @export
vnr.bond = function(x, ...) {
refdate = crf.options$get("REFDATE")
vnr_p = x$cashflow %>% filter(Dates <= refdate) %>% pull(VNR_p)
last_vnr_p = if (length(vnr_p) == 0) 1 else last(vnr_p)
notional(x) * last_vnr_p
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment