private void priceCheck(double[] strikes) { for (int i = 0; i < N; i++) { double ivNormalComputed = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, strikes[i], T, SIGMA_BLACK[i]); double priceNormalComputed = NormalFormulaRepository.price(FORWARD, strikes[i], T, ivNormalComputed, PutCall.CALL) * DF; double priceBlack = BlackFormulaRepository.price(FORWARD, strikes[i], T, SIGMA_BLACK[i], true) * DF; assertEquals(priceNormalComputed, priceBlack, TOLERANCE_PRICE); } }
//------------------------------------------------------------------------- /// <summary> /// Computes the implied volatility. /// <para> /// If the volatility data is not zero, it is used as a starting point for the volatility search. /// </para> /// <para> /// Note that the 'numeraire' is a simple multiplier and is the responsibility of the caller. /// /// </para> /// </summary> /// <param name="optionPrice"> the price of the option </param> /// <param name="forward"> the forward value of the underlying </param> /// <param name="strike"> the strike </param> /// <param name="timeToExpiry"> the time to expiry </param> /// <param name="initialNormalVol"> the normal volatility used to start the search </param> /// <param name="numeraire"> the numeraire </param> /// <param name="putCall"> whether it is put or call </param> /// <returns> the implied volatility </returns> public static double impliedVolatility(double optionPrice, double forward, double strike, double timeToExpiry, double initialNormalVol, double numeraire, PutCall putCall) { double intrinsicPrice = numeraire * Math.Max(0, (putCall.Call ? 1 : -1) * (forward - strike)); ArgChecker.isTrue(optionPrice > intrinsicPrice || DoubleMath.fuzzyEquals(optionPrice, intrinsicPrice, 1e-6), "Option price (" + optionPrice + ") less than intrinsic value (" + intrinsicPrice + ")"); if (System.BitConverter.DoubleToInt64Bits(optionPrice) == Double.doubleToLongBits(intrinsicPrice)) { return(0d); } double sigma = (Math.Abs(initialNormalVol) < 1e-10 ? 0.3 * forward : initialNormalVol); double maxChange = 0.5 * forward; ValueDerivatives price = priceAdjoint(forward, strike, timeToExpiry, sigma, numeraire, putCall); double vega = price.getDerivative(1); double change = (price.Value - optionPrice) / vega; double sign = Math.Sign(change); change = sign * Math.Min(maxChange, Math.Abs(change)); if (change > 0 && change > sigma) { change = sigma; } int count = 0; while (Math.Abs(change) > EPS) { sigma -= change; price = priceAdjoint(forward, strike, timeToExpiry, sigma, numeraire, putCall); vega = price.getDerivative(1); change = (price.Value - optionPrice) / vega; sign = Math.Sign(change); change = sign * Math.Min(maxChange, Math.Abs(change)); if (change > 0 && change > sigma) { change = sigma; } if (count++ > MAX_ITERATIONS) { BracketRoot bracketer = new BracketRoot(); BisectionSingleRootFinder rootFinder = new BisectionSingleRootFinder(EPS); System.Func <double, double> func = (double?volatility) => { return(numeraire * NormalFormulaRepository.price(forward, strike, timeToExpiry, volatility.Value, putCall) - optionPrice); }; double[] range = bracketer.getBracketedPoints(func, 0d, 10d); return(rootFinder.getRoot(func, range[0], range[1]).Value); } } return(sigma); }
public virtual void implied_volatility_adjoint() { double shiftFd = 1.0E-6; for (int i = 0; i < N; i++) { double impliedVol = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i]); ValueDerivatives impliedVolAdj = NormalFormulaRepository.impliedVolatilityFromBlackApproximatedAdjoint(FORWARD, STRIKES[i], T, SIGMA_BLACK[i]); assertEquals(impliedVolAdj.Value, impliedVol, TOLERANCE_VOL); double impliedVolP = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i] + shiftFd); double impliedVolM = NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, STRIKES[i], T, SIGMA_BLACK[i] - shiftFd); double derivativeApproximated = (impliedVolP - impliedVolM) / (2 * shiftFd); assertEquals(impliedVolAdj.Derivatives.size(), 1); assertEquals(impliedVolAdj.getDerivative(0), derivativeApproximated, TOLERANCE_VOL); } }
/// <summary> /// Computes vega of an option in the normally distributed assets hypothesis (Bachelier model). /// </summary> /// <param name="option"> the option description </param> /// <param name="data"> the model data </param> /// <returns> vega </returns> public double getVega(EuropeanVanillaOption option, NormalFunctionData data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); return(data.Numeraire * NormalFormulaRepository.vega(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, option.PutCall)); }
/// <summary> /// Computes the price of an option in the normally distributed assets hypothesis (Bachelier model). /// The first order price derivatives are also provided. /// </summary> /// <param name="option"> the option description </param> /// <param name="data"> the model data </param> /// <returns> a <seealso cref="ValueDerivatives"/> with the price in the value and the derivatives with /// respect to [0] the forward, [1] the volatility and [2] the strike </returns> public ValueDerivatives getPriceAdjoint(EuropeanVanillaOption option, NormalFunctionData data) { ArgChecker.notNull(option, "option"); ArgChecker.notNull(data, "data"); return(NormalFormulaRepository.priceAdjoint(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @SuppressWarnings("synthetic-access") @Override public System.Nullable<double> apply(NormalFunctionData data) public override double?apply(NormalFunctionData data) { ArgChecker.notNull(data, "data"); return(data.Numeraire * NormalFormulaRepository.price(data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, option.PutCall)); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test(expectedExceptions = IllegalArgumentException.class) public void wrong_forward() public virtual void wrong_forward() { NormalFormulaRepository.impliedVolatilityFromBlackApproximated(-1.0d, FORWARD, T, 0.20d); }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test(expectedExceptions = IllegalArgumentException.class) public void wrong_strike() public virtual void wrong_strike() { NormalFormulaRepository.impliedVolatilityFromBlackApproximated(FORWARD, -1.0d, T, 0.20d); }
private double impliedVolatility(NormalFunctionData data, EuropeanVanillaOption option, double price) { return(NormalFormulaRepository.impliedVolatility(price, data.Forward, option.Strike, option.TimeToExpiry, data.NormalVolatility, data.Numeraire, option.PutCall)); }