American options and Greeks

library(greeks)

American options can be exercised at any time before maturity. The package prices American calls and puts with a binomial tree via Binomial_American_Greeks(). The fair value is computed by the tree, and the Greeks are computed by finite differences around that fair value.

The tests verify the binomial implementation against an independent tree and check finite-difference Greeks. The examples below show the same ideas on small, readable inputs.

Pricing an American option

american_put <- Binomial_American_Greeks(
  initial_price = 100,
  exercise_price = 100,
  r = 0.03,
  time_to_maturity = 1,
  dividend_yield = 0,
  volatility = 0.3,
  payoff = "put",
  greek = c("fair_value", "delta", "gamma", "vega", "theta", "rho"),
  steps = 200
)

round(american_put, 4)
#> fair_value      delta      gamma       vega      theta        rho 
#>    10.6149    -0.4281     0.0108    38.6709    -4.6290   -39.0559

The generic Greeks() wrapper can be used for the same option by setting option_type = "American".

round(
  Greeks(
    initial_price = 100,
    exercise_price = 100,
    r = 0.03,
    time_to_maturity = 1,
    dividend_yield = 0,
    volatility = 0.3,
    payoff = "put",
    option_type = "American",
    greek = c("fair_value", "delta", "rho"),
    steps = 200
  ),
  4
)
#> fair_value      delta        rho 
#>    10.6149    -0.4281   -39.0559

Early-exercise premium

For a put option, the American value can exceed the corresponding European Black-Scholes value because early exercise may be beneficial.

european_put_value <- BS_European_Greeks(
  initial_price = 100,
  exercise_price = 100,
  r = 0.03,
  time_to_maturity = 1,
  dividend_yield = 0,
  volatility = 0.3,
  payoff = "put",
  greek = "fair_value"
)

american_put_value <- Binomial_American_Greeks(
  initial_price = 100,
  exercise_price = 100,
  r = 0.03,
  time_to_maturity = 1,
  dividend_yield = 0,
  volatility = 0.3,
  payoff = "put",
  greek = "fair_value",
  steps = 400
)

round(
  c(
    european_put = european_put_value,
    american_put = american_put_value,
    early_exercise_premium = american_put_value - european_put_value
  ),
  4
)
#>           european_put.fair_value           american_put.fair_value 
#>                           10.3279                           10.6118 
#> early_exercise_premium.fair_value 
#>                            0.2839

Choosing the number of tree steps

A larger number of tree steps generally gives a more accurate binomial approximation, at the cost of more computation.

steps <- c(25, 50, 100, 200, 400)

prices <- vapply(
  steps,
  function(n_steps) {
    Binomial_American_Greeks(
      initial_price = 100,
      exercise_price = 100,
      r = 0.03,
      time_to_maturity = 1,
      dividend_yield = 0,
      volatility = 0.3,
      payoff = "put",
      greek = "fair_value",
      steps = n_steps
    )
  },
  numeric(1)
)

data.frame(steps = steps, fair_value = round(prices, 4))
#>   steps fair_value
#> 1    25    10.6098
#> 2    50    10.6331
#> 3   100    10.6212
#> 4   200    10.6149
#> 5   400    10.6118

A finite-difference delta

The implementation computes American Greeks by perturbing one model parameter at a time. This reproduces the calculation for delta.

fair_value_at <- function(initial_price) {
  Binomial_American_Greeks(
    initial_price = initial_price,
    exercise_price = 100,
    r = 0.03,
    time_to_maturity = 1,
    dividend_yield = 0,
    volatility = 0.3,
    payoff = "put",
    greek = "fair_value",
    steps = 200
  )
}

step_size <- 0.01
finite_difference_delta <-
  (fair_value_at(100 + step_size) - fair_value_at(100 - step_size)) /
  (2 * step_size)

reported_delta <- Binomial_American_Greeks(
  initial_price = 100,
  exercise_price = 100,
  r = 0.03,
  time_to_maturity = 1,
  dividend_yield = 0,
  volatility = 0.3,
  payoff = "put",
  greek = "delta",
  steps = 200,
  eps = step_size
)

round(
  c(
    reported_delta = reported_delta,
    finite_difference_delta = finite_difference_delta,
    absolute_error = abs(reported_delta - finite_difference_delta)
  ),
  8
)
#>               reported_delta.delta finite_difference_delta.fair_value 
#>                         -0.4280888                         -0.4280888 
#>               absolute_error.delta 
#>                          0.0000000

Reference

The binomial option pricing model is presented in Hull (2022).