/**
* Copyright (C) 2011 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.interestrate.payments.method;
import org.apache.commons.lang.Validate;
import com.opengamma.analytics.financial.interestrate.InstrumentDerivative;
import com.opengamma.analytics.financial.interestrate.YieldCurveBundle;
import com.opengamma.analytics.financial.interestrate.method.PricingMethod;
import com.opengamma.analytics.financial.interestrate.payments.derivative.CapFloorIbor;
import com.opengamma.analytics.financial.model.option.definition.SABRInterestRateDataBundle;
import com.opengamma.analytics.math.function.Function1D;
import com.opengamma.analytics.math.integration.RungeKuttaIntegrator1D;
import com.opengamma.util.money.CurrencyAmount;
/**
* Class used to compute the price and sensitivity of a Ibor cap/floor in arrears.
* The cap/floor are supposed to be exactly in arrears. The payment date is ignored and the start fixing period date is used instead.
* @deprecated {@link PricingMethod} is deprecated
*/
@Deprecated
public class CapFloorIborInArrearsGenericReplicationMethod implements PricingMethod {
/**
* Base method for the pricing of standard cap/floors.
*/
private final PricingMethod _baseMethod;
/**
* Range of the integral. Used only for caps. Represent the approximation of infinity in the strike dimension.
* The range is [strike, strike+integrationInterval].
*/
private final double _integrationInterval = 2.0;
/**
* Minimal number of integration steps in the replication.
*/
private final int _nbIteration = 6;
/**
* Constructor of the in-arrears pricing method.
* @param baseMethod The base method for the pricing of standard cap/floors.
*/
public CapFloorIborInArrearsGenericReplicationMethod(final PricingMethod baseMethod) {
_baseMethod = baseMethod;
}
/**
* Computes the present value of an Ibor cap/floor in arrears by replication.
* @param cap The cap/floor.
* @param sabrData The SABR data.
* @return The present value.
*/
public CurrencyAmount presentValue(final CapFloorIbor cap, final SABRInterestRateDataBundle sabrData) {
Validate.notNull(cap);
Validate.notNull(sabrData);
final CapFloorIbor capStandard = new CapFloorIbor(cap.getCurrency(), cap.getFixingPeriodEndTime(), cap.getFundingCurveName(), cap.getPaymentYearFraction(), cap.getNotional(), cap.getFixingTime(),
cap.getIndex(), cap.getFixingPeriodStartTime(), cap.getFixingPeriodEndTime(), cap.getFixingAccrualFactor(), cap.getForwardCurveName(), cap.getStrike(), cap.isCap());
final double beta = sabrData.getCurve(cap.getForwardCurveName()).getDiscountFactor(cap.getFixingPeriodStartTime())
/ sabrData.getCurve(cap.getForwardCurveName()).getDiscountFactor(cap.getFixingPeriodEndTime()) * sabrData.getCurve(cap.getFundingCurveName()).getDiscountFactor(cap.getFixingPeriodEndTime())
/ sabrData.getCurve(cap.getFundingCurveName()).getDiscountFactor(cap.getFixingPeriodStartTime());
final double strikePart = (1.0 + cap.getFixingAccrualFactor() * cap.getStrike()) * _baseMethod.presentValue(capStandard, sabrData).getAmount();
final double absoluteTolerance = 1.0;
final double relativeTolerance = 1E-10;
final RungeKuttaIntegrator1D integrator = new RungeKuttaIntegrator1D(absoluteTolerance, relativeTolerance, _nbIteration);
final InArrearsIntegrant integrant = new InArrearsIntegrant(_baseMethod, capStandard, sabrData);
double integralPart;
try {
if (cap.isCap()) {
integralPart = integrator.integrate(integrant, cap.getStrike(), cap.getStrike() + _integrationInterval);
} else {
integralPart = integrator.integrate(integrant, 0.0, cap.getStrike());
}
} catch (final Exception e) {
throw new RuntimeException(e);
}
integralPart *= 2.0 * cap.getFixingAccrualFactor();
final double pv = (strikePart + integralPart) / beta;
return CurrencyAmount.of(cap.getCurrency(), pv);
}
@Override
public CurrencyAmount presentValue(final InstrumentDerivative instrument, final YieldCurveBundle curves) {
Validate.isTrue(instrument instanceof CapFloorIbor, "Cap/Floor on Ibor");
Validate.isTrue(curves instanceof SABRInterestRateDataBundle, "SABR interest rate data bundle required");
return presentValue((CapFloorIbor) instrument, (SABRInterestRateDataBundle) curves);
}
/**
* Inner class to implement the integration used in price replication.
*/
private static final class InArrearsIntegrant extends Function1D<Double, Double> {
/**
* The base method for the pricing of standard cap/floors.
*/
private final PricingMethod _basePricingMethod;
/**
* The standard cap/floor used for replication.
*/
private final CapFloorIbor _capStandard;
/**
* The SABR data bundle used in the standard cap/floor pricing.
*/
private final SABRInterestRateDataBundle _sabrData;
/**
* Constructor with the required data.
* @param baseMethod The base method for the pricing of standard cap/floors.
* @param capStandard The standard cap/floor used for replication.
* @param sabrData The SABR data bundle used in the standard cap/floor pricing.
*/
public InArrearsIntegrant(final PricingMethod baseMethod, final CapFloorIbor capStandard, final SABRInterestRateDataBundle sabrData) {
this._basePricingMethod = baseMethod;
this._capStandard = capStandard;
this._sabrData = sabrData;
}
@Override
public Double evaluate(final Double x) {
final CapFloorIbor capStrike = _capStandard.withStrike(x);
return _basePricingMethod.presentValue(capStrike, _sabrData).getAmount();
}
}
}