Skip to content

Commit d658db1

Browse files
authored
Merge pull request #7 from PyFE/desc
Changes for package
2 parents 62e1287 + 4e6c47e commit d658db1

14 files changed

+138
-99
lines changed

pkg/DESCRIPTION

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
Package: FER
2-
Title: Financial Engineering functions in R
3-
Version: 0.9
2+
Title: Financial Engineering (FE) functions in R
3+
Version: 0.91
44
Authors@R: person("Jaehyuk", "Choi", email = "[email protected]", role = c("aut", "cre"))
5-
Description: What the package does (one paragraph).
5+
Description: R implementations of standard financial engineering codes;
6+
vanilla option pricing models such as Black-Scholes, Bachelier, CEV, and
7+
SABR.
8+
URL: https://github.com/PyFE/FE-R
9+
BugReports: https://github.com/PyFE/FE-R/issues
610
Depends:
711
R (>= 3.3.1)
12+
NeedsCompilation: no
813
License: MIT + file LICENSE
914
Encoding: UTF-8
1015
LazyData: true
1116
RoxygenNote: 7.1.1
1217
Imports:
18+
stats,
1319
statmod,
1420
devtools
1521
Suggests:

pkg/NAMESPACE

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,3 @@ export(BlackScholesImpvol)
66
export(BlackScholesPrice)
77
export(CevPrice)
88
export(SabrHagan2002)
9-
import(stats)

pkg/R/bachelier_impvol.R

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,14 @@
66
#' @param texp (vector of) time to expiry
77
#' @param intr interest rate
88
#' @param divr dividend rate
9-
#' @param cpsign call/put sign. 1 for call, -1 for put.
9+
#' @param cp call/put sign. \code{1} for call, \code{-1} for put.
1010
#' @param forward forward price. If given, \code{forward} overrides \code{spot}
1111
#' @param df discount factor. If given, \code{df} overrides \code{intr}
1212
#' @return Bachelier implied volatility
1313
#'
14-
#' @references Choi, J., Kim, K., & Kwak, M. (2009). Numerical Approximation of the Implied Volatility Under Arithmetic Brownian Motion. Applied Mathematical Finance, 16(3), 261–268.
14+
#' @references Choi, J., Kim, K., & Kwak, M. (2009).
15+
#' Numerical Approximation of the Implied Volatility Under Arithmetic Brownian
16+
#' Motion. Applied Mathematical Finance, 16(3), 261-268.
1517
#' \url{https://doi.org/10.1080/13504860802583436}
1618
#'
1719
#' @export
@@ -23,18 +25,17 @@
2325
#' sigma <- 20
2426
#' intr <- 0.05
2527
#' price <- 20
26-
#' vol <- FER::BachelierImpvol(price, strike, spot, texp, intr=intr)
28+
#' FER::BachelierImpvol(price, strike, spot, texp, intr=intr)
2729
#'
2830
#' @seealso \code{\link{BachelierPrice}}
2931
#'
3032
BachelierImpvol <- function(
31-
price, strike = forward, spot, texp = 1,
32-
intr = 0, divr = 0, cpsign = 1,
33-
forward = spot*exp(-divr*texp)/df,
34-
df = exp(-intr*texp)
33+
price, strike=forward, spot, texp=1,
34+
intr=0, divr=0, cp=1L,
35+
forward=spot*exp(-divr*texp)/df, df=exp(-intr*texp)
3536
){
3637

37-
price.straddle = 2*price/df - cpsign*(forward - strike)
38+
price.straddle <- 2*price/df - cp*(forward - strike)
3839

3940
# vectors a and b used for rational Chebyshev approximation
4041
a <- c(3.994961687345134e-1,

pkg/R/bachelier_price.R

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,34 +6,37 @@
66
#' @param sigma (vector of) volatility
77
#' @param intr interest rate
88
#' @param divr dividend rate
9-
#' @param cpsign call/put sign. 1 for call, -1 for put.
9+
#' @param cp call/put sign. \code{1} for call, \code{-1} for put.
1010
#' @param forward forward price. If given, \code{forward} overrides \code{spot}
1111
#' @param df discount factor. If given, \code{df} overrides \code{intr}
1212
#' @return option price
13-
#' @import stats
1413
#' @export
1514
#'
15+
#' @references Choi, J., Kim, K., & Kwak, M. (2009).
16+
#' Numerical Approximation of the Implied Volatility Under Arithmetic Brownian
17+
#' Motion. Applied Mathematical Finance, 16(3), 261-268.
18+
#' \url{https://doi.org/10.1080/13504860802583436}
19+
#'
1620
#' @examples
1721
#' spot <- 100
1822
#' strike <- seq(80,125,5)
1923
#' texp <- 1.2
2024
#' sigma <- 20
2125
#' intr <- 0.05
22-
#' price <- FER::BachelierPrice(strike, spot, texp, sigma, intr=intr)
26+
#' FER::BachelierPrice(strike, spot, texp, sigma, intr=intr)
2327
#'
2428
#' @seealso \code{\link{BachelierImpvol}}
2529
#'
2630
BachelierPrice <- function(
27-
strike = forward, spot, texp = 1, sigma,
28-
intr = 0, divr = 0, cpsign=1,
29-
forward = spot*exp(-divr*texp)/df,
30-
df = exp(-intr*texp)
31+
strike=forward, spot, texp=1, sigma,
32+
intr=0, divr=0, cp=1L,
33+
forward=spot*exp(-divr*texp)/df, df=exp(-intr*texp)
3134
){
3235
stdev <- sigma*sqrt(texp)
3336
stdev[stdev < 1e-32] <- 1e-32
34-
dn <- cpsign*(forward-strike) / stdev
37+
dn <- cp*(forward-strike)/stdev
3538

3639
#Option Price
37-
price <- df*(cpsign*(forward-strike)*pnorm(dn) + stdev*dnorm(dn))
40+
price <- df * (cp*(forward-strike)*stats::pnorm(dn) + stdev*stats::dnorm(dn))
3841
return( price )
3942
}

pkg/R/blackscholes_impvol.R

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@
66
#' @param texp (vector of) time to expiry
77
#' @param intr interest rate
88
#' @param divr dividend rate
9-
#' @param cpsign call/put sign. 1 for call, -1 for put.
9+
#' @param cp call/put sign. \code{1} for call, \code{-1} for put.
1010
#' @param forward forward price. If given, \code{forward} overrides \code{spot}
1111
#' @param df discount factor. If given, \code{df} overrides \code{intr}
1212
#' @return Black-Scholes implied volatility
1313
#'
14+
#' @references Giner, G., & Smyth, G. K. (2016). statmod: Probability Calculations
15+
#' for the Inverse Gaussian Distribution. The R Journal, 8(1), 339-351.
16+
#' \url{https://doi.org/10.32614/RJ-2016-024}
17+
#'
1418
#' @export
1519
#'
1620
#' @examples
@@ -20,17 +24,16 @@
2024
#' sigma <- 0.2
2125
#' intr <- 0.05
2226
#' price <- 20
23-
#' vol <- FER::BlackScholesImpvol(price, strike, spot, texp, intr=intr)
27+
#' FER::BlackScholesImpvol(price, strike, spot, texp, intr=intr)
2428
#'
2529
#' @seealso \code{\link{BlackScholesPrice}}
2630
#'
2731
BlackScholesImpvol <- function(
28-
price, strike = forward, spot, texp = 1,
29-
intr = 0, divr = 0, cpsign = 1,
30-
forward = spot*exp(-divr*texp)/df,
31-
df = exp(-intr*texp)
32+
price, strike=forward, spot, texp=1,
33+
intr=0, divr=0, cp=1L,
34+
forward=spot*exp(-divr*texp)/df, df=exp(-intr*texp)
3235
){
33-
optval = (price/df - pmax(cpsign*(forward-strike), 0))/pmin(forward, strike)
36+
optval <- (price/df - pmax(cp*(forward-strike), 0))/pmin(forward, strike)
3437

3538
# we use inverse CDF of inversegaussian distribution
3639
mu <- 2/abs(log(strike/forward))

pkg/R/blackscholes_price.R

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
#' @param sigma (vector of) volatility
77
#' @param intr interest rate
88
#' @param divr dividend rate
9-
#' @param cpsign call/put sign. 1 for call, -1 for put.
9+
#' @param cp call/put sign. \code{1} for call, \code{-1} for put.
1010
#' @param forward forward price. If given, \code{forward} overrides \code{spot}
1111
#' @param df discount factor. If given, \code{df} overrides \code{intr}
1212
#' @return option price
13-
#' @import stats
1413
#' @export
1514
#'
1615
#' @examples
@@ -19,25 +18,23 @@
1918
#' texp <- 1.2
2019
#' sigma <- 0.2
2120
#' intr <- 0.05
22-
#' price <- FER::BlackScholesPrice(strike, spot, texp, sigma, intr=intr)
21+
#' FER::BlackScholesPrice(strike, spot, texp, sigma, intr=intr)
2322
#'
2423
#' @seealso \code{\link{BlackScholesImpvol}}
2524
#'
2625
BlackScholesPrice <- function(
27-
strike = forward, spot, texp = 1, sigma,
28-
intr = 0, divr = 0, cpsign = 1,
29-
forward = spot*exp(-divr*texp)/df,
30-
df = exp(-intr*texp)
26+
strike=forward, spot, texp=1, sigma,
27+
intr=0, divr=0, cp=1L,
28+
forward=spot*exp(-divr*texp)/df, df=exp(-intr*texp)
3129
){
3230
stdev <- sigma*sqrt(texp)
3331

3432
# a trick to get the intrinsic value for negative or zero vol
35-
# also avoid NAN in case forward = strike
33+
# also avoid NAN in case forward=strike
3634
stdev[stdev < 1e-32] <- 1e-32
3735

3836
d1 <- log(forward/strike)/stdev + 0.5*stdev
3937
d2 <- d1 - stdev
40-
disc.factor <- exp(-intr*texp)
41-
price <- df * cpsign*(forward*pnorm(cpsign*d1) - strike*pnorm(cpsign*d2))
38+
price <- df * cp*(forward*stats::pnorm(cp*d1) - strike*stats::pnorm(cp*d2))
4239
return( price )
4340
}

pkg/R/cev_price.R

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#' Constant Elasticity Of Variance (CEV) model option price
1+
#' Calculate the constant elasticity of variance (CEV) model option price
22
#'
33
#' @param strike (vector of) strike price
44
#' @param spot (vector of) spot price
@@ -7,11 +7,15 @@
77
#' @param beta beta
88
#' @param intr interest rate
99
#' @param divr dividend rate
10-
#' @param cpsign call/put sign. 1 for call, -1 for put.
10+
#' @param cp call/put sign. \code{1} for call, \code{-1} for put.
1111
#' @param forward forward price. If given, \code{forward} overrides \code{spot}
1212
#' @param df discount factor. If given, \code{df} overrides \code{intr}
1313
#' @return option price
1414
#'
15+
#' @references Schroder, M. (1989). Computing the constant elasticity
16+
#' of variance option pricing formula. Journal of Finance,
17+
#' 44(1), 211-219. https://doi.org/10.1111/j.1540-6261.1989.tb02414.x
18+
#'
1519
#' @export
1620
#'
1721
#' @examples
@@ -20,24 +24,23 @@
2024
#' texp <- 1.2
2125
#' beta <- 0.5
2226
#' sigma <- 2
23-
#' price <- FER::CevPrice(strike, spot, texp, sigma, beta)
27+
#' FER::CevPrice(strike, spot, texp, sigma, beta)
2428
#'
2529
CevPrice <- function(
26-
strike = forward, spot, texp = 1, sigma, beta=0.5,
27-
intr = 0, divr = 0, cpsign = 1,
28-
forward = spot*exp(-divr*texp)/df,
29-
df = exp(-intr*texp)
30+
strike=forward, spot, texp=1, sigma, beta=0.5,
31+
intr=0, divr=0, cp=1L,
32+
forward=spot*exp(-divr*texp)/df, df=exp(-intr*texp)
3033
){
3134
betac <- 1.0 - beta
3235
scale <- (betac*sigma)^2*texp
33-
strike_cov = strike^(2*betac) / scale # strike change of variable
34-
forward_cov = forward^(2*betac) / scale # forward change of variable
36+
strike_cov <- strike^(2*betac) / scale # strike change of variable
37+
forward_cov <- forward^(2*betac) / scale # forward change of variable
3538
deg <- 1/betac # degree of freedom
3639

37-
term1 <- stats::pchisq(strike_cov, df=deg+2, ncp=forward_cov, lower.tail=(cpsign<0))
38-
term2 <- stats::pchisq(forward_cov, df=deg, ncp=strike_cov, lower.tail=(cpsign>0))
40+
term1 <- stats::pchisq(strike_cov, df=deg+2, ncp=forward_cov, lower.tail=(cp<0))
41+
term2 <- stats::pchisq(forward_cov, df=deg, ncp=strike_cov, lower.tail=(cp>0))
3942

40-
price <- cpsign*df*(forward*term1 - strike*term2)
43+
price <- cp*df*(forward*term1 - strike*term2)
4144

4245
return(price)
4346
}

pkg/R/sabr_hagan2002.R

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
1-
#' Hagan approximation for the SABR model
1+
#' Calculate the equivalent BS volatility (Hagan et al. 2002) for
2+
#' the Stochatic-Alpha-Beta-Rho (SABR) model
23
#'
34
#' @param strike (vector of) strike price
45
#' @param spot (vector of) spot price
56
#' @param texp (vector of) time to expiry
67
#' @param sigma (vector of) volatility
7-
#' @param vov vol-of-vol
8-
#' @param rho correlation
9-
#' @param beta beta
8+
#' @param vov (vector of) vol-of-vol
9+
#' @param rho (vector of) correlation
10+
#' @param beta (vector of) beta
1011
#' @param intr interest rate
1112
#' @param divr dividend rate
12-
#' @param cpsign call/put sign. NULL for BS vol (default), 1 for call price, -1 for put price.
13+
#' @param cp call/put sign. \code{NULL} for BS vol (default), \code{1} for call price, \code{-1} for put price.
1314
#' @param forward forward price. If given, \code{forward} overrides \code{spot}
1415
#' @param df discount factor. If given, \code{df} overrides \code{intr}
15-
#' @return BS volatility or option price based on cpsign
16+
#' @return BS volatility or option price based on \code{cp}
1617
#'
17-
#' @references Hagan, P. S., Kumar, D., Lesniewski, A. S., & Woodward, D. E. (2002). Managing Smile Risk. Wilmott, September, 84–108.
18+
#' @references Hagan, P. S., Kumar, D., Lesniewski, A. S., & Woodward, D. E. (2002).
19+
#' Managing Smile Risk. Wilmott, September, 84-108.
1820
#'
1921
#' @export
2022
#'
@@ -26,43 +28,46 @@
2628
#' texp <- 10
2729
#' strike <- seq(0.1, 2, 0.1)
2830
#' FER::SabrHagan2002(strike, 1, texp, sigma, vov, rho, beta)
31+
#' FER::SabrHagan2002(strike, 1, texp, sigma, vov, rho, beta, cp=1)
2932
#'
3033
SabrHagan2002 <- function(
31-
strike = forward, spot, texp = 1, sigma, vov=0, rho=0, beta=1,
32-
intr = 0, divr = 0, cpsign = NULL,
33-
forward = spot*exp(-divr*texp)/df,
34-
df = exp(-intr*texp)
34+
strike=forward, spot, texp=1, sigma, vov=0, rho=0, beta=1,
35+
intr=0, divr=0, cp=NULL,
36+
forward=spot*exp(-divr*texp)/df, df=exp(-intr*texp)
3537
){
3638
betac <- 1 - beta
39+
betac2 <- betac*betac
40+
rho2 <- rho*rho
41+
3742
powFwdStrk <- (forward*strike)^(betac/2)
3843
logFwdStrk <- log(forward/strike)
3944
logFwdStrk2 <- logFwdStrk^2
4045

41-
pre1 = powFwdStrk*( 1 + betac^2/24 * logFwdStrk2*(1 + betac^2/80 * logFwdStrk2) )
46+
pre1 <- powFwdStrk*( 1 + betac2/24 * logFwdStrk2*(1 + betac2/80 * logFwdStrk2) )
4247

43-
pre2alp0 <- (2-3*rho^2)*vov^2/24
48+
pre2alp0 <- (2-3*rho2)*vov^2/24
4449
pre2alp1 <- vov*rho*beta/4/powFwdStrk
45-
pre2alp2 <- betac^2/24/powFwdStrk^2
50+
pre2alp2 <- betac2/24/powFwdStrk^2
4651

4752
pre2 <- 1 + texp*( pre2alp0 + sigma*(pre2alp1 + pre2alp2*sigma) )
4853

4954
zz <- powFwdStrk*logFwdStrk*vov/sigma # need to make sure sig > 0
5055
yy <- sqrt(1 + zz*(zz-2*rho))
5156

52-
rho2 <- rho*rho
53-
xx_zz = 1 + (zz/2)*(rho + zz*((rho2-1/3) + (5*rho2-3)/4*rho*zz))
57+
xx_zz <- 1 + (zz/2)*(rho + zz*((rho2-1/3) + (5*rho2-3)/4*rho*zz))
5458

5559
I <- (zz >= 1e-5)
56-
xx_zz[I] = log( (yy[I] + (zz[I]-rho))/(1-rho) ) / zz[I]
60+
xx_zz[I] <- log( (yy[I] + (zz[I]-rho))/(1-rho) ) / zz[I]
5761
I <- (zz <= -1e-5)
58-
xx_zz[I] = log( (1+rho)/(yy[I] - (zz[I]-rho)) ) / zz[I]
62+
xx_zz[I] <- log( (1+rho)/(yy[I] - (zz[I]-rho)) ) / zz[I]
5963

60-
vol.bs = sigma*pre2/(pre1*xx_zz) # blks vol
64+
vol.bs <- sigma*pre2/(pre1*xx_zz) # BS volatility
6165

62-
if(is.null(cpsign)){
66+
if(is.null(cp)){
6367
return(vol.bs)
6468
} else {
65-
p <- BlackScholesPrice(strike, forward, texp, vol.bs, cpsign=cpsign)
66-
return(df*p)
69+
# if cp is specified, calculate option price
70+
p <- df * BlackScholesPrice(strike, forward, texp, sigma=vol.bs, cp=cp)
71+
return(p)
6772
}
6873
}

pkg/man/BachelierImpvol.Rd

Lines changed: 6 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)