| Title: | Empirical 'Martingale' Option Pricing from Historical Data |
|---|---|
| Description: | Prices European and arithmetic Asian options directly from a single historical price series, with no option-market calibration input. An AR(1) filter removes linear predictability from discounted log-prices, a stationary block bootstrap (Politis and Romano, 1994) resamples the residuals to preserve dependence beyond the mean, and a Duan-Simonato (1998) scalar correction enforces the martingale condition required by the Fundamental Theorem of Asset Pricing. Intended for underlyings with no quoted option market to calibrate against (private indices, embedded insurance options, participation certificates). |
| Authors: | Thierry Moudiki [aut, cre] |
| Maintainer: | Thierry Moudiki <[email protected]> |
| License: | BSD_3_clause + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-09-29 11:38:48 UTC |
| Source: | https://github.com/thierrymoudiki/empiricaloptions |
Fits a no-intercept AR(1) to first-differenced, discounted log-prices,
then resamples the centered residuals with a stationary block bootstrap
(Politis and Romano, 1994). The resulting pool is the reusable input to
eq_price and eq_price_asian: build it once per
discount rate and price as many strikes, maturities, and payoff types as
needed from it.
eq_pool(prices, r, dt = 1/252, window = NULL, n_sims = 10000L, seed = 123)eq_pool(prices, r, dt = 1/252, window = NULL, n_sims = 10000L, seed = 123)
prices |
Numeric vector of historical prices, ordered by date, with
no missing values (interpolate or drop |
r |
Discount / funding rate (annualized, continuously compounded)
used to discount |
dt |
Time step between observations, in years (default |
window |
Optional trailing window length, in observations, to use
instead of the full history (e.g. |
n_sims |
Number of bootstrap paths to draw (default |
seed |
Random seed used for the bootstrap draw, for reproducibility. |
An object of class "eq_pool": a list with the resampled
residual matrix (n_w rows by n_sims columns), the fitted
AR(1) coefficient, and diagnostic statistics (Ljung-Box and ARCH-LM
p-values on the pre-bootstrap residuals, annualized volatility, skew,
and excess kurtosis).
Politis, D. N. and Romano, J. P. (1994). The stationary bootstrap. Journal of the American Statistical Association, 89(428), 1303-1313.
set.seed(1) prices <- cumprod(1 + rnorm(500, 0.0003, 0.01)) * 100 pool <- eq_pool(prices, r = 0.03) poolset.seed(1) prices <- cumprod(1 + rnorm(500, 0.0003, 0.01)) * 100 pool <- eq_pool(prices, r = 0.03) pool
Reconstructs terminal prices at maturity T by cumulating bootstrap
residuals in log-space, applies a Duan-Simonato (1998) scalar martingale
correction, and Monte Carlo-prices the requested strikes. Calls and puts
are priced from the same simulated terminal draws, so put-call
parity holds up to Monte Carlo noise by construction.
eq_price(pool, S0, T, K, type = c("call", "put"), eps_scale = 1)eq_price(pool, S0, T, K, type = c("call", "put"), eps_scale = 1)
pool |
An |
S0 |
Current (spot) price of the underlying. |
T |
Maturity, in years. |
K |
Numeric vector of strikes. |
type |
|
eps_scale |
Optional scalar multiplier applied to the bootstrapped
residuals before reconstruction (default |
A list with components prices (named by strike), c_ds
(the Duan-Simonato correction applied), and sigma_atm (the
annualized at-the-money volatility implied by the simulated terminal
distribution).
Duan, J.-C. and Simonato, J.-G. (1998). Empirical martingale simulation for asset prices. Management Science, 44(9), 1218-1233.
set.seed(1) prices <- cumprod(1 + rnorm(500, 0.0003, 0.01)) * 100 pool <- eq_pool(prices, r = 0.03) eq_price(pool, S0 = 100, T = 0.5, K = c(95, 100, 105), type = "call")set.seed(1) prices <- cumprod(1 + rnorm(500, 0.0003, 0.01)) * 100 pool <- eq_pool(prices, r = 0.03) eq_price(pool, S0 = 100, T = 0.5, K = c(95, 100, 105), type = "call")
Extends eq_price to a path-dependent payoff by applying a
date-specific Duan-Simonato correction at each fixing date, then averaging
the corrected simulated path before applying the payoff. Requires no
additional inputs beyond the pool already built for European pricing.
eq_price_asian(pool, S0, T, K, n_fix)eq_price_asian(pool, S0, T, K, n_fix)
pool |
An |
S0 |
Current (spot) price of the underlying. |
T |
Maturity, in years. |
K |
Numeric vector of strikes. |
n_fix |
Number of (equally spaced) fixing/averaging dates up to |
Named numeric vector of arithmetic Asian call prices, one per strike.