discountFactor() публичный Метод

public discountFactor ( Date d1, Date d2 ) : double
d1 Date
d2 Date
Результат double
        public static double simpleDuration(List <CashFlow> cashflows, InterestRate y, Date settlementDate)
        {
            if (cashflows.Count == 0)
            {
                return(0.0);
            }

            double     P = 0, dPdy = 0;
            DayCounter dc = y.dayCounter();

            foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate)))
            {
                double t = dc.yearFraction(settlementDate, cf.date());
                double c = cf.amount();
                double B = y.discountFactor(t);
                P    += c * B;
                dPdy += t * c * B;
            }


            // no cashflows
            if (P == 0.0)
            {
                return(0.0);
            }
            return(dPdy / P);
        }
        public static double modifiedDuration(List <CashFlow> cashflows, InterestRate y, Date settlementDate)
        {
            if (cashflows.Count == 0)
            {
                return(0.0);
            }

            double     P    = 0.0;
            double     dPdy = 0.0;
            double     r    = y.rate();
            int        N    = (int)y.frequency();
            DayCounter dc   = y.dayCounter();

            foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate)))
            {
                double t = dc.yearFraction(settlementDate, cf.date());
                double c = cf.amount();
                double B = y.discountFactor(t);

                P += c * B;

                switch (y.compounding())
                {
                case Compounding.Simple:
                    dPdy -= c * B * B * t;
                    break;

                case Compounding.Compounded:
                    dPdy -= c * t * B / (1 + r / N);
                    break;

                case Compounding.Continuous:
                    dPdy -= c * B * t;
                    break;

                case Compounding.SimpleThenCompounded:
                    if (t <= 1.0 / N)
                    {
                        dPdy -= c * B * B * t;
                    }
                    else
                    {
                        dPdy -= c * t * B / (1 + r / N);
                    }
                    break;

                default:
                    throw new ArgumentException("unknown compounding convention (" + y.compounding() + ")");
                }
            }

            if (P == 0.0) // no cashflows
            {
                return(0.0);
            }

            return(-dPdy / P); // reverse derivative sign
        }
Пример #3
0
        public static double simpleDuration(Leg leg, InterestRate y, bool includeSettlementDateFlows,
                                            Date settlementDate, Date npvDate)
        {
            if (leg.empty())
            {
                return(0.0);
            }

            if (settlementDate == null)
            {
                settlementDate = Settings.evaluationDate();
            }

            if (npvDate == null)
            {
                npvDate = settlementDate;
            }

            double P        = 0.0;
            double dPdy     = 0.0;
            double t        = 0.0;
            Date   lastDate = npvDate;

            DayCounter dc = y.dayCounter();

            for (int i = 0; i < leg.Count; ++i)
            {
                if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
                {
                    continue;
                }

                double c = leg[i].amount();
                if (leg[i].tradingExCoupon(settlementDate))
                {
                    c = 0.0;
                }

                t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate);
                double B = y.discountFactor(t);
                P    += c * B;
                dPdy += t * c * B;

                lastDate = leg[i].date();
            }

            if (P.IsEqual(0.0)) // no cashflows
            {
                return(0.0);
            }
            return(dPdy / P);
        }
Пример #4
0
        // NPV of the cash flows.
        // The NPV is the sum of the cash flows, each discounted
        // according to the given constant interest rate.  The result
        // is affected by the choice of the interest-rate compounding
        // and the relative frequency and day counter.
        public static double npv(Leg leg, InterestRate yield, bool includeSettlementDateFlows,
                                 Date settlementDate = null, Date npvDate = null)
        {
            if (leg.empty())
            {
                return(0.0);
            }

            if (settlementDate == null)
            {
                settlementDate = Settings.evaluationDate();
            }

            if (npvDate == null)
            {
                npvDate = settlementDate;
            }

            double     npv      = 0.0;
            double     discount = 1.0;
            Date       lastDate = npvDate;
            DayCounter dc       = yield.dayCounter();

            for (int i = 0; i < leg.Count; ++i)
            {
                if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
                {
                    continue;
                }

                double amount = leg[i].amount();
                if (leg[i].tradingExCoupon(settlementDate))
                {
                    amount = 0.0;
                }

                double b = yield.discountFactor(getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate));
                discount *= b;
                lastDate  = leg[i].date();

                npv += amount * discount;
            }
            return(npv);
        }
      public static double simpleDuration(List<CashFlow> cashflows, InterestRate y, Date settlementDate) 
      {
         if (cashflows.Count == 0)
            return 0.0;

         double P = 0, dPdy = 0;
         DayCounter dc = y.dayCounter();
         foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) 
         {
            double t = dc.yearFraction(settlementDate, cf.date());
            double c = cf.amount();
            double B = y.discountFactor(t);
            P += c * B;
            dPdy += t * c * B;
         }


         // no cashflows
         if (P == 0.0) return 0.0;
         return dPdy / P;
      }
Пример #6
0
      public static double modifiedDuration(Leg leg,InterestRate y, bool includeSettlementDateFlows,
                                            Date settlementDate,Date npvDate) 
      {
         if (leg.empty())
            return 0.0;

         if (settlementDate == null)
            settlementDate = Settings.evaluationDate();

         if (npvDate == null)
            npvDate = settlementDate;

         double P = 0.0;
         double t = 0.0;
         double dPdy = 0.0;
         double r = y.rate();
         int N = (int)y.frequency();
         Date lastDate = npvDate;
         Date refStartDate, refEndDate;
         DayCounter dc = y.dayCounter();

         for (int i=0; i<leg.Count; ++i) 
         {
            if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
               continue;

            double c = leg[i].amount();
				if (leg[i].tradingExCoupon(settlementDate))
				{
					c = 0.0;
				}
            Date couponDate = leg[i].date();
            Coupon coupon = leg[i] as Coupon;
            if (coupon != null) 
            {
               refStartDate = coupon.refPeriodStart;
               refEndDate = coupon.refPeriodEnd;
            } 
            else 
            {
               if (lastDate == npvDate) 
               {
                  // we don't have a previous coupon date,
                  // so we fake it
                  refStartDate = couponDate - new Period(1,TimeUnit.Years);
               } 
               else  
               {
                  refStartDate = lastDate;
               }
               refEndDate = couponDate;
            }
                
            t += dc.yearFraction(lastDate, couponDate, refStartDate, refEndDate);
                
            double B = y.discountFactor(t);
            P += c * B;
            switch (y.compounding()) 
            {
               case Compounding.Simple:
                  dPdy -= c * B*B * t;
                  break;
               case Compounding.Compounded:
                  dPdy -= c * t * B/(1+r/N);
                  break;
               case Compounding.Continuous:
                  dPdy -= c * B * t;
                  break;
               case Compounding.SimpleThenCompounded:
                  if (t<=1.0/N)
                     dPdy -= c * B*B * t;
                  else
                     dPdy -= c * t * B/(1+r/N);
                  break;
               default:
                  Utils.QL_FAIL("unknown compounding convention (" + y.compounding() + ")");
                  break;
            }
            lastDate = couponDate;
         }

         if (P == 0.0) // no cashflows
            return 0.0;
         return -dPdy/P; // reverse derivative sign
      }
      public void testConversions()
      {
         InterestRateData[] cases = {
         // data from "Option Pricing Formulas", Haug, pag.181-182
         // Rate,Compounding,        Frequency,   Time, Compounding2,      Frequency2,  Rate2, precision
         new InterestRateData(0.0800, Compounding.Compounded, Frequency.Quarterly, 1.00, Compounding.Continuous, Frequency.Annual,     0.0792, 4),
         new InterestRateData(0.1200, Compounding.Continuous, Frequency.Annual,    1.00, Compounding.Compounded, Frequency.Annual,     0.1275, 4),
         new InterestRateData(0.0800, Compounding.Compounded, Frequency.Quarterly, 1.00, Compounding.Compounded, Frequency.Annual,     0.0824, 4),
         new InterestRateData(0.0700, Compounding.Compounded, Frequency.Quarterly, 1.00, Compounding.Compounded, Frequency.Semiannual, 0.0706, 4),
         // undocumented, but reasonable :)
         new InterestRateData(0.0100, Compounding.Compounded, Frequency.Annual,            1.00,   Compounding.Simple,     Frequency.Annual,           0.0100, 4),
         new InterestRateData(0.0200, Compounding.Simple,     Frequency.Annual,            1.00,   Compounding.Compounded, Frequency.Annual,           0.0200, 4),
         new InterestRateData(0.0300, Compounding.Compounded, Frequency.Semiannual,        0.50,   Compounding.Simple,     Frequency.Annual,           0.0300, 4),
         new InterestRateData(0.0400, Compounding.Simple,     Frequency.Annual,            0.50,   Compounding.Compounded, Frequency.Semiannual,       0.0400, 4),
         new InterestRateData(0.0500, Compounding.Compounded, Frequency.EveryFourthMonth,  1.0/3,  Compounding.Simple,     Frequency.Annual,           0.0500, 4),
         new InterestRateData(0.0600, Compounding.Simple,     Frequency.Annual,            1.0/3,  Compounding.Compounded, Frequency.EveryFourthMonth, 0.0600, 4),
         new InterestRateData(0.0500, Compounding.Compounded, Frequency.Quarterly,         0.25,   Compounding.Simple,     Frequency.Annual,           0.0500, 4),
         new InterestRateData(0.0600, Compounding.Simple,     Frequency.Annual,            0.25,   Compounding.Compounded, Frequency.Quarterly,        0.0600, 4),
         new InterestRateData(0.0700, Compounding.Compounded, Frequency.Bimonthly,         1.0/6,  Compounding.Simple,     Frequency.Annual,           0.0700, 4),
         new InterestRateData(0.0800, Compounding.Simple,     Frequency.Annual,            1.0/6,  Compounding.Compounded, Frequency.Bimonthly,        0.0800, 4),
         new InterestRateData(0.0900, Compounding.Compounded, Frequency.Monthly,           1.0/12, Compounding.Simple,     Frequency.Annual,           0.0900, 4),
         new InterestRateData(0.1000, Compounding.Simple,     Frequency.Annual,            1.0/12, Compounding.Compounded, Frequency.Monthly,          0.1000, 4),

         new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.25, Compounding.Simple,     Frequency.Annual,     0.0300, 4),
         new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.25, Compounding.Simple,     Frequency.Semiannual, 0.0300, 4),
         new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.25, Compounding.Simple,     Frequency.Quarterly,  0.0300, 4),
         new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.50, Compounding.Simple,     Frequency.Annual,     0.0300, 4),
         new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.50, Compounding.Simple,     Frequency.Semiannual, 0.0300, 4),
         new InterestRateData(0.0300, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.75, Compounding.Compounded, Frequency.Semiannual, 0.0300, 4),

         new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.25, Compounding.SimpleThenCompounded, Frequency.Quarterly,  0.0400, 4),
         new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.25, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.0400, 4),
         new InterestRateData(0.0400, Compounding.Simple, Frequency.Semiannual, 0.25, Compounding.SimpleThenCompounded, Frequency.Annual,     0.0400, 4),

         new InterestRateData(0.0400, Compounding.Compounded, Frequency.Quarterly,  0.50, Compounding.SimpleThenCompounded, Frequency.Quarterly,  0.0400, 4),
         new InterestRateData(0.0400, Compounding.Simple,     Frequency.Semiannual, 0.50, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.0400, 4),
         new InterestRateData(0.0400, Compounding.Simple,     Frequency.Semiannual, 0.50, Compounding.SimpleThenCompounded, Frequency.Annual,     0.0400, 4),

         new InterestRateData(0.0400, Compounding.Compounded, Frequency.Quarterly,  0.75, Compounding.SimpleThenCompounded, Frequency.Quarterly,  0.0400, 4),
         new InterestRateData(0.0400, Compounding.Compounded, Frequency.Semiannual, 0.75, Compounding.SimpleThenCompounded, Frequency.Semiannual, 0.0400, 4),
         new InterestRateData(0.0400, Compounding.Simple,     Frequency.Semiannual, 0.75, Compounding.SimpleThenCompounded, Frequency.Annual,     0.0400, 4)
         };

         Rounding roundingPrecision;
         double r3;
         double r2;
         Date d1 = Date.Today;
         Date d2;
         InterestRate ir;
         InterestRate ir2;
         InterestRate ir3;
         InterestRate expectedIR;
         double compoundf;
         double error;
         double disc;

         for (int i = 0; i < cases.Length-1 ; i++)
         {
            ir = new InterestRate(cases[i].r, new Actual360(), cases[i].comp, cases[i].freq);
            d2 = d1 + new Period((int)(360 * cases[i].t + 0.5) ,TimeUnit.Days);
            roundingPrecision = new Rounding(cases[i].precision);

            // check that the compound factor is the inverse of the discount factor
            compoundf = ir.compoundFactor(d1, d2);
            disc = ir.discountFactor(d1, d2);
            error = Math.Abs(disc - 1.0 / compoundf);
            if (error > 1e-15)
               Assert.Fail(ir + "  1.0/compound_factor: " + 1.0 / compoundf);

            // check that the equivalent InterestRate with *same* daycounter,
            // compounding, and frequency is the *same* InterestRate
            ir2 = ir.equivalentRate(d1, d2, ir.dayCounter(), ir.compounding(), ir.frequency());
            error = Math.Abs(ir.rate() - ir2.rate());
            if (error > 1e-15)
               Assert.Fail("original interest rate: " + ir + " equivalent interest rate: " + ir2 + " rate error: " + error);
            if (ir.dayCounter() != ir2.dayCounter())
               Assert.Fail("day counter error original interest rate: " + ir + " equivalent interest rate: " + ir2);
            if (ir.compounding() != ir2.compounding())
               Assert.Fail("compounding error original interest rate: " + ir + " equivalent interest rate: " + ir2);
            if (ir.frequency() != ir2.frequency())
               Assert.Fail("frequency error original interest rate: " + ir + " equivalent interest rate: " + ir2);

            // check that the equivalent rate with *same* daycounter,
            // compounding, and frequency is the *same* rate
            r2 = ir.equivalentRate(d1, d2, ir.dayCounter(), ir.compounding(), ir.frequency()).rate();
            error = Math.Abs(ir.rate() - r2);
            if (error > 1e-15)
               Assert.Fail("original rate: " + ir + " equivalent rate: " + r2 + " error: " + error);

            // check that the equivalent InterestRate with *different*
            // compounding, and frequency is the *expected* InterestRate
            ir3 = ir.equivalentRate(d1, d2, ir.dayCounter(), cases[i].comp2, cases[i].freq2);
            expectedIR = new InterestRate(cases[i].expected, ir.dayCounter(), cases[i].comp2, cases[i].freq2);
            r3 = roundingPrecision.Round(ir3.rate());
            error = Math.Abs(r3 - expectedIR.rate());
            if (error > 1.0e-17)
               Assert.Fail("original interest rate: " + ir + " calculated equivalent interest rate: " + ir3 + " truncated equivalent rate: " + r3 + " expected equivalent interest rate: " + expectedIR + " rate error: " + error);
            if (ir3.dayCounter() != expectedIR.dayCounter())
               Assert.Fail("day counter error original interest rate: " + ir3 + " equivalent interest rate: " + expectedIR);
            if (ir3.compounding() != expectedIR.compounding())
               Assert.Fail("compounding error original interest rate: " + ir3 + " equivalent interest rate: " + expectedIR);
            if (ir3.frequency() != expectedIR.frequency())
               Assert.Fail("frequency error original interest rate: " + ir3 + " equivalent interest rate: " + expectedIR);

            // check that the equivalent rate with *different*
            // compounding, and frequency is the *expected* rate
            r3 = ir.equivalentRate(d1, d2, ir.dayCounter(), cases[i].comp2, cases[i].freq2).rate();
            r3 = roundingPrecision.Round(r3);
            error = Math.Abs(r3 - cases[i].expected);
            if (error > 1.0e-17)
               Assert.Fail("calculated equivalent rate: " + r3 + " expected equivalent rate: " + cases[i].expected + " error: " + error);

         }

      }
        //! Cash-flow convexity

        /*! The convexity of a string of cash flows is defined as
         *            \f[
         *            C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2}
         *            \f]
         *            where \f$ P \f$ is the present value of the cash flows according to the given IRR \f$ y \f$.
         */
        public static double convexity(List <CashFlow> cashflows, InterestRate rate, Date settlementDate = null)
        {
            if (cashflows.Count == 0)
            {
                return(0.0);
            }

            if (settlementDate == null)
            {
                settlementDate = Settings.evaluationDate();
            }

            DayCounter dayCounter = rate.dayCounter();

            double P      = 0;
            double d2Pdy2 = 0;
            double y      = rate.rate();
            int    N      = (int)rate.frequency();


            foreach (CashFlow cashflow in cashflows.Where(cashflow => !cashflow.hasOccurred(settlementDate)))
            {
                double t = dayCounter.yearFraction(settlementDate, cashflow.date());
                double c = cashflow.amount();
                double B = rate.discountFactor(t);

                P += c * B;

                switch (rate.compounding())
                {
                case Compounding.Simple:
                    d2Pdy2 += c * 2.0 * B * B * B * t * t;
                    break;

                case Compounding.Compounded:
                    d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N));
                    break;

                case Compounding.Continuous:
                    d2Pdy2 += c * B * t * t;
                    break;

                case Compounding.SimpleThenCompounded:
                    if (t <= 1.0 / N)
                    {
                        d2Pdy2 += c * 2.0 * B * B * B * t * t;
                    }
                    else
                    {
                        d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N));
                    }
                    break;

                default:
                    throw new ArgumentException("unknown compounding convention (" + rate.compounding() + ")");
                }
            }

            // no cashflows

            if (P == 0)
            {
                return(0);
            }
            return(d2Pdy2 / P);
        }
        public static double npv(List <CashFlow> leg, InterestRate y, bool includeSettlementDateFlows,
                                 Date settlementDate = null, Date npvDate = null)
        {
            if (leg == null || leg.empty())
            {
                return(0.0);
            }

            if (settlementDate == null)
            {
                settlementDate = Settings.evaluationDate();
            }

            if (npvDate == null)
            {
                npvDate = settlementDate;
            }

            double npv = 0.0;
            double discount = 1.0;
            Date   lastDate = npvDate;
            Date   refStartDate, refEndDate;

            for (int i = 0; i < leg.Count; ++i)
            {
                if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
                {
                    continue;
                }

                Date   couponDate = leg[i].date();
                double amount     = leg[i].amount();
                Coupon coupon     = leg[i] as Coupon;
                if (coupon != null)
                {
                    refStartDate = coupon.accrualStartDate();
                    refEndDate   = coupon.accrualEndDate();
                }
                else
                {
                    if (lastDate == npvDate)
                    {
                        // we don't have a previous coupon date,
                        // so we fake it
                        refStartDate = couponDate - new Period(1, TimeUnit.Years);
                    }
                    else
                    {
                        refStartDate = lastDate;
                    }
                    refEndDate = couponDate;
                }
                double b = y.discountFactor(lastDate, couponDate, refStartDate, refEndDate);
                discount *= b;
                lastDate  = couponDate;

                npv += amount * discount;
            }

            return(npv);
        }
Пример #10
0
        public static double modifiedDuration(Leg leg, InterestRate y, bool includeSettlementDateFlows,
                                              Date settlementDate, Date npvDate)
        {
            if (leg.empty())
            {
                return(0.0);
            }

            if (settlementDate == null)
            {
                settlementDate = Settings.evaluationDate();
            }

            if (npvDate == null)
            {
                npvDate = settlementDate;
            }

            double     P        = 0.0;
            double     t        = 0.0;
            double     dPdy     = 0.0;
            double     r        = y.rate();
            int        N        = (int)y.frequency();
            Date       lastDate = npvDate;
            DayCounter dc       = y.dayCounter();

            for (int i = 0; i < leg.Count; ++i)
            {
                if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
                {
                    continue;
                }

                double c = leg[i].amount();
                if (leg[i].tradingExCoupon(settlementDate))
                {
                    c = 0.0;
                }

                t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate);

                double B = y.discountFactor(t);
                P += c * B;
                switch (y.compounding())
                {
                case Compounding.Simple:
                    dPdy -= c * B * B * t;
                    break;

                case Compounding.Compounded:
                    dPdy -= c * t * B / (1 + r / N);
                    break;

                case Compounding.Continuous:
                    dPdy -= c * B * t;
                    break;

                case Compounding.SimpleThenCompounded:
                    if (t <= 1.0 / N)
                    {
                        dPdy -= c * B * B * t;
                    }
                    else
                    {
                        dPdy -= c * t * B / (1 + r / N);
                    }
                    break;

                default:
                    Utils.QL_FAIL("unknown compounding convention (" + y.compounding() + ")");
                    break;
                }
                lastDate = leg[i].date();
            }

            if (P.IsEqual(0.0)) // no cashflows
            {
                return(0.0);
            }
            return(-dPdy / P); // reverse derivative sign
        }
Пример #11
0
        //! Cash-flow convexity
        public static double convexity(Leg leg, InterestRate yield, bool includeSettlementDateFlows,
                                       Date settlementDate = null, Date npvDate = null)
        {
            if (leg.empty())
            {
                return(0.0);
            }

            if (settlementDate == null)
            {
                settlementDate = Settings.evaluationDate();
            }

            if (npvDate == null)
            {
                npvDate = settlementDate;
            }

            DayCounter dc = yield.dayCounter();

            double P        = 0.0;
            double t        = 0.0;
            double d2Pdy2   = 0.0;
            double r        = yield.rate();
            int    N        = (int)yield.frequency();
            Date   lastDate = npvDate;


            for (int i = 0; i < leg.Count; ++i)
            {
                if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
                {
                    continue;
                }

                double c = leg[i].amount();
                if (leg[i].tradingExCoupon(settlementDate))
                {
                    c = 0.0;
                }

                t += getStepwiseDiscountTime(leg[i], dc, npvDate, lastDate);

                double B = yield.discountFactor(t);
                P += c * B;
                switch (yield.compounding())
                {
                case  Compounding.Simple:
                    d2Pdy2 += c * 2.0 * B * B * B * t * t;
                    break;

                case Compounding.Compounded:
                    d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + r / N) * (1 + r / N));
                    break;

                case Compounding.Continuous:
                    d2Pdy2 += c * B * t * t;
                    break;

                case Compounding.SimpleThenCompounded:
                    if (t <= 1.0 / N)
                    {
                        d2Pdy2 += c * 2.0 * B * B * B * t * t;
                    }
                    else
                    {
                        d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + r / N) * (1 + r / N));
                    }
                    break;

                default:
                    Utils.QL_FAIL("unknown compounding convention (" + yield.compounding() + ")");
                    break;
                }
                lastDate = leg[i].date();
            }

            if (P.IsEqual(0.0))
            {
                // no cashflows
                return(0.0);
            }

            return(d2Pdy2 / P);
        }
      public static double modifiedDuration(List<CashFlow> cashflows, InterestRate y, Date settlementDate) 
      {
         if (cashflows.Count == 0)
            return 0.0;

         double P = 0.0;
         double dPdy = 0.0;
         double r = y.rate();
         int N = (int)y.frequency();
         DayCounter dc = y.dayCounter();

         foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) 
         {

            double t = dc.yearFraction(settlementDate, cf.date());
            double c = cf.amount();
            double B = y.discountFactor(t);

            P += c * B;

            switch (y.compounding()) 
            {
               case Compounding.Simple:
                  dPdy -= c * B * B * t;
                  break;
                  
               case Compounding.Compounded:
                  dPdy -= c * t * B / (1 + r / N);
                  break;
                  
               case Compounding.Continuous:
                  dPdy -= c * B * t;
                  break;
                  
               case Compounding.SimpleThenCompounded:
                  if (t <= 1.0 / N)
                     dPdy -= c * B * B * t;
                  else
                     dPdy -= c * t * B / (1 + r / N);
                     break;
                    
               default:
                  throw new ArgumentException("unknown compounding convention (" + y.compounding() + ")");
            }
         }
         
         if (P == 0.0) // no cashflows
            return 0.0;
            
         return -dPdy / P; // reverse derivative sign
      }
      //! Cash-flow convexity
      /*! The convexity of a string of cash flows is defined as
	            \f[
	            C = \frac{1}{P} \frac{\partial^2 P}{\partial y^2}
	            \f]
	            where \f$ P \f$ is the present value of the cash flows according to the given IRR \f$ y \f$.
	        */
      public static double convexity(List<CashFlow> cashflows, InterestRate rate, Date settlementDate = null) 
        {
           if (cashflows.Count == 0)
              return 0.0;

           if (settlementDate == null) settlementDate = Settings.evaluationDate();

           DayCounter dayCounter = rate.dayCounter();

           double P = 0;
           double d2Pdy2 = 0;
           double y = rate.rate();
           int N = (int)rate.frequency();

           
           foreach (CashFlow cashflow in cashflows.Where(cashflow => !cashflow.hasOccurred(settlementDate))) 
           {
              double t = dayCounter.yearFraction(settlementDate, cashflow.date());
              double c = cashflow.amount();
              double B = rate.discountFactor(t);

              P += c * B;

              switch (rate.compounding()) 
              {
                 case Compounding.Simple:
                    d2Pdy2 += c * 2.0 * B * B * B * t * t;
                    break;
                    
                 case Compounding.Compounded:
                    d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N));
                    break;
                    
                 case Compounding.Continuous:
                    d2Pdy2 += c * B * t * t;
                    break;
                    
                 case Compounding.SimpleThenCompounded:
                    if (t <= 1.0 / N)
                       d2Pdy2 += c * 2.0 * B * B * B * t * t;
                    else
                       d2Pdy2 += c * B * t * (N * t + 1) / (N * (1 + y / N) * (1 + y / N));
                    break;
                    
                 default:
                    throw new ArgumentException("unknown compounding convention (" + rate.compounding() + ")");
              }
           }

           // no cashflows
           
           if (P == 0) return 0;
           return d2Pdy2 / P;
        }
Пример #14
0
      public static double simpleDuration(Leg leg,InterestRate y, bool includeSettlementDateFlows,
                                          Date settlementDate,Date npvDate) 
      {
         if (leg.empty())                
            return 0.0;

         if (settlementDate == null)
            settlementDate = Settings.evaluationDate();

         if (npvDate == null)
            npvDate = settlementDate;

         double P = 0.0;
         double dPdy = 0.0;
         double t = 0.0;
         Date lastDate = npvDate;
         Date refStartDate, refEndDate;

         DayCounter dc = y.dayCounter();
         for (int i=0; i<leg.Count; ++i) 
         {
            if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
               continue;

            double c = leg[i].amount();
				if (leg[i].tradingExCoupon(settlementDate))
				{
					c = 0.0;
				}
            Date couponDate = leg[i].date();
            Coupon coupon = leg[i] as Coupon;
            if (coupon != null) 
            {
               refStartDate = coupon.refPeriodStart;
               refEndDate = coupon.refPeriodEnd;
            } 
            else 
            {
               if (lastDate == npvDate) 
               {
                  // we don't have a previous coupon date,
                  // so we fake it
                  refStartDate = couponDate - new Period(1,TimeUnit.Years);
               } 
               else  
               {
                  refStartDate = lastDate;
               }
               refEndDate = couponDate;
            }

            t += dc.yearFraction(lastDate, couponDate, refStartDate, refEndDate);
            double B = y.discountFactor(t);
            P += c * B;
            dPdy += t * c * B;
                
            lastDate = couponDate;
         }
            
         if (P == 0.0) // no cashflows
            return 0.0;
         return dPdy/P;
      }
Пример #15
0
 protected override double discountImpl(double t)
 {
     calculate();
     return(rate_.discountFactor(t));
 }
Пример #16
0
      // NPV of the cash flows.
      // The NPV is the sum of the cash flows, each discounted
      // according to the given constant interest rate.  The result
      // is affected by the choice of the interest-rate compounding
      // and the relative frequency and day counter.
      public static double npv(Leg leg, InterestRate yield, bool includeSettlementDateFlows,
                               Date settlementDate = null, Date npvDate = null)
      {
         if (leg.empty())
            return 0.0;

         if (settlementDate == null)
            settlementDate = Settings.evaluationDate();

         if (npvDate == null)
            npvDate = settlementDate;

         double npv = 0.0;
         double discount = 1.0;
         Date lastDate = npvDate;
         Date refStartDate, refEndDate;

         for (int i=0; i<leg.Count; ++i) 
         {
            if (leg[i].hasOccurred(settlementDate, includeSettlementDateFlows))
                continue;

            Date couponDate = leg[i].date();
            double amount = leg[i].amount();
				if (leg[i].tradingExCoupon(settlementDate))
				{
					amount = 0.0;
				}
            Coupon coupon = leg[i] as Coupon;
            if (coupon != null ) 
            {
                refStartDate = coupon.refPeriodStart;
                refEndDate = coupon.refPeriodEnd;
            } 
            else 
            {
               if (lastDate == npvDate) 
               {
                  // we don't have a previous coupon date,
                  // so we fake it
                  refStartDate = couponDate - new Period(1,TimeUnit.Years);
                } 
               else  
               {
                  refStartDate = lastDate;
               }
               refEndDate = couponDate;
            }
            
            double b = yield.discountFactor(lastDate, couponDate, refStartDate, refEndDate);
            discount *= b;
            lastDate = couponDate;

            npv += amount * discount;
        }
        return npv;
      }
Пример #17
0
        public static double dirtyPriceFromYield(double faceAmount, List <CashFlow> cashflows, double yield, DayCounter dayCounter,
                                                 Compounding compounding, Frequency frequency, Date settlement)
        {
            if (frequency == Frequency.NoFrequency || frequency == Frequency.Once)
            {
                frequency = Frequency.Annual;
            }

            InterestRate y = new InterestRate(yield, dayCounter, compounding, frequency);

            double price    = 0.0;
            double discount = 1.0;
            Date   lastDate = null;

            for (int i = 0; i < cashflows.Count - 1; ++i)
            {
                if (cashflows[i].hasOccurred(settlement))
                {
                    continue;
                }

                Date   couponDate = cashflows[i].Date;
                double amount     = cashflows[i].amount();
                if (lastDate == null)
                {
                    // first not-expired coupon
                    if (i > 0)
                    {
                        lastDate = cashflows[i - 1].Date;
                    }
                    else
                    {
                        if (cashflows[i].GetType().IsSubclassOf(typeof(Coupon)))
                        {
                            lastDate = ((Coupon)cashflows[i]).accrualStartDate();
                        }
                        else
                        {
                            lastDate = couponDate - new Period(1, TimeUnit.Years);
                        }
                    }
                    discount *= y.discountFactor(settlement, couponDate, lastDate, couponDate);
                }
                else
                {
                    discount *= y.discountFactor(lastDate, couponDate);
                }
                lastDate = couponDate;

                price += amount * discount;
            }

            CashFlow redemption = cashflows.Last();

            if (!redemption.hasOccurred(settlement))
            {
                Date   redemptionDate = redemption.Date;
                double amount         = redemption.amount();
                if (lastDate == null)
                {
                    // no coupons
                    lastDate  = redemptionDate - new Period(1, TimeUnit.Years);
                    discount *= y.discountFactor(settlement, redemptionDate, lastDate, redemptionDate);
                }
                else
                {
                    discount *= y.discountFactor(lastDate, redemptionDate);
                }

                price += amount * discount;
            }

            return(price / faceAmount * 100.0);
        }