示例#1
0
        public PiecewiseconstantHazardRate makeFromRT(List <double> t, double[] ht)
        {
            List <DateTime> jumpdate = jumpDates_;

            PiecewiseconstantHazardRate curve = new PiecewiseconstantHazardRate(latestReference_, null, jumpDates_, t, ht.ToList());

            return(curve);
        }
示例#2
0
        public double ProtectionLegNPV_Exact(List <CashFlow> cf, double notional, PiecewiseconstantHazardRate hazard,
                                             YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double recoveryrate, List <DateTime> Jumps, List <DateTime> creditCurveKnot)
        {
            DateTime Stepindate = tradedate.AddDays(1);

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

            if (cf.Count() == 0)
            {
                return(0.0);
            }
            DateTime        t0        = tradedate;
            DateTime        T         = cf.Last().CashFlowDate;
            List <DateTime> JumpNodes = new List <DateTime>();

            JumpNodes.Add(t0);
            for (int j = 0; j < Jumps.Count; j++)
            {
                if ((DateTime.Compare(Jumps[j], T) < 0))
                {
                    JumpNodes.Add(Jumps[j]);
                }
            }
            JumpNodes.Add(T);
            double ht0 = hazard.getRT(JumpNodes[0]);
            double rt0 = yt.getRT(JumpNodes[0]);
            double b0  = Math.Exp(-ht0 - rt0); // risky discount factor

            double pv  = 0.0;
            double dPV = 0.0;

            for (int i = 1; i < JumpNodes.Count; ++i)
            {
                double ht1 = hazard.getRT(JumpNodes[i]);
                double rt1 = yt.getRT(JumpNodes[i]);
                double b1  = Math.Exp(-ht1 - rt1);

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

                // The formula has been modified from ISDA (but is equivalent) to avoid log(exp(x)) and explicitly
                // calculating the time step - it also handles the limit
                if (Math.Abs(dhrt) < 1e-5)
                {
                    dPV = dht * b0 * (Math.Exp(-dhrt) - 1) / (-dhrt);
                }
                else
                {
                    dPV = (b0 - b1) * dht / dhrt;
                }
                pv += dPV;
                ht0 = ht1;
                rt0 = rt1;
                b0  = b1;
            }
            return(pv * notional * (1 - recoveryrate) / yt.discount(settlementDate));
        }
        /**
         * The normalised expected default settlement value paid on the exercise settlement
         * date <b>when no defaults have yet occurred</b>.
         * The actual default settlement is this multiplied by the (initial)
         * index notional. This calculation assumes an homogeneous pool that can be described by a single index curve.
         *
         * @param timeToExpiry Time to expiry
         * @param indexCurve Pseudo credit curve for the index.
         * @param lgd The index Loss Given Default (LGD)
         * @return  The normalised expected default settlement value
         */
        public double expectedDefaultSettlementValue(
            double timeToExpiry,
            PiecewiseconstantHazardRate indexCurve,
            double lgd)
        {
            double q = Math.Exp(-indexCurve.getRT_(timeToExpiry));
            double d = lgd * (1 - q);

            return(d);
        }
        /**
         * For a future expiry date, the default adjusted forward index value is the expected (full)
         * value of the index plus the cash settlement of any defaults before
         * the expiry date, valued on the (forward) cash settlement date (usually 3 working days after
         * the expiry date - i.e. the expiry settlement date).
         * This calculation assumes an homogeneous pool that can be described by a single index curve.
         *
         * @param fwdStartingCDS A forward starting CDS to represent cash flows in the index.
         *  The stepin date should be one day after the expiry and the cashSettlement
         *  date (usually) 3 working days after expiry. This must contain the index recovery rate.
         * @param timeToExpiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param yieldCurve The yield curve
         * @param indexCoupon The coupon of the index
         * @param indexCurve  Pseudo credit curve for the index.
         * @return the default adjusted forward index value
         */
        public double defaultAdjustedForwardIndexValue(
            CDS fwdStartingCDS,
            double timeToExpiry,
            YieldTermStructure yieldCurve,
            double indexCoupon,
            PiecewiseconstantHazardRate indexCurve)
        {
            double defSet = expectedDefaultSettlementValue(timeToExpiry, indexCurve, fwdStartingCDS.getLGD());

            return(defSet + _pricer.pv(fwdStartingCDS, yieldCurve, indexCurve, indexCoupon));
        }
示例#5
0
        private PiecewiseconstantHazardRate[] adjustCurves(PiecewiseconstantHazardRate[] creditCurve, double amount)
        {
            int nCurves = creditCurve.Length;

            PiecewiseconstantHazardRate[] adjCurves = new PiecewiseconstantHazardRate[nCurves];
            for (int jj = 0; jj < nCurves; jj++)
            {
                adjCurves[jj] = adjustCreditCurve(creditCurve[jj], amount);
            }
            return(adjCurves);
        }
示例#6
0
        public static PiecewiseconstantHazardRate[] buildCreditCurves(DateTime tradeDate, double[,] parSpreads, double[] recoveryRates, int[] tenors,
                                                                      YieldTermStructure yieldCurve)
        {
            CdsAnalyticFactory factory = new CdsAnalyticFactory(0.0);

            CDS[] pillarCDS = factory.makeImmCds(tradeDate, CDX_HY_TENORS);
            int   indexSize = parSpreads.GetLength(0);

            PiecewiseconstantHazardRate[] creditCurves = new PiecewiseconstantHazardRate[indexSize];

            //this section of code is hugely wasteful. If we do this for real (i.e. not just in a test), must improve

            for (int i = 0; i < indexSize; i++)
            {
                int      m       = parSpreads.GetLength(1);
                double[] spreads = new double[m];
                for (int j = 0; j < m; j++)
                {
                    spreads[j] = parSpreads[i, j];
                }
                int      nPillars    = spreads.Length;
                CDS[]    tempCDS     = new CDS[nPillars];
                double[] tempSpreads = new double[nPillars];
                int      count       = 0;
                for (int j = 0; j < nPillars; j++)
                {
                    if (!double.IsNaN(parSpreads[i, j]))
                    {
                        tempCDS[count]     = pillarCDS[j].withRecoveryRate(recoveryRates[i]);
                        tempSpreads[count] = spreads[j];
                        count++;
                    }
                }

                CDS[]    calCDS     = null;
                double[] calSpreads = null;
                if (count == nPillars)
                {
                    calCDS     = tempCDS;
                    calSpreads = tempSpreads;
                }
                else
                {
                    calCDS     = new CDS[count];
                    calSpreads = new double[count];
                    Array.Copy(tempCDS, 0, calCDS, 0, count);
                    Array.Copy(tempSpreads, 0, calSpreads, 0, count);
                }

                CreditCurveCalibrator calibrator = new CreditCurveCalibrator(calCDS, yieldCurve);
                creditCurves[i] = calibrator.calibrate(calSpreads);
            }
            return(creditCurves);
        }
        /**
         * The (default adjusted) intrinsic forward spread of an index <b>when no defaults have yet occurred</b>.
         * This is defined as the ratio of expected value of the
         * protection leg and default settlement to the expected value of the annuity at expiry.
         * This calculation assumes an homogeneous pool that can be described by a single index curve.
         *
         * @param fwdStartingCDS forward starting CDS to represent cash flows in the index.
         *  The stepin date should be one day after the expiry and the cashSettlement
         * date (usually) 3 working days after expiry
         * @param timeToExpiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param yieldCurve The yield curve
         * @param indexCurve Pseudo credit curve for the index.
         * @return The normalised expected default settlement value
         */
        public double defaultAdjustedForwardSpread(
            CDS fwdStartingCDS,
            double timeToExpiry,
            YieldTermStructure yieldCurve,
            PiecewiseconstantHazardRate indexCurve)
        {
            double defSettle = expectedDefaultSettlementValue(timeToExpiry, indexCurve, fwdStartingCDS.getLGD());
            double protLeg   = _pricer.protectionLeg(fwdStartingCDS, yieldCurve, indexCurve);
            double ann       = _pricer.annuity(fwdStartingCDS, yieldCurve, indexCurve);

            return((protLeg + defSettle) / ann);
        }
示例#8
0
        public PiecewiseconstantHazardRate makeFromR(List <double> t, double[] h)
        {
            List <DateTime> jumpdate = jumpDates_;
            List <double>   rt_      = new List <double>();

            for (int i = 0; i < t.Count; i++)
            {
                rt_.Add(h[i] * t[i]);  // We make no check that rt is ascending (i.e. we allow negative forward rates)
            }
            PiecewiseconstantHazardRate curve = new PiecewiseconstantHazardRate(latestReference_, null, jumpDates_, t, rt_);

            return(curve);
        }
        /**
         * The normalised expected default settlement value paid on the  exercise settlement date.
         * The actual default settlement is this multiplied by the (initial)
         * index notional.   This calculation assumes an homogeneous pool that can be described by a single index curve.
         * @param initialIndexSize Initial index size
         * @param timeToExpiry Time to expiry
         * @param indexCurve Pseudo credit curve for the index.
         * @param lgd The index Loss Given Default (LGD)
         * @param initialDefaultSettlement  The (normalised) value of any defaults that have already occurred
         *  (e.g. if two defaults have occurred from an index with
         *  initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 )
         * @param numDefaults The number of defaults that have already occurred
         * @return The normalised expected default settlement value
         */
        public double expectedDefaultSettlementValue(
            int initialIndexSize,
            double timeToExpiry,
            PiecewiseconstantHazardRate indexCurve,
            double lgd,
            double initialDefaultSettlement,
            int numDefaults)
        {
            double defFrac = numDefaults / ((double)initialIndexSize);
            // this upper range is if all current defaults have zero recovery
            double q = Math.Exp(-indexCurve.getRT_(timeToExpiry));
            double d = (1 - defFrac) * lgd * (1 - q) + initialDefaultSettlement;

            return(d);
        }
示例#10
0
        public void Pricing(YieldTermStructure yt, PiecewiseconstantHazardRate hazard)
        {
            //Calculate PV for both legs

            CashFlowCalculation engine = new CashFlowCalculation();

            this.FixLeg = engine.Calculation(this.PremiumRate, this.Notional, this.Payment_Schedule, this.tradedate, yt, hazard, this.Cashsettlement, formerpaymentdate);

            NPV_PricingEngine engine2       = new NPV_PricingEngine();
            double            pv_premium    = engine2.PremiumLegNPV_Exact(this.FixLeg, this.piecewiseHazardRate, this.yieldcurve, this.tradedate, this.tradedate.AddDays(3), this.Notional, this.PremiumRate, yt.jumpDates_, formerpaymentdate);
            double            pv_protection = engine2.ProtectionLegNPV_Exact(this, this.Notional, this.piecewiseHazardRate, this.yieldcurve, this.tradedate, this.tradedate.AddDays(3), this.Recovery, yt.t, hazard.t);

            this.pv          = pv_protection - pv_premium;
            this.marketvalue = this.pv + accruedamt;
        }
示例#11
0
        public PiecewiseconstantHazardRate adjustCreditCurve(
            PiecewiseconstantHazardRate creditCurve,
            double amount,
            int firstKnot,
            int lastKnot)
        {
            double[] rt    = creditCurve.rt.ToArray();
            double[] rtAdj = rt;
            for (int i = firstKnot; i < lastKnot; i++)
            {
                rtAdj[i] = rt[i] * amount;
            }
            PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurve.latestReference_, null, null, null, null);

            return(hazard.makeFromRT(creditCurve.t, rtAdj));
        }
示例#12
0
        /**
         * For a future expiry date, the default adjusted forward index value is the expected (full)
         * value of the index plus the cash settlement of any defaults before
         * the expiry date, valued on the (forward) cash settlement date (usually 3 working days after
         * the expiry date - i.e. the expiry settlement date).
         * This calculation assumes an homogeneous pool that can be described by a single index curve.
         *
         * @param fwdStartingCDS A forward starting CDS to represent cash flows in the index.
         *  The stepin date should be one day after the expiry and the cashSettlement
         *  date (usually) 3 working days after expiry. This must contain the index recovery rate.
         * @param timeToExpiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param initialIndexSize The initial number of names in the index
         * @param yieldCurve The yield curve
         * @param indexCoupon The coupon of the index
         * @param indexCurve  Pseudo credit curve for the index.
         * @param initialDefaultSettlement The (normalised) value of any defaults that have already
         *  occurred (e.g. if two defaults have occurred from an index with
         *  initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 )
         * @param numDefaults The number of defaults that have already occurred
         * @return the default adjusted forward index value
         */
        public double defaultAdjustedForwardIndexValue(
            CDS fwdStartingCDS,
            double timeToExpiry,
            int initialIndexSize,
            YieldTermStructure yieldCurve,
            double indexCoupon,
            PiecewiseconstantHazardRate indexCurve,
            double initialDefaultSettlement,
            int numDefaults)
        {
            double f      = (initialIndexSize - numDefaults) / ((double)initialIndexSize);
            double defSet = expectedDefaultSettlementValue(initialIndexSize, timeToExpiry, indexCurve, fwdStartingCDS.getLGD(),
                                                           initialDefaultSettlement, numDefaults);

            return(defSet + f * _pricer.pv(fwdStartingCDS, yieldCurve, indexCurve, indexCoupon));
        }
示例#13
0
        /**
         * The (default adjusted) intrinsic forward spread of an index.
         * This is defined as the ratio of expected value of the protection leg and default settlement to
         * the expected value of the annuity at expiry.  This calculation assumes an homogeneous pool that
         * can be described by a single index curve.
         *
         * @param fwdStartingCDS forward starting CDS to represent cash flows in the index.
         *  The stepin date should be one day after the expiry and the cashSettlement
         *  date (usually) 3 working days after expiry
         * @param timeToExpiry the time in years between the trade date and expiry.
         *  This should use the same DCC as the curves (ACT365F unless manually changed).
         * @param initialIndexSize The initial number of names in the index
         * @param yieldCurve The yield curve
         * @param indexCurve Pseudo credit curve for the index.
         * @param initialDefaultSettlement The (normalised) value of any defaults that have
         *  already occurred (e.g. if two defaults have occurred from an index with
         *  initially 100 entries, and the realised recovery rates are 0.2 and 0.35, the this value is (0.8 + 0.65)/100 )
         * @param numDefaults The number of defaults that have already occurred
         * @return The normalised expected default settlement value
         */
        public double defaultAdjustedForwardSpread(
            CDS fwdStartingCDS,
            double timeToExpiry,
            int initialIndexSize,
            YieldTermStructure yieldCurve,
            PiecewiseconstantHazardRate indexCurve,
            double initialDefaultSettlement,
            int numDefaults)
        {
            double f         = (initialIndexSize - numDefaults) / ((double)initialIndexSize);
            double defSettle = expectedDefaultSettlementValue(initialIndexSize, timeToExpiry, indexCurve, fwdStartingCDS.getLGD(),
                                                              initialDefaultSettlement, numDefaults);
            double protLeg = f * _pricer.protectionLeg(fwdStartingCDS, yieldCurve, indexCurve);
            double ann     = f * _pricer.annuity(fwdStartingCDS, yieldCurve, indexCurve);

            return((protLeg + defSettle) / ann);
        }
示例#14
0
        public PiecewiseconstantHazardRate adjustCreditCurve(PiecewiseconstantHazardRate creditCurve, double amount)
        {
            if (creditCurve == null)
            {
                return(creditCurve);
            }
            int nKnots = creditCurve.t.Count;

            double[] rt    = creditCurve.rt.ToArray();
            double[] rtAdj = new double[nKnots];
            for (int i = 0; i < nKnots; i++)
            {
                rtAdj[i] = rt[i] * amount;
            }
            PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurve.latestReference_, null, null, null, null);

            return(hazard.makeFromRT(creditCurve.t, rtAdj));
        }
示例#15
0
        public void curve_output(YieldTermStructure yt, PiecewiseconstantHazardRate ct)
        {
            double        it    = ct.SurvivalProb(new DateTime(2021, 06, 20));
            List <double> yield = new List <double>();

            for (int j = 1; j < 120; j++)
            {
                DateTime t  = this.evalDate.AddMonths(j);
                double   t_ = (double)j / 12;
                yield.Add(-Math.Log(yt.discount(t)) / t_);
            }
            this.yield_series = yield;
            List <double> survival = new List <double>();

            for (int j = 1; j < 120; j++)
            {
                DateTime t = this.tradedate.AddMonths(j);
                survival.Add(ct.SurvivalProb(t));
            }
            this.survival_prob = survival;
        }
示例#16
0
        public double PremiumLegNPV_Exact(CDS cds, PiecewiseconstantHazardRate hazard,
                                          YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double notional, double coupon, List <double> Jumps, DateTime lastpayment)
        {
            double ita      = (double)365 / 360;
            double totalNPV = 0.0;

            CdsCoupon[] cf = cds.getCoupons();
            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].getEffEnd()));
            }
            double accrualpaidondefault = calculateSinglePeriodAccrualOnDefault(cf, coupon, tradedate, yt, hazard, lastpayment);

            totalNPV += ita * coupon * accrualpaidondefault * notional / yt.discount(tradedate.AddDays(3));
            OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360();
            Calendar calendar = new UnitedStates();


            return(totalNPV / Math.Exp(-yt.getRT_(cds.getCashSettleTime())));
        }
示例#17
0
        public PiecewiseconstantHazardRate[] adjustCurves(
            PiecewiseconstantHazardRate[] creditCurve,
            double amount,
            int[] firstKnots,
            int[] lastknots)
        {
            int nCurves = creditCurve.Length;

            PiecewiseconstantHazardRate[] adjCurves = new PiecewiseconstantHazardRate[nCurves];
            for (int jj = 0; jj < nCurves; jj++)
            {
                if (creditCurve[jj] == null)
                {
                    adjCurves[jj] = null;
                }
                else
                {
                    adjCurves[jj] = adjustCreditCurve(creditCurve[jj], amount, firstKnots[jj], lastknots[jj]);
                }
            }
            return(adjCurves);
        }
示例#18
0
        public double PremiumLegNPV_Exact(List <CashFlow> cf, PiecewiseconstantHazardRate hazard,
                                          YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double notional, double coupon, List <DateTime> Jumps, DateTime lastpayment)
        {
            if (cf.Count() == 0)
            {
                return(0.0);
            }
            double ita      = (double)365 / 360;
            double totalNPV = 0.0;

            for (int i = 0; i < cf.Count; ++i)
            {
                totalNPV += cf[i].Amount * cf[i].DiscountFactor * cf[i].Survivalprobability;
            }
            double accrualpaidondefault = calculateSinglePeriodAccrualOnDefault(cf, coupon, tradedate, yt, hazard, Jumps, lastpayment);

            totalNPV += ita * coupon * accrualpaidondefault * notional / yt.discount(tradedate.AddDays(3));
            OMLib.Conventions.DayCount.Actual360 dc = new OMLib.Conventions.DayCount.Actual360();
            Calendar calendar = new UnitedStates();


            return(totalNPV / yt.discount(settlementDate));
        }
示例#19
0
        public double PremiumLegNPV_Approx(List <CashFlow> cf, PiecewiseconstantHazardRate HazardTermStructure,
                                           YieldTermStructure yt, DateTime tradedate, DateTime settlementDate)
        {
            if (cf.Count() == 0)
            {
                return(0.0);
            }
            double totalNPV = 0.0;

            for (int i = 0; i < cf.Count; ++i)
            {
                if (i == 0)
                {
                    totalNPV += cf[i].Amount * cf[i].DiscountFactor * 1 / 2 * (1 + cf[i].Survivalprobability);
                }
                else
                {
                    totalNPV += cf[i].Amount * 1 / 2 * (cf[i].Survivalprobability
                                                        + cf[i - 1].Survivalprobability) * cf[i].DiscountFactor;
                }
            }

            return(totalNPV);
        }
示例#20
0
        public IntrinsicIndexDataBundle adjustCurves(
            double[] indexPUF,
            CDS[] indexCDS,
            double indexCoupon,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData)
        {
            int nIndexTerms = indexCDS.Length;

            if (nIndexTerms == 1)
            {
                return(adjustCurves(indexPUF[0], indexCDS[0], indexCoupon, yieldCurve, intrinsicData));
            }
            double[] indexKnots = new double[nIndexTerms];
            for (int i = 0; i < nIndexTerms; i++)
            {
                indexKnots[i] = indexCDS[i].getProtectionEnd();
            }

            PiecewiseconstantHazardRate[] creditCurves = intrinsicData.getCreditCurves();
            int nCurves = creditCurves.Length;

            //we cannot assume that all the credit curves have knots at the same times or that the terms of the indices fall on these knots.
            PiecewiseconstantHazardRate[] modCreditCurves = new PiecewiseconstantHazardRate[nCurves];
            int[,] indexMap = new int[nCurves, nIndexTerms];
            for (int i = 0; i < nCurves; i++)
            {
                if (creditCurves[i] == null)
                {
                    modCreditCurves[i] = null; //null credit curves correspond to defaulted names, so are ignored
                }
                else
                {
                    double[] ccKnots  = creditCurves[i].t.ToArray();
                    double[] comKnots = DoublesScheduleGenerator.combineSets(ccKnots, indexKnots);
                    int      nKnots   = comKnots.Length;
                    if (nKnots == ccKnots.Length)
                    {
                        modCreditCurves[i] = creditCurves[i];
                    }
                    else
                    {
                        double[] rt = new double[nKnots];
                        for (int j = 0; j < nKnots; j++)
                        {
                            rt[j] = creditCurves[i].getRT_(comKnots[j]);
                        }
                        PiecewiseconstantHazardRate hazard = new PiecewiseconstantHazardRate(creditCurves[i].latestReference_, null, null, null, null);
                        modCreditCurves[i] = hazard.makeFromRT(comKnots.ToList(), rt);
                    }

                    for (int j = 0; j < nIndexTerms; j++)
                    {
                        int index = Array.BinarySearch(modCreditCurves[i].t.ToArray(), indexKnots[j]);

                        indexMap[i, j] = index;
                    }
                }
            }

            int[]  startKnots = new int[nCurves];
            int[]  endKnots   = new int[nCurves];
            double alpha      = 1.0;

            for (int i = 0; i < nIndexTerms; i++)
            {
                if (i == (nIndexTerms - 1))
                {
                    for (int jj = 0; jj < nCurves; jj++)
                    {
                        if (modCreditCurves[jj] != null)
                        {
                            endKnots[jj] = modCreditCurves[jj].t.Count;
                        }
                    }
                }
                else
                {
                    for (int jj = 0; jj < nCurves; jj++)
                    {
                        if (modCreditCurves[jj] != null)
                        {
                            endKnots[jj] = indexMap[jj, i] + 1;
                        }
                    }
                }

                IntrinsicIndexDataBundle modIntrinsicData = intrinsicData.withCreditCurves(modCreditCurves);
                Func <double, double>    func             = getHazardRateAdjFunction(indexPUF[i], indexCDS[i], indexCoupon, yieldCurve,
                                                                                     modIntrinsicData, startKnots, endKnots);
                alpha           = ROOTFINDER.getRoot(func, alpha);
                modCreditCurves = adjustCurves(modCreditCurves, alpha, startKnots, endKnots);
                startKnots      = endKnots;
            }

            return(intrinsicData.withCreditCurves(modCreditCurves));
        }
示例#21
0
        public PiecewiseconstantHazardRate impliedHazardRate(double targetNPV, double Notional, DateTime tradedate, List <double> spreads, List <DateTime> tenor,
                                                             YieldTermStructure yt,
                                                             OMLib.Conventions.DayCount.DayCounter dayCounter, string frequency, DateTime firstpaymentdate, DateTime lastpaymentdate, List <DateTime> Jumps,
                                                             double recoveryRate = 0.4,
                                                             double accuracy     = 1e-8)
        {
            OMLib.Calendars.Calendar cal = new OMLib.Calendars.Calendar();

            PiecewiseconstantHazardRate probability = new PiecewiseconstantHazardRate(tradedate, null, tenor,
                                                                                      null, null);

            double            error         = 2;
            double            pv_premium    = 0;
            double            pv_protection = 0;
            NPV_PricingEngine engine        = new NPV_PricingEngine();

            //Join the knots
            List <DateTime> result = new List <DateTime>();
            int             index = 0, indexj = 0, lastIndex = 0;

            while (index < Jumps.Count || indexj < tenor.Count)
            {
                if (lastIndex > 0)
                {
                    if (index >= Jumps.Count)
                    {
                        if (!DateTime.Equals(result.Last(), tenor[indexj]))
                        {
                            result.Add(tenor[indexj]);
                            lastIndex++;
                        }
                        indexj++;
                        continue;
                    }
                    if (indexj >= tenor.Count)
                    {
                        if (!DateTime.Equals(result.Last(), Jumps[index]))
                        {
                            result.Add(Jumps[index]);
                            lastIndex++;
                        }
                        index++;
                        continue;
                    }
                }
                DateTime smallestVal = tenor.Last();

                // Choose the smaller of a or b
                if (DateTime.Compare(Jumps[index], tenor[indexj]) < 0)
                {
                    smallestVal = Jumps[index++];
                }
                else
                {
                    smallestVal = tenor[indexj++];
                }

                // Don't insert duplicates
                if (lastIndex > 0)
                {
                    if (!DateTime.Equals(result.Last(), smallestVal))
                    {
                        result.Add(smallestVal);
                        lastIndex++;
                    }
                }
                else
                {
                    result.Add(smallestVal);
                    lastIndex++;
                }
            }
            for (int i = 0; i < spreads.Count(); i++)
            {
                //Accrued Interest
                double guess = spreads[i] / (1 - recoveryRate);
                //spreads[i] / (1 - recoveryRate);
                probability.addhazardrate(tenor[i], guess);
                double target = targetNPV - (double)85 / 360 * spreads[i] * Notional;
                error = 2;
                double step    = guess * 0.01;
                int    j       = 0;
                double error_0 = 1000;
                while (Math.Abs(error) > accuracy)
                {
                    CashFlowCalculation cf_calculation = new CashFlowCalculation();
                    //Schedule should be built here
                    List <DateTime> schedule = new List <DateTime>();
                    schedule = PremiumDates(tenor[i], firstpaymentdate, frequency);

                    List <CashFlow> FixLeg = cf_calculation.Calculation(spreads[i], Notional, schedule, tradedate, yt, probability, 3, lastpaymentdate);
                    //pv_premium = engine.PremiumLegNPV_Approx(FixLeg, probability, yt, tradedate.AddDays(1), tradedate.AddDays(3)/*,Notional,spreads[i]*/);
                    pv_premium    = engine.PremiumLegNPV_Exact(FixLeg, probability, yt, tradedate, tradedate.AddDays(3), Notional, spreads[i], Jumps, lastpaymentdate);
                    pv_protection = engine.ProtectionLegNPV_Exact(FixLeg, Notional, probability, yt, tradedate, tradedate.AddDays(3), recoveryRate, result, tenor);
                    //pv_protection = engine.ProtectionLeg_Approx(FixLeg, Notional, probability, yt, tradedate, tradedate.AddDays(3), recoveryRate);
                    int k1 = dayCounter.DayCount(tradedate, FixLeg[1].CashFlowDate);
                    error = pv_protection - pv_premium - target;

                    if (j > 1)
                    {
                        double temp = guess;
                        guess = guess + step * error / (error_0 - error);
                        step  = guess - temp;
                    }
                    else
                    {
                        guess = guess + step;
                    }
                    error_0 = error;
                    j       = j + 1;
                    probability.update(guess);
                }
            }
            //     probability.update2();

            return(probability);
        }
示例#22
0
        public List <CashFlow> Calculation(double fixrate, double initialNotional, List <DateTime> fixedSchedule, DateTime tradedate,
                                           YieldTermStructure yt, PiecewiseconstantHazardRate piecewiseFlatHazardRate, int settlement, DateTime lastpaymentdate)
        {
            List <CashFlow> result = new List <CashFlow>();

            OMLib.Conventions.DayCount.Actual360 daycountconvention = new OMLib.Conventions.DayCount.Actual360();
            for (int i = 0; i < fixedSchedule.Count; i++)
            {
                CashFlow cf       = new CashFlow();
                Calendar calendar = new UnitedStates();
                //fixedSchedule[i] = calendar.adjust(fixedSchedule[i], BusinessDayConvention.Following);
                cf.CashFlowDate = fixedSchedule[i];
                if (i == 0)
                {
                    //The protection buyer pays the next coupon in full on the coupon date,
                    //(even if this is the next day); in return the buyer receives (from the protection seller) the accrued
                    //interest[Geoff Chaplin. Credit Derivatives.], which is paid on the cash settlement date.
                    if (lastpaymentdate != null)
                    {
                        lastpaymentdate = calendar.adjust(lastpaymentdate, BusinessDayConvention.Following);
                        cf.Amount       = (double)initialNotional * fixrate * (daycountconvention.DayCount(lastpaymentdate, fixedSchedule[i])) / 360;
                    }
                    else
                    {
                        cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(tradedate, fixedSchedule[i])) / 360;
                    }
                }
                else
                {
                    //Each coupon is equal to (annual coupon/360) (# of days in accrual period).
                    //The accrual period always stretches from (previous coupon payment date) through (this coupon
                    //payment date–1), inclusive; except a contract's last accrual period, which ends with (and
                    //includes) the unadjusted maturity date.
                    if (i == fixedSchedule.Count - 1)
                    {
                        cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(fixedSchedule[i - 1], fixedSchedule[i].AddDays(1))) / 360;
                    }
                    else
                    {
                        cf.Amount = (double)initialNotional * fixrate * (daycountconvention.DayCount(fixedSchedule[i - 1], fixedSchedule[i])) / 360;
                    }
                }

                //Assume all cash flows are discounted to the cash settlement date

                cf.DiscountFactor = yt.discount(fixedSchedule[i]);

                if (i == fixedSchedule.Count - 1)
                {
                    cf.Survivalprobability = piecewiseFlatHazardRate.SurvivalProb(fixedSchedule[i].AddDays(1));
                }
                else
                {
                    cf.Survivalprobability = piecewiseFlatHazardRate.SurvivalProb(fixedSchedule[i]);
                }

                result.Add(cf);
            }

            return(result);
        }
示例#23
0
        public void testMethod1()
        {
            for (int i = 0; i < PRICES.Length; i++)
            {
                PILLAR_PUF[i] = new PointsUpFront(INDEX_COUPON, 1 - PRICES[i]);
            }
            int pos        = 1; // target CDX is 5Y
            CDS targentCDX = CDX[pos];
            int n          = PILLAR_PUF.Length;

            double[] indexPUF = new double[n];
            for (int i = 0; i < n; i++)
            {
                indexPUF[i] = PILLAR_PUF[i].getPointsUpFront();
            }

            IntrinsicIndexDataBundle dataDefaulted = INTRINSIC_DATA;
            int    accrualDays    = targentCDX.getAccuredDays();
            double accruedPremium = targentCDX.getAccruedPremium(INDEX_COUPON) * NOTIONAL * dataDefaulted.getIndexFactor();

            /*
             * Using credit curves for constituent single name CDSs.
             * The curves are adjusted by using only the target CDX.
             */

            double cleanPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted) * NOTIONAL;
            double dirtyPV      = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted, CdsPriceType.DIRTY) * NOTIONAL; // should be consistent with 1 - PRICES[pos]
            double expectedLoss = INDEX_CAL.expectedDefaultSettlementValue(targentCDX.getProtectionEnd(), dataDefaulted) * NOTIONAL;
            double cleanRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, dataDefaulted);
            double dirtyRPV01   = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, dataDefaulted, CdsPriceType.DIRTY);
            double durationWeightedAverageSpread = INDEX_CAL.intrinsicIndexSpread(targentCDX, YIELD_CURVE, dataDefaulted) *
                                                   TEN_THOUSAND;
            double parallelIR01 = INDEX_CAL.parallelIR01(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted) * NOTIONAL;

            double[] jumpToDefault = INDEX_CAL.jumpToDefault(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted);
            for (int i = 0; i < jumpToDefault.Length; ++i)
            {
                jumpToDefault[i] *= NOTIONAL;
            }
            double[] recovery01 = INDEX_CAL.recovery01(targentCDX, INDEX_COUPON, YIELD_CURVE, dataDefaulted);
            for (int i = 0; i < recovery01.Length; ++i)
            {
                recovery01[i] *= NOTIONAL;
            }


            IntrinsicIndexDataBundle adjCurvesAll = PSA.adjustCurves(indexPUF, CDX, INDEX_COUPON, YIELD_CURVE,
                                                                     dataDefaulted);
            double cleanPVAll = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll) * NOTIONAL;
            double dirtyPVAll = INDEX_CAL.indexPV(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll, CdsPriceType.DIRTY) *
                                NOTIONAL; // should be consistent with 1 - PRICES[pos]
            double expectedLossAll = INDEX_CAL.expectedDefaultSettlementValue(targentCDX.getProtectionEnd(), adjCurvesAll) *
                                     NOTIONAL;
            double cleanRPV01All = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurvesAll);
            double dirtyRPV01All = INDEX_CAL.indexAnnuity(targentCDX, YIELD_CURVE, adjCurvesAll, CdsPriceType.DIRTY);
            double durationWeightedAverageSpreadAll = INDEX_CAL.intrinsicIndexSpread(targentCDX, YIELD_CURVE, adjCurvesAll) *
                                                      TEN_THOUSAND;
            double parallelIR01All = INDEX_CAL.parallelIR01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll) * NOTIONAL;

            double[] jumpToDefaultAll = INDEX_CAL.jumpToDefault(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll);
            for (int i = 0; i < jumpToDefaultAll.Length; ++i)
            {
                jumpToDefaultAll[i] *= NOTIONAL;
            }
            double[] recovery01All = INDEX_CAL.recovery01(targentCDX, INDEX_COUPON, YIELD_CURVE, adjCurvesAll);
            for (int i = 0; i < recovery01All.Length; ++i)
            {
                recovery01All[i] *= NOTIONAL;
            }
            PiecewiseconstantHazardRate indexCurve = (new Commons.FastCreditCurveBuilder()).calibrateCreditCurve(targentCDX,
                                                                                                                 INDEX_COUPON, YIELD_CURVE, indexPUF[pos]); // single node index curve, indexFactors cancel out
            double cleanPriceIndexCurve = PRICER_OG_FIX.pv(targentCDX, YIELD_CURVE, indexCurve, INDEX_COUPON) *
                                          dataDefaulted.getIndexFactor() * NOTIONAL;
            double dirtyPriceIndexCurve = PRICER_OG_FIX.pv(targentCDX, YIELD_CURVE, indexCurve, INDEX_COUPON,
                                                           CdsPriceType.DIRTY) * dataDefaulted.getIndexFactor() * NOTIONAL;
            double cleanRPV01IndexCurve = PRICER_OG_FIX.annuity(targentCDX, YIELD_CURVE, indexCurve) *
                                          dataDefaulted.getIndexFactor();
            double dirtyRPV01IndexCurve = PRICER_OG_FIX.annuity(targentCDX, YIELD_CURVE, indexCurve, CdsPriceType.DIRTY) *
                                          dataDefaulted.getIndexFactor();
            double spreadIndexCurve = PRICER_OG_FIX.parSpread(targentCDX, YIELD_CURVE, indexCurve) * TEN_THOUSAND;
        }
示例#24
0
        //public double ProtectionLeg_Approx(List<CashFlow> cf, double notional, PiecewiseconstantHazardRate HazardTermStructure,
        //    YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double recoveryrate)
        //{
        //    if (cf.Count() == 0)
        //    {
        //        return 0.0;
        //    }
        //    double totalNPV = 0.0;
        //    for (int i = 0; i < cf.Count; ++i)
        //    {
        //        if (i == 0)
        //        {
        //            totalNPV += (1 - recoveryrate)*notional * cf[i].DiscountFactor * (1- cf[i].Survivalprobability);

        //        }
        //        else
        //        {
        //            totalNPV += notional * cf[i].DiscountFactor * (cf[i - 1].Survivalprobability
        //            - cf[i].Survivalprobability) * (1 - recoveryrate);

        //        }
        //    }
        //    return totalNPV/yt.discount(settlementDate);
        //}


        public double calculateSinglePeriodAccrualOnDefault(List <CashFlow> cf, double coupon,
                                                            DateTime tradedate,
                                                            YieldTermStructure yieldCurve,
                                                            PiecewiseconstantHazardRate creditCurve, List <DateTime> Jumps, DateTime lastpayment)
        {
            double   Acc            = 0;
            DateTime effectiveStart = tradedate.AddDays(1);

            for (int i = 0; i < cf.Count; ++i)
            {
                //Accured on default
                DateTime t_0 = (i > 0) ? cf[i - 1].CashFlowDate.AddDays(-1) : tradedate;
                DateTime T   = cf[i].CashFlowDate;
                if (i == cf.Count - 1)
                {
                    T = cf[i].CashFlowDate;
                }
                else
                {
                    T = cf[i].CashFlowDate.AddDays(-1);
                }

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

                DateTime 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 = (double)dc.DayCount(lastpayment.AddDays(1), knots[0]) / 365;
                }
                else
                {
                    t0 = (double)dc.DayCount(cf[i].CashFlowDate.AddDays(1), knots[0]) / 365;
                }
                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 = (double)dc.DayCount(knots[j - 1], knots[j]) / 365;

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

                    double tPV;
                    double t1;
                    if (i == 0)
                    {
                        t1 = (double)dc.DayCount(lastpayment.AddDays(1), knots[j]) / 365;
                    }
                    else
                    {
                        t1 = (double)dc.DayCount(cf[i].CashFlowDate.AddDays(1), knots[j]) / 365;
                    }
                    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 * dt / dhrt * ((b0 - b1) / dhrt - b1);
                    }
                    t0  = t1;
                    pv += tPV;
                    ht0 = ht1;
                    rt0 = rt1;
                    b0  = b1;
                }
                Acc += pv;
            }
            return(Acc);
        }
示例#25
0
        public double calculateSinglePeriodAccrualOnDefault(CdsCoupon[] cf, double coupon,
                                                            DateTime tradedate,
                                                            YieldTermStructure yieldCurve,
                                                            PiecewiseconstantHazardRate creditCurve, DateTime lastpayment)
        {
            double   Acc            = 0;
            DateTime effectiveStart = tradedate.AddDays(1);

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

                T = cf[i].getPaymentTime();
                List <double> knots = new List <double>();
                knots.Add(t_0);
                for (int j = 0; j < yieldCurve.t.Count; j++)
                {
                    if ((yieldCurve.t[j] < T) && (t_0 < yieldCurve.t[j]))
                    {
                        knots.Add(yieldCurve.t[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] - cf[0].getEffStart();
                }
                else
                {
                    t0 = knots[0] - cf[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] - cf[0].getEffStart();
                    }
                    else
                    {
                        t1 = knots[j] - cf[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 * dt / dhrt * ((b0 - b1) / dhrt - b1);
                    }
                    t0  = t1;
                    pv += tPV;
                    ht0 = ht1;
                    rt0 = rt1;
                    b0  = b1;
                }
                Acc += pv;
            }
            return(Acc);
        }
示例#26
0
        public void hazardratecurve(YieldTermStructure yt, OMLib.Conventions.DayCount.Actual365 dayCounter, List <double> QuotedSpot, List <double> QuotedSpread, double FixRate, double Spread_traded, double Upfront, DateTime maturity,
                                    DateTime firstpaymentdate, DateTime evalDate, DateTime formerpaymentdate, string frequency, double recovery)
        {
            List <DateTime> dates         = new List <DateTime>();
            List <DateTime> discountDates = new List <DateTime>();
            int             accrued       = dayCounter.DayCount(formerpaymentdate, tradedate);

            if (QuotedSpread == null)
            {
                if (Spread_traded > 0)
                {
                    // Infer the constant hazard rate from the quoted spread

                    /*When the Spread is input: Consider a CDS with exactly the same specification as
                     * the Standard CDS except that its Coupon Rate is equal to the Spread. Assume that
                     * the Upfront of this CDS is zero. Solve for the Constant Hazard Rate that gives this
                     * CDS a MTM equal to minus its Accrued Premium (based on a Coupon Rate equal
                     * to Spread) discounted riskless to T
                     */
                    impliedhazardrate ih     = new impliedhazardrate();
                    List <double>     spread = new List <double> {
                        Spread_traded
                    };
                    List <DateTime> mat = new List <DateTime> {
                        maturity
                    };
                    PiecewiseconstantHazardRate flatrate = ih.impliedHazardRate(-this.Notional * Spread_traded * accrued / 360, this.Notional,
                                                                                this.tradedate, spread, mat, yt, dayCounter, frequency, firstpaymentdate, this.formerpaymentdate, this.Jump_Nodes, recovery);

                    this.piecewiseHazardRate = flatrate;
                }
                else if (Upfront > 0)
                {
                    // Infer the constant hazard rate from the quoted upfront

                    /*When the Upfront is input: Solve for the Constant Hazard Rate that gives the
                     * Standard CDS a MTM equal to Notional * Upfront – AccruedPremium discounted riskless to T*/
                    impliedhazardrate ih     = new impliedhazardrate();
                    List <double>     spread = new List <double> {
                        Spread_traded
                    };
                    List <DateTime> mat = new List <DateTime> {
                        maturity
                    };
                    PiecewiseconstantHazardRate flatrate = ih.impliedHazardRate(this.Notional * Upfront - this.accruedamt, this.Notional, this.tradedate,
                                                                                spread, mat, yt, dayCounter, frequency, firstpaymentdate, this.formerpaymentdate, this.Jump_Nodes, recovery);
                    this.piecewiseHazardRate = flatrate;
                }
            }
            else
            //  Construct the credit curve with the predefined term structure
            {
                dates.Add(firstpaymentdate.AddMonths(6));
                dates.Add(firstpaymentdate.AddYears(1));
                dates.Add(firstpaymentdate.AddYears(3));
                dates.Add(firstpaymentdate.AddYears(5));
                dates.Add(firstpaymentdate.AddYears(7));
                dates.Add(firstpaymentdate.AddYears(10));
                for (int i = 0; i < QuotedSpread.Count(); i++)
                {
                    QuotedSpread[i] = QuotedSpread[i] / 10000;
                }
                impliedhazardrate           implied     = new impliedhazardrate();
                PiecewiseconstantHazardRate hazardcurve = implied.impliedHazardRate(0, this.Notional, this.tradedate, QuotedSpread, dates, yt, dayCounter,
                                                                                    frequency, this.firstpaymentdate, this.formerpaymentdate, this.Jump_Nodes, recovery);
                this.piecewiseHazardRate = hazardcurve;
                List <double> survival = new List <double>();
                for (int i = 0; i < dates.Count; i++)
                {
                    survival.Add(piecewiseHazardRate.SurvivalProb(dates[i].AddDays(1)));
                }
            }
        }