Calibration Tutorials¶
Practical, hands-on tutorials that demonstrate calibration workflows from basic to advanced topics. Each tutorial includes complete code examples, explanations, and best practices.
Learning Path¶
Follow this recommended learning path to master calibration in Neutryx:
1. Fundamentals (Start Here)¶
Getting Started with SABR Learn the basics of model calibration by fitting a SABR model to FX or interest rate volatility data.
from neutryx.calibration.sabr import SABRCalibrator
from neutryx.models.sabr import SABRParams
import jax.numpy as jnp
# Your first calibration
calibrator = SABRCalibrator()
market_data = {
"forward": 1.10,
"strikes": jnp.array([1.00, 1.05, 1.10, 1.15, 1.20]),
"maturities": jnp.array([0.25, 0.5, 1.0]),
"target_vols": jnp.array([0.15, 0.14, 0.13, 0.14, 0.16])
}
result = calibrator.calibrate(market_data)
Topics covered: - Setting up market data - Running a basic calibration - Interpreting calibration results - Checking convergence
Estimated time: 15 minutes
Understanding Parameters and Constraints Deep dive into parameter specifications, transformations, and bounds.
from neutryx.calibration.base import ParameterSpec
from neutryx.calibration.constraints import positive, bounded, symmetric
# Define constrained parameters
params = {
"alpha": ParameterSpec(init=0.2, transform=positive()), # α > 0
"beta": ParameterSpec(init=0.5, transform=bounded(0.0, 1.0)), # 0 ≤ β < 1
"rho": ParameterSpec(init=-0.3, transform=symmetric(0.99)), # |ρ| < 0.99
"nu": ParameterSpec(init=0.4, transform=positive()) # ν > 0
}
Topics covered: - Parameter transformation functions - Enforcing bounds and constraints - Custom constraint functions - Initial value selection strategies
Estimated time: 20 minutes
2. Model-Specific Calibration¶
Heston Model for Equity Options Calibrate the Heston stochastic volatility model to SPX or equity index options.
from neutryx.calibration.heston import HestonCalibrator
from neutryx.models.heston import HestonParams
# Calibrate to equity volatility surface
calibrator = HestonCalibrator()
result = calibrator.calibrate({
"spot": 4500.0,
"strikes": strikes, # Array of strike prices
"maturities": maturities, # Array of maturities
"target_prices": prices, # Market option prices
"rate": 0.05,
"dividend": 0.02
})
print(f"v0={result.params['v0']:.4f}, kappa={result.params['kappa']:.4f}")
Topics covered: - Heston model parameters and interpretation - Fourier-based pricing in calibration - Handling equity-specific features (dividends) - Common calibration challenges (local minima)
Estimated time: 30 minutes
Stochastic-Local Volatility (SLV) Calibration Fit hybrid SLV models for complex payoff valuations.
from neutryx.calibration.slv import SLVCalibrator
calibrator = SLVCalibrator()
result = calibrator.calibrate(market_data)
# SLV provides flexible smile interpolation
print(f"Local slope: {result.params['local_slope']:.4f}")
print(f"Mixing parameter: {result.params['mixing']:.4f}")
Topics covered: - SLV model structure and use cases - Balancing local vs stochastic components - Calibration to exotic option prices - Stability across strikes and maturities
Estimated time: 30 minutes
3. Advanced Topics¶
Multi-Instrument Joint Calibration Calibrate to multiple instrument types simultaneously for consistency.
from neutryx.calibration.joint_calibration import (
MultiInstrumentCalibrator,
InstrumentSpec
)
# Calibrate to calls, puts, and variance swaps jointly
calibrator = MultiInstrumentCalibrator([
InstrumentSpec(name="calls", weight=1.0, loss_fn="rmse"),
InstrumentSpec(name="puts", weight=1.0, loss_fn="rmse"),
InstrumentSpec(name="var_swaps", weight=2.0, loss_fn="relative")
])
result = calibrator.calibrate({
"calls": call_data,
"puts": put_data,
"var_swaps": variance_swap_data
})
Topics covered: - Multi-instrument data structures - Loss function weighting strategies - Resolving conflicting instrument signals - Put-call parity consistency checks
Estimated time: 45 minutes
Time-Dependent Calibration Calibrate piecewise-constant parameters across time segments.
from neutryx.calibration.joint_calibration import (
TimeDependentCalibrator,
TimeSegment
)
# Piece-wise constant volatility term structure
calibrator = TimeDependentCalibrator([
TimeSegment(start=0.0, end=1.0, params=["theta"]), # Short term
TimeSegment(start=1.0, end=5.0, params=["theta"]), # Medium term
TimeSegment(start=5.0, end=10.0, params=["theta"]) # Long term
])
result = calibrator.calibrate(full_surface_data)
Topics covered: - Time segment definition - Smoothness regularization - Calendar arbitrage constraints - Parameter evolution analysis
Estimated time: 45 minutes
Cross-Asset Calibration Joint calibration with shared parameters across multiple assets.
from neutryx.calibration.joint_calibration import (
CrossAssetCalibrator,
AssetClassSpec
)
# Calibrate equity indices with shared correlation
calibrator = CrossAssetCalibrator([
AssetClassSpec(name="SPX", weight=1.0, shared_params=["rho"]),
AssetClassSpec(name="NDX", weight=0.8, shared_params=["rho"]),
AssetClassSpec(name="RTY", weight=0.6, shared_params=["rho"])
])
result = calibrator.calibrate(multi_asset_data)
Topics covered: - Shared parameter specifications - Asset-specific vs global parameters - Cross-asset consistency constraints - Portfolio-level risk implications
Estimated time: 45 minutes
4. Diagnostics & Validation¶
Calibration Diagnostics Deep Dive Comprehensive post-calibration analysis and quality checks.
from neutryx.calibration.diagnostics import (
generate_calibration_diagnostics,
build_residual_plot_data,
compute_identifiability_metrics
)
# Generate full diagnostic report
diagnostics = generate_calibration_diagnostics(result, market_data)
print(f"RMSE: {diagnostics.rmse:.4f}")
print(f"Max error: {diagnostics.max_abs_error:.4f}")
print(f"Condition number: {diagnostics.identifiability.condition_number:.2f}")
# Visualize residuals
residual_data = build_residual_plot_data(result, market_data)
# ... plotting code
Topics covered: - Residual analysis (strikes, maturities, moneyness) - Parameter identifiability and covariance - Convergence diagnostics - Red flags and warning signs - Iteration and retry strategies
Estimated time: 40 minutes
Model Selection and Comparison Statistical comparison of competing models using information criteria.
from neutryx.calibration.model_selection import compare_models
# Compare SABR, Heston, and SLV
comparison = compare_models([
("SABR", sabr_result, market_data),
("Heston", heston_result, market_data),
("SLV", slv_result, market_data)
])
print(f"Best by AIC: {comparison.best_by_aic}")
print(f"Best by BIC: {comparison.best_by_bic}")
print(f"AIC weights: {comparison.aic_weights}")
Topics covered: - AIC, BIC, AICc, HQIC information criteria - Model complexity penalties - Overfitting detection - Model selection best practices
Estimated time: 35 minutes
Cross-Validation Strategies Validate calibration robustness with k-fold and time-series CV.
from neutryx.calibration.model_selection import (
cross_validate,
k_fold_split,
time_series_split
)
# K-fold cross-validation
cv_result = cross_validate(
calibrator=calibrator,
data=market_data,
split_fn=k_fold_split(n_folds=5),
n_trials=10
)
print(f"Mean CV error: {cv_result.mean_error:.4f}")
print(f"Std CV error: {cv_result.std_error:.4f}")
# Time-series walk-forward validation
ts_result = cross_validate(
calibrator=calibrator,
data=time_series_data,
split_fn=time_series_split(n_splits=10)
)
Topics covered: - K-fold cross-validation setup - Time-series splitting strategies - Out-of-sample validation metrics - Overfitting diagnosis - Production model validation
Estimated time: 40 minutes
Sensitivity Analysis Analyze parameter sensitivity and uncertainty propagation.
from neutryx.calibration.model_selection import (
compute_local_sensitivity,
sobol_indices
)
# Local sensitivity (gradient-based)
local_sens = compute_local_sensitivity(
calibrator,
result.params,
market_data
)
# Global sensitivity (variance-based)
param_ranges = {
"alpha": (0.1, 0.5),
"rho": (-0.8, -0.2),
"nu": (0.2, 0.8)
}
global_sens = sobol_indices(
calibrator,
param_ranges,
market_data,
n_samples=2048
)
print(f"First-order Sobol indices: {global_sens.first_order}")
print(f"Total Sobol indices: {global_sens.total}")
Topics covered: - Local vs global sensitivity - Finite difference gradients - Sobol variance decomposition - Parameter uncertainty quantification - Risk factor importance ranking
Estimated time: 50 minutes
5. Advanced Techniques¶
Bayesian Model Averaging Combine multiple models using Bayesian model averaging for robust predictions.
from neutryx.calibration.bayesian_model_averaging import (
BayesianModelAveraging,
WeightingScheme
)
# Fit ensemble of models
bma = BayesianModelAveraging(
models=[sabr_calibrator, heston_calibrator, slv_calibrator],
weighting_scheme=WeightingScheme.STACKING
)
bma_result = bma.fit(training_data)
predictions = bma.predict(new_market_conditions)
print(f"Model weights: {bma_result.weights}")
print(f"Ensemble predictions: {predictions}")
Topics covered: - BMA theoretical foundations - Weighting schemes (stacking, pseudo-BMA, IC-based) - Ensemble prediction - Model uncertainty quantification - Production deployment considerations
Estimated time: 50 minutes
Regularization Techniques Apply regularization for stable, smooth parameter evolution.
from neutryx.calibration.regularization import (
L2Regularization,
SmoothnessRegularization
)
# L2 penalty on parameter deviations
l2_penalty = L2Regularization(
reference_params=historical_params,
weights={"alpha": 0.01, "nu": 0.01}
)
# Smoothness penalty for time-dependent calibration
smoothness_penalty = SmoothnessRegularization(
time_segments=segments,
weight=0.05
)
calibrator = MyCalibrator(penalty_fn=l2_penalty)
Topics covered: - L1/L2 regularization - Smoothness constraints - Historical parameter anchoring - Regularization strength tuning - Bias-variance tradeoff
Estimated time: 40 minutes
Custom Loss Functions Design custom loss functions for specific calibration objectives.
from neutryx.calibration import losses
import jax.numpy as jnp
def custom_weighted_loss(model_vals, target_vals, weights=None):
"""Emphasize ATM options and recent expiries."""
errors = model_vals - target_vals
# Weight by moneyness
atm_weights = jnp.exp(-moneyness**2 / 0.05)
# Weight by time to maturity
time_weights = jnp.exp(-maturities / 2.0)
# Combined weights
combined = atm_weights * time_weights
if weights is not None:
combined = combined * weights
return jnp.sqrt(jnp.mean(combined * errors**2))
calibrator = MyCalibrator(loss_fn=custom_weighted_loss)
Topics covered: - Standard loss functions (RMSE, MAE, MAPE) - Custom weighting schemes - Robust loss functions (Huber) - Multi-objective calibration - Domain-specific loss design
Estimated time: 45 minutes
Complete Masterclass¶
For a comprehensive, end-to-end calibration workshop covering all topics above in depth, see:
Calibration Masterclass and Tuning Workshop
This advanced curriculum includes: - Complete theory-to-practice walkthroughs - Production deployment patterns - Performance optimization techniques - Troubleshooting guides - Real-world case studies
Estimated time: 6-8 hours
Quick Reference¶
Common Calibration Patterns¶
Pattern 1: Basic Single-Model Calibration
calibrator = SABRCalibrator()
result = calibrator.calibrate(market_data)
diagnostics = generate_calibration_diagnostics(result, market_data)
Pattern 2: Multi-Model Comparison
models = [SABRCalibrator(), HestonCalibrator(), SLVCalibrator()]
results = [m.calibrate(market_data) for m in models]
comparison = compare_models(zip(["SABR", "Heston", "SLV"], results, [market_data]*3))
Pattern 3: Cross-Validated Calibration
calibrator = MyCalibrator()
cv_result = cross_validate(calibrator, market_data, k_fold_split(5))
final_result = calibrator.calibrate(market_data) if cv_result.mean_error < threshold else None
Troubleshooting Guide¶
Calibration Not Converging?¶
- Check initial values: Use
default_parameter_specs()for sensible defaults - Inspect loss history: Look for plateaus or divergence patterns
- Adjust optimizer: Try different learning rates or switch optimizers
- Add constraints: Ensure parameter bounds match model requirements
- Simplify the problem: Start with fewer parameters or data points
Poor Fit Quality?¶
- Check residual patterns: Systematic errors indicate model misspecification
- Increase weighting: Weight ATM options or liquid strikes more heavily
- Try different models: SABR vs Heston vs SLV have different smile capabilities
- Add data: More market quotes improve identifiability
- Regularize: Add smoothness or historical anchoring penalties
Unstable Parameters?¶
- Check identifiability: High condition numbers indicate collinearity
- Cross-validate: High CV error variance indicates overfitting
- Regularize: Add L2 penalty to stabilize parameter estimates
- Simplify model: Reduce number of free parameters
- Add prior information: Use parameter bounds based on historical ranges
Next Steps¶
- API Documentation: See Reference for detailed API docs
- Production Workflows: Explore Playbooks for enterprise patterns
- Theory: Study Calibration Theory for mathematical foundations
Feedback¶
Found an issue or have a suggestion? Open an issue on GitHub