Title: | Basic Finance; NPV/IRR/Annuities/Bond-Pricing; Black Scholes |
---|---|
Description: | 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. |
Authors: | Jayanth Varma [aut, cre] |
Maintainer: | Jayanth Varma <[email protected]> |
License: | GPL (>=2) |
Version: | 1.4.3 |
Built: | 2024-10-27 05:49:46 UTC |
Source: | https://github.com/jrvarma/jrvfinance |
This 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, NPV and duration of possibly irregularly spaced cash flows and annuities. Bond pricing, YTM and duration calculations are included. Black Scholes option pricing, Greeks and implied volatility are also provided.
Important functions include:
npv
, irr
, duration
,
annuity.pv
, bond.price
, bond.yield
,
GenBS
, GenBSImplied
For more details, see the vignette
Prof. Jayanth R. Varma [email protected]
The 30/360 day count was converted from C++ code in the QuantLib library. The Newton Raphson solver was converted from C++ code in the Boost library
Functions to compute present value and future value of annuities, to find instalment given the present value or future value. Can also find the rate or the number of periods given other parameters.
annuity.pv( rate, n.periods = Inf, instalment = 1, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.fv( rate, n.periods = Inf, instalment = 1, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.instalment( rate, n.periods = Inf, pv = if (missing(fv)) 1 else 0, fv = 0, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.periods( rate, instalment = 1, pv = if (missing(fv)) 1 else 0, fv = 0, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1, round2int.digits = 3 ) annuity.rate( n.periods = Inf, instalment = 1, pv = if (missing(fv)) 1 else 0, fv = 0, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.instalment.breakup( rate, n.periods = Inf, pv = 1, immediate.start = FALSE, cf.freq = 1, comp.freq = 1, period.no = 1 )
annuity.pv( rate, n.periods = Inf, instalment = 1, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.fv( rate, n.periods = Inf, instalment = 1, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.instalment( rate, n.periods = Inf, pv = if (missing(fv)) 1 else 0, fv = 0, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.periods( rate, instalment = 1, pv = if (missing(fv)) 1 else 0, fv = 0, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1, round2int.digits = 3 ) annuity.rate( n.periods = Inf, instalment = 1, pv = if (missing(fv)) 1 else 0, fv = 0, terminal.payment = 0, immediate.start = FALSE, cf.freq = 1, comp.freq = 1 ) annuity.instalment.breakup( rate, n.periods = Inf, pv = 1, immediate.start = FALSE, cf.freq = 1, comp.freq = 1, period.no = 1 )
rate |
The interest rate in decimal (0.10 or 10e-2 for 10%) |
n.periods |
The number of periods in the annuity. |
instalment |
The instalment (cash flow) per period. |
terminal.payment |
Any cash flow at the end of the annuity. For example, a bullet repayment at maturity of the unamortized principal. |
immediate.start |
Logical variable which is |
cf.freq |
Frequency of annuity payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
comp.freq |
Frequency of compounding of interest rates: 1 for annual, 2 for semi-annual, 12 for monthly, Inf for continuous compounding. |
pv |
The present value of all the cash flows including the terminal payment. |
fv |
The future value (at the end of the annuity) of all the cash flows including the terminal payment. |
round2int.digits |
Used only in |
period.no |
Used only in |
These functions are based on the Present Value relationship:
where
is the
discount factor and
is the per period interest rate computed using
rate, cf.freq and comp.freq.
It is intended that only one of or
is used in any function call, but
internally the functions use
as the
LHS of the present value relationship under the assumption that only of the
two is non zero.
The function annuity.instalment.breakup
regards the annuity as a repayment
of a loan equal to pv
plus the present value of terminal.payment. The
instalment paid in period period.no is broken up into the principal
repayment (amortization) and interest components.
For most functions, the return value is one of the arguments
described above. For example annuity.pv
returns pv
. The only exception is
annuity.instalment.breakup
. This returns a list with the following
components:
opening.principal |
The principal balance at the beginning of the period |
closing.principal |
The principal balance at the end of the period |
interest.part |
The portion of the instalment which represents interest |
principal.part |
The portion of the instalment which represents principal repayment |
Prof. Jayanth R. Varma [email protected]
Tries to find the zero of a function by using the bisection method
(uniroot
). To call
uniroot
, the zero must be bracketed by
finding two points at which the function value has opposite
signs. The main code in this function is a grid search to find
such a pair of points. A geometric grid of points between
lower
and guess
and also between guess
and
upper
. This grid is searched for two neighbouring points
across which the function changes sign. This brackets the root,
and then we try to locate the root by calling
uniroot
bisection.root(f, guess, lower, upper, nstep = 100, toler = 1e-06)
bisection.root(f, guess, lower, upper, nstep = 100, toler = 1e-06)
f |
The function whose zero is to be found. An R function object that takes one numeric argument and returns a numeric value. In an IRR application, this will be the NPV function. In an implied volatility application, the value will be the option price. |
guess |
The starting value (guess) from which the solver starts searching for the root. Must be positive. |
lower |
The lower end of the interval within which to search for the root. Must be positive. |
upper |
The upper end of the interval within which to search for the root. Must be positive. |
nstep |
The number of steps in the grid search to bracket the zero. See details. |
toler |
The criterion to determine whether a zero has been
found. This is passed on to |
The root (or NA if the method fails)
Prof. Jayanth R. Varma
bond.price computes the price given the yield to maturity
bond.duration computes the duration given the yield to maturity
bond.yield computes the yield to maturity given the price
bond.prices, bond.durations and bond.yields are wrapper functions
that use mapply
to vectorize bond.price, bond.duration and bond.yield
All arguments to bond.prices, bond.durations and bond.yields
can be vectors.
On the other hand, bond.price, bond.duration and bond.yield do not allow vectors
Standard compounding and day count conventions are supported for all functions.
bond.price( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.yield( settle, mature, coupon, freq = 2, price, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.duration( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), modified = FALSE, comp.freq = freq, redemption_value = 100 ) bond.TCF( settle, mature, coupon, freq = 2, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), redemption_value = 100 ) bond.prices( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.yields( settle, mature, coupon, freq = 2, price, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.durations( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), modified = FALSE, comp.freq = freq, redemption_value = 100 )
bond.price( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.yield( settle, mature, coupon, freq = 2, price, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.duration( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), modified = FALSE, comp.freq = freq, redemption_value = 100 ) bond.TCF( settle, mature, coupon, freq = 2, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), redemption_value = 100 ) bond.prices( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.yields( settle, mature, coupon, freq = 2, price, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), comp.freq = freq, redemption_value = 100 ) bond.durations( settle, mature, coupon, freq = 2, yield, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E"), modified = FALSE, comp.freq = freq, redemption_value = 100 )
settle |
The settlement date for which the bond is traded. Can be a
character string or any object that can be converted into date using
|
mature |
The maturity date of the bond. Can be a character string or
any object that can be converted into date using |
coupon |
The coupon rate in decimal (0.10 or 10e-2 for 10%) |
freq |
The frequency of coupon payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
yield |
The yield to maturity of the bond |
convention |
The daycount convention |
comp.freq |
The frequency of compounding of the bond yield: 1 for annual, 2 for semi-annual, 12 for monthly. Usually same as freq. |
redemption_value |
The principal amount that the bond will pay on maturity or call. Typically necessary when the bond is expected to be called at premium to par. |
price |
The clean price of the bond. |
modified |
A logical value used in duration. |
bond.TCF
returns a list of three components
t |
A vector of cash flow dates in number of years |
cf |
A vector of cash flows |
accrued |
The accrued interest |
Prof. Jayanth R. Varma [email protected]
Convenience functions for finding coupon dates and number of coupons of a bond.
coupons.dates(settle, mature, freq = 2) coupons.n(settle, mature, freq = 2) coupons.next(settle, mature, freq = 2) coupons.prev(settle, mature, freq = 2)
coupons.dates(settle, mature, freq = 2) coupons.n(settle, mature, freq = 2) coupons.next(settle, mature, freq = 2) coupons.prev(settle, mature, freq = 2)
settle |
The settlement date for which the bond is traded. Can be a
character string or any object that can be converted into date using
|
mature |
The maturity date of the bond. Can be a character string or
any object that can be converted into date using |
freq |
The frequency of coupon payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
Prof. Jayanth R. Varma [email protected]
Implements 30/360, ACT/360, ACT/360 and 30/360E day count conventions.
yearFraction( d1, d2, r1, r2, freq = 2, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E") ) daycount.actual(d1, d2, variant = c("bond")) daycount.30.360(d1, d2, variant = c("US", "EU", "IT"))
yearFraction( d1, d2, r1, r2, freq = 2, convention = c("30/360", "ACT/ACT", "ACT/360", "30/360E") ) daycount.actual(d1, d2, variant = c("bond")) daycount.30.360(d1, d2, variant = c("US", "EU", "IT"))
d1 |
The starting date of period for day counts |
d2 |
The ending date of period for day counts |
r1 |
The starting date of reference period for ACT/ACT day counts |
r2 |
The ending date of reference period for ACT/ACT day counts |
freq |
The frequency of coupon payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
convention |
The daycount convention |
variant |
Three variants of the 30/360 convention are implemented, but only one variant of ACT/ACT is currently implemented |
Prof. Jayanth R. Varma [email protected]
The 30/360 day count was converted from C++ code in the QuantLib library
Computes Duration and Modified Duration for cash flows with different cash flow and compounding conventions. Cash flows need not be evenly spaced.
duration( cf, rate, cf.freq = 1, comp.freq = 1, cf.t = seq(from = ifelse(immediate.start, 0, 1/cf.freq), by = 1/cf.freq, along.with = cf), immediate.start = FALSE, modified = FALSE )
duration( cf, rate, cf.freq = 1, comp.freq = 1, cf.t = seq(from = ifelse(immediate.start, 0, 1/cf.freq), by = 1/cf.freq, along.with = cf), immediate.start = FALSE, modified = FALSE )
cf |
Vector of cash flows |
rate |
The interest rate in decimal (0.10 or 10e-2 for 10%) |
cf.freq |
Frequency of annuity payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
comp.freq |
Frequency of compounding of interest rates: 1 for annual, 2 for semi-annual, 12 for monthly, Inf for continuous compounding. |
cf.t |
Optional vector of timing (in years) of cash flows. If omitted regular sequence of years is assumed. |
immediate.start |
Logical variable which is |
modified |
in function duration, |
Convenience function for finding the same date in different months. Used for example
to find coupon dates of bonds given the maturity date. See coupons
edate(from, months = 1)
edate(from, months = 1)
from |
starting date - a character string or any object that can be
converted into date using |
months |
Number of months (can be negative) |
Converts an interest rate from one compounding convention to another (for example from semi-annual to monthly compounding or from annual to continuous compounding)
equiv.rate(rate, from.freq = 1, to.freq = 1)
equiv.rate(rate, from.freq = 1, to.freq = 1)
rate |
The interest rate in decimal (0.10 or 10e-2 for 10%) |
from.freq |
Frequency of compounding of the given interest rate: 1 for annual, 2 for semi-annual, 12 for monthly, Inf for continuous compounding. |
to.freq |
Frequency of compounding to which the given
interest rate is to be converted: 1 for annual, 2 for
semi-annual, 12 for monthly, |
Compute values of call and put options as well as the Greeks - the sensitivities of the option price to various input arguments using the Generalized Black Scholes model. "Generalized" means that the asset can have a continuous dividend yield.
GenBS(s, X, r, Sigma, t, div_yield = 0)
GenBS(s, X, r, Sigma, t, div_yield = 0)
s |
the spot price of the asset (the stock price for options on stocks) |
X |
the exercise or strike price of the option |
r |
the continuously compounded rate of interest in decimal (0.10 or 10e-2 for 10%)
(use |
Sigma |
the volatility of the asset price in decimal (0.20 or 20e-2 for 20%) |
t |
the maturity of the option in years |
div_yield |
the continuously compounded dividend yield (0.05 or 5e-2 for 5%)
(use |
The Generalized Black Scholes formula for call options is
where
and
N denotes the normal CDF (pnorm
)
For put options, the formula is
where and
A list of the following elements
call |
the value of a call option |
put |
the value of a put option |
Greeks |
a list of the following elements |
Greeks$callDelta |
the delta of a call option - the sensitivity to the spot price of the asset |
Greeks$putDelta |
the delta of a put option - the sensitivity to the spot price of the asset |
Greeks$callTheta |
the theta of a call option - the time decay of the option value with passage of time. Note that time is measured in years. To find a daily theta divided by 365. |
Greeks$putTheta |
the theta of a put option |
Greeks$Gamma |
the gamma of a call or put option - the second derivative with respect to the spot price or the sensitivity of delta to the spot price |
Greeks$Vega |
the vega of a call or put option - the sensitivity to the volatility |
Greeks$callRho |
the rho of a call option - the sensitivity to the interest rate |
Greeks$putRho |
the rho of a put option - the sensitivity to the interest rate |
extra |
a list of the following elements |
extra$d1 |
the d1 of the Generalized Black Scholes formula |
extra$d2 |
the d2 of the Generalized Black Scholes formula |
extra$Nd1 |
is |
extra$Nd2 |
is |
extra$Nminusd1 |
is |
extra$Nminusd2 |
is |
extra$callProb |
the (risk neutral) probability that the call will be exercised = |
extra$putProb |
the (risk neutral) probability that the put will be exercised = |
Find implied volatility given the option price using the generalized Black Scholes model. "Generalized" means that the asset can have a continuous dividend yield.
GenBSImplied( s, X, r, price, t, div_yield, PutOpt = FALSE, toler = 1e-06, max.iter = 100, convergence = 1e-08 )
GenBSImplied( s, X, r, price, t, div_yield, PutOpt = FALSE, toler = 1e-06, max.iter = 100, convergence = 1e-08 )
s |
the spot price of the asset (the stock price for options on stocks) |
X |
the exercise or strike price of the option |
r |
the continuously compounded rate of interest in decimal (0.10 or 10e-2 for 10%)
(use |
price |
the price of the option |
t |
the maturity of the option in years |
div_yield |
the continuously compounded dividend yield (0.05 or 5e-2 for 5%)
(use |
PutOpt |
|
toler |
passed on to |
max.iter |
passed on to |
convergence |
passed on to |
GenBSImplied
calls newton.raphson.root
and
if that fails uniroot
Computes IRR (Internal Rate of Return) for cash flows with different cash flow and compounding conventions. Cash flows need not be evenly spaced.
irr( cf, interval = NULL, cf.freq = 1, comp.freq = 1, cf.t = seq(from = 0, by = 1/cf.freq, along.with = cf), r.guess = NULL, toler = 1e-06, convergence = 1e-08, max.iter = 100, method = c("default", "newton", "bisection") )
irr( cf, interval = NULL, cf.freq = 1, comp.freq = 1, cf.t = seq(from = 0, by = 1/cf.freq, along.with = cf), r.guess = NULL, toler = 1e-06, convergence = 1e-08, max.iter = 100, method = c("default", "newton", "bisection") )
cf |
Vector of cash flows |
interval |
the interval c(lower, upper) within which to search for the IRR |
cf.freq |
Frequency of annuity payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
comp.freq |
Frequency of compounding of interest rates: 1 for annual, 2 for semi-annual, 12 for monthly, Inf for continuous compounding. |
cf.t |
Optional vector of timing (in years) of cash flows. If omitted regular sequence of years is assumed. |
r.guess |
the starting value (guess) from which the solver starts searching for the IRR |
toler |
the argument |
convergence |
the argument |
max.iter |
the argument |
method |
The root finding method to be used. The
|
This function computes the internal rate of return at which the
net present value equals zero. It requires as input a function
that computes the net present value of a series of cash flows for
a given interest rate as well as the derivative of the NPV with
respect to the interest rate (10,000 times this derivative is the
PVBP or DV01). In this package, irr.solve
is primarily
intended to be called by the irr
and
bond.yield
functions. It is made available for those
who want to find IRR of more complex instruments.
irr.solve( f, interval = NULL, r.guess = NULL, toler = 1e-06, convergence = 1e-08, max.iter = 100, method = c("default", "newton", "bisection") )
irr.solve( f, interval = NULL, r.guess = NULL, toler = 1e-06, convergence = 1e-08, max.iter = 100, method = c("default", "newton", "bisection") )
f |
The function whose zero is to be found. An R function object that takes one numeric argument and returns a list of two components (value and gradient). In the IRR applications, these two components will be the NPV and its derivative |
interval |
The interval c(lower, upper) within which to search for the IRR |
r.guess |
The starting value (guess) from which the solver starts searching for the IRR |
toler |
The argument |
convergence |
The argument |
max.iter |
The maximum number of iterations of the Newton-Raphson procedure |
method |
The root finding method to be used. The
|
The function irr.solve
is basically an interface to the
general root finder newton.raphson.root
. However, if
newton.raphson.root
fails, irr.solve
makes an
attempt to find the root using uniroot
from the R
stats package. Uniroot
uses bisection and it requires the root to
be bracketed (the function must be of opposite sign at the two end
points - lower and upper).
The function irr.solve
returns NA
if the IRR/YTM
could not be found. Otherwise it returns the IRR/YTM. When
NA
is returned, a warning message is printed
Prof. Jayanth R. Varma [email protected]
The function newton.raphson.root
is a general root finder which
can find the zero of any function whose derivative is available.
In this package, it is called by irr.solve
and by
GenBSImplied
. It can be used in other situations as
well - see the examples below.
newton.raphson.root( f, guess = 0, lower = -Inf, upper = Inf, max.iter = 100, toler = 1e-06, convergence = 1e-08 )
newton.raphson.root( f, guess = 0, lower = -Inf, upper = Inf, max.iter = 100, toler = 1e-06, convergence = 1e-08 )
f |
The function whose zero is to be found. An R function object that takes one numeric argument and returns a list of two components (value and gradient). In an IRR application, these two components will be the NPV and the DV01/10000. In an implied volatility application, the components will be the option price and the vega. See also the examples below |
guess |
The starting value (guess) from which the solver starts searching for the IRR |
lower |
The lower end of the interval within which to search for the root |
upper |
The upper end of the interval within which to search for the root |
max.iter |
The maximum number of iterations of the Newton-Raphson procedure |
toler |
The criterion to determine whether a zero has been
found. If the value of the function exceeds |
convergence |
The relative tolerance threshold used to
determine whether the Newton-Raphson procedure has
converged. The procedure terminates when the last step is less
than |
The function returns NA
under either of two conditions: (a)
the procedure did not converge after max.iter
iterations,
or (b) the procedure converged but the function value is not zero
within the limits of toler
at this point. The second
condition usually implies that the procedure has converged to a
non zero local minimum from which there is no downhill gradient.
If the iterations converge to a genuine root (within the limits of
toler
), then it returns the root that was found.
The Newton Raphson solver was converted from C++ code in the Boost library
Computes NPV (Net Present Value) for cash flows with different cash flow and compounding conventions. Cash flows need not be evenly spaced.
npv( cf, rate, cf.freq = 1, comp.freq = 1, cf.t = seq(from = if (immediate.start) 0 else 1/cf.freq, by = 1/cf.freq, along.with = cf), immediate.start = FALSE )
npv( cf, rate, cf.freq = 1, comp.freq = 1, cf.t = seq(from = if (immediate.start) 0 else 1/cf.freq, by = 1/cf.freq, along.with = cf), immediate.start = FALSE )
cf |
Vector of cash flows |
rate |
The interest rate in decimal (0.10 or 10e-2 for 10%) |
cf.freq |
Frequency of annuity payments: 1 for annual, 2 for semi-annual, 12 for monthly. |
comp.freq |
Frequency of compounding of interest rates: 1 for annual, 2 for semi-annual, 12 for monthly, Inf for continuous compounding. |
cf.t |
Optional vector of timing (in years) of cash flows. If omitted regular sequence of years is assumed. |
immediate.start |
Logical variable which is |