/**
  * This is the present value of the premium leg per unit coupon, seen at the cash-settlement date.
  * It is equal to 10,000 times the RPV01 (Risky PV01). The actual PV of the leg is this multiplied by the
  * notional and the fractional spread (i.e. coupon in basis points divided by 10,000).
  *
  * @param cds  the analytic description of a CDS traded at a certain time
  * @param yieldCurve  the yield (or discount) curve
  * @param creditCurve  the credit (or survival) curve
  * @param cleanOrDirty  the clean or dirty price
  * @return 10,000 times the RPV01 (on a notional of 1)
  * @see #annuity
  * @see #dirtyAnnuity
  */
 public double annuity(
     CDS cds,
     YieldTermStructure yieldCurve,
     PiecewiseconstantHazardRate creditCurve,
     CdsPriceType cleanOrDirty)
 {
     return(annuity(cds, yieldCurve, creditCurve, cleanOrDirty, cds.getCashSettleTime()));
 }
        public double pvPremiumLegCreditSensitivity(
            CDS cds,
            YieldTermStructure yieldCurve,
            PiecewiseconstantHazardRate creditCurve,
            int creditCurveNode)
        {
            if (cds.getProtectionEnd() <= 0.0)
            { //short cut already expired CDSs
                return(0.0);
            }

            int    n       = cds.getNumPayments();
            double pvSense = 0.0;

            for (int i = 0; i < n; i++)
            {
                CdsCoupon c             = cds.getCoupon(i);
                double    paymentTime   = c.getPaymentTime();
                double    creditObsTime = c.getEffEnd();
                double    dqdh          = creditCurve.getSingleNodeDiscountFactorSensitivity(creditObsTime, creditCurveNode);
                if (dqdh == 0)
                {
                    continue;
                }
                double p = Math.Exp(-yieldCurve.getRT_(paymentTime));
                pvSense += c.getYearFrac() * p * dqdh;
            }

            if (cds.isPayAccOnDefault())
            {
                double   start = cds.getNumPayments() == 1 ? cds.getEffectiveProtectionStart() : cds.getAccStart();
                double[] integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(start, cds.getProtectionEnd(), yieldCurve, creditCurve);

                double accPVSense = 0.0;
                for (int i = 0; i < n; i++)
                {
                    accPVSense += calculateSinglePeriodAccrualOnDefaultCreditSensitivity(
                        cds.getCoupon(i),
                        cds.getEffectiveProtectionStart(), integrationSchedule, yieldCurve, creditCurve, creditCurveNode);
                }
                pvSense += accPVSense;
            }

            double df = Math.Exp(-yieldCurve.getRT_(cds.getCashSettleTime()));

            pvSense /= df;
            return(pvSense);
        }
        /**
         * Compute the present value of the protection leg with a notional of 1, which is given by the integral
         * $\frac{1-R}{P(T_{v})} \int_{T_a} ^{T_b} P(t) \frac{dQ(t)}{dt} dt$ where $P(t)$ and $Q(t)$ are the discount
         * and survival curves respectively, $T_a$ and $T_b$ are the start and end of the protection respectively,
         * $T_v$ is the valuation time (all measured from $t = 0$, 'today') and $R$ is the recovery rate.
         *
         * @param cds  the analytic description of a CDS traded at a certain time
         * @param yieldCurve  the yield (or discount) curve
         * @param creditCurve  the credit (or survival) curve
         * @param valuationTime  the valuation time, if time is zero, leg is valued today,
         *  value often quoted for cash-settlement date
         * @return the value of the protection leg (on a unit notional)
         */
        public double annuity(
            CDS cds,
            YieldTermStructure yieldCurve,
            PiecewiseconstantHazardRate creditCurve,
            CdsPriceType cleanOrDirty,
            double valuationTime)
        {
            double pv    = dirtyAnnuity(cds, yieldCurve, creditCurve);
            double valDF = Math.Exp(-yieldCurve.getRT_(valuationTime));

            if (cleanOrDirty == CdsPriceType.CLEAN)
            {
                double csTime    = cds.getCashSettleTime();
                double protStart = cds.getEffectiveProtectionStart();
                double csDF      = valuationTime == csTime ? valDF :Math.Exp(-yieldCurve.getRT_(csTime));
                double q         = protStart == 0 ? 1.0 : Math.Exp(-creditCurve.getRT_(protStart));
                double acc       = cds.getAccruedYearFraction();
                pv -= acc * csDF * q; //subtract the accrued risky discounted to today
            }

            pv /= valDF; //roll forward to valuation date
            return(pv);
        }
Example #4
0
            public Pricer(
                CDS cds,
                YieldTermStructure yieldCurve,
                double[] creditCurveKnots,
                double fractionalSpread,
                double pointsUpfront)
            {
                _cds           = cds;
                _fracSpread    = fractionalSpread;
                _pointsUpfront = pointsUpfront;

                // protection leg
                _proLegIntPoints = DoublesScheduleGenerator.getIntegrationsPoints(
                    cds.getEffectiveProtectionStart(),
                    cds.getProtectionEnd(),
                    yieldCurve.t.ToArray(),
                    creditCurveKnots);
                _nProPoints = _proLegIntPoints.Length;
                double lgd = cds.getLGD();

                _valuationDF     = Math.Exp(-yieldCurve.getRT_(cds.getCashSettleTime()));
                _lgdDF           = lgd / _valuationDF;
                _proYieldCurveRT = new double[_nProPoints];
                _proDF           = new double[_nProPoints];
                for (int i = 0; i < _nProPoints; i++)
                {
                    _proYieldCurveRT[i] = yieldCurve.getRT_(_proLegIntPoints[i]);
                    _proDF[i]           = Math.Exp(-_proYieldCurveRT[i]);
                }

                // premium leg
                _nPayments = cds.getNumPayments();
                _paymentDF = new double[_nPayments];
                for (int i = 0; i < _nPayments; i++)
                {
                    _paymentDF[i] = Math.Exp(-yieldCurve.getRT_(cds.getCoupon(i).getPaymentTime()));
                }

                if (cds.isPayAccOnDefault())
                {
                    double   tmp = cds.getNumPayments() == 1 ? cds.getEffectiveProtectionStart() : cds.getAccStart();
                    double[] integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(
                        tmp, cds.getProtectionEnd(), yieldCurve.t.ToArray(), creditCurveKnots);

                    _accRate          = new double[_nPayments];
                    _offsetAccStart   = new double[_nPayments];
                    _premLegIntPoints = new double[_nPayments][];
                    _premDF           = new double[_nPayments][];
                    _rt     = new double[_nPayments][];
                    _premDt = new double[_nPayments][];
                    for (int i = 0; i < _nPayments; i++)
                    {
                        CdsCoupon c = cds.getCoupon(i);
                        _offsetAccStart[i] = c.getEffStart();
                        double offsetAccEnd = c.getEffEnd();
                        _accRate[i] = c.getYFRatio();
                        double start = Math.Max(_offsetAccStart[i], cds.getEffectiveProtectionStart());
                        if (start >= offsetAccEnd)
                        {
                            continue;
                        }
                        _premLegIntPoints[i] = DoublesScheduleGenerator.truncateSetInclusive(start, offsetAccEnd, integrationSchedule);
                        int n = _premLegIntPoints[i].Length;
                        _rt[i]     = new double[n];
                        _premDF[i] = new double[n];
                        for (int k = 0; k < n; k++)
                        {
                            _rt[i][k]     = yieldCurve.getRT_(_premLegIntPoints[i][k]);
                            _premDF[i][k] = Math.Exp(-_rt[i][k]);
                        }
                        _premDt[i] = new double[n - 1];

                        for (int k = 1; k < n; k++)
                        {
                            double dt = _premLegIntPoints[i][k] - _premLegIntPoints[i][k - 1];
                            _premDt[i][k - 1] = dt;
                        }
                    }
                }
                else
                {
                    _accRate          = null;
                    _offsetAccStart   = null;
                    _premDF           = null;
                    _premDt           = null;
                    _rt               = null;
                    _premLegIntPoints = null;
                }
            }
        /**
         * The sensitivity of the PV of the protection leg to the zero rate of a given node (knot) of the yield curve.
         *
         * @param cds  the analytic description of a CDS traded at a certain time
         * @param yieldCurve  the yield (or discount) curve
         * @param creditCurve  the credit (or survival) curve
         * @param yieldCurveNode  the yield curve node
         * @return the sensitivity (on a unit notional)
         */
        public double protectionLegYieldSensitivity(
            CDS cds,
            YieldTermStructure yieldCurve,
            PiecewiseconstantHazardRate creditCurve,
            int yieldCurveNode)
        {
            if ((yieldCurveNode != 0 && cds.getProtectionEnd() <= yieldCurve.t[yieldCurveNode - 1]) ||
                (yieldCurveNode != creditCurve.getNumberOfKnots() - 1 &&
                 cds.getEffectiveProtectionStart() >= yieldCurve.t[yieldCurveNode + 1]))
            {
                return(0.0); // can't have any sensitivity in this case
            }
            if (cds.getProtectionEnd() <= 0.0)
            { //short cut already expired CDSs
                return(0.0);
            }

            double[] integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(
                cds.getEffectiveProtectionStart(), cds.getProtectionEnd(), yieldCurve, creditCurve);

            double t       = integrationSchedule[0];
            double ht0     = creditCurve.getRT_(t);
            double rt0     = yieldCurve.getRT_(t);
            double dpdr0   = yieldCurve.getSingleNodeDiscountFactorSensitivity(t, yieldCurveNode);
            double q0      = Math.Exp(-ht0);
            double p0      = Math.Exp(-rt0);
            double pvSense = 0.0;
            int    n       = integrationSchedule.Length;

            for (int i = 1; i < n; ++i)
            {
                t = integrationSchedule[i];
                double ht1   = creditCurve.getRT_(t);
                double dpdr1 = yieldCurve.getSingleNodeDiscountFactorSensitivity(t, yieldCurveNode);
                double rt1   = yieldCurve.getRT_(t);
                double q1    = Math.Exp(-ht1);
                double p1    = Math.Exp(-rt1);

                if (dpdr0 == 0.0 && dpdr1 == 0.0)
                {
                    ht0 = ht1;
                    rt0 = rt1;
                    p0  = p1;
                    q0  = q1;
                    continue;
                }

                double hBar  = ht1 - ht0;
                double fBar  = rt1 - rt0;
                double fhBar = hBar + fBar;

                double dPVSense;
                double e      = Maths.Epsilon.epsilon(-fhBar);
                double eP     = Maths.Epsilon.epsilonP(-fhBar);
                double dPVdp0 = q0 * hBar * (e - eP);
                double dPVdp1 = hBar * p0 * q0 / p1 * eP;
                dPVSense = dPVdp0 * dpdr0 + dPVdp1 * dpdr1;

                pvSense += dPVSense;

                ht0   = ht1;
                dpdr0 = dpdr1;
                rt0   = rt1;
                p0    = p1;
                q0    = q1;
            }
            pvSense *= cds.getLGD();

            // Compute the discount factor discounting the upfront payment made on the cash settlement date back to the valuation date
            double df = Math.Exp(-yieldCurve.getRT_(cds.getCashSettleTime()));

            pvSense /= df;

            //TODO this was put in quickly the get the right sensitivity to the first node
            double dfSense = yieldCurve.getSingleNodeDiscountFactorSensitivity(cds.getCashSettleTime(), yieldCurveNode);

            if (dfSense != 0.0)
            {
                double pro = protectionLeg(cds, yieldCurve, creditCurve);
                pvSense -= pro / df * dfSense;
            }

            return(pvSense);
        }
        public double protectionLegCreditSensitivity(
            CDS cds,
            YieldTermStructure yieldCurve,
            PiecewiseconstantHazardRate creditCurve,
            int creditCurveNode)
        {
            if ((creditCurveNode != 0 && cds.getProtectionEnd() <= creditCurve.getTimeAtIndex(creditCurveNode - 1)) ||
                (creditCurveNode != creditCurve.t.Count - 1 &&
                 cds.getEffectiveProtectionStart() >= creditCurve.getTimeAtIndex(creditCurveNode + 1)))
            {
                return(0.0); // can't have any sensitivity in this case
            }
            if (cds.getProtectionEnd() <= 0.0)
            { //short cut already expired CDSs
                return(0.0);
            }

            double[] integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(
                cds.getEffectiveProtectionStart(), cds.getProtectionEnd(), yieldCurve, creditCurve);

            double t       = integrationSchedule[0];
            double ht0     = creditCurve.getRT_(t);
            double rt0     = yieldCurve.getRT_(t);
            double dqdr0   = creditCurve.getSingleNodeDiscountFactorSensitivity(t, creditCurveNode);
            double q0      = Math.Exp(-ht0);
            double p0      = Math.Exp(-rt0);
            double pvSense = 0.0;
            int    n       = integrationSchedule.Length;

            for (int i = 1; i < n; ++i)
            {
                t = integrationSchedule[i];
                double ht1   = creditCurve.getRT_(t);
                double dqdr1 = creditCurve.getSingleNodeDiscountFactorSensitivity(t, creditCurveNode);
                double rt1   = yieldCurve.getRT_(t);
                double q1    = Math.Exp(-ht1);
                double p1    = Math.Exp(-rt1);

                if (dqdr0 == 0.0 && dqdr1 == 0.0)
                {
                    ht0 = ht1;
                    rt0 = rt1;
                    p0  = p1;
                    q0  = q1;
                    continue;
                }

                double hBar  = ht1 - ht0;
                double fBar  = rt1 - rt0;
                double fhBar = hBar + fBar;

                double dPVSense;
                if (Math.Abs(fhBar) < 1e-5)
                {
                    double e      = Maths.Epsilon.epsilon(-fhBar);
                    double eP     = Maths.Epsilon.epsilonP(-fhBar);
                    double dPVdq0 = p0 * ((1 + hBar) * e - hBar * eP);
                    double dPVdq1 = -p0 * q0 / q1 * (e - hBar * eP);
                    dPVSense = dPVdq0 * dqdr0 + dPVdq1 * dqdr1;
                }
                else
                {
                    double w = fBar / fhBar * (p0 * q0 - p1 * q1);
                    dPVSense = ((w / q0 + hBar * p0) / fhBar) * dqdr0 - ((w / q1 + hBar * p1) / fhBar) * dqdr1;
                }

                pvSense += dPVSense;

                ht0   = ht1;
                dqdr0 = dqdr1;
                rt0   = rt1;
                p0    = p1;
                q0    = q1;
            }
            pvSense *= cds.getLGD();

            // Compute the discount factor discounting the upfront payment made on the cash settlement date back to the valuation date
            double df = Math.Exp(-yieldCurve.getRT_(cds.getCashSettleTime()));

            pvSense /= df;

            return(pvSense);
        }
 /**
  * Compute the present value of the protection leg with a notional of 1, which is given by the integral
  * $\frac{1-R}{P(T_{v})} \int_{T_a} ^{T_b} P(t) \frac{dQ(t)}{dt} dt$ where $P(t)$ and $Q(t)$ are the discount
  * and survival curves respectively, $T_a$ and $T_b$ are the start and end of the protection respectively,
  * $T_v$ is the valuation time (all measured from $t = 0$, 'today') and $R$ is the recovery rate.
  *
  * @param cds  the analytic description of a CDS traded at a certain time
  * @param yieldCurve  the yield (or discount) curve
  * @param creditCurve  the credit (or survival) curve
  * @return the value of the protection leg (on a unit notional)
  */
 public double protectionLeg(CDS cds, YieldTermStructure yieldCurve, PiecewiseconstantHazardRate creditCurve)
 {
     return(protectionLeg(cds, yieldCurve, creditCurve, cds.getCashSettleTime()));
 }