Java tutorial
/** * Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.interestrate.swaption.method; import org.apache.commons.lang.Validate; import com.opengamma.analytics.financial.interestrate.CashFlowEquivalentCalculator; import com.opengamma.analytics.financial.interestrate.InstrumentDerivative; import com.opengamma.analytics.financial.interestrate.YieldCurveBundle; import com.opengamma.analytics.financial.interestrate.annuity.derivative.AnnuityPaymentFixed; import com.opengamma.analytics.financial.interestrate.method.PricingMethod; import com.opengamma.analytics.financial.interestrate.swaption.derivative.SwaptionPhysicalFixedIbor; import com.opengamma.analytics.financial.model.interestrate.HullWhiteOneFactorPiecewiseConstantInterestRateModel; import com.opengamma.analytics.financial.model.interestrate.definition.HullWhiteOneFactorPiecewiseConstantDataBundle; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.integration.RungeKuttaIntegrator1D; import com.opengamma.util.money.CurrencyAmount; /** * Method to compute the present value of physical delivery European swaptions with the Hull-White one factor model by numerical integration. */ public class SwaptionPhysicalFixedIborHullWhiteNumericalIntegrationMethod implements PricingMethod { /** * The model used in computations. */ private static final HullWhiteOneFactorPiecewiseConstantInterestRateModel MODEL = new HullWhiteOneFactorPiecewiseConstantInterestRateModel(); /** * The cash flow equivalent calculator used in computations. */ private static final CashFlowEquivalentCalculator CFEC = CashFlowEquivalentCalculator.getInstance(); /** * Minimal number of integration steps in the replication. */ private static final int NB_INTEGRATION = 6; /** * 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); double expiryTime = swaption.getTimeToExpiry(); AnnuityPaymentFixed cfe = CFEC.visit(swaption.getUnderlyingSwap(), hwData); double[] alpha = new double[cfe.getNumberOfPayments()]; double[] df = new double[cfe.getNumberOfPayments()]; 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 CurrencyAmount presentValue(InstrumentDerivative instrument, YieldCurveBundle curves) { Validate.isTrue(instrument instanceof SwaptionPhysicalFixedIbor, "Physical delivery swaption"); Validate.isTrue(curves instanceof HullWhiteOneFactorPiecewiseConstantDataBundle, "Bundle should contain Hull-White data"); return presentValue((SwaptionPhysicalFixedIbor) instrument, (HullWhiteOneFactorPiecewiseConstantDataBundle) curves); } /** * Inner class to implement the integration used in price replication. */ private class SwaptionIntegrant extends Function1D<Double, Double> { private final double[] _discountedCashFlow; private final double[] _alpha; /** * Constructor to the integrant function. * @param discountedCashFlow The discounted cash flows. * @param alpha The bond volatilities. */ public SwaptionIntegrant(final double[] discountedCashFlow, final double[] alpha) { _discountedCashFlow = discountedCashFlow; _alpha = alpha; } @Override public Double evaluate(final Double x) { double result = 0.0; for (int loopcf = 0; loopcf < _discountedCashFlow.length; loopcf++) { result += _discountedCashFlow[loopcf] * Math.exp(-(x + _alpha[loopcf]) * (x + _alpha[loopcf]) / 2.0); } return Math.max(result, 0.0); } } }