Every interest rate calculation needs a period of time: a rate is
compounded for some time, and a curve has a rate at
each maturity. In fixedincome this period of time is a
Term object.
A Term is a number with a unit. The units can be
"day", "month" or "year", and the
plural forms are also accepted.
t <- term(6, "months")
t
#> [1] "6 months"Term extends numeric, so it is a vector: it
has a length, it can be indexed and it can be used as a column of a
data.frame.
terms <- term(c(1, 21, 42, 63), "days")
length(terms)
#> [1] 4
terms[2:3]
#> [1] "21 days" "42 days"
data.frame(terms = terms, rate = c(0.1365, 0.1366, 0.1368, 0.1371))
#> terms rate
#> 1 1 day 0.1365
#> 2 21 days 0.1366
#> 3 42 days 0.1368
#> 4 63 days 0.1371The units are kept in the units slot, and
as.numeric() returns the value without the units.
t@units
#> [1] "month"
as.numeric(t)
#> [1] 6When the units are not given, days are used.
term(10)
#> [1] "10 days"There are three ways to create a Term.
From a number and its units, with term(). Each element
can have its own units.
term(1:3, "years")
#> [1] "1 year" "2 years" "3 years"
term(c(10, 6), c("days", "months"))
#> [1] "10 days" "6 months"From text, with as.term().
From two dates and a calendar, with term(). This creates
a DateRangeTerm, a Term in days that also
keeps the two dates and the calendar used to count the days between
them. The days are counted with the bizdays package,
so with the "Brazil/ANBIMA" calendar only business days are
counted.
How many days are there in one year? It depends on the market
convention: 252 business days in Brazil, 360 or 365 actual days
elsewhere. This convention is the daycount, so converting a
Term from one unit to another needs a daycount. This is
done with todays(), tomonths() and
toyears().
one_year <- term(1, "year")
todays(daycount("business/252"), one_year)
#> [1] "252 days"
todays(daycount("actual/360"), one_year)
#> [1] "360 days"
todays(daycount("actual/365"), one_year)
#> [1] "365 days"
toyears(daycount("business/252"), term(126, "days"))
#> [1] "0.5 year"
tomonths(daycount("business/252"), term(63, "days"))
#> [1] "3 months"A month is one twelfth of a year, so with business/252
one month has 21 days.
The article Day Count Conventions explains daycounts in detail.
Arithmetic with a number keeps the Term and its units,
and comparison with a number returns a logical.
Arithmetic and comparison between two Terms work when both have the same units:
+, - and %% return a
Term;/ and %/% return a number, because the
units cancel out;
t1 <- term(42, "days")
t2 <- term(21, "days")
t1 - t2
#> [1] "21 days"
t1 / t2
#> [1] 2
t1 > t2
#> [1] TRUE* and ^ between two Terms are not defined,
because days times days has no meaning as a period of time.
try(t1 * t2)
#> Error in t1 * t2 : Operation * is not defined for two TermsTerms with different units can’t be combined directly. To add one month and twelve days, the month must first be converted into days, and that needs a daycount. So these operations raise an error.
try(term(1, "month") + term(12, "days"))
#> Error : Terms with different units: convert them first with todays(), tomonths() or toyears(), or use with_daycount()Convert first, then operate.
Or evaluate the operations with a daycount, using
with_daycount(). The Terms are converted to the smallest
unit among them: years become months, and months become days.
with_daycount("business/252", term(1, "month") + term(12, "days"))
#> [1] "33 days"
with_daycount("business/252", term(1, "year") + term(6, "months"))
#> [1] "18 months"The result depends on the daycount: one year is 252 days with
business/252, but not with actual/360.
with_daycount("business/252", term(252, "days") == term(1, "year"))
#> [1] TRUE
with_daycount("actual/360", term(252, "days") == term(1, "year"))
#> [1] FALSEOutside with_daycount() the daycount is not set, so
these operations raise an error again.
c() combines Terms, and each element keeps its own
units.
c(term(1, "day"), term(5, "days"))
#> [1] "1 day" "5 days"
c(term(10, "days"), term(6, "months"))
#> [1] "10 days" "6 months"diff() returns the Terms between consecutive elements,
and shift() moves the elements, filling the gap with
NA.
terms <- term(c(1, 21, 42, 63), "days")
diff(terms)
#> [1] "20 days" "21 days" "21 days"
shift(terms)
#> [1] "NA days" "1 day" "21 days" "42 days"Summary functions like sum() and cumsum()
return plain numbers. Use term() to get a Term
back.
A spot rate is compounded for a Term. The units of the
Term are converted with the daycount of the rate, so six
months and half a year give the same compounding factor.
sr <- spotrate(0.1375, "discrete", "business/252", "Brazil/ANBIMA")
compound(sr, term(6, "months"))
#> [1] 1.066536
compound(sr, term(0.5, "years"))
#> [1] 1.066536
compound(sr, term(126, "days"))
#> [1] 1.066536The terms of a SpotRateCurve are kept in days. Indexing
a curve with [[ accepts a Term in any units,
and converts it to days with the daycount of the curve.
curve <- spotratecurve(
c(0.1315, 0.1319, 0.1338, 0.1348, 0.1372, 0.1381),
c(1, 21, 42, 63, 126, 252),
"discrete", "business/252", "Brazil/ANBIMA",
refdate = as.Date("2022-08-05")
)
curve[[term(1, "year")]]
#> SpotRateCurve
#> 252 days 0.1381
#> discrete business/252 Brazil/ANBIMA
#> Reference date: 2022-08-05
curve[[term(c(3, 6), "months")]]
#> SpotRateCurve
#> 63 days 0.1348
#> 126 days 0.1372
#> discrete business/252 Brazil/ANBIMA
#> Reference date: 2022-08-05With an interpolation, the curve also returns rates between its terms.
interpolation(curve) <- interp_flatforward()
curve[[term(c(10, 100), "days")]]
#> SpotRateCurve
#> 10 days 0.1319
#> 100 days 0.1366
#> discrete business/252 Brazil/ANBIMA
#> Reference date: 2022-08-05Forward rates between two Terms are computed with
forwardrate().
forwardrate(curve, term(3, "months"), term(6, "months"))
#> ForwardRate
#> 63 days 0.1396051
#> discrete business/252 Brazil/ANBIMA