Skip to content

adrianskw/AmericanOptions

Repository files navigation

AmericanOptions

A high-performance Python library for pricing American and European equity options using Binomial Trees (CRR, Leisen-Reimer) and Analytical approximations (Black-Scholes-Merton, Barone-Adesi & Whaley).

Key Features

  • Optimized Binomial Engines: $\mathcal{O}(n)$ space complexity with vectorized backward induction for Cox-Ross-Rubinstein (CRR) and Leisen-Reimer (LR) trees.
  • Analytical Models: Unified Black-Scholes-Merton (BSM) for European options and Barone-Adesi & Whaley (BAW) quadratic approximation for American options.
  • Volatility Calibration: Model-agnostic implied volatility solver and automated IV smile fitting using cubic splines with flat-wing extrapolation.
  • Validation Pipeline: Integrated 3-stage pipeline to evaluate analytical convergence, in-sample calibration consistency, and out-of-sample predictive accuracy using live market data.

Project Structure

Module Description
options/analytic.py Combined BSM (European) and BAW (American) analytical pricers.
options/binomial.py Binomial Tree engines (CRR and Leisen-Reimer) with $\mathcal{O}(n)$ space optimization.
options/vol_surface.py Implied Volatility smile calibration and cubic spline interpolation.
options/base.py Base interfaces, OptionContract frozen dataclass, and shared IV solvers.
benchmark/runner.py Parallelized benchmarking engine using ThreadPoolExecutor.
benchmark/market_data.py Real-time option chain fetching and cleaning via yfinance.
main.py CLI entry point demonstrating the 3-stage validation pipeline.

Core Pricing Models

Analytical Models: Black-Scholes-Merton vs. Barone-Adesi & Whaley (BAW)

Theoretical Foundation: Both models provide instantaneous, continuous-time pricing. The Barone-Adesi & Whaley (BAW) quadratic approximation model is linked to the Black-Scholes-Merton (BSM) framework, utilizing the European BSM value as its baseline.

Core Distinctions: The standard BSM formula is strictly limited to European options, which can only be exercised at expiration $T$. BAW extends this framework to American options by isolating the early-exercise premium. It calculates a critical asset price boundary, $S^*$, above which (for calls) it is optimal to exercise immediately. The American price $V_{Am}$ is approximated as the European price $V_{Eu}$ plus an early-exercise premium structured around the solutions to a quadratic equation.

Code Structure: Both models reside in options/analytic.py. The BAWPricer delegates the base European valuation directly to the core BSM function. To determine the critical boundary $S^*$, it employs a high-precision Brent's root-finding algorithm (scipy.optimize.brentq).

The Bridge to Binomial Trees

While analytical approximations like BAW are computationally efficient, their accuracy can degrade under extreme parameter regimes—such as deep-in-the-money options or exceptionally long maturities. Binomial trees bridge this theoretical gap by explicitly evaluating the optimal early-exercise constraint $V = \max(V_{hold}, V_{exercise})$ at every single node via backward induction.

Binomial Lattices: Cox-Ross-Rubinstein (CRR) vs. Leisen-Reimer (LR)

Theoretical Foundation: Both methodologies construct a recombining lattice of asset prices mapping the underlying process. The core backward-induction mechanism—discounting the risk-neutral expected value and enforcing the early-exercise condition—is mathematically identical across both models.

Core Distinctions:

  • CRR (Cox-Ross-Rubinstein) parameterizes the tree using symmetric logarithmic jumps $u = e^{\sigma \sqrt{\Delta t}}$ and $d = 1/u$. However, because the terminal tree nodes rarely align with the option's strike price $K$, CRR suffers from numerical oscillation (sawtooth convergence) as the step count $n$ changes.
  • LR (Leisen-Reimer) resolves this by replacing standard binomial probabilities with the Peizer-Pratt inversion algorithm. This mathematically forces the terminal nodes to straddle the strike price $K$, aligning the tree with the continuous-time probabilities. The result is a dramatic elimination of oscillation and roughly 16x the computational efficiency of CRR for equivalent accuracy on standard contracts.

Code Structure: Both engines are unified within options/binomial.py. They inherit from the abstract BinomialPricer class and share a highly optimized, $\mathcal{O}(n)$ space complexity _backward_induction engine utilizing vectorized NumPy arrays. They diverge solely in their _get_params implementation, providing a rigorous application of the Template Method pattern.

Validation Pipeline

The library enforces a strict three-stage validation pipeline:

  1. Analytical Validation: Ensures tree models converge to the exact BSM solution (European) and align closely with the BAW approximation (American).
  2. Calibration Self-Consistency: Verifies the IV solver and spline interpolation by calibrating a 1-D volatility smile to market data and repricing those same contracts to guarantee a near-100% hit rate within the bid-ask spread.
  3. Cross-Expiry Benchmarking: Tests out-of-sample predictive power by calibrating the smile on one expiry (~30 DTE) and evaluating contracts on a subsequent expiry (~35-45 DTE).

Usage

Pricing a Contract

from options import BAWPricer, OptionContract, OptionType, ExerciseStyle

# Define an American Put using the immutable dataclass
contract = OptionContract(
    spot=100.0, 
    strike=105.0, 
    time_to_expiry=0.5, 
    volatility=0.2, 
    option_type=OptionType.PUT,
    exercise_style=ExerciseStyle.AMERICAN
)

pricer = BAWPricer()
price = pricer.price(contract)
print(f"BAW American Price: {price:.4f}")

Running the Validation Pipeline

Run the full 3-stage validation pipeline across multiple tickers:

# Evaluate SPY and QQQ using the CRR model with 200 steps
python main.py --symbols SPY QQQ --steps 200 --model crr

Testing

Run the comprehensive test suite with pytest:

pytest tests/

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages