//------------------------------------------------------------------------- public virtual void test_volatility() { for (int i = 0; i < NB_EXPIRY; i++) { double expiryTime = VOLS.relativeTime(TEST_EXPIRY[i]); for (int j = 0; j < NB_STRIKE; ++j) { double volExpected = SMILE_TERM.volatility(expiryTime, TEST_STRIKE[j], FORWARD[i]); double volComputed = VOLS.volatility(CURRENCY_PAIR, TEST_EXPIRY[i], TEST_STRIKE[j], FORWARD[i]); assertEquals(volComputed, volExpected, TOLERANCE); } } }
/// <summary> /// Tests the interpolation in the time and strike dimensions. /// </summary> public virtual void volatilityTimeInterpolation() { double forward = 1.40; double timeToExpiry = 0.75; double strike = 1.50; double[] vol050 = SMILE_TERM.VolatilityTerm.get(2).Volatility.toArray(); double[] vol100 = SMILE_TERM.VolatilityTerm.get(3).Volatility.toArray(); double[] vol = new double[vol050.Length]; for (int loopvol = 0; loopvol < vol050.Length; loopvol++) { vol[loopvol] = Math.Sqrt(((vol050[loopvol] * vol050[loopvol] * TIME_TO_EXPIRY.get(2) + vol100[loopvol] * vol100[loopvol] * TIME_TO_EXPIRY.get(3)) / 2.0) / timeToExpiry); } SmileDeltaParameters smile = SmileDeltaParameters.of(timeToExpiry, DELTA, DoubleArray.copyOf(vol)); DoubleArray strikes = smile.strike(forward); double volExpected = INTERPOLATOR_STRIKE.bind(strikes, DoubleArray.copyOf(vol), FLAT, FLAT).interpolate(strike); double volComputed = SMILE_TERM.volatility(timeToExpiry, strike, forward); assertEquals(volComputed, volExpected, TOLERANCE_VOL, "Smile by delta term structure: vol interpolation on strike"); double volTriple = SMILE_TERM.volatility(timeToExpiry, strike, forward); assertEquals(volTriple, volComputed, TOLERANCE_VOL, "Smile by delta term structure: vol interpolation on strike"); InterpolatedStrikeSmileDeltaTermStructure smileTerm2 = InterpolatedStrikeSmileDeltaTermStructure.of(VOLATILITY_TERM, ACT_360); double volComputed2 = smileTerm2.volatility(timeToExpiry, strike, forward); assertEquals(volComputed2, volComputed, TOLERANCE_VOL, "Smile by delta term structure: vol interp on strike"); }
//------------------------------------------------------------------------- /// <summary> /// Tests the volatility at a point of the grid. /// </summary> public virtual void volatilityAtPoint() { double forward = 1.40; double timeToExpiry = 0.50; double[] strikes = SMILE_TERM.VolatilityTerm.get(2).strike(forward).toArray(); double volComputed = SMILE_TERM.volatility(timeToExpiry, strikes[1], forward); double volExpected = SMILE_TERM.VolatilityTerm.get(2).Volatility.get(1); assertEquals(volComputed, volExpected, TOLERANCE_VOL, "Smile by delta term structure: volatility at a point"); }
//------------------------------------------------------------------------- public virtual void test_price_presentValue() { double priceCallOtm = PRICER.price(CALL_OTM, RATES_PROVIDER, VOLS); CurrencyAmount pvCallOtm = PRICER.presentValue(CALL_OTM, RATES_PROVIDER, VOLS); double pricePutOtm = PRICER.price(PUT_OTM, RATES_PROVIDER, VOLS); CurrencyAmount pvPutOtm = PRICER.presentValue(PUT_OTM, RATES_PROVIDER, VOLS); double timeToExpiry = VOLS.relativeTime(EXPIRY); double df = RATES_PROVIDER.discountFactor(USD, PAYMENT_DATE); double forward = PRICER.DiscountingFxSingleProductPricer.forwardFxRate(FX_PRODUCT_HIGH, RATES_PROVIDER).fxRate(CURRENCY_PAIR); double volHigh = SMILE_TERM.volatility(timeToExpiry, STRIKE_RATE_HIGH, forward); double volLow = SMILE_TERM.volatility(timeToExpiry, STRIKE_RATE_LOW, forward); double expectedPriceCallOtm = df * BlackFormulaRepository.price(forward, STRIKE_RATE_HIGH, timeToExpiry, volHigh, true); double expectedPricePutOtm = df * BlackFormulaRepository.price(forward, STRIKE_RATE_LOW, timeToExpiry, volLow, false); double expectedPvCallOtm = -NOTIONAL *df *BlackFormulaRepository.price(forward, STRIKE_RATE_HIGH, timeToExpiry, volHigh, true); double expectedPvPutOtm = -NOTIONAL *df *BlackFormulaRepository.price(forward, STRIKE_RATE_LOW, timeToExpiry, volLow, false); assertEquals(priceCallOtm, expectedPriceCallOtm, TOL); assertEquals(pvCallOtm.Currency, USD); assertEquals(pvCallOtm.Amount, expectedPvCallOtm, NOTIONAL * TOL); assertEquals(pricePutOtm, expectedPricePutOtm, TOL); assertEquals(pvPutOtm.Currency, USD); assertEquals(pvPutOtm.Amount, expectedPvPutOtm, NOTIONAL * TOL); }
/// <summary> /// Tests the interpolation and its derivative with respect to the data by comparison to finite difference. /// </summary> public virtual void volatilityAjoint() { double forward = 1.40; double[] timeToExpiry = new double[] { 0.75, 1.00, 2.50 }; double[] strike = new double[] { 1.50, 1.70, 2.20 }; double[] tolerance = new double[] { 3e-2, 1e-1, 1e-5 }; int nbTest = strike.Length; double shift = 0.00001; for (int looptest = 0; looptest < nbTest; looptest++) { double vol = SMILE_TERM.volatility(timeToExpiry[looptest], strike[looptest], forward); //JAVA TO C# CONVERTER NOTE: The following call to the 'RectangularArrays' helper class reproduces the rectangular array initialization that is automatic in Java: //ORIGINAL LINE: double[][] bucketTest = new double[TIME_TO_EXPIRY.size()][2 * DELTA.size() + 1]; double[][] bucketTest = RectangularArrays.ReturnRectangularDoubleArray(TIME_TO_EXPIRY.size(), 2 * DELTA.size() + 1); VolatilityAndBucketedSensitivities volComputed = SMILE_TERM.volatilityAndSensitivities(timeToExpiry[looptest], strike[looptest], forward); DoubleMatrix bucketSensi = volComputed.Sensitivities; assertEquals(volComputed.Volatility, vol, 1.0E-10, "Smile by delta term structure: volatility adjoint"); SmileDeltaParameters[] volData = new SmileDeltaParameters[TIME_TO_EXPIRY.size()]; double[] volBumped = new double[2 * DELTA.size() + 1]; for (int loopexp = 0; loopexp < TIME_TO_EXPIRY.size(); loopexp++) { for (int loopsmile = 0; loopsmile < 2 * DELTA.size() + 1; loopsmile++) { Array.Copy(SMILE_TERM.VolatilityTerm.toArray(), 0, volData, 0, TIME_TO_EXPIRY.size()); Array.Copy(SMILE_TERM.VolatilityTerm.get(loopexp).Volatility.toArray(), 0, volBumped, 0, 2 * DELTA.size() + 1); volBumped[loopsmile] += shift; volData[loopexp] = SmileDeltaParameters.of(TIME_TO_EXPIRY.get(loopexp), DELTA, DoubleArray.copyOf(volBumped)); InterpolatedStrikeSmileDeltaTermStructure smileTermBumped = InterpolatedStrikeSmileDeltaTermStructure.of(ImmutableList.copyOf(volData), ACT_360); bucketTest[loopexp][loopsmile] = (smileTermBumped.volatility(timeToExpiry[looptest], strike[looptest], forward) - volComputed.Volatility) / shift; assertEquals(bucketSensi.get(loopexp, loopsmile), bucketTest[loopexp][loopsmile], tolerance[looptest], "Smile by delta term structure: (test: " + looptest + ") volatility bucket sensitivity " + loopexp + " - " + loopsmile); } } } }