/** * @param date The valuation date, not null * @param indexFixingTS The index fixing time series, not null * @param settlementDate The settlement date, not null * @param yieldCurveNames The yield curve names, not null, must have at least two entries * @return The security * @deprecated Use the version that does not take curve names */ @Deprecated public BondIborSecurity toDerivative( final ZonedDateTime date, final DoubleTimeSeries<ZonedDateTime> indexFixingTS, final ZonedDateTime settlementDate, final String... yieldCurveNames) { // Implementation note: First yield curve used for coupon and notional (credit), the second for // risk free settlement. ArgumentChecker.notNull(date, "date"); ArgumentChecker.notNull(indexFixingTS, "fixing time series"); ArgumentChecker.notNull(settlementDate, "settlement date"); ArgumentChecker.notNull(yieldCurveNames, "yield curve names"); ArgumentChecker.isTrue(yieldCurveNames.length > 1, "at least two curves required"); final String creditCurveName = yieldCurveNames[0]; final String riskFreeCurveName = yieldCurveNames[1]; double settlementTime; if (settlementDate.isBefore(date)) { settlementTime = 0.0; } else { settlementTime = TimeCalculator.getTimeBetween(date, settlementDate); } final AnnuityPaymentFixed nominal = (AnnuityPaymentFixed) getNominal().toDerivative(date, creditCurveName); final Annuity<Coupon> coupon = (Annuity<Coupon>) getCoupons().toDerivative(date, indexFixingTS, yieldCurveNames); return new BondIborSecurity( nominal.trimBefore(settlementTime), coupon.trimBefore(settlementTime), settlementTime, riskFreeCurveName); }
@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); }
@Override public DecisionSchedule visitSwaptionCashFixedIbor( final SwaptionCashFixedIbor swaption, final MulticurveProviderInterface multicurves) { final double[] decisionTime = new double[] {swaption.getTimeToExpiry()}; final AnnuityPaymentFixed cfeIbor = swaption.getUnderlyingSwap().getSecondLeg().accept(CFEC, multicurves); final int nbCfeIbor = cfeIbor.getNumberOfPayments(); final int nbCpnFixed = swaption.getUnderlyingSwap().getFixedLeg().getNumberOfPayments(); final double[][] impactTime = new double[1][nbCpnFixed + nbCfeIbor]; final double[][] impactAmount = new double[1][nbCpnFixed + nbCfeIbor]; // Fixed leg for (int loopcf = 0; loopcf < nbCpnFixed; loopcf++) { impactTime[0][loopcf] = swaption.getUnderlyingSwap().getFixedLeg().getNthPayment(loopcf).getPaymentTime(); impactAmount[0][loopcf] = swaption.getUnderlyingSwap().getFixedLeg().getNthPayment(loopcf).getPaymentYearFraction() * swaption.getUnderlyingSwap().getFixedLeg().getNthPayment(loopcf).getNotional(); } // Ibor leg for (int loopcf = 0; loopcf < nbCfeIbor; loopcf++) { impactTime[0][nbCpnFixed + loopcf] = cfeIbor.getNthPayment(loopcf).getPaymentTime(); impactAmount[0][nbCpnFixed + loopcf] = cfeIbor.getNthPayment(loopcf).getAmount(); } final DecisionSchedule decision = new DecisionSchedule(decisionTime, impactTime, impactAmount); return decision; }
/** * @param date The valuation date, not null * @param indexFixingTS The index fixing time series, not null * @param settlementDate The settlement date, not null * @return The security */ public BondIborSecurity toDerivative( final ZonedDateTime date, final DoubleTimeSeries<ZonedDateTime> indexFixingTS, final ZonedDateTime settlementDate) { ArgumentChecker.notNull(date, "date"); ArgumentChecker.notNull(indexFixingTS, "fixing time series"); ArgumentChecker.notNull(settlementDate, "settlement date"); double settlementTime; if (settlementDate.isBefore(date)) { settlementTime = 0.0; } else { settlementTime = TimeCalculator.getTimeBetween(date, settlementDate); } final AnnuityPaymentFixed nominal = (AnnuityPaymentFixed) getNominal().toDerivative(date); final Annuity<Coupon> coupon = (Annuity<Coupon>) getCoupons().toDerivative(date, indexFixingTS); return new BondIborSecurity( nominal.trimBefore(settlementTime), coupon.trimBefore(settlementTime), settlementTime); }
/** * Computes the present value of the Physical delivery swaption. * * @param swaption The swaption. * @param hwData The Hull-White parameters and the curves. * @return The present value. */ public CurrencyAmount presentValue( final SwaptionPhysicalFixedIbor swaption, final HullWhiteOneFactorPiecewiseConstantDataBundle hwData) { Validate.notNull(swaption); Validate.notNull(hwData); final double expiryTime = swaption.getTimeToExpiry(); final AnnuityPaymentFixed cfe = swaption.getUnderlyingSwap().accept(CFEC, hwData); final double[] alpha = new double[cfe.getNumberOfPayments()]; final double[] df = new double[cfe.getNumberOfPayments()]; final double[] discountedCashFlow = new double[cfe.getNumberOfPayments()]; for (int loopcf = 0; loopcf < cfe.getNumberOfPayments(); loopcf++) { alpha[loopcf] = MODEL.alpha( hwData.getHullWhiteParameter(), 0.0, expiryTime, expiryTime, cfe.getNthPayment(loopcf).getPaymentTime()); df[loopcf] = hwData .getCurve(cfe.getDiscountCurve()) .getDiscountFactor(cfe.getNthPayment(loopcf).getPaymentTime()); discountedCashFlow[loopcf] = df[loopcf] * cfe.getNthPayment(loopcf).getAmount(); } // Integration final SwaptionIntegrant integrant = new SwaptionIntegrant(discountedCashFlow, alpha); final double limit = 10.0; final double absoluteTolerance = 1.0E-2; final double relativeTolerance = 1.0E-6; final RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, NB_INTEGRATION); double pv = 0.0; try { pv = 1.0 / Math.sqrt(2.0 * Math.PI) * integrator.integrate(integrant, -limit, limit) * (swaption.isLong() ? 1.0 : -1.0); } catch (final Exception e) { throw new RuntimeException(e); } return CurrencyAmount.of(swaption.getCurrency(), pv); }
@Override public DecisionSchedule visitSwaptionPhysicalFixedIbor( final SwaptionPhysicalFixedIbor swaption, final MulticurveProviderInterface multicurves) { final double[] decisionTime = new double[] {swaption.getTimeToExpiry()}; final AnnuityPaymentFixed cfe = swaption.getUnderlyingSwap().accept(CFEC, multicurves); final double[][] impactTime = new double[1][cfe.getNumberOfPayments()]; final double[][] impactAmount = new double[1][cfe.getNumberOfPayments()]; for (int loopcf = 0; loopcf < cfe.getNumberOfPayments(); loopcf++) { impactTime[0][loopcf] = cfe.getNthPayment(loopcf).getPaymentTime(); impactAmount[0][loopcf] = cfe.getNthPayment(loopcf).getAmount(); } final DecisionSchedule decision = new DecisionSchedule(decisionTime, impactTime, impactAmount); return decision; }
@Override public DecisionSchedule visitAnnuityCouponIborRatchet( final AnnuityCouponIborRatchet annuity, final MulticurveProviderInterface multicurves) { final int nbCpn = annuity.getNumberOfPayments(); final double[] decisionTime = new double[nbCpn]; final double[][] impactTime = new double[nbCpn][]; final double[][] impactAmount = new double[nbCpn][]; for (int loopcpn = 0; loopcpn < nbCpn; loopcpn++) { final AnnuityPaymentFixed cfe = annuity.getNthPayment(loopcpn).accept(CFEC, multicurves); decisionTime[loopcpn] = annuity.isFixed()[loopcpn] ? 0.0 : ((CouponFloating) annuity.getNthPayment(loopcpn)).getFixingTime(); impactTime[loopcpn] = new double[cfe.getNumberOfPayments()]; impactAmount[loopcpn] = new double[cfe.getNumberOfPayments()]; for (int loopcf = 0; loopcf < cfe.getNumberOfPayments(); loopcf++) { impactTime[loopcpn][loopcf] = cfe.getNthPayment(loopcf).getPaymentTime(); impactAmount[loopcpn][loopcf] = cfe.getNthPayment(loopcf).getAmount(); } } final DecisionSchedule decision = new DecisionSchedule(decisionTime, impactTime, impactAmount); return decision; }
/** * Computes the present value of the Physical delivery swaption through approximation.. * * @param swaption The swaption. * @param cfe The swaption cash flow equiovalent. * @param g2Data The G2++ parameters and the curves. * @return The present value. */ public CurrencyAmount presentValue( final SwaptionPhysicalFixedIbor swaption, final AnnuityPaymentFixed cfe, final G2ppPiecewiseConstantDataBundle g2Data) { YieldAndDiscountCurve dsc = g2Data.getCurve(swaption.getUnderlyingSwap().getFixedLeg().getDiscountCurve()); int nbCf = cfe.getNumberOfPayments(); double[] cfa = new double[nbCf]; double[] t = new double[nbCf]; for (int loopcf = 0; loopcf < nbCf; loopcf++) { cfa[loopcf] = -Math.signum(cfe.getNthPayment(0).getAmount()) * cfe.getNthPayment(loopcf).getAmount(); t[loopcf] = cfe.getNthPayment(loopcf).getPaymentTime(); } double rhog2pp = g2Data.getG2ppParameter().getCorrelation(); double[][] ht0 = MODEL_G2PP.volatilityMaturityPart(g2Data.getG2ppParameter(), t[0], t); double[] dfswap = new double[nbCf]; double[] p0 = new double[nbCf]; double[] cP = new double[nbCf]; for (int loopcf = 0; loopcf < nbCf; loopcf++) { dfswap[loopcf] = dsc.getDiscountFactor(t[loopcf]); p0[loopcf] = dfswap[loopcf] / dfswap[0]; cP[loopcf] = cfa[loopcf] * p0[loopcf]; } double k = -cfa[0]; double b0 = 0.0; for (int loopcf = 1; loopcf < nbCf; loopcf++) { b0 += cP[loopcf]; } double[] alpha0 = new double[nbCf - 1]; double[] beta0 = new double[2]; for (int loopcf = 0; loopcf < nbCf - 1; loopcf++) { alpha0[loopcf] = cfa[loopcf + 1] * p0[loopcf + 1] / b0; beta0[0] += alpha0[loopcf] * ht0[0][loopcf + 1]; beta0[1] += alpha0[loopcf] * ht0[1][loopcf + 1]; } double[][] gamma = MODEL_G2PP.gamma(g2Data.getG2ppParameter(), 0, swaption.getTimeToExpiry()); double[] tau = new double[nbCf]; for (int loopcf = 0; loopcf < nbCf; loopcf++) { tau[loopcf] = gamma[0][0] * ht0[0][loopcf] * ht0[0][loopcf] + gamma[1][1] * ht0[1][loopcf] * ht0[1][loopcf] + 2 * rhog2pp * gamma[0][1] * ht0[0][loopcf] * ht0[1][loopcf]; } double xbarnum = 0.0; double xbarde = 0.0; for (int loopcf = 0; loopcf < nbCf; loopcf++) { xbarnum += cP[loopcf] - cP[loopcf] * tau[loopcf] * tau[loopcf] / 2.0; xbarde += cP[loopcf] * tau[loopcf]; } double xbar = xbarnum / xbarde; double[] pK = new double[nbCf]; for (int loopcf = 0; loopcf < nbCf; loopcf++) { pK[loopcf] = p0[loopcf] * (1.0 - tau[loopcf] * xbar - tau[loopcf] * tau[loopcf] / 2.0); } double[] alphaK = new double[nbCf - 1]; double[] betaK = new double[2]; for (int loopcf = 0; loopcf < nbCf - 1; loopcf++) { alphaK[loopcf] = cfa[loopcf + 1] * pK[loopcf + 1] / k; betaK[0] += alphaK[loopcf] * ht0[0][loopcf + 1]; betaK[1] += alphaK[loopcf] * ht0[1][loopcf + 1]; } double[] betaBar = new double[] {(beta0[0] + betaK[0]) / 2.0, (beta0[1] + betaK[1]) / 2.0}; double sigmaBar2 = gamma[0][0] * betaBar[0] * betaBar[0] + gamma[1][1] * betaBar[1] * betaBar[1] + 2 * rhog2pp * gamma[0][1] * betaBar[0] * betaBar[1]; double sigmaBar = Math.sqrt(sigmaBar2); EuropeanVanillaOption option = new EuropeanVanillaOption(k, 1, !swaption.isCall()); final BlackPriceFunction blackFunction = new BlackPriceFunction(); final BlackFunctionData dataBlack = new BlackFunctionData(b0, dfswap[0], sigmaBar); final Function1D<BlackFunctionData, Double> func = blackFunction.getPriceFunction(option); final double price = func.evaluate(dataBlack) * (swaption.isLong() ? 1.0 : -1.0); return CurrencyAmount.of(swaption.getCurrency(), price); }