/**
* Copyright (C) 2009 - 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.ObjectUtils;
import com.opengamma.analytics.math.curve.Curve;
import com.opengamma.analytics.math.curve.DoublesCurve;
import com.opengamma.analytics.math.curve.InterpolatedDoublesCurve;
import com.opengamma.analytics.math.interpolation.Interpolator1D;
import com.opengamma.util.ArgumentChecker;
/**
*
*/
public class DiscountCurve extends YieldAndDiscountCurve {
/**
* The curve storing the required data as discount factors.
*/
private final DoublesCurve _curve;
private static final double SMALL_TIME = 1.0E-6;
/**
* Constructor from a curve containing the discount factors.
* @param name The discount curve name.
* @param discountFactorCurve The underlying curve.
*/
public DiscountCurve(final String name, final DoublesCurve discountFactorCurve) {
super(name);
ArgumentChecker.notNull(discountFactorCurve, "Curve");
_curve = discountFactorCurve;
}
/**
* Builder from a DoublesCurve using the name of the DoublesCurve as the name of the DiscountCurve.
* @param discountFactorCurve The underlying curve based on discount factors.
* @return The discount curve.
*/
public static DiscountCurve from(final DoublesCurve discountFactorCurve) {
ArgumentChecker.notNull(discountFactorCurve, "Curve");
return new DiscountCurve(discountFactorCurve.getName(), discountFactorCurve);
}
/**
* Builder of an interpolated discount factor curve from yields (continuously compounded).
* @param nodePoints The node points for the interpolated curve.
* @param yields The yields (cc) at the node points.
* @param interpolator The discount factors interpolator.
* @param name The curve name.
* @return The discount curve.
*/
public static DiscountCurve fromYieldsInterpolated(final double[] nodePoints, final double[] yields, final Interpolator1D interpolator, final String name) {
final int nbYields = yields.length;
ArgumentChecker.isTrue(nodePoints.length == nbYields, "Yields array of incorrect length");
final double[] discountFactor = new double[nbYields];
for (int loopy = 0; loopy < nbYields; loopy++) {
discountFactor[loopy] = Math.exp(-nodePoints[loopy] * yields[loopy]);
}
final InterpolatedDoublesCurve curve = new InterpolatedDoublesCurve(nodePoints, discountFactor, interpolator, false);
return new DiscountCurve(name, curve);
}
@Override
public double getInterestRate(final Double time) {
if (Math.abs(time) > SMALL_TIME) {
return -Math.log(getDiscountFactor(time)) / time;
}
// Implementation note: if time too close to 0, compute the limit for t->0.
final double dfP = getDiscountFactor(time + SMALL_TIME);
final double df = getDiscountFactor(time);
return (df - dfP) / (SMALL_TIME * df);
}
@Override
public double getDiscountFactor(final double t) {
return _curve.getYValue(t);
}
@Override
public double getForwardRate(final double t) {
return -_curve.getDyDx(t) / _curve.getYValue(t);
}
@Override
public double[] getInterestRateParameterSensitivity(final double time) {
final Double[] dfSensitivity = _curve.getYValueParameterSensitivity(time);
final double[] rSensitivity = new double[dfSensitivity.length];
// Implementation note: if time = 0, the rate is ill-defined: return 0 sensitivity
if (Math.abs(time) < SMALL_TIME) {
return rSensitivity;
}
final double df = getDiscountFactor(time);
for (int loopp = 0; loopp < dfSensitivity.length; loopp++) {
rSensitivity[loopp] = -dfSensitivity[loopp] / (time * df);
}
return rSensitivity;
}
@Override
public int getNumberOfParameters() {
return _curve.size();
}
@Override
public List<String> getUnderlyingCurvesNames() {
return new ArrayList<>();
}
/**
* Gets the underlying curve.
* @return The curve.
*/
public Curve<Double, Double> getCurve() {
return _curve;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + _curve.hashCode();
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DiscountCurve other = (DiscountCurve) obj;
return ObjectUtils.equals(_curve, other._curve);
}
}