/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.financial.credit.isdastandardmodel; import static com.opengamma.analytics.financial.credit.isdastandardmodel.DoublesScheduleGenerator.truncateSetInclusive; import com.opengamma.analytics.math.utilities.Epsilon; /** * */ public class AnnuityForSpreadContPemiumApproxFunction extends AnnuityForSpreadFunction { private final int _n; private final double[] _knots; private final double[] _rt; private final double _lgd; private final double _eta; /** * For a given quoted spread (aka 'flat' spread), this function returns the risky annuity (aka risky PV01, RPV01 or risky duration). * This works by using the credit triangle approximation; that is, the premiums are assumed to be paid continuously. * @param cds analytic description of a CDS traded at a certain time * @param yieldCurve Calibrated yield curve */ public AnnuityForSpreadContPemiumApproxFunction(final CDSAnalytic cds, final ISDACompliantYieldCurve yieldCurve) { _knots = truncateSetInclusive(cds.getEffectiveProtectionStart(), cds.getProtectionEnd(), yieldCurve.getKnotTimes()); _n = _knots.length; _rt = new double[_n]; for (int i = 0; i < _n; i++) { _rt[i] = yieldCurve.getRT(_knots[i]); } _lgd = cds.getLGD(); _eta = cds.getCoupon(0).getYFRatio(); } @Override public Double evaluate(final Double spread) { final double lambda = _eta * spread / _lgd; return annuity(lambda); } private double annuity(final double hazardRate) { double rt0 = _rt[0]; double sum = 0; for (int i = 1; i < _n; i++) { final double rt1 = _rt[i]; final double dt = _knots[i] - _knots[i - 1]; final double theta = rt1 - rt0 + hazardRate * dt; sum += dt * Math.exp(-rt0 - hazardRate * _knots[i - 1]) * Epsilon.epsilon(-theta); rt0 = rt1; } return _eta * sum; } }