@Test public void firstDerivativeTest() { double a = 1.0; double b = 1.5; double c = -0.5; double[] x = new double[] {0., 2., 5.}; int n = x.length; double[] y = new double[n]; for (int i = 0; i < n; i++) { y[i] = a + b * x[i] + c * x[i] * x[i]; } Interpolator1D interpolator = new NaturalCubicSplineInterpolator1D(); Interpolator1DDataBundle db = interpolator.getDataBundle(x, y); Double grad = interpolator.firstDerivative(db, x[n - 1]); Function1D<Double, Double> func = interpolator.getFunction(db); ScalarFirstOrderDifferentiator diff = new ScalarFirstOrderDifferentiator(); Function1D<Double, Boolean> domain = new Function1D<Double, Boolean>() { @Override public Boolean evaluate(Double x) { return x <= 5.0; } }; Function1D<Double, Double> gradFunc = diff.differentiate(func, domain); assertEquals(gradFunc.evaluate(x[n - 1]), grad, 1e-8); }
/** * Calculates the present value of the swaption product. * * <p>The result is expressed using the currency of the swapion. * * @param swaption the product to price * @param ratesProvider the rates provider * @param volatilityProvider the normal volatility provider * @return the present value of the swaption product */ public CurrencyAmount presentValue( SwaptionProduct swaption, RatesProvider ratesProvider, NormalVolatilitySwaptionProvider volatilityProvider) { ExpandedSwaption expanded = swaption.expand(); validate(ratesProvider, expanded, volatilityProvider); ZonedDateTime expiryDateTime = expanded.getExpiryDateTime(); double expiry = volatilityProvider.relativeTime(expiryDateTime); ExpandedSwap underlying = expanded.getUnderlying(); ExpandedSwapLeg fixedLeg = fixedLeg(underlying); if (expiry < 0.0d) { // Option has expired already return CurrencyAmount.of(fixedLeg.getCurrency(), 0.0d); } double forward = swapPricer.parRate(underlying, ratesProvider); double pvbp = swapPricer.getLegPricer().pvbp(fixedLeg, ratesProvider); double strike = swapPricer.getLegPricer().couponEquivalent(fixedLeg, ratesProvider, pvbp); double tenor = volatilityProvider.tenor(fixedLeg.getStartDate(), fixedLeg.getEndDate()); double volatility = volatilityProvider.getVolatility(expiryDateTime, tenor, strike, forward); NormalFunctionData normalData = NormalFunctionData.of(forward, Math.abs(pvbp), volatility); boolean isCall = (fixedLeg.getPayReceive() == PayReceive.PAY); // Payer at strike is exercise when rate > strike, i.e. call on rate EuropeanVanillaOption option = EuropeanVanillaOption.of(strike, expiry, isCall ? PutCall.CALL : PutCall.PUT); // option required to pass the strike (in case the swap has non-constant coupon). Function1D<NormalFunctionData, Double> func = NORMAL.getPriceFunction(option); double pv = func.evaluate(normalData) * ((expanded.getLongShort() == LongShort.LONG) ? 1.0 : -1.0); return CurrencyAmount.of(fixedLeg.getCurrency(), pv); }
static { final double[] t = new double[] {0.0, 0.5, 1.0, 2.0, 3.0, 5.0, 7.0, 10.0, 15.0, 17.5, 20.0, 25.0, 30.0}; final int n = t.length; final double[] r = new double[n]; for (int i = 0; i < n; i++) { r[i] = FUNCTION.evaluate(t[i]); } DATA = new Interpolator1DCubicSplineDataBundle(new ArrayInterpolator1DDataBundle(t, r)); }