ProbCurve represents the risk-neutral probability distribution implied by a single-expiry option chain. You can build one directly from an option chain, or derive one from a fitted VolCurve when you want to inspect the volatility fit first. You can then query probabilities, moments, and quantiles, export a DataFrame, or render a plot.
Constructors
You normally build aProbCurve in one of two ways:
- Use
ProbCurve.from_chain(...)when you want OIPD to fit the volatility smile and derive the probability curve in one step. - Use
VolCurve.implied_distribution(...)when you already have a fittedVolCurveand want to reuse it.
ProbCurve.from_chain
The one-step constructor. Accepts a single-expiry option chain DataFrame and market inputs, fits an SVI smile, and derives the risk-neutral distribution.
pd.DataFrame
required
Option chain DataFrame for a single expiry. Must contain an
expiry column and at least one supported price column (last_price, or bid/ask).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"}. For example, {"type": "option_type"} means your DataFrame has a type column and OIPD should treat it as option_type. See Standard columns for the target names.int
default:"3"
Maximum age of option quotes in calendar days, relative to the valuation date. Rows older than this threshold are filtered out before fitting.
Literal['warn', 'raise']
default:"warn"
Policy for handling CDF monotonicity violations during materialization.
"warn" repairs the CDF and records a diagnostic warning; "raise" raises a CalculationError on material violations.ValueError if the chain contains multiple expiries. CalculationError if volatility calibration fails.
From a fitted VolCurve
If you have already fitted a VolCurve, call implied_distribution() on that object:
VolCurve.implied_distribution.
Methods
pdf(price)
pdf(price)
Evaluate the Probability Density Function at one or more price levels.
float | np.ndarray
required
Price level or array of price levels to evaluate.
float | np.ndarray
PDF value(s). Returns a scalar
float when price is a scalar, or an ndarray otherwise. Values outside the fitted domain return 0.0.ProbCurve is also callable: prob(price) is an alias for prob.pdf(price).prob_below(price)
prob_below(price)
prob_above(price)
prob_above(price)
prob_between(low, high)
prob_between(low, high)
mean()
mean()
Expected value of the asset price under the fitted PDF.
float
E[S], computed by numerical integration of
price × pdf over the domain.variance()
variance()
skew()
skew()
Skewness (third standardized moment) of the fitted PDF.
float
Skew = E[(S - μ)³] / σ³. Negative values indicate a fat left tail, which is typical for equity distributions.
kurtosis()
kurtosis()
Excess kurtosis (fourth standardized moment minus 3) of the fitted PDF.
float
Excess kurtosis = E[(S - μ)⁴] / σ⁴ - 3. Zero implies a normal distribution; positive values indicate fat tails.
quantile(q)
quantile(q)
density_results(domain, points, full_domain)
density_results(domain, points, full_domain)
Export the fitted distribution as a DataFrame for analysis or custom plotting.
tuple[float, float] | None
default:"None"
Optional explicit export domain as
(min_price, max_price). When provided, the native distribution is resampled onto this range. Takes precedence over full_domain.int
default:"200"
Number of output rows when resampling to a compact or explicit domain. Ignored when
full_domain=True and no domain is specified.bool
default:"False"
When
True and domain is not set, returns the full native distribution arrays without resampling.pd.DataFrame
DataFrame with columns
price, pdf, and cdf.plot(kind, figsize, title, xlim, ylim, points, full_domain)
plot(kind, figsize, title, xlim, ylim, points, full_domain)
Render the risk-neutral probability distribution as a matplotlib figure.
Literal['pdf', 'cdf', 'both']
default:"both"
Which distribution curve(s) to render.
tuple[float, float]
default:"(10, 5)"
Figure size as (width, height) in inches.
str | None
default:"None"
Custom title. Auto-generated from market metadata when omitted.
tuple[float, float] | None
default:"None"
Optional explicit x-axis (price) limits.
tuple[float, float] | None
default:"None"
Optional explicit y-axis limits.
int
default:"800"
Number of display points for plot resampling.
bool
default:"False"
When
True and xlim is not set, plots across the full native probability domain instead of the compact default view domain.matplotlib.figure.Figure
The rendered matplotlib figure.
Properties
np.ndarray
The default price grid used for standard visualization. Accessing this property triggers lazy distribution materialization on first call.
np.ndarray
Probability densities over the stored price grid, in decimal form.
np.ndarray
Cumulative probabilities over the stored price grid, in decimal form.
WarningDiagnostics
Structured diagnostic events recorded during fitting and materialization. Inspect
.warning_diagnostics.events for details on data-quality issues, model-risk warnings, or CDF repairs.ResolvedMarket
Immutable snapshot of the market inputs used during calibration, including the resolved underlying price, risk-free rate, and valuation date.
dict[str, Any]
Metadata captured during estimation, including the expiry timestamp, time to expiry in years, diagnostics, and domain information.