@Test public void testNormal() { final ProbabilityDistribution<Double> highDOF = new StudentTDistribution(1000000, ENGINE); final ProbabilityDistribution<Double> normal = new NormalDistribution(0, 1, ENGINE); final double eps = 1e-4; double x; for (int i = 0; i < 100; i++) { x = RANDOM.nextDouble(); assertEquals(highDOF.getCDF(x), normal.getCDF(x), eps); assertEquals(highDOF.getPDF(x), normal.getPDF(x), eps); assertEquals(highDOF.getInverseCDF(x), normal.getInverseCDF(x), eps); } }
@Test /** Test the present value. */ public void presentValueExplicit() { final MultipleCurrencyAmount pv = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, HW_MULTICURVES); final double timeToExpiry = SWAPTION_LONG_PAYER.getTimeToExpiry(); final AnnuityPaymentFixed cfe = CFEC.visitSwap(SWAPTION_LONG_PAYER.getUnderlyingSwap(), MULTICURVES); final int numberOfPayments = cfe.getNumberOfPayments(); final double alpha[] = new double[numberOfPayments]; final double disccf[] = new double[numberOfPayments]; for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) { alpha[loopcf] = MODEL.alpha( HW_PARAMETERS, 0.0, timeToExpiry, timeToExpiry, cfe.getNthPayment(loopcf).getPaymentTime()); disccf[loopcf] = MULTICURVES.getDiscountFactor(EUR, cfe.getNthPayment(loopcf).getPaymentTime()) * cfe.getNthPayment(loopcf).getAmount(); } final double kappa = MODEL.kappa(disccf, alpha); double pvExpected = 0.0; for (int loopcf = 0; loopcf < numberOfPayments; loopcf++) { pvExpected += disccf[loopcf] * NORMAL.getCDF(-kappa - alpha[loopcf]); } assertEquals( "Swaption physical - Hull-White - present value", pvExpected, pv.getAmount(EUR), 1E-2); final MultipleCurrencyAmount pv2 = METHOD_HW.presentValue(SWAPTION_LONG_PAYER, cfe, HW_MULTICURVES); assertEquals("Swaption physical - Hull-White - present value", pv, pv2); }
/** * Compute theta price of cash-or-nothing option * * @param spot The spot * @param strike The strike * @param timeToExpiry The time to expiry * @param lognormalVol The log-normal volatility * @param interestRate The interest rate * @param costOfCarry The cost-of-carry * @param isCall True for calls, false for puts * @return The option price */ public static double theta( final double spot, final double strike, final double timeToExpiry, final double lognormalVol, final double interestRate, final double costOfCarry, final boolean isCall) { ArgumentChecker.isTrue(spot > 0.0, "negative/NaN spot; have {}", spot); ArgumentChecker.isTrue(strike > 0.0, "negative/NaN strike; have {}", strike); ArgumentChecker.isTrue(timeToExpiry > 0.0, "negative/NaN timeToExpiry; have {}", timeToExpiry); ArgumentChecker.isTrue(lognormalVol > 0.0, "negative/NaN lognormalVol; have {}", lognormalVol); ArgumentChecker.isFalse(Double.isNaN(interestRate), "interestRate is NaN"); ArgumentChecker.isFalse(Double.isNaN(costOfCarry), "costOfCarry is NaN"); final double d = (Math.log(spot / strike) + (costOfCarry - 0.5 * lognormalVol * lognormalVol) * timeToExpiry) / lognormalVol / Math.sqrt(timeToExpiry); final double sign = isCall ? 1. : -1.; final double div = 0.5 * (-Math.log(spot / strike) / Math.pow(timeToExpiry, 1.5) + (costOfCarry - 0.5 * lognormalVol * lognormalVol) / Math.pow(timeToExpiry, 0.5)) / lognormalVol; return interestRate * Math.exp(-interestRate * timeToExpiry) * NORMAL.getCDF(sign * d) - sign * Math.exp(-interestRate * timeToExpiry) * NORMAL.getPDF(d) * div; }
/** * Computes the price curve sensitivity in the Hull-White one factor model. * * @param security The option security. * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters. * @return The curve sensitivity. */ @Override public MulticurveSensitivity priceCurveSensitivity( final InterestRateFutureOptionMarginSecurity security, final HullWhiteOneFactorProviderInterface hwMulticurves) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data"); ArgumentChecker.isTrue( security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()), "Model currency incompatible with security currency"); final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider(); final HullWhiteOneFactorPiecewiseConstantParameters parameters = hwMulticurves.getHullWhiteParameters(); final double k = security.getStrike(); final double ktilde = 1.0 - k; final double theta = security.getExpirationTime(); final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor(); final double t0 = security.getUnderlyingFuture().getTradingLastTime(); final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime(); final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime(); // forward sweep final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2); final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2); final double forward = multicurves.getSimplyCompoundForwardRate( security.getUnderlyingFuture().getIborIndex(), t1, t2, delta); final double kappa = -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha; // Bakcward sweep final double priceBar = 1.0; double forwardBar; if (security.isCall()) { final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha); forwardBar = -gamma * normalAlphaKappa * priceBar; } else { final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha); forwardBar = gamma * normalAlphaKappa * priceBar; } final Map<String, List<ForwardSensitivity>> mapFwd = new HashMap<>(); final List<ForwardSensitivity> listForward = new ArrayList<>(); listForward.add(new SimplyCompoundedForwardSensitivity(t1, t2, delta, forwardBar)); mapFwd.put( hwMulticurves .getMulticurveProvider() .getName(security.getUnderlyingFuture().getIborIndex()), listForward); return MulticurveSensitivity.ofForward(mapFwd); }
@Test public void test() { ProbabilityDistribution<Double> dist = new StudentTDistribution(1, ENGINE); assertCDFWithNull(dist); assertPDFWithNull(dist); assertInverseCDF(X, dist); for (int i = 0; i < 10; i++) { dist = new StudentTDistribution(DOF[i], ENGINE); assertEquals(P[i], dist.getCDF(X[i]), EPS); } }
/** * Computes the price in the Hull-White one factor model. * * @param security The option security. * @param hwMulticurves The multi-curves provider with Hull-White one factor parameters. * @return The price. */ @Override public double price( final InterestRateFutureOptionMarginSecurity security, final HullWhiteOneFactorProviderInterface hwMulticurves) { ArgumentChecker.notNull(security, "Option security"); ArgumentChecker.notNull(hwMulticurves, "Hull-White and multi-curves data"); ArgumentChecker.isTrue( security.getCurrency().equals(hwMulticurves.getHullWhiteCurrency()), "Model currency incompatible with security currency"); final MulticurveProviderInterface multicurves = hwMulticurves.getMulticurveProvider(); final HullWhiteOneFactorPiecewiseConstantParameters parameters = hwMulticurves.getHullWhiteParameters(); final double k = security.getStrike(); final double ktilde = 1.0 - k; final double theta = security.getExpirationTime(); final double delta = security.getUnderlyingFuture().getFixingPeriodAccrualFactor(); final double t0 = security.getUnderlyingFuture().getTradingLastTime(); final double t1 = security.getUnderlyingFuture().getFixingPeriodStartTime(); final double t2 = security.getUnderlyingFuture().getFixingPeriodEndTime(); final double alpha = MODEL.alpha(parameters, 0.0, theta, t1, t2); final double gamma = MODEL.futuresConvexityFactor(parameters, t0, t1, t2); final double forward = multicurves.getSimplyCompoundForwardRate( security.getUnderlyingFuture().getIborIndex(), t1, t2, delta); final double kappa = -Math.log((1 + delta * ktilde) / (1 + delta * forward) / gamma) / alpha - 0.5 * alpha; if (security.isCall()) { final double normalKappa = NORMAL.getCDF(-kappa); final double normalAlphaKappa = NORMAL.getCDF(-kappa - alpha); return (1 - k + 1.0 / delta) * normalKappa - (1.0 / delta + forward) * gamma * normalAlphaKappa; } final double normalKappa = NORMAL.getCDF(kappa); final double normalAlphaKappa = NORMAL.getCDF(kappa + alpha); return (1.0 / delta + forward) * gamma * normalAlphaKappa - (1 - k + 1.0 / delta) * normalKappa; }