Skip to main content
ProbSurface extends the single-expiry ProbCurve concept to multiple maturities. You normally build one with ProbSurface.from_chain(...), or by calling VolSurface.implied_distribution(...) on a fitted volatility surface. Once built, you can evaluate the PDF or CDF within the fitted maturity range, extract ProbCurve slices, export a long-format DataFrame, and visualize the distribution with a fan chart.

Constructors

You normally build a ProbSurface in one of two ways:

ProbSurface.from_chain

The one-step constructor. It fits the underlying VolSurface internally and returns a ready-to-query ProbSurface.
pd.DataFrame
required
Multi-expiry option chain DataFrame. Must contain an expiry column and at least two unique expiry dates.
MarketInputs
required
Market inputs providing the risk-free rate, valuation date, and underlying price.
dict[str, str] | None
default:"None"
Optional mapping in the form {"dataframe_column": "oipd_column"}. See Standard columns for the target names.
int
default:"3"
Maximum age of option quotes in calendar days. Rows older than this threshold are filtered before fitting each slice.
Literal['skip_warn', 'raise']
default:"skip_warn"
Controls how individual expiry calibration failures are handled. "skip_warn" skips the failing expiry and continues; "raise" propagates the error immediately.
Literal['warn', 'raise']
default:"warn"
Policy for CDF monotonicity violations. "warn" repairs and warns; "raise" fails on material violations.
Raises: ValueError if failure_policy is not a supported value. CalculationError if fewer than two expiries remain after filtering, or if calibration fails.

From a fitted VolSurface

If you have already fitted a VolSurface, call implied_distribution() on that object:
This is the recommended path when you want to inspect or reuse the volatility surface before deriving probabilities. See VolSurface.implied_distribution.

Methods

Evaluate the PDF at given price level(s) and maturity.
float | np.ndarray
required
Price level or array of price levels to evaluate.
float | str | date | pd.Timestamp
required
Maturity. Pass a year-fraction float (e.g., 45/365) or a date-like value (e.g., "2025-06-20"). The surface interpolates to any maturity within the fitted range.
np.ndarray
Interpolated PDF values at price for the given maturity. Values outside the domain return 0.0.
Evaluate the CDF at given price level(s) and maturity.
float | np.ndarray
required
Price level or array of price levels to evaluate.
float | str | date | pd.Timestamp
required
Maturity as a year-fraction float or date-like value.
np.ndarray
Cumulative probability values. Returns 0.0 below the domain and 1.0 above.
Inverse CDF: returns the price level at quantile q for maturity t.
float
required
Target probability in the open interval (0, 1).
float | str | date | pd.Timestamp
required
Maturity as a year-fraction float or date-like value.
float
Price S such that P(Asset < S) = q at maturity t.
Raises: ValueError if q is not in (0, 1).
Extract a single-expiry ProbCurve for a maturity within the fitted range. If expiry matches a fitted pillar exactly, the method returns a curve built from that pillar’s data. Otherwise, it builds a synthetic curve via total-variance interpolation.
str | date | pd.Timestamp
required
Target expiry. Accepts ISO date strings like "2025-06-20", Python date objects, or pd.Timestamp.
ProbCurve
Probability curve for the requested maturity.
Raises: ValueError if the surface is empty or the maturity is outside the fitted range.
Export a long-format DataFrame of probability slices across expiries.
tuple[float, float] | None
default:"None"
Optional export price domain as (min_price, max_price). Takes precedence over full_domain.
int
default:"200"
Number of price points per expiry slice in the output.
str | date | pd.Timestamp | None
default:"None"
Lower expiry bound for the export. Defaults to the first fitted pillar expiry.
str | date | pd.Timestamp | None
default:"None"
Upper expiry bound for the export. Defaults to the last fitted pillar expiry.
int | None
default:"1"
Calendar-day sampling interval between exported slices. Fitted pillar expiries are always included. Pass None to export fitted pillars only.
bool
default:"False"
When True and domain is not set, each slice exports its full native domain without resampling.
pd.DataFrame
Long-format DataFrame with columns expiry, price, pdf, and cdf.
Plot a fan chart of risk-neutral quantiles across all expiries.
tuple[float, float]
default:"(10, 6)"
Figure size as (width, height) in inches.
str | None
default:"None"
Custom title. Auto-generated when omitted.
matplotlib.figure.Figure
The rendered fan chart figure.
Raises: ValueError if the surface has no fitted expiries, or if no valid slices remain after skipping invalid fan slices.

Properties

tuple[pd.Timestamp, ...]
All fitted pillar maturities as a tuple of pd.Timestamp objects, in ascending order.
WarningDiagnostics
Structured diagnostic events accumulated across all surface operations. Inspect .warning_diagnostics.events for data-quality, model-risk, and workflow events.

Example