Class VannaVolga
fx.FxVolSurface solves from broker RR/BF quotes).
The idea: hedge the flat-vol Black-Scholes price's vega, vanna and volga with a portfolio of the three pillars; the market cost of that hedge is the smile adjustment. The classic log-strike weight form used here makes the construction exact at the pillars (pricing a pillar strike returns the pillar's own market vol) and interpolates smoothly between and beyond them:
price(K) = BS(K; σ_atm) + Σᵢ wᵢ(K) · [BS(Kᵢ; σᵢ) − BS(Kᵢ; σ_atm)] w₁(K) = vega(K)/vega(K₁) · ln(K₂/K)·ln(K₃/K) / (ln(K₂/K₁)·ln(K₃/K₁))
(cyclic for w₂, w₃). impliedVol(double, double) inverts the adjusted price
back through Black-Scholes, giving a full smile from three quotes — the
standard method for consistent barrier/touch adjustments and broken-strike
marks on FX desks. Conventions match BlackScholes: carry
is the continuous yield (foreign rate for FX).
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final doubleForward delta of the strikes beyond whichimpliedVol(double, double)stops using the raw formula. -
Constructor Summary
ConstructorsConstructorDescriptionVannaVolga(double[] strikes, double[] vols, double rate, double carry, double timeYears) -
Method Summary
Modifier and TypeMethodDescriptiondoublecarry()double[]exactWeights(double spot, double strike) Exact vanna-volga hedge weights for a vanilla atstrike: the solution x of the 3x3 systemdoubleimpliedVol(double spot, double strike) Smile-consistent implied vol at any strike: the vanna-volga price inverted through Black-Scholes.static VannaVolgaofPillars(double[] strikes, double[] vols, double rate, double carry, double timeYears) Builds directly from a solvedfx.FxVolSurfacepillar (25Δ set).doublepillarSmileCost(double spot, int i) Market cost of the smile on each pillar: BS(Kᵢ; σᵢ) − BS(Kᵢ; σ_atm), calls (put-call parity makes the put value identical).doubleprice(BlackScholes.OptionType type, double spot, double strike) Smile-consistent price of a vanilla at any strike.doublepriceExact(BlackScholes.OptionType type, double spot, double strike) Vanilla price with weights from the exact 3x3 solve (exactWeights(double, double)): BS(K; σ_atm) + Σ xᵢ · pillar smile cost.doublerate()doublestrike(int i) Pillar strikei(0 put wing, 1 ATM, 2 call wing).doubledoublevol(int i) Market vol at pillari.double[]weightsFor(double spot, double targetVega, double targetVanna, double targetVolga) Pillar weights that replicate a target's vega, vanna and volga (all at the ATM vol): the general form of the vanna-volga system, used for exotics such as one-touches.
-
Field Details
-
WING_DELTA
public static final double WING_DELTAForward delta of the strikes beyond whichimpliedVol(double, double)stops using the raw formula.- See Also:
-
-
Constructor Details
-
VannaVolga
public VannaVolga(double[] strikes, double[] vols, double rate, double carry, double timeYears) - Parameters:
strikes- three ascending pillar strikes (25Δput, ATM, 25Δcall)vols- their market vols; vols[1] is the ATM anchor
-
-
Method Details
-
ofPillars
public static VannaVolga ofPillars(double[] strikes, double[] vols, double rate, double carry, double timeYears) Builds directly from a solvedfx.FxVolSurfacepillar (25Δ set). -
price
Smile-consistent price of a vanilla at any strike. -
impliedVol
public double impliedVol(double spot, double strike) Smile-consistent implied vol at any strike: the vanna-volga price inverted through Black-Scholes. Pillar strikes recover their market vols exactly.The inversion uses the out-of-the-money option (put below the forward, call above), whose price is all time value; inverting a deep in-the-money call loses the smile adjustment in the intrinsic value.
Wings. Beyond the
WING_DELTAstrikes (forward delta at the ATM vol, never inside the outer pillars) the quadratic log-strike weights grow without bound and produce negative butterflies, so the raw formula is not used there. Where the vol at the cutoff falls going outward it is held flat (a convex join); where it rises outward it is continued linearly in log-strike with the cutoff slope, which joins smoothly instead of leaving the concave kink a flat cap would. The continuation does not enforce Lee's (2004) moment bound and should not be pushed many standard deviations out. -
exactWeights
public double[] exactWeights(double spot, double strike) Exact vanna-volga hedge weights for a vanilla atstrike: the solution x of the 3x3 systemΣᵢ xᵢ · vega(Kᵢ) = vega(K) Σᵢ xᵢ · vanna(Kᵢ) = vanna(K) Σᵢ xᵢ · volga(Kᵢ) = volga(K)
with all Greeks at the ATM vol (Castagna and Mercurio 2007, "The vanna-volga method for implied volatilities", Risk, January, equation 3). Castagna and Mercurio show that for Black-Scholes vanillas this system has the closed-form solution used by
price(BlackScholes.OptionType, double, double), so the two agree up to rounding; the linear solve is the version that generalises to non-vanilla targets (seeweightsFor(double, double, double, double)). -
weightsFor
public double[] weightsFor(double spot, double targetVega, double targetVanna, double targetVolga) Pillar weights that replicate a target's vega, vanna and volga (all at the ATM vol): the general form of the vanna-volga system, used for exotics such as one-touches. -
pillarSmileCost
public double pillarSmileCost(double spot, int i) Market cost of the smile on each pillar: BS(Kᵢ; σᵢ) − BS(Kᵢ; σ_atm), calls (put-call parity makes the put value identical). -
priceExact
Vanilla price with weights from the exact 3x3 solve (exactWeights(double, double)): BS(K; σ_atm) + Σ xᵢ · pillar smile cost. -
strike
public double strike(int i) Pillar strikei(0 put wing, 1 ATM, 2 call wing). -
vol
public double vol(int i) Market vol at pillari. -
rate
public double rate() -
carry
public double carry() -
timeYears
public double timeYears()
-