Пример #1
0
        public YieldTermStructure fitSwap(int curveIndex, BasicFixedLeg swap, YieldTermStructure curve, double swapRate)
        {
            int    nPayments = swap._nPayments;
            int    nNodes    = curve.nJumps_;
            double t1        = curveIndex == 0 ? 0.0 : curve.t[curveIndex - 1];
            double t2        = curveIndex == nNodes - 1 ? double.PositiveInfinity : curve.t[curveIndex + 1];

            double temp  = 0;
            double temp2 = 0;
            int    i1    = 0;
            int    i2    = nPayments;

            double[] paymentAmounts = new double[nPayments];
            for (int i = 0; i < nPayments; i++)
            {
                double t = swap.getPaymentTime(i);
                paymentAmounts[i] = swap.getPaymentAmounts(i, swapRate);
                if (t <= t1)
                {
                    double df = Math.Exp(-curve.getRT_(t));
                    temp  += paymentAmounts[i] * df;
                    temp2 -= paymentAmounts[i] * curve.getSingleNodeDiscountFactorSensitivity(t, curveIndex);
                    i1++;
                }
                else if (t >= t2)
                {
                    double df = Math.Exp(-curve.getRT_(t));
                    temp  += paymentAmounts[i] * df;
                    temp2 += paymentAmounts[i] * curve.getSingleNodeDiscountFactorSensitivity(t, curveIndex);
                    i2--;
                }
            }
            double cachedValues = temp;
            double cachedSense  = temp2;
            int    index1       = i1;
            int    index2       = i2;

            BracketRoot BRACKETER = new BracketRoot();
            NewtonRaphsonSingleRootFinder ROOTFINDER = new NewtonRaphsonSingleRootFinder();
            Func <double, double>         func       = x => apply_(x, curve, curveIndex, cachedValues, index1, index2,
                                                                   swap, paymentAmounts);

            Func <double, double> grad = x => apply_sen(x, curve, curveIndex, cachedSense, index1, index2,
                                                        swap, swapRate);

            double guess = curve.getZeroRateAtIndex(curveIndex);

            if (guess == 0.0 && func(guess) == 0.0)
            {
                return(curve);
            }
            double[] bracket = BRACKETER.getBracketedPoints(func, 0.8 * guess, 1.25 * guess, 0, double.PositiveInfinity);
            double   r       = ROOTFINDER.getRoot(func, grad, bracket[0], bracket[1]);

            return(curve.withRate(r, curveIndex));
        }
Пример #2
0
        public double ProtectionLegNPV_Exact(CDS cds, double notional, PiecewiseconstantHazardRate hazard,
                                             YieldTermStructure yt, DateTime tradedate, DateTime settlementDate, double recoveryrate, List <double> Jumps, List <double> creditCurveKnot)
        {
            DateTime Stepindate = tradedate.AddDays(1);

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


            double        t0        = 0;
            double        T         = cds.getProtectionEnd();
            List <double> JumpNodes = new List <double>();

            JumpNodes.Add(t0);
            for (int j = 0; j < Jumps.Count; j++)
            {
                if (Jumps[j] < T)
                {
                    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));
        }
Пример #3
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())));
        }
Пример #4
0
        public double apply_(double x, YieldTermStructure curve, int curveIndex, double cachedValues, int index1, int index2,
                             BasicFixedLeg swap, double[] paymentAmounts)
        {
            YieldTermStructure tempCurve = curve.withRate(x, curveIndex);
            double             sum       = 1.0 - cachedValues; // Floating leg at par

            for (int i = index1; i < index2; i++)
            {
                double t = swap.getPaymentTime(i);
                sum -= paymentAmounts[i] * Math.Exp(-tempCurve.getRT_(t));
            }
            return(sum);
        }
Пример #5
0
        /**
         * The  intrinsic annuity of a CDS portfolio (index) for a unit (initial) notional.
         * The value of the premium leg is this multiplied by the <b> initial</b> notional of the index
         * and the index coupon (as a fraction).
         *
         * @param indexCDS representation of the index cashflows (seen from today).
         * @param yieldCurve The current yield curves
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         * @param priceType Clean or dirty
         * @param valuationTime Valuation time. The leg value is calculated for today (t=0),
         *  then rolled forward (using the risk free yield curve) to the valuation time.
         *  This is because cash payments occur on the cash-settlement-date, which is usually
         *  three working days after the trade date (today)
         * @return The  intrinsic annuity of a CDS portfolio (index)
         */
        public double indexAnnuity(
            CDS indexCDS,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData,
            CdsPriceType priceType,
            double valuationTime)
        {
            int    n = intrinsicData.getIndexSize();
            double a = 0;

            for (int i = 0; i < n; i++)
            {
                if (!intrinsicData.isDefaulted(i))
                {
                    a += intrinsicData.getWeight(i) * _pricer.annuity(indexCDS, yieldCurve, intrinsicData.getCreditCurve(i), priceType, 0);
                }
            }
            a /= Math.Exp(-yieldCurve.getRT_(valuationTime));

            return(a);
        }
Пример #6
0
        /**
         * The normalised intrinsic value of the protection leg of a CDS portfolio (index).
         * The actual value of the leg is this multiplied by the <b>initial</b>  notional of the index.
         *
         * @param indexCDS representation of the index cashflows (seen from today).
         * @param yieldCurve The current yield curves
         * @param intrinsicData credit curves, weights and recovery rates of the intrinsic names
         * @param valuationTime Valuation time. The leg value is calculated for today (t=0),
         *  then rolled forward (using the risk free yield curve) to the valuation time.
         *  This is because cash payments occur on the cash-settlement-date, which is usually
         *  three working days after the trade date (today)
         * @return The normalised intrinsic value of the protection leg.
         */
        public double indexProtLeg(
            CDS indexCDS,
            YieldTermStructure yieldCurve,
            IntrinsicIndexDataBundle intrinsicData,
            double valuationTime)
        {
            CDS    cds     = indexCDS.withRecoveryRate(0.0);
            int    n       = intrinsicData.getIndexSize();
            double protLeg = 0;

            for (int i = 0; i < n; i++)
            {
                if (!intrinsicData.isDefaulted(i))
                {
                    protLeg += intrinsicData.getWeight(i) * intrinsicData.getLGD(i) *
                               _pricer.protectionLeg(cds, yieldCurve, intrinsicData.getCreditCurve(i), 0);
                }
            }
            protLeg /= Math.Exp(-yieldCurve.getRT_(valuationTime));
            return(protLeg);
        }
Пример #7
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);
        }