/** * Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.model.volatility.local; import org.apache.commons.lang.Validate; import com.opengamma.analytics.financial.model.interestrate.curve.ForwardCurve; import com.opengamma.analytics.math.function.Function; import com.opengamma.analytics.math.surface.FunctionalDoublesSurface; /** * */ public abstract class LocalVolatilitySurfaceConverter { public static LocalVolatilitySurfaceMoneyness toMoneynessSurface(final LocalVolatilitySurfaceStrike from, final ForwardCurve fwdCurve) { final Function<Double, Double> surFunc = new Function<Double, Double>() { @Override public Double evaluate(final Double... tx) { final double t = tx[0]; final double x = tx[1]; final double f = fwdCurve.getForward(t); final double k = x * f; return from.getVolatility(t, k); } }; return new LocalVolatilitySurfaceMoneyness(FunctionalDoublesSurface.from(surFunc), fwdCurve); } public static LocalVolatilitySurfaceStrike toStrikeSurface(final LocalVolatilitySurfaceMoneyness from) { final Function<Double, Double> surFunc = new Function<Double, Double>() { @Override public Double evaluate(final Double... tk) { final double t = tk[0]; final double k = tk[1]; return from.getVolatility(t, k); } }; return new LocalVolatilitySurfaceStrike(FunctionalDoublesSurface.from(surFunc)); } /** * Under the usual local volatility assumption, the expiry-strike parameterised surface is invariant to a change in the * forward curve of the underlying. This of course means that the expiry-moneyness parameterised surface (where moneyness * = strike/forward) is not invariant. This gives a new expiry-moneyness local volatility surface under a shifted forward curve. * @param from The original expiry-moneyness local volatility surface * @param newForwardCurve New Forward Curve * @return New expiry-moneyness local volatility surface, such that the expiry-strike surface would be unchanged */ public static LocalVolatilitySurfaceMoneyness shiftForwardCurve(final LocalVolatilitySurfaceMoneyness from, final ForwardCurve newForwardCurve) { final ForwardCurve forwardCurve = from.getForwardCurve(); final Function<Double, Double> surFunc = new Function<Double, Double>() { @Override public Double evaluate(final Double... tx) { final double t = tx[0]; final double x = tx[1]; final double f = forwardCurve.getForward(t); final double fPrime = newForwardCurve.getForward(t); final double xPrime = x * fPrime / f; return from.getVolatilityForMoneyness(t, xPrime); } }; return new LocalVolatilitySurfaceMoneyness(FunctionalDoublesSurface.from(surFunc), newForwardCurve); } /** * Under the usual local volatility assumption, the expiry-strike parameterised surface is invariant to a change in the * forward curve of the underlying. This of course means that the expiry-moneyness parameterised surface (where moneyness * = strike/forward) is not invariant. This gives a new expiry-moneyness local volatility surface under a shifted forward curve. * @param from The original expiry-moneyness local volatility surface * @param shift fraction shift amount, i.e. 0.1 with produce a forward curve 10% larger than the original * @return New expiry-moneyness local volatility surface, such that the expiry-strike surface would be unchanged */ public static LocalVolatilitySurfaceMoneyness shiftForwardCurve(final LocalVolatilitySurfaceMoneyness from, final double shift) { Validate.isTrue(shift > -1, "shift must be > -1"); final ForwardCurve newForwardCurve = from.getForwardCurve().withFractionalShift(shift); final Function<Double, Double> surFunc = new Function<Double, Double>() { @Override public Double evaluate(final Double... tx) { final double t = tx[0]; final double x = tx[1]; final double xPrime = x * (1 + shift); return from.getVolatilityForMoneyness(t, xPrime); } }; return new LocalVolatilitySurfaceMoneyness(FunctionalDoublesSurface.from(surFunc), newForwardCurve); } }