---
title: "jrvFinance Usage"
author: "Jayanth R. Varma"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{jrvFinance Usage}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
# Contents
* [Introduction](#intro)
* [Net Present Value (NPV) and Internal Rate of Return (IRR)](#npv)
* [Duration of general cash flows](#dur)
* [Annuity functions](#annuity)
* [Bond Pricing](#bond)
* [(Generalized) Black Scholes Formulas](#gbs)
* [Utility functions](#util)
# Introduction
The `jrvFinance` R package implements the basic financial analysis
functions similar to (but not identical to) what is available in most
spreadsheet software. This includes finding the IRR and NPV of
regularly spaced cash flows and annuities. Bond pricing and YTM
calculations are included. In addition, Black Scholes option pricing
and Greeks are also provided.
```{r}
library(jrvFinance)
```
# NPV and IRR
Find Net Present Value (NPV) at 5% of cash flows of 100, 250 and 300
in years 1, 2 and 3 respectively:
```{r}
npv(cf=c(100,250,300), rate=5e-2)
```
Find NPV at 10% of cash flows of 1, 3 and 2 in years 0.3, 1.9 and 2.5
respectively (this is known in XNPV in spreadsheet software):
```{r}
npv(cf=c(1,3,2), rate=10e-2, cf.t=c(0.3,1.9,2.5))
```
Find the rate of interest (IRR) if a loan of 600 is repaid in two
annual instalments of 300 and 400:
```{r}
irr(c(-600,300,400))
```
Negative interest rates are handled without difficulty
```{r}
irr(c(-600,100,400))
```
Find the rate of interest if a loan of 450 is repaid by paying 100
after 0.3 years, 300 after 1.9 years and 200 after 2.5 years (this is
known in XIRR in spreadsheet software)
```{r}
irr(cf=c(-450,100,300,200), cf.t=c(0, 0.3,1.9,2.5))
```
Find multiple IRRs by providing interval within which to search for
the IRR:
```{r}
irr(cf=c(100, -230, 132), interval = c(0.05, 0.17))
irr(cf=c(100, -230, 132), interval = c(0.17, 0.50))
```
Find multiple IRRs by providing different guess values for the IRR:
```{r}
irr(cf=c(100, -230, 132), r.guess = 0)
irr(cf=c(100, -230, 132), r.guess = 0.5)
```
# Duration of general cash flows
There is a separate set of functions for computing duration for
bonds. In this section, we look at the functions for computing
duration of general sequence of cash flows.
Find duration of a stream of cash flows of 100, 250 and 300 in years
1, 2 and 3 when the interest rate is 5%:
```{r}
duration(cf=c(100,250,300), rate=5e-2)
```
Find modified duration of same cash flows:
```{r}
duration(cf=c(100,250,300), rate=5e-2, modified=TRUE)
```
# Annuity functions
Find the present value at 10% of 15 annual instalments of 1 each
period:
```{r}
annuity.pv(rate=10e-2, n.periods=15)
```
Find present value at 10% of 15 annual instalments of 1 each period
where the annuity starts immediately:
```{r}
annuity.pv(rate=10e-2, n.periods=15, immediate.start = TRUE)
```
Find the present value at 7% of a perpetuity of 35 per annum :
```{r}
annuity.pv(rate=7e-2, instalment = 35, n.periods=Inf)
## or more simply
annuity.pv(rate=7e-2, instalment = 35)
```
Consider an annuity of 360 monthly instalments (30 years) where each
instalment is 450. Find the present value of the above annuity at 10%
semi-annually compounded:
```{r}
annuity.pv(rate=10e-2, instalment = 450, n.periods=360, cf.freq=12, comp.freq=2)
```
Find the semi-annually compounded rate if the above annuity has
present value of 50,000:
```{r}
annuity.rate(pv=50000, instalment = 450, n.periods=360, cf.freq=12, comp.freq=2)
```
Negative interest rates are handled without difficulty:
```{r}
annuity.rate(pv=250000, instalment = 450, n.periods=360, cf.freq=12, comp.freq=2)
```
Suppose a loan of 10,000 is to be repaid in 8 equal annual instalments
and the interest rate is 9% annually compounded. Find the annual
instalment:
```{r}
annuity.instalment(rate=9e-2, pv=10000, n.periods=8)
```
Breakup the 5th instalment of above annuity into its principal and
interest components:
```{r}
AIB <- annuity.instalment.breakup(rate=9e-2, pv=10000, n.periods=8,
period.no=5)
# we use unlist to print the result more compactly
unlist(AIB)
```
# Bond Price, Yield and Duration
Find price on 15 April 2012 of 8% bond maturing on 1 January 2022 at
8.8843% yield (By default, all the bond functions assume semi-annual
coupons and semi-annually compounded yield):
```{r}
bond.price(settle="2012-04-15", mature="2022-01-01", coupon=8e-2,
yield=8.8843e-2)
```
Same bond with annual coupons and annually compounded yield (We use
the `freq` argument to change the coupon frequency. By default,
compounding frequency of the yield is assumed to be the same as the
coupon frequency):
```{r}
bond.price(settle="2012-04-15", mature="2022-01-01", coupon=8e-2,
yield=8.8843e-2, freq=1)
```
Same bond with annual coupon and semi-annually compounded yield (We
set the `comp-freq` argument to use a compounding frequency different
from the coupon frequency):
```{r}
bond.price(settle="2012-04-15", mature="2022-01-01", coupon=8e-2,
yield=8.8843e-2, freq=1, comp.freq=2)
```
A bond with 5% coupon is callable at 102 on 1-Jan-2023 and is trading at an yield to call of 6% on 1-Jan-2018. The price is:
```{r}
bond.yield(settle='2018-01-01', mature='2023-01-01', coupon=5e-2, price=101,
redemption_value = 102)
```
Compute the yield given the price:
```{r}
bond.yield(settle="2012-04-15", mature="2022-01-01", coupon=8e-2,
price=95)
```
Negative yields are handled properly:
```{r}
bond.yield(settle="2012-04-15", mature="2017-01-01", coupon=1e-2,
price=120)
```
Yield to call:
```{r}
bond.yield(settle='2018-01-01', mature='2023-01-01', coupon=5e-2, price=101,
redemption_value = 102)
```
Duration on 15 April 2012 of 8% bond maturing on 1 January 2022 at
8.8843% yield (semi-annual coupons and semi-annually compounded
yield)
```{r}
bond.duration(settle="2012-04-15", mature="2022-01-01", coupon=8e-2,
yield=8.8843e-2)
```
Modified duration of same bond:
```{r}
bond.duration(settle="2012-04-15", mature="2022-01-01", coupon=8e-2,
yield=8.8843e-2, modified=TRUE)
```
Find prices of many bonds with one function call:
```{r}
bond.prices(settle="2012-01-01", mature=c("2022-01-01", "2032-01-01"),
coupon=c(0.09, 0.08,0.07,0.06), yield=0.10)
```
Find yields of many bonds with one function call
```{r}
bond.yields(settle="2012-01-01", mature=c("2022-01-01", "2032-01-01"),
coupon=c(0.09, 0.08,0.07,0.06),
price=c(94, 83, 81, 65))
```
Find durations of many bonds with one function call:
```{r}
bond.durations(settle="2012-01-01",
mature=c("2022-01-01", "2032-01-01"),
coupon=c(0.09, 0.08,0.07,0.06), yield=0.10)
```
Find all the coupon dates of a bond:
```{r}
coupons.dates(settle="2012-04-15", mature="2022-01-01")
coupons.dates(settle="2012-04-15", mature="2022-01-01", freq=1)
```
Find a specific coupon date:
```{r}
coupons.next(settle="2012-04-15", mature="2022-04-01")
coupons.prev(settle="2012-04-15", mature="2022-04-01")
```
Find the number of coupons:
```{r}
coupons.n(settle="2012-04-15", mature="2017-07-01")
```
# (Generalized) Black Scholes Formulas
Find Black Scholes options values and Greeks when spot price and
strike = 100, interest rate = 10%, volatility = 20%, maturity = 1
year:
```{r}
BS <- GenBS(s=100, X=100, r=0.1, Sigma=20e-2, t=1, div_yield=0)
# we use unlist to print the result more compactly
unlist(BS)
```
Next we illustrate the generalized Black Scholes formulas where the
asset pays a continuous dividend yield. This is useful for foreign
currency options, options on futures and options on stock indices.
Spot price =100, strike = 120, interest rate = 10%, volatility = 15%,
maturity = 1 year, and dividend yield = 5.8%:
```{r}
GBS <- GenBS(s=100, X=120, r=0.1, Sigma=15e-2, t=1, div_yield=5.8e-2)
# we use unlist to print the result more compactly
unlist(GBS)
```
Find implied volatility when call price is 7.97 ,spot price and strike
= 100, interest rate zero, and maturity is 1 year:
```{r}
GenBSImplied(s=100, X=100, r=0, price=7.97, t=1, div_yield=0)
```
Same as above but strike = 90. Since the option price is less than
intrinsic value, the implied volatility is undefined:
```{r}
GenBSImplied(s=100, X=90, r=0, price=7.97, t=1, div_yield=0)
```
Same as above but strike = 900. Since the strike is so far out of the
money, a rather high implied volatility is needed for the option to be
valuable:
```{r}
GenBSImplied(s=100, X=900, r=0, price=7.97, t=1, div_yield=0)
```
# Utility functions
## Equivalent rate with different compounding frequency
Convert 10% monthly compounded rate to equivalent semi-annually
compounded rate
```{r}
equiv.rate(10e-2, from.freq = 12, to.freq = 2)
```
Convert 15% annually compounded rate to equivalent continuously
compounded rate
```{r}
equiv.rate(15e-2, from.freq = 1, to.freq = Inf)
```
## edate
`edate` is a common spreadsheet function which is used in this package
for finding coupon dates. It is made available for general use.
Find date eight months prior to 17 May 2005:
```{r}
edate("2005-05-17", -8)
```
Find date four months after 28 February 2007. Note that the output is
the last day of June and not the 28th June
```{r}
edate("2007-02-28", 4)
```
But things change in a leap year
```{r}
edate("2008-02-28", 4)
```
## Newton Raphson root solver
The package implements a Newton Raphson root solver that is used
internally to calculate IRR and YTM. It is available for general use.
Find root of the equation *sin(x) = cos(x)*. (Analytically, the root
is known to be π/4)
```{r}
fn1 <-function(x){list(value=sin(x)-cos(x), gradient=cos(x)+sin(x))}
newton.raphson.root(fn1)
```
Try to find root of equation which has no real root: *sin(x) = -2*
```{r}
fn2 <-function(x){list(value=2 + sin(x), gradient=cos(x))}
newton.raphson.root(fn2)
```
## Bisection root solver
The package implements a bisection root solver that does a geometric
grid search to bracket the root and then calls `uniroot` to find the
root within this interval. The package uses the function internally to
calculate IRR and YTM, but `bisection.root` is available for general
use.
For example, the values of 1, 7, 12 and 13 do not bracket the root of
sin(x) since the function is positive at all these values, but
`bisection.root` finds the root given these numbers as the
interval and the guess value.
```{r}
bisection.root(sin, guess = 7, lower=1, upper=13)
bisection.root(sin, guess = 12, lower=1, upper=13)
```