# Implied volatility

    library(greeks)

Implied volatility is the volatility parameter that makes a model price match an observed option price. In `greeks`, `BS_Implied_Volatility()` handles European Black-Scholes calls and puts directly. `Implied_Volatility()` provides a wrapper for other option types by repeatedly evaluating the corresponding pricing function and vega.

The test suite checks implied volatility by a round trip:

1. choose a volatility;
2. compute an option price from that volatility;
3. infer implied volatility from the option price;
4. price the same option again with the inferred volatility.

## European Black-Scholes implied volatility

    true_volatility <- 0.28

    option_price <- BS_European_Greeks(
      initial_price = 100,
      exercise_price = 105,
      r = 0.03,
      time_to_maturity = 1.25,
      dividend_yield = 0.01,
      volatility = true_volatility,
      payoff = "call",
      greek = "fair_value"
    )

    implied_volatility <- BS_Implied_Volatility(
      option_price = option_price,
      initial_price = 100,
      exercise_price = 105,
      r = 0.03,
      time_to_maturity = 1.25,
      dividend_yield = 0.01,
      payoff = "call",
      start_volatility = 0.2
    )

    round(
      c(
        option_price = option_price,
        true_volatility = true_volatility,
        implied_volatility = implied_volatility
      ),
      6
    )
    #> option_price.fair_value         true_volatility      implied_volatility
    #>                11.27819                 0.28000                 0.28000

The reconstructed price should match the original option price up to numerical precision.

    reconstructed_price <- BS_European_Greeks(
      initial_price = 100,
      exercise_price = 105,
      r = 0.03,
      time_to_maturity = 1.25,
      dividend_yield = 0.01,
      volatility = implied_volatility,
      payoff = "call",
      greek = "fair_value"
    )

    round(
      c(
        original_price = option_price,
        reconstructed_price = reconstructed_price,
        absolute_error = abs(option_price - reconstructed_price)
      ),
      10
    )
    #>      original_price.fair_value reconstructed_price.fair_value
    #>                       11.27819                       11.27819
    #>      absolute_error.fair_value
    #>                        0.00000

## Implied volatility for other option types

For non-European options, use `Implied_Volatility()`. The wrapper uses the same pricing entry point as `Greeks()`.

    geometric_true_volatility <- 0.35

    geometric_price <- Greeks(
      initial_price = 100,
      exercise_price = 100,
      r = 0.02,
      time_to_maturity = 1,
      dividend_yield = 0,
      volatility = geometric_true_volatility,
      option_type = "Geometric Asian",
      payoff = "put",
      greek = "fair_value"
    )

    geometric_implied_volatility <- Implied_Volatility(
      option_price = geometric_price,
      initial_price = 100,
      exercise_price = 100,
      r = 0.02,
      time_to_maturity = 1,
      dividend_yield = 0,
      option_type = "Geometric Asian",
      payoff = "put"
    )

    geometric_reconstructed_price <- Greeks(
      initial_price = 100,
      exercise_price = 100,
      r = 0.02,
      time_to_maturity = 1,
      dividend_yield = 0,
      volatility = geometric_implied_volatility,
      option_type = "Geometric Asian",
      payoff = "put",
      greek = "fair_value"
    )

    round(
      c(
        original_price = geometric_price,
        true_volatility = geometric_true_volatility,
        implied_volatility = geometric_implied_volatility,
        reconstructed_price = geometric_reconstructed_price,
        absolute_error = abs(geometric_price - geometric_reconstructed_price)
      ),
      6
    )
    #>      original_price.fair_value                true_volatility
    #>                       7.897869                       0.350000
    #>             implied_volatility reconstructed_price.fair_value
    #>                       0.350000                       7.897869
    #>      absolute_error.fair_value
    #>                       0.000000

## Prices below the zero-volatility value

An implied volatility is not defined when the requested option price is below the lowest value attainable by the pricing model. A practical first check is to compare the observed price with a near-zero-volatility model value.

    near_zero_volatility_price <- Greeks(
      initial_price = 100,
      exercise_price = 100,
      r = 0.02,
      time_to_maturity = 1,
      dividend_yield = 0,
      volatility = 1e-12,
      option_type = "Geometric Asian",
      payoff = "put",
      greek = "fair_value"
    )

    round(near_zero_volatility_price, 6)
    #> fair_value
    #>          0

If the observed option price is lower than this value, the implied volatility calculation should be treated as infeasible rather than as a numerical tuning problem.

## Reference

The concept of implied volatility and the Black-Scholes model are standard option pricing material; see Hull (2022).