Last active
May 4, 2018 16:56
-
-
Save wilsonfreitas/80ff2bd8800732969a4f71e6f77d3846 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' @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