--- title: "Implied volatility" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Implied volatility} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} 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 ```{r} 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 ) ``` The reconstructed price should match the original option price up to numerical precision. ```{r} 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 ) ``` ## Implied volatility for other option types For non-European options, use `Implied_Volatility()`. The wrapper uses the same pricing entry point as `Greeks()`. ```{r} 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 ) ``` ## 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. ```{r} 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) ``` 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).