American Option Pricing Via Least Squares Monte Carlo
Project Goal
This project implements a high-performance pricing engine for American and Bermudan options using the Least Squares Monte Carlo (LSM) approach.
The primary focus is on enhancing the standard Longstaff-Schwartz (2001) method with advanced variance reduction techniques, specifically Control Variates and Leave-One-Out (LOO) regression to reduce pricing error and in-sample bias. The engine can also be applied to other payoff structures, such as multi-asset max American calls, swing options, quantos, etc.
Features
- Core LSM Algorithm: Backward induction with regression-based continuation value estimation.
- Advanced Stochastic Processes: Simulates multi-dimensional correlated assets (GBM), Quanto asset dynamics, and path-dependent stochastic interest rates (Vasicek/Hull-White dynamics for domestic and foreign rates).
- Flexible Payoffs: Vanilla puts/calls, max calls, swing options, and Quanto options (supporting both fixed FX and stochastic rates).
- Variance and Bias Reduction: Antithetic variates, control variates (European options sampled at maturity or exercise times), and Leave-One-Out (LOO) cross-validation to eliminate look-ahead bias.
- Regression Bases: Laguerre polynomials and power polynomials for basis functions.
- Multi-Asset Support: Handles correlated assets via Cholesky decomposition.
- Benchmarks: Comparison against Binomial Trees, Finite Difference Methods (QuantLib), and Black-Scholes.
- Performance: Optimized for speed and accuracy with configurable paths and steps.
Project Structure
├── .github/
│ └── workflows/
│ ├── ci.yml # GitHub Actions automated testing
│ └── publish.yml # PyPI publishing pipeline
├── LSM/
│ ├── __init__.py
│ ├── algorithms.py # Core LeastSquaresMonteCarlo engine (American & Swing)
│ ├── stochastic_processes.py # GBM, QuantoGBM, and Stochastic Rates processes
│ ├── payoffs.py # Vanilla, MaxCall, Swing, and Quanto payoffs/features
│ ├── regression_bases.py # Laguerre and Power polynomial bases
│ ├── control_variate.py # Black-Scholes European prices and CV logic
│ └── binomial_tree.py # CRR Binomial Tree for benchmarking
├── notebooks/
│ ├── demo.ipynb # Quick start and Colab demonstration
│ └── tests.ipynb # Benchmark tests and advanced payoffs
├── tests/
│ ├── test_lsm.py # Pytest suite for core LSM functionality
│ ├── test_quanto.py # Pytest suite for Quanto pricing and stochastic rates
│ └── test_swing.py # Pytest suite for Swing option constraints and pricing
├── pyproject.toml # Build metadata and dependencies
└── README.md
Installation
You can install the package via pip:
pip install lsm-option-pricing
Quick Start
Import the modules and create an LSM engine:
import numpy as np
from LSM.stochastic_processes import GeometricBrownianMotion
from LSM.payoffs import VanillaPayoff
from LSM.regression_bases import LaguerrePolynomials
from LSM.algorithms import LeastSquaresMonteCarlo
# Set up process, payoff, and basis
gbm = GeometricBrownianMotion(S0=36.0, r=0.06, q=0.0, sigma=0.2)
payoff = VanillaPayoff(strike=40.0, option_type="put")
basis = LaguerrePolynomials(degree=3)
# Create LSM engine and price option
lsm = LeastSquaresMonteCarlo(process=gbm, payoff_function=payoff, basis_function=basis)
price, stderr = lsm.pricer(T=1.0, n_steps=50, n_paths=10000)
print(f"American Put Price: {price:.4f} ± {stderr:.4f}")
API Reference
LeastSquaresMonteCarlo.pricer()
Prices the option using the standard Least Squares Monte Carlo algorithm. Evaluates the option by comparing immediate intrinsic value against the conditional expected continuation value.
| Parameter | Type | Default | Description |
|---|---|---|---|
T |
float |
Required | Time to maturity in years. |
n_steps |
int |
Required | Number of discrete time steps for the simulation. |
n_paths |
int |
Required | Number of Monte Carlo paths to generate (generates n_paths/2 pairs if use_antithetic=True). |
rng |
np.random.Generator |
None |
NumPy random number generator instance for reproducible paths. |
use_antithetic |
bool |
False |
If True, uses antithetic variates for variance reduction. |
control_variate |
str |
None |
European option control variate method. Options: 'european_at_maturity', 'european_at_exercise', or None. |
cv_oos |
bool |
True |
If True, uses out-of-sample path estimation for the European CV to eliminate look-ahead bias and over-fitting during stopping time determination. |
create_features |
Callable |
None |
Function to create custom basis features for regression (e.g., cross-terms for multi-asset or Quanto options). |
cache |
bool |
False |
If True, caches the cash flow matrix allowing retrieval via get_cashflow(). |
exercise_times |
array-like |
None |
Specific exercise times for Bermudan options (e.g., [0.25, 0.5, 1.0]). If None, assumes an American option (exercisable at every step). |
simulation_times |
array-like |
None |
Custom time grid passed directly to the simulator. If provided, overrides T and n_steps. |
use_loo |
bool |
False |
If True, applies Leave-One-Out (LOO) cross-validation to reduce in-sample regression bias. |
LeastSquaresMonteCarlo.swing_pricer()
Prices a natural gas or electricity swing option with specific volume constraints. Assumes every step in the simulation grid is a valid daily exercise opportunity.
| Parameter | Type | Default | Description |
|---|---|---|---|
T |
float |
Required | Total time to maturity in years. |
n_steps |
int |
Required | Number of discrete time steps. |
n_paths |
int |
Required | Number of Monte Carlo paths to simulate. |
rng |
np.random.Generator |
None |
NumPy random number generator instance for reproducible paths. |
use_antithetic |
bool |
False |
If True, uses antithetic variates for variance reduction. |
contract_prices |
np.ndarray |
None |
1D array of shape (n_steps + 1,) representing the fixed strike price or forward curve value at each time step. |
simulation_times |
np.ndarray |
None |
Custom time grid. Overrides T and n_steps. Must exactly match the length of contract_prices. |
DCQ |
float |
1.0 |
Daily Contract Quantity (the maximum volume allowed per single exercise). |
Ed |
int |
1 |
Total number of exercise rights available (Annual Contract Quantity / DCQ). |
ToP_rights |
int |
0 |
Minimum number of times the option MUST be exercised to avoid Take-or-Pay penalties. |
Note:
- "Bang-Bang" Exercise: Decisions are strictly all-or-nothing (0 or exactly
DCQ). Partial volume exercises are not supported.- Hard ToP Penalties: Failing to meet
ToP_rightsinvalidates the simulation path (assigns-infvalue) rather than applying a proportional cash penalty.- No Operational Friction: Assumes immediate exercise rights without advance notice periods, resting times, or dynamic capacity limits.
Returns: A tuple (price, std_err) containing the estimated option price and the standard error.
Demo
An interactive demo showing error convergence and basic pricing is available here:
Dependencies
- Python
- NumPy
- SciPy
- Pandas (for data handling)
- Matplotlib (for plotting)
- Jupyter (for notebooks)
- QuantLib (optional, for FDM benchmarks)
License
This project is licensed under the MIT License (see the LICENSE file for details).
References
- Longstaff, F. A., and E. S. Schwartz (2001). "Valuing American Options by Simulation: A Simple Least-Squares Approach.": Seminal LSM paper.
- Broadie, M., and P. Glasserman (2004). "A Stochastic Mesh Method for Pricing High-Dimensional American Options." Journal of Computational Finance.: Multi-asset American max call benchmarks.
- Jaillet, P., Ronn, E. I., and S. Tompaidis (2004). "Valuation of Commodity-Based Swing Options.": American equivalency and European strip bounds for swing options.
- Hanfeld, M., and S. Schlüter (2016). "Operating a swing option on today's gas markets: How least squares Monte Carlo works and why it is beneficial." Working Paper.: Detailed backward induction logic for the $q_{n,t}$ offtake levels and the 2D state grid used in our swing_pricer.
- Glasserman, P. (2004). Monte Carlo Methods in Financial Engineering.: Quantos and other payoff structures, critique about LSM, etc.
- Rasmussen, H. O. (2005). "Control Variates for American Options.": Control variates for American options sampled at exercise.
- Woo, R., et al. (2019). "Leave-one-out Least Squares Monte Carlo.": Leave-one-out LSM.
- GitHub: luphord/longstaff_schwartz. "An implementation of the Longstaff-Schwartz algorithm for American option pricing.": Another LSM implementation.
Acknowledgements
- Inspiration and repository structure:
luphord/longstaff_schwartz(see References).
Release files for lsm-option-pricing 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lsm_option_pricing-0.1.0.tar.gz | 23.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lsm_option_pricing-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 44.3 kB
Release files / lsm_option_pricing-0.1.0.tar.gz
| Download URL | lsm_option_pricing-0.1.0.tar.gz |
|---|---|
| Size | 23.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b9cce2e8ddea844522eeb43ba0f791e3d053f8029a99642bd958fd4797dbcc21
|
|
BLAKE2b-256 checksum How to use checksums |
1b2ef0489acb7687f1ede036dfcf045d9d76f1117058010e40dc6c194102128d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 13, 2026.
Transparency logRelease files / lsm_option_pricing-0.1.0-py3-none-any.whl
| Download URL | lsm_option_pricing-0.1.0-py3-none-any.whl |
|---|---|
| Size | 21.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c94a957c7b73434833a016ee3cda6f9cc39241012d6c2ab40630f0b48d9117ee
|
|
BLAKE2b-256 checksum How to use checksums |
20ab87e6375721d69c680f12bb25d275e2d784e66b4a3a0148ae46142ac2a1e5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 13, 2026.
Transparency log