---
title: "American options and Greeks"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{American options and Greeks}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
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

```{r}
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)
```

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

```{r}
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
)
```

## Early-exercise premium

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

```{r}
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
)
```

## 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.

```{r}
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))
```

## A finite-difference delta

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

```{r}
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
)
```

## Reference

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

