/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.interestrate.curve;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.NotImplementedException;
import com.opengamma.analytics.financial.interestrate.InterestRate;
import com.opengamma.analytics.financial.interestrate.PeriodicInterestRate;
import com.opengamma.analytics.math.curve.DoublesCurve;
import com.opengamma.util.ArgumentChecker;
/**
* YieldPeriodicCurve created by adding the periodic compounded rate of two curves.
* One curve is fixed and there is no sensitivity to that curve.
* The term "fixed" for the second curve means that no parameter is associated to that curve.
*/
public class YieldPeriodicAddZeroFixedCurve extends YieldAndDiscountCurve {
/**
* The number of compounding periods per year of the base curve.
*/
private final int _compoundingPeriodsPerYear;
/**
* The base curve.
*/
private final DoublesCurve _baseCurve;
/**
* The fixed curve.
*/
private final DoublesCurve _fixedCurve;
/**
* If 1 the rates are added, if -1, they are subtracted (curve - curveFixed).
*/
private final double _sign;
/**
* Constructor for periodic yield curve that takes a base curve and a fixed curve. The new curve interest rate
* (zero-coupon continuously compounded) will be the sum (or the difference) of the different underlying curves. There
* will be sensitivity to the base curve only, not to the fixed curve.
* @param name the curve name.
* @param subtract if true, the rate of all curves, except the first one, will be subtracted from the first one. If
* false, all the rates are added.
* @param curve the main curve.
* @param curveFixed the fixed curve (as a spread).
*/
public YieldPeriodicAddZeroFixedCurve(String name,
boolean subtract,
YieldPeriodicCurve curve,
DoublesCurve curveFixed) {
super(name);
ArgumentChecker.notNull(curve, "curve");
ArgumentChecker.notNull(curveFixed, "curveFixed");
_baseCurve = curve.getCurve();
_fixedCurve = curveFixed;
_compoundingPeriodsPerYear = curve.getCompoundingPeriodsPerYear();
_sign = subtract ? -1.0 : 1.0;
}
@Override
public double getInterestRate(Double time) {
final double rate = _baseCurve.getYValue(time) + _sign * _fixedCurve.getYValue(time);
return _compoundingPeriodsPerYear * Math.log(1.0d + rate / _compoundingPeriodsPerYear);
}
@Override
public double getForwardRate(double t) {
throw new NotImplementedException("Instantaneous Forward rate not implemented for Periodic rate curves.");
}
@Override
public double getDiscountFactor(double t) {
final double rate = _baseCurve.getYValue(t) + _sign * _fixedCurve.getYValue(t);
return Math.pow(1 + rate / _compoundingPeriodsPerYear, -_compoundingPeriodsPerYear * t);
}
@Override
public double getPeriodicInterestRate(double t, int compoundingPeriodsPerYear) {
double baseIR = _baseCurve.getYValue(t) + _sign * _fixedCurve.getYValue(t);
if (compoundingPeriodsPerYear == _compoundingPeriodsPerYear) {
return baseIR;
}
InterestRate baseRate = new PeriodicInterestRate(baseIR, _compoundingPeriodsPerYear);
// rate in the composition of the storage.
InterestRate periodicRate = baseRate.toPeriodic(compoundingPeriodsPerYear);
return periodicRate.getRate();
}
@Override
public double[] getInterestRateParameterSensitivity(double time) {
Double[] drPdp = _baseCurve.getYValueParameterSensitivity(time); // d (r_Periodic) / d parameters
int nbParam = drPdp.length;
double rPS = _baseCurve.getYValue(time) + _sign * _fixedCurve.getYValue(time); // r_Periodic +/- spread
double drCdrP = 1.0d / (1.0d + rPS / _compoundingPeriodsPerYear); // d (r_ContinouslyCompounded) / d (r_Periodic)
double[] drCdp = new double[nbParam]; // d (r_ContinouslyCompounded) / d parameters
for (int i = 0; i < nbParam; i++) {
drCdp[i] = drCdrP * drPdp[i];
}
return drCdp;
}
@Override
public int getNumberOfParameters() {
return _baseCurve.size();
}
@Override
public List<String> getUnderlyingCurvesNames() {
return new ArrayList<>();
}
}