Skip to content

Commit 27ccaef

Browse files
committed
All code copied (and modified) from ASP.2016 repo
1 parent ec0d907 commit 27ccaef

13 files changed

+492
-0
lines changed

pkg/.Rbuildignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
^.*\.Rproj$
2+
^\.Rproj\.user$

pkg/DESCRIPTION

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Package: FER
2+
Title: Financial Engineering functions in R
3+
Version: 0.9
4+
Authors@R: person("Jaehyuk", "Choi", email = "[email protected]", role = c("aut", "cre"))
5+
Description:
6+
Depends:
7+
R (>= 3.3.1)
8+
License: What license is it under?
9+
Encoding: UTF-8
10+
LazyData: true
11+
RoxygenNote: 5.0.1

pkg/FE-R.Rproj

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Version: 1.0
2+
3+
RestoreWorkspace: No
4+
SaveWorkspace: No
5+
AlwaysSaveHistory: Default
6+
7+
EnableCodeIndexing: Yes
8+
UseSpacesForTab: Yes
9+
NumSpacesForTab: 2
10+
Encoding: UTF-8
11+
12+
RnwWeave: Sweave
13+
LaTeX: pdfLaTeX
14+
15+
AutoAppendNewline: Yes
16+
StripTrailingWhitespace: Yes
17+
18+
BuildType: Package
19+
PackageUseDevtools: Yes
20+
PackageInstallArgs: --no-multiarch --with-keep.source
21+
PackageRoxygenize: rd,collate,namespace

pkg/NAMESPACE

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Generated by roxygen2: do not edit by hand
2+
3+
export(BachelierImpvol)
4+
export(BachelierPrice)
5+
export(BlackScholesImpvol)
6+
export(BlackScholesPrice)

pkg/R/bachelier_impvol.R

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#' Calculate normal model implied vol
2+
#'
3+
#' @param type option type either 'call' or 'put'
4+
#' @param price Price
5+
#' @param spot current stock price
6+
#' @param forward forward stock price
7+
#' @param strike strike price
8+
#' @param t.exp time to expiry
9+
#' @param r interest rate
10+
#' @param div dividend rate
11+
#' @return implied vol
12+
#' @examples
13+
#' spot <- 100
14+
#' strike <- 100
15+
#' t.exp <- 1.2
16+
#' sigma <- 0.2
17+
#' r <- 0.05
18+
#' price <- 20
19+
#' vol <- FER::BachelierImpvol(price=price, spot=spot, strike=strike, t.exp=t.exp, r=r)
20+
#' @export
21+
BachelierImpvol <- function(
22+
type = "call", price, spot, forward = spot*exp((r-div)*t.exp),
23+
strike = forward, t.exp = 1, r = 0, div = 0
24+
){
25+
26+
price.forward = price * exp(r*t.exp)
27+
28+
if( type == "call" ) {
29+
price.straddle <- 2*price.forward - (forward - strike)
30+
} else if( type == "put" ) {
31+
price.straddle <- 2*price.forward + (forward - strike)
32+
} else if( type == "straddle") {
33+
price.straddle <- price.forward
34+
}
35+
36+
#vectors a and b used for rational Chebyshev approximation
37+
a <- c(3.994961687345134e-1,
38+
2.100960795068497e1,
39+
4.980340217855084e1,
40+
5.988761102690991e2,
41+
1.848489695437094e3,
42+
6.106322407867059e3,
43+
2.493415285349361e4,
44+
1.266458051348246e4)
45+
46+
b <- c(1.000000000000000,
47+
4.990534153589422e1,
48+
3.093573936743112e1,
49+
1.495105008310999e3,
50+
1.323614537899738e3,
51+
1.598919697679745e4,
52+
2.392008891720782e4,
53+
3.608817108375034e3,
54+
-2.067719486400926e2,
55+
1.174240599306013e1)
56+
57+
#implied volatility when current stock price
58+
#is different from the strike price
59+
60+
#variable v which is bounded in the range [-1, 1],
61+
#since the straddle price is always worth more
62+
#than the intrinsic value |F-K|.
63+
v <- abs( forward - strike ) / price.straddle
64+
#transformation of v used for better
65+
#approximation of h
66+
67+
nu <- ifelse(v<1e-8, 1/(1+v*v*(1/3 + v*v/5)), v/atanh(v))
68+
69+
poly.a <- (((((((a[8]*nu+a[7])*nu+a[6])*nu+a[5]))*nu+a[4])*nu+a[3])*nu+a[2])*nu+a[1]
70+
poly.b <- (((((((((b[10]*nu+b[9])*nu+b[8])*nu+b[7]))*nu+b[6])*nu+b[5])*nu+b[4])*nu+b[3])*nu+b[2])*nu+b[1]
71+
72+
#approximation of h(n)
73+
#implied volatility
74+
vol <- sqrt(pi*nu/(2*t.exp)) * price.straddle * (poly.a/poly.b)
75+
76+
return(vol)
77+
}

pkg/R/bachelier_price.R

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
#' Calculate normal model option price
2+
#'
3+
#' @param type option type either "call" or "put"
4+
#' @param price Price
5+
#' @param spot current stock price
6+
#' @param forward forward stock price
7+
#' @param t.exp time to expiry
8+
#' @param r interest rate
9+
#' @param div dividend rate
10+
#' @param sigma volatility
11+
#' @return option price
12+
#' @examples
13+
#' spot <- 100
14+
#' strike <- seq(80,125,5)
15+
#' t.exp <- 1.2
16+
#' sigma <- 0.2
17+
#' r <- 0.05
18+
#' price <- FER::BachelierPrice(spot=spot, t.exp = t.exp, sigma=sigma, strike=strike, r=r)
19+
#' @export
20+
BachelierPrice <- function(
21+
type = "call", spot, forward = spot*exp((r-div)*t.exp),
22+
strike = forward, t.exp = 1, r = 0, div = 0, sigma
23+
){
24+
25+
#------------------------------------------------
26+
#------------------------------------------------
27+
#Inputs:
28+
# type: "call","put","straddle","digital"
29+
# s: spot price of the underlying asset
30+
# k: strike price
31+
# t: time to maturity
32+
# r: risk-free rate
33+
# sigma: volatility
34+
#Outputs:
35+
# price: option price
36+
# delta: option delta
37+
# gamma: option gamma
38+
# vega: option vega
39+
#------------------------------------------------
40+
#------------------------------------------------
41+
42+
stdev <- sigma*sqrt(t.exp)
43+
d1 <- (forward-strike) / stdev
44+
pnorm.d1 <- pnorm(d1) # normal CDF
45+
dnorm.d1 <- dnorm(d1) # normal PDF =exp(-d1*d1/2)/sqrt(2*pi)
46+
disc.factor <- exp(-r*t.exp)
47+
48+
if(type=="call"){
49+
#Option Price
50+
price <- (forward-strike)*pnorm.d1 + stdev*dnorm.d1
51+
#Greeks
52+
delta <- pnorm.d1 #Delta
53+
gamma <- 1 / (sigma*t.exp)/sqrt(2*pi)*exp(-d1^2/2)#Gamma
54+
vega <- sqrt(t.exp)/sqrt(2*pi)*exp(-d1^2/2)#Vega
55+
56+
}else if (type=="put"){
57+
#Option Price
58+
price <- (strike-forward)*(1-pnorm.d1) + stdev*dnorm.d1
59+
#Greeks
60+
delta <- pnorm.d1 - 1 #Delta
61+
gamma <- 1 / (sigma*t.exp)/sqrt(2*pi)*exp(-d1^2/2)#Gamma
62+
vega <- sqrt(t.exp)/sqrt(2*pi)*exp(-d1^2/2)#Vega
63+
64+
} else if (type=="straddle"){
65+
#Straddle price
66+
price <- (forward-strike)*(2*pnorm.d1-1) + 2*stdev*dnorm.d1
67+
delta <- 2*pnorm.d1 - 1
68+
gamma <- 2 / (sigma*t.exp)/sqrt(2*pi)*exp(-d1^2/2)
69+
vega <- 2 * sqrt(t.exp)/sqrt(2*pi)*exp(-d1^2/2)#Vega
70+
71+
} else if (type== "digital call"){
72+
#Digital call price
73+
price <- pnorm(d1)
74+
delta <- 1 / sqrt(2*pi)*exp(-d1^2/2)/(sigma*sqrt(t))
75+
gamma <- 1 / sqrt(2*pi)*exp(-d1^2/2)/(sigma^2*t)
76+
vega <- -1 / sqrt(2*pi)*exp(-d1^2/2)*(spot-strike)/(sigma^2*sqrt(t))
77+
78+
} else if (type== "digital put"){
79+
#Digital put price
80+
price <- pnorm(-d1)
81+
delta <- -1 / sqrt(2*pi)*exp(-d1^2/2)/(sigma*sqrt(t))
82+
gamma <- 1 / sqrt(2*pi)*exp(-d1^2/2)/(sigma^2*t)
83+
vega <- -1 / sqrt(2*pi)*exp(-d1^2/2)*(spot-strike)/(sigma^2*sqrt(t))
84+
} else {
85+
cat("Error! Please input: call/put/straddle/digital call/digital put")
86+
}
87+
return( disc.factor * price )
88+
}
89+

pkg/R/blackscholes_impvol.R

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#' Calculate Black-Scholes-Merton implied vol
2+
#'
3+
#' @param type option type either 'call' or 'put'
4+
#' @param price Price
5+
#' @param spot current stock price
6+
#' @param forward forward stock price
7+
#' @param strike strike price
8+
#' @param t.exp time to expiry
9+
#' @param r interest rate
10+
#' @param div dividend rate
11+
#' @return Implied vol
12+
#' @examples
13+
#' spot <- 100
14+
#' strike <- 100
15+
#' t.exp <- 1.2
16+
#' sigma <- 0.2
17+
#' r <- 0.05
18+
#' price <- 20
19+
#' vol <- FER::BlackScholesImpvol(price=price, spot=spot, strike=strike, t.exp=t.exp, r=r)
20+
#' @export
21+
BlackScholesImpvol <- function(
22+
type = "call", price, spot, forward = spot*exp((r-div)*t.exp),
23+
strike = forward, t.exp = 1, r = 0, div = 0
24+
){
25+
price.forward = price * exp( r*t.exp)
26+
27+
n.price = length(price.forward)
28+
n.strike = length(strike)
29+
30+
vol <- rep(NA, n.price )
31+
32+
if( length(strike) > 1L ) {
33+
stopifnot(n.price == n.strike )
34+
strike.vec <- strike
35+
} else {
36+
strike.vec <- rep( strike, n.price )
37+
}
38+
39+
for(k in 1:n.price) {
40+
# Be careful here.... Chekc how functional works in R.
41+
sub <- function(sigma){
42+
f <- CalcBsmPrice(
43+
type = type, forward = forward, strike = strike.vec[k], t.exp = t.exp, sigma = sigma
44+
)[1] - price.forward[k]
45+
return(f)
46+
}
47+
vol[k] <- uniroot(f = sub,interval = c(0,10), tol = .Machine$double.eps * 1e4)$root
48+
}
49+
return(vol)
50+
}

pkg/R/blackscholes_price.R

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#' Calculate Black-Scholes-Merton option price
2+
#'
3+
#' @param type option type either 'call' or 'put'
4+
#' @param spot current stock price
5+
#' @param forward forward stock price
6+
#' @param strike strike price
7+
#' @param t.exp time to expiry
8+
#' @param r interest rate
9+
#' @param div dividend rate
10+
#' @param sigma volatility
11+
#' @return option price
12+
#' @examples
13+
#' spot <- 100
14+
#' strike <- seq(80,125,5)
15+
#' t.exp <- 1.2
16+
#' sigma <- 0.2
17+
#' r <- 0.05
18+
#' price <- FER::BlackScholesPrice(spot=spot, t.exp = t.exp, sigma=sigma, strike=strike, r=r)
19+
#' @export
20+
BlackScholesPrice <- function(
21+
type = "call", spot, forward = spot*exp((r-div)*t.exp),
22+
strike = forward, t.exp = 1, r = 0, div = 0, sigma
23+
){
24+
stdev <- sigma*sqrt(t.exp)
25+
26+
# a trick to get the intrinsic value for negative or zero vol
27+
# also avoid NAN in case forward = strike
28+
stdev[stdev < 1e-32] <- 1e-32
29+
30+
d1 <- log(forward/strike)/stdev + 0.5*stdev
31+
d2 <- d1 - stdev
32+
disc.factor <- exp(-r*t.exp)
33+
34+
pnorm.d1 <- pnorm(d1)
35+
pnorm.d2 <- pnorm(d2)
36+
37+
if (type == "call" ){
38+
price <- forward*pnorm.d1 - strike*pnorm.d2
39+
delta <- pnorm.d1
40+
}else if (type == "put"){
41+
price <- strike*(1-pnorm.d2) - forward*(1-pnorm.d1)
42+
delta <- pnorm.d1 - 1
43+
}else if (type == "straddle"){
44+
price <- forward*(2*pnorm.d1 - 1) - strike*(2*pnorm.d2 - 1)
45+
delta <- 2*pnorm.d1 - 1
46+
}else if (type == "digit"){
47+
price <- pnorm.d2
48+
delta <- 1/sqrt(2*pi)*exp(-d2^2/2)/(s*stdev)
49+
}
50+
return( disc.factor * price )
51+
}

pkg/README.txt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
This R package is the basic option pricing functions the students contributed for the Applied Stochastic Processed class.
2+
3+
You can install this package in two ways. Either way, you need to install install 'devtools' package
4+
5+
> install.packages("devtools")
6+
7+
8+
1. Install from the project in a local location.
9+
10+
1) Download this folder.
11+
2) Open the R project file (phbsasp.Rproj) from R.
12+
3) run
13+
14+
> devtools::install()
15+
16+
17+
2. Install directly from GitHub.
18+
19+
> devtools::install_github("PyFE/FE-R", subdir="pakage")

pkg/man/BachelierImpvol.Rd

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

0 commit comments

Comments
 (0)