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);
        }
        /**
         * The value of the full (or dirty) annuity (or RPV01 - the premium leg per unit of coupon) today (t=0).
         * The cash flows from premium payments and accrual-on-default are risky discounted to t=0
         * The actual value of the leg is this multiplied by the notional and the fractional coupon
         * (i.e. coupon in basis points divided by 10,000).
         * <p>
         * This is valid for both spot and forward starting CDS.
         *
         * @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 full (or dirty) annuity valued today. <b>Note</b> what is usually quoted is the clean annuity
         */
        public double dirtyAnnuity(CDS cds,
                                   YieldTermStructure yt, PiecewiseconstantHazardRate hazard)
        {
            DateTime        tradedate      = cds.tradedate;
            List <DateTime> Jumps          = yt.jumpDates_;
            DateTime        settlementDate = tradedate.AddDays(0);
            double          recoveryrate   = cds.Recovery;
            DateTime        Stepindate     = tradedate.AddDays(1);
            double          coupon         = cds.PremiumRate;

            OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360();

            CdsCoupon[] cf       = cds.getCoupons();
            double      notional = cds.Notional;

            double ita      = (double)365 / 360;
            double totalNPV = 0.0;

            for (int i = 0; i < cf.Length; ++i)
            {
                totalNPV += cf[i].getYearFrac() * notional * Math.Exp(-hazard.getRT_(cf[i].getEffEnd()))
                            * Math.Exp(-yt.getRT_(cf[i].getPaymentTime()));
            }

            double start = cds.getNumPayments() == 1 ? cds.getEffectiveProtectionStart() : cds.getAccStart();

            double[] integrationSchedule = DoublesScheduleGenerator.getIntegrationsPoints(start, cds.getProtectionEnd(), yt, hazard);
            double   accPV = 0.0;

            for (int i = 0; i < cf.Length; ++i)
            {
                accPV += calculateSinglePeriodAccrualOnDefault(cf[i], cds.getEffectiveProtectionStart(), integrationSchedule, yt, hazard);
            }
            totalNPV += accPV;

            return(totalNPV);
        }
Example #3
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;
                }
            }
        public double calculateSinglePeriodAccrualOnDefault(CDS cds,
                                                            YieldTermStructure yieldCurve,
                                                            PiecewiseconstantHazardRate creditCurve)
        {
            double Acc = 0;

            List <double> Jumps          = yieldCurve.t;
            DateTime      tradedate      = cds.tradedate;
            DateTime      settlementDate = tradedate.AddDays(cds.Cashsettlement);
            double        recoveryrate   = cds.Recovery;
            DateTime      Stepindate     = tradedate.AddDays(1);

            double   notional       = cds.Notional;
            double   coupon         = cds.PremiumRate;
            DateTime lastpayment    = cds.formerpaymentdate;
            DateTime effectiveStart = tradedate.AddDays(1);

            CdsCoupon[] cc = cds.getCoupons();

            for (int i = 0; i < cds.getNumPayments(); ++i)
            {
                //Accured on default
                double t_0 = (i > 0) ? cc[i].getEffStart():0;
                double T   = cc[i].getEffEnd();


                List <double> knots = new List <double>();
                knots.Add(t_0);
                for (int j = 0; j < Jumps.Count; j++)
                {
                    if ((Jumps[j] < T) && (t_0 < Jumps[j]))
                    {
                        knots.Add(Jumps[j]);
                    }
                }
                knots.Add(T);

                double t   = knots[0];
                double ht0 = creditCurve.getRT_(t);
                double rt0 = yieldCurve.getRT_(t);
                double b0  = Math.Exp(-rt0 - ht0); // this is the risky discount factor

                OMLib.Conventions.DayCount.Actual365 dc = new OMLib.Conventions.DayCount.Actual365();
                double t0;
                if (i == 0)
                {
                    t0 = knots[0] - cc[0].getEffStart();
                }
                else
                {
                    t0 = knots[0] - cc[i].getEffStart();
                }
                double pv     = 0.0;
                int    nItems = knots.Count;
                for (int j = 1; j < nItems; ++j)
                {
                    t = knots[j];
                    double ht1 = creditCurve.getRT_(t);
                    double rt1 = yieldCurve.getRT_(t);
                    double b1  = Math.Exp(-rt1 - ht1);

                    double dt = knots[j] - knots[j - 1];

                    double dht  = ht1 - ht0;
                    double drt  = rt1 - rt0;
                    double dhrt = dht + drt + 1e-50;

                    double tPV;
                    double t1;
                    if (i == 0)
                    {
                        t1 = knots[j] - cc[0].getEffStart();
                    }
                    else
                    {
                        t1 = knots[j] - cc[i].getEffStart();
                    }
                    if (Math.Abs(dhrt) < 1e-5)
                    {
                        tPV = dht * b0 * (t0 * (Math.Exp(-dhrt) - 1) / (-dhrt) + dt * ((-dhrt - 1) * (Math.Exp(-dhrt) - 1) - dhrt) / (dhrt * dhrt));
                    }
                    else
                    {
                        tPV = dht / dhrt * (t0 * b0 - t1 * b1 + dt / dhrt * (b0 - b1));
                    }
                    t0  = t1;
                    pv += tPV;
                    ht0 = ht1;
                    rt0 = rt1;
                    b0  = b1;
                }
                Acc += pv;
            }
            return(Acc);
        }