Finance · probability distributions · JDistlib 0.9.0+

Move from tails to option-implied probabilities without hiding numerical risk

The finance layer treats a price, return, loss, payoff, path functional, or posterior output as a probability distribution. Approximate operations return error, work, strategy, warning, and convergence information.

Core in 0.9.0 · advanced follow-ups complete

Conventions first

Say whether the input is a loss or a return

Normal dailyReturn = new Normal(0.0004, 0.018);
double var99 = FinancialRisk.valueAtRisk(
    dailyReturn, 0.99, RiskConvention.RETURN);
NumericalEstimate es99 = FinancialRisk.expectedShortfall(
    dailyReturn, 0.99, RiskConvention.RETURN);

if (!es99.isConverged()) {
    throw new IllegalStateException(es99.getWarning());
}

NumericalEstimate entropic = AdvancedRiskMeasures.entropic(
    dailyReturn, 8.0, RiskConvention.RETURN);
NumericalEstimate wang = AdvancedRiskMeasures.distortedExpectation(
    dailyReturn, RiskConvention.RETURN,
    AdvancedRiskMeasures.wang(0.25));

Expected shortfall is a quantile integral, so a CDF jump is split correctly at the requested probability. The same layer provides lower/upper partial moments, stop-loss and option payoffs, downside deviation, expectiles, spectral risk, distortion/Choquet expectations, and MGF-checked entropic risk. Spectra are normalized numerically; distortions must be finite, nondecreasing, and map 0 and 1 to themselves.

Transform-domain foundation

Inspect existence before using an MGF

Gamma waitingTime = new Gamma(2.0, 0.5);
TransformDomain domain = waitingTime.momentGeneratingDomain();
Complex logCf = waitingTime.logCharacteristic(3.0);
NumericalEstimate variance =
    DistributionTransforms.cumulant(waitingTime, 2);

DistributionTransforms.TiltResult tilted =
    DistributionTransforms.esscherTilt(new Normal(), 0.25);

CgmyDistribution cgmy =
    new CgmyDistribution(.4, 5, 7, .7, .001);
NormalTemperedStableDistribution nts =
    new NormalTemperedStableDistribution(.6, 2, .8, -.01, .03, 0);
MeixnerDistribution meixner =
    new MeixnerDistribution(.03, -.2, 1.5, 0);

NumericalEstimate checkedCdf = DistributionTransforms.cumulativeAdaptive(
    cgmy, 0, FourierInversionOptions.defaults().withTolerance(1e-7));

Normal, gamma, Poisson, and Student-t objects implement the transform contract directly. Generalized hyperbolic/NIG, variance-gamma, CGMY/KoBoL, normal-tempered-stable, Meixner, and S1 alpha-stable laws expose ordinary distribution APIs, transforms, MGF domains, and parameter getters. Adaptive Fourier inversion reports frequency-truncation error and work; COS inversion and Lugannani–Rice saddlepoints provide alternative checked paths. Stable laws use analytical normal, Cauchy, and one-sided Lévy reductions where available, plus named S0 conversion and tail asymptotics.

Shared-mixture dependence

Project a multivariate law without losing its family

MultivariateFinancialDistribution joint =
    MultivariateFinancialDistribution.varianceGamma(
        1.8,
        new double[] {.001, -.0003},
        new double[] {-.01, .005},
        new double[][] {{.0004, .00012}, {.00012, .0009}});

GenericDistribution portfolio =
    joint.linearCombination(new double[] {.65, .35});
double[] reproducibleDraw = joint.random(20260828L);

The same construction supports generalized-hyperbolic, NIG, variance-gamma, symmetric stable, and normal-tempered-stable vectors. It validates a positive-definite covariance matrix, accepts caller-controlled or seeded streams, and reduces every scalar linear combination to the corresponding univariate family exactly. These are static multivariate distribution models, not time-varying covariance or portfolio-accounting systems.

Independent composition

Keep approximation and seed provenance beside the law

DistributionApproximation portfolio =
    DistributionAggregation.weightedSum(
        new GenericDistribution[] {assetA, assetB},
        new double[] {0.6, 0.4}, 50_000, 914L);

System.out.println(portfolio.getDiagnostics().getStrategy());
double q01 = portfolio.getDistribution().quantile(0.01);

DistributionApproximation exact =
    DistributionAggregation.exactDiscreteConvolution(lossA, lossB);
DistributionApproximation fft = DistributionAggregation.fftConvolution(
    firstMass, 0, secondMass, 0, 1);
DistributionApproximation panjer = DistributionAggregation.panjerCompound(
    0, poissonMean, Math.exp(-poissonMean), severityMass, 200);

Finite integer laws use exact convolution; equal-step grids can use zero-padded FFT convolution; and suitable compound-count laws can use Panjer recursion. COS inversion discretizes a transform law on a caller-declared interval. Each path returns a DistributionApproximation with strategy, work, truncation/roundoff error, and warnings. General weighted sums, compound sums, products, ratios, and scenarios retain the reproducible Monte Carlo fallback. Conditional intervals and iid extrema remain exact.

From increments to path outputs

Return a distribution, not only one simulated statistic

DistributionApproximation maxDrawdown =
    PathFunctionalDistributions.maximumDrawdown(
        new Normal(.001, .02), 252, 20_000, 81L);

Normal unitBrownian = new Normal();
LevyIncrementDistribution quarter =
    new LevyIncrementDistribution(unitBrownian, .25);
LevyIncrementDistribution year = quarter.plus(
    new LevyIncrementDistribution(unitBrownian, .75));

Running maxima and minima of iid observations are exact order-statistic laws. Maximum and terminal drawdowns use a documented iid-increment Monte Carlo model and retain seed and MC error. LevyIncrementDistribution scales any infinitely-divisible log transform by time and composes independent increments sharing the same unit exponent; it also remains usable for stable laws whose MGF exists only at zero.

Tail-sensitive dependence and EVT

Do not reduce dependence to one central rank statistic

Copula survival = new RotatedCopula(
    new ClaytonCopula(2, 2.0),
    RotatedCopula.Rotation.SURVIVAL_180);
NumericalEstimate lambdaUpper =
    CopulaTailAnalysis.upperTailDependence(survival);
double jointStress = CopulaTailAnalysis.stressProbability(
    survival, Tail.UPPER, .99, Tail.UPPER, .99);

Rotations, the Joe and BB1 families, finite-level concentration, mixed stress regions, and tail-weighted likelihoods integrate with the existing copula interfaces. DistributionFit supplies bounded MLE/MAP and exact/censored/interval likelihoods. ExtremeValueInference adds GEV MLE/PWM, GPD peaks over threshold, Hill/Pickands estimates, return levels, bootstrap uncertainty, mean residual life, and threshold stability diagnostics.

Quotes to a distribution

Repair the curve before differentiating it

ImpliedVolatilityResult iv =
    ReferenceOptions.impliedBlackScholes(
        price, forward, strike, discount, maturity, true);

OptionCurve curve = OptionCurve.build(
    forward, discount, maturity, quotes);
OptionImpliedDistribution q = curve.getDistribution();

double chanceAbove120 = q.cumulative(120, false, false);
double interval = curve.strikeIntervalProbability(95, 115);

SmoothOptionDistributionResult smooth = curve.smoothDistribution(2.0);
System.out.println(smooth.getMaximumPriceResidual());
System.out.println(smooth.getDifferentiationUncertainty());

Inversion reports price bounds, residual, iterations, bracket, and status. The curve converts puts by parity, enforces bounds, monotonicity, convexity, and terminal conditions, then returns an atom-aware normalized risk-neutral distribution. The optional smooth path reflects Gaussian kernels at zero, preserves the forward mean, and reports bandwidth, normalization error, reconstructed quote residual, and differentiation uncertainty. Keep the atom-aware result when the observations do not justify smoothing. Always inspect OptionCurve.Diagnostics; repaired observations are evidence about the inputs, not noise to suppress.

Follow the complete worked options analysis →

Uncertainty over distributions

Label Q and physical/predictive outputs explicitly

OptionCalibration fits compatible parametric laws to bid/ask or point quotes and retains residual and identifiability diagnostics. OptionInference.likelihood creates a reusable interval/heteroskedastic model factor. OptionInference.posterior turns retained draws into terminal-price, payoff, strike-event, VaR, and expected-shortfall ensembles with MCSE, seed, chain provenance, and an explicit RISK_NEUTRAL or PHYSICAL_PREDICTIVE label.

Library boundary

This is probability machinery, not a trading platform

JDistlib does not ingest market data, manage surfaces or instruments, calculate a general Greeks hierarchy, choose trades, backtest, account for a portfolio, or execute orders. Those systems can use these distributions and diagnostics without making them part of the statistical core.

Compile-ready entry points are FinanceFeatureExamples.java and AdvancedFinanceExamples.java.