protected override double zeroYieldImpl(double t) {
     // to be fixed: user-defined daycounter should be used
     InterestRate zeroRate = originalCurve_.link.zeroRate(t, comp_, freq_, true);
     InterestRate spreadedRate = new InterestRate(zeroRate.value() + spread_.value(), zeroRate.dayCounter(),
                                                  zeroRate.compounding(), zeroRate.frequency());
     return spreadedRate.equivalentRate(t, Compounding.Continuous, Frequency.NoFrequency).value();
 }
Пример #2
0
 // constructors
 public FixedRateCoupon(double nominal, Date paymentDate, double rate, DayCounter dayCounter,
                        Date accrualStartDate, Date accrualEndDate, 
                        Date refPeriodStart = null, Date refPeriodEnd = null,double? amount = null) 
    : base(nominal, paymentDate, accrualStartDate, accrualEndDate, refPeriodStart, refPeriodEnd, amount) 
 {
    rate_ = new InterestRate(rate, dayCounter, Compounding.Simple,Frequency.Annual);
 }
Пример #3
0
 public FixedRateCoupon(double nominal, Date paymentDate, InterestRate interestRate, 
                        Date accrualStartDate, Date accrualEndDate, 
                        Date refPeriodStart = null, Date refPeriodEnd = null,double? amount = null) 
    : base(nominal, paymentDate, accrualStartDate, accrualEndDate, refPeriodStart, refPeriodEnd, amount) 
 {
    rate_ = interestRate;
 }
      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
      }
Пример #5
0
		private void CHECK_NPV(bool includeRef, double expected, InterestRate no_discount, List<CashFlow> leg,Date today)                             
		{
			do 
			{                                                            
				double NPV = CashFlows.npv(leg, no_discount, includeRef, today); 
				if (Math.Abs(NPV - expected) > 1e-6) 
				{                         
					Assert.Fail("NPV mismatch:\n"                               
									+ "    calculated: " + NPV + "\n"            
									+ "    expected: " + expected);               
				}                                                               
			} 
			while (false);
		}
      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;
      }
Пример #7
0
        public void testBondFromScheduleWithDateVector()
        {
            // Testing South African R2048 bond price using Schedule constructor with Date vector
             SavedSettings backup = new SavedSettings();

             //When pricing bond from Yield To Maturity, use NullCalendar()
             Calendar calendar = new NullCalendar();

             int settlementDays = 3;

             Date issueDate = new Date(29, Month.June, 2012);
             Date today = new Date(7, Month.September, 2015);
             Date evaluationDate = calendar.adjust(today);
             Date settlementDate = calendar.advance(evaluationDate, new Period(settlementDays, TimeUnit.Days));
             Settings.setEvaluationDate(evaluationDate);

             // For the schedule to generate correctly for Feb-28's, make maturity date on Feb 29
             Date maturityDate = new Date(29, Month.February, 2048);

             double coupon = 0.0875;
             Compounding comp = Compounding.Compounded;
             Frequency freq = Frequency.Semiannual;
             DayCounter dc = new ActualActual(ActualActual.Convention.Bond);

             // Yield as quoted in market
             InterestRate yield = new InterestRate(0.09185, dc, comp, freq);

             Period tenor = new Period(6, TimeUnit.Months);
             Period exCouponPeriod = new Period(10, TimeUnit.Days);

             // Generate coupon dates for 31 Aug and end of Feb each year
             // For leap years, this will generate 29 Feb, but the bond
             // actually pays coupons on 28 Feb, regardsless of whether
             // it is a leap year or not.
             Schedule schedule = new Schedule(issueDate, maturityDate, tenor,
            new NullCalendar(), BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
            DateGeneration.Rule.Backward, true);

             // Adjust the 29 Feb's to 28 Feb
             List<Date> dates = new List<Date>();
             for (int i = 0; i < schedule.Count; ++i)
             {
            Date d = schedule.date(i);
            if (d.Month == 2 && d.Day == 29)
               dates.Add(new Date(28, Month.February, d.Year));
            else
               dates.Add(d);
             }

             schedule = new Schedule(dates,
                                 schedule.calendar(),
                                 schedule.businessDayConvention(),
                                 schedule.terminationDateBusinessDayConvention(),
                                 schedule.tenor(),
                                 schedule.rule(),
                                 schedule.endOfMonth(),
                                 schedule.isRegular());

             FixedRateBond bond = new FixedRateBond(
             0,
             100.0,
             schedule,
             new List<double>() { coupon },
             dc, BusinessDayConvention.Following, 100.0,
             issueDate, calendar,
             exCouponPeriod, calendar, BusinessDayConvention.Unadjusted, false);

             double calculatedPrice = BondFunctions.dirtyPrice(bond, yield, settlementDate);
             double expectedPrice = 95.75706;
             double tolerance = 1e-5;
             if (Math.Abs(calculatedPrice - expectedPrice) > tolerance)
             {
            Assert.Fail(string.Format("failed to reproduce R2048 dirty price\nexpected: {0}\ncalculated: {1}", expectedPrice, calculatedPrice));
             }
        }
Пример #8
0
      //! Basis-point sensitivity of the cash flows.
      // The result is the change in NPV due to a uniform
      // 1-basis-point change in the rate paid by the cash
      // flows. The change for each coupon is 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 bps(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;

         FlatForward flatRate = new FlatForward(settlementDate, yield.rate(), yield.dayCounter(),
                                               yield.compounding(), yield.frequency());
         return bps(leg, flatRate, includeSettlementDateFlows, settlementDate, npvDate);
      }
Пример #9
0
        //! 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);
        }
Пример #10
0
 public override double value(double y) 
 {
    InterestRate yield = new InterestRate(y, dayCounter_, compounding_, frequency_);
    double NPV = CashFlows.npv(leg_, yield, includeSettlementDateFlows_, settlementDate_, npvDate_);
    return npv_ - NPV;
 }
Пример #11
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;
      }
Пример #12
0
            public override double derivative(double y)
            {
                InterestRate yield = new InterestRate(y, dayCounter_, compounding_, frequency_);

                return(modifiedDuration(leg_, yield, includeSettlementDateFlows_, settlementDate_, npvDate_));
            }
Пример #13
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
      }
Пример #14
0
 public FixedRateLeg withCouponRates(InterestRate couponRate)
 {
    couponRates_.Clear();
    couponRates_.Add(couponRate);
    return this;
 }
Пример #15
0
 protected override void performCalculations()
 {
     rate_ = new InterestRate(forward_.value(), dayCounter(), compounding_, frequency_);
 }
 public override double derivative(double x) {
     InterestRate y = new InterestRate(x, dayCounter_, compounding_, frequency_);
     return modifiedDuration(cashflows_, y, settlementDate_);
 }
 // Basis-point sensitivity of the cash flows.
   // The result is the change in NPV due to a uniform 1-basis-point change in the rate paid by the cash flows. The change for each coupon is 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 bps(List<CashFlow> cashflows, InterestRate irr, Date settlementDate = null) {
       if (settlementDate == null)
           settlementDate = Settings.evaluationDate();
       var flatRate = new FlatForward(settlementDate, irr.rate(), irr.dayCounter(), irr.compounding(), irr.frequency());
       return bps(cashflows, flatRate, settlementDate, settlementDate);
   }
Пример #18
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);
        }
Пример #19
0
 public static double cleanPrice(Bond bond, InterestRate yield, Date settlementDate = null)
 {
     return(dirtyPrice(bond, yield, settlementDate) - bond.accruedAmount(settlementDate));
 }
Пример #20
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);
        }
Пример #21
0
        // creator
        public override List <CashFlow> value()
        {
            if (couponRates_.Count == 0)
            {
                throw new ArgumentException("no coupon rates given");
            }
            if (notionals_.Count == 0)
            {
                throw new ArgumentException("no nominals given");
            }

            List <CashFlow> leg = new List <CashFlow>();

            Calendar schCalendar = schedule_.calendar();

            // first period might be short or long
            Date         start = schedule_[0], end = schedule_[1];
            Date         paymentDate = calendar_.adjust(end, paymentAdjustment_);
            InterestRate rate        = couponRates_[0];
            double       nominal     = notionals_[0];

            if (schedule_.isRegular(1))
            {
                if (!(firstPeriodDC_ == null || firstPeriodDC_ == rate.dayCounter()))
                {
                    throw new ArgumentException("regular first coupon does not allow a first-period day count");
                }
                leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
            }
            else
            {
                Date refer = end - schedule_.tenor();
                refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
                InterestRate r = new InterestRate(rate.rate(),
                                                  (firstPeriodDC_ == null || firstPeriodDC_.empty()) ? rate.dayCounter() : firstPeriodDC_,
                                                  rate.compounding(), rate.frequency());
                leg.Add(new FixedRateCoupon(nominal, paymentDate, r, start, end, refer, end));
            }

            // regular periods
            for (int i = 2; i < schedule_.Count - 1; ++i)
            {
                start       = end; end = schedule_[i];
                paymentDate = calendar_.adjust(end, paymentAdjustment_);
                if ((i - 1) < couponRates_.Count)
                {
                    rate = couponRates_[i - 1];
                }
                else
                {
                    rate = couponRates_.Last();
                }
                if ((i - 1) < notionals_.Count)
                {
                    nominal = notionals_[i - 1];
                }
                else
                {
                    nominal = notionals_.Last();
                }

                leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
            }

            if (schedule_.Count > 2)
            {
                // last period might be short or long
                int N = schedule_.Count;
                start       = end; end = schedule_[N - 1];
                paymentDate = calendar_.adjust(end, paymentAdjustment_);

                if ((N - 2) < couponRates_.Count)
                {
                    rate = couponRates_[N - 2];
                }
                else
                {
                    rate = couponRates_.Last();
                }
                if ((N - 2) < notionals_.Count)
                {
                    nominal = notionals_[N - 2];
                }
                else
                {
                    nominal = notionals_.Last();
                }

                if (schedule_.isRegular(N - 1))
                {
                    leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
                }
                else
                {
                    Date refer = start + schedule_.tenor();
                    refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
                    leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, refer));
                }
            }
            return(leg);
        }
Пример #22
0
 public FixedRateLeg withCouponRates(InterestRate couponRate)
 {
     couponRates_.Clear();
     couponRates_.Add(couponRate);
     return(this);
 }
Пример #23
0
      // creator
      public override List<CashFlow> value() 
      {
      
         if (couponRates_.Count == 0) throw new ArgumentException("no coupon rates given");
         if (notionals_.Count == 0) throw new ArgumentException("no nominals given");

         List<CashFlow> leg = new List<CashFlow>();

         Calendar schCalendar = schedule_.calendar();

         // first period might be short or long
         Date start = schedule_[0], end = schedule_[1];
         Date paymentDate = calendar_.adjust(end, paymentAdjustment_);
         InterestRate rate = couponRates_[0];
         double nominal = notionals_[0];
         if (schedule_.isRegular(1)) 
         {
            if (!(firstPeriodDC_ == null || firstPeriodDC_ == rate.dayCounter()))
                throw new ArgumentException("regular first coupon does not allow a first-period day count");
            leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
         } 
         else 
         {
             Date refer = end - schedule_.tenor();
             refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
             InterestRate r = new InterestRate(rate.rate(),
                                               (firstPeriodDC_ == null || firstPeriodDC_.empty()) ? rate.dayCounter() : firstPeriodDC_,
                                               rate.compounding(), rate.frequency());
             leg.Add(new FixedRateCoupon(nominal, paymentDate, r, start, end, refer, end));
         }

         // regular periods
         for (int i=2; i<schedule_.Count-1; ++i) 
         {
            start = end; end = schedule_[i];
            paymentDate = calendar_.adjust(end, paymentAdjustment_);
            if ((i - 1) < couponRates_.Count) rate = couponRates_[i - 1];
            else                              rate = couponRates_.Last();
            if ((i - 1) < notionals_.Count)   nominal = notionals_[i - 1];
            else                              nominal = notionals_.Last();

            leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
         }

         if (schedule_.Count > 2) {
             // last period might be short or long
             int N = schedule_.Count;
             start = end; end = schedule_[N-1];
             paymentDate = calendar_.adjust(end, paymentAdjustment_);

             if ((N - 2) < couponRates_.Count) rate = couponRates_[N - 2];
             else                              rate = couponRates_.Last();
             if ((N - 2) < notionals_.Count)   nominal = notionals_[N - 2];
             else                              nominal = notionals_.Last();

             if (schedule_.isRegular(N-1))
                 leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, end));
             else {
                 Date refer = start + schedule_.tenor();
                 refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
                 leg.Add(new FixedRateCoupon(nominal, paymentDate, rate, start, end, start, refer));
             }
         }
         return leg;
     }
Пример #24
0
        public void testSettings()
        {
            // Testing cash-flow settings...
            SavedSettings backup = new SavedSettings();

            Date today = Date.Today;
            Settings.setEvaluationDate(today);

            // cash flows at T+0, T+1, T+2
            List<CashFlow> leg = new List<CashFlow>();

            for (int i=0; i<3; ++i)
                leg.Add(new SimpleCashFlow(1.0, today+i));

            // case 1: don't include reference-date payments, no override at
            //         today's date

            Settings.includeReferenceDateEvents = false;
            Settings.includeTodaysCashFlows = null;

            CHECK_INCLUSION(0, 0, false,leg,today);
            CHECK_INCLUSION(0, 1, false,leg,today);

            CHECK_INCLUSION(1, 0, true,leg,today);
            CHECK_INCLUSION(1, 1, false,leg,today);
            CHECK_INCLUSION(1, 2, false,leg,today);

            CHECK_INCLUSION(2, 1, true,leg,today);
            CHECK_INCLUSION(2, 2, false,leg,today);
            CHECK_INCLUSION(2, 3, false,leg,today);

            // case 2: same, but with explicit setting at today's date

            Settings.includeReferenceDateEvents = false;
            Settings.includeTodaysCashFlows = false;

            CHECK_INCLUSION(0, 0, false,leg,today);
            CHECK_INCLUSION(0, 1, false,leg,today);

            CHECK_INCLUSION(1, 0, true,leg,today);
            CHECK_INCLUSION(1, 1, false,leg,today);
            CHECK_INCLUSION(1, 2, false,leg,today);

            CHECK_INCLUSION(2, 1, true,leg,today);
            CHECK_INCLUSION(2, 2, false,leg,today);
            CHECK_INCLUSION(2, 3, false,leg,today);

            // case 3: do include reference-date payments, no override at
            //         today's date

            Settings.includeReferenceDateEvents = true;
            Settings.includeTodaysCashFlows = null;

            CHECK_INCLUSION(0, 0, true,leg,today);
            CHECK_INCLUSION(0, 1, false,leg,today);

            CHECK_INCLUSION(1, 0, true,leg,today);
            CHECK_INCLUSION(1, 1, true,leg,today);
            CHECK_INCLUSION(1, 2, false,leg,today);

            CHECK_INCLUSION(2, 1, true,leg,today);
            CHECK_INCLUSION(2, 2, true,leg,today);
            CHECK_INCLUSION(2, 3, false,leg,today);

            // case 4: do include reference-date payments, explicit (and same)
            //         setting at today's date

            Settings.includeReferenceDateEvents = true;
            Settings.includeTodaysCashFlows = true;

            CHECK_INCLUSION(0, 0, true,leg,today);
            CHECK_INCLUSION(0, 1, false,leg,today);

            CHECK_INCLUSION(1, 0, true,leg,today);
            CHECK_INCLUSION(1, 1, true,leg,today);
            CHECK_INCLUSION(1, 2, false,leg,today);

            CHECK_INCLUSION(2, 1, true,leg,today);
            CHECK_INCLUSION(2, 2, true,leg,today);
            CHECK_INCLUSION(2, 3, false,leg,today);

            // case 5: do include reference-date payments, override at
            //         today's date

            Settings.includeReferenceDateEvents = true;
            Settings.includeTodaysCashFlows = false;

            CHECK_INCLUSION(0, 0, false,leg,today);
            CHECK_INCLUSION(0, 1, false,leg,today);

            CHECK_INCLUSION(1, 0, true,leg,today);
            CHECK_INCLUSION(1, 1, true,leg,today);
            CHECK_INCLUSION(1, 2, false,leg,today);

            CHECK_INCLUSION(2, 1, true,leg,today);
            CHECK_INCLUSION(2, 2, true,leg,today);
            CHECK_INCLUSION(2, 3, false,leg,today);

            // no discount to make calculations easier
            InterestRate no_discount = new InterestRate(0.0, new Actual365Fixed(), Compounding.Continuous, Frequency.Annual);

            // no override
            Settings.includeTodaysCashFlows = null;

            CHECK_NPV(false, 2.0,no_discount,leg,today);
            CHECK_NPV(true, 3.0,no_discount,leg,today);

            // override
            Settings.includeTodaysCashFlows = false;

            CHECK_NPV(false, 2.0,no_discount,leg,today);
            CHECK_NPV(true, 2.0,no_discount,leg,today);
        }
Пример #25
0
      //! Basis-point value
      /*! Obtained by setting dy = 0.0001 in the 2nd-order Taylor
          series expansion.
      */
      public static double basisPointValue(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 = CashFlows.npv(leg, yield,includeSettlementDateFlows,settlementDate, npvDate);
         double modifiedDuration = CashFlows.duration(leg, yield, Duration.Type.Modified,includeSettlementDateFlows,
                                                      settlementDate, npvDate);
         double convexity = CashFlows.convexity(leg, yield, includeSettlementDateFlows, settlementDate, npvDate);
         double delta = -modifiedDuration*npv;
         double gamma = (convexity/100.0)*npv;

         double shift = 0.0001;
         delta *= shift;
         gamma *= shift*shift;

         return delta + 0.5*gamma;
      }
Пример #26
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
        }
Пример #27
0
        public void testBrazilianCached()
        {
            //("Testing Brazilian public bond prices against cached values...");

             CommonVars vars = new CommonVars();

             double faceAmount = 1000.0;
             double redemption = 100.0;
             Date issueDate = new Date(1, Month.January, 2007);

             Date today = new Date(6, Month.June, 2007);
             Settings.setEvaluationDate(today);

             // NTN-F maturity dates
             InitializedList<Date> maturityDates = new InitializedList<Date>(6);
             maturityDates[0] = new Date(1, Month.January, 2008);
             maturityDates[1] = new Date(1, Month.January, 2010);
             maturityDates[2] = new Date(1, Month.July, 2010);
             maturityDates[3] = new Date(1, Month.January, 2012);
             maturityDates[4] = new Date(1, Month.January, 2014);
             maturityDates[5] = new Date(1, Month.January, 2017);

             // NTN-F yields
             InitializedList<double> yields = new InitializedList<double>(6);
             yields[0] = 0.114614;
             yields[1] = 0.105726;
             yields[2] = 0.105328;
             yields[3] = 0.104283;
             yields[4] = 0.103218;
             yields[5] = 0.102948;

             // NTN-F prices
             InitializedList<double> prices = new InitializedList<double>(6);
             prices[0] = 1034.63031372;
             prices[1] = 1030.09919487;
             prices[2] = 1029.98307160;
             prices[3] = 1028.13585068;
             prices[4] = 1028.33383817;
             prices[5] = 1026.19716497;

             int settlementDays = 1;
             vars.faceAmount = 1000.0;

             // The tolerance is high because Andima truncate yields
             double tolerance = 1.0e-4;

             InitializedList<InterestRate> couponRates = new InitializedList<InterestRate>(1);
             couponRates[0] = new InterestRate(0.1, new Thirty360(), Compounding.Compounded, Frequency.Annual);

             for (int bondIndex = 0; bondIndex < maturityDates.Count; bondIndex++)
             {

            // plain
            InterestRate yield = new InterestRate(yields[bondIndex], new Business252(new Brazil()),
                                                  Compounding.Compounded, Frequency.Annual);

            Schedule schedule = new Schedule(new Date(1, Month.January, 2007),
                              maturityDates[bondIndex], new Period(Frequency.Semiannual),
                              new Brazil(Brazil.Market.Settlement),
                              BusinessDayConvention.Unadjusted, BusinessDayConvention.Unadjusted,
                              DateGeneration.Rule.Backward, false);

            FixedRateBond bond = new FixedRateBond(settlementDays,
                                                   faceAmount,
                                                   schedule,
                                                   couponRates,
                                                   BusinessDayConvention.Following,
                                                   redemption,
                                                   issueDate);

            double cachedPrice = prices[bondIndex];

            double price = vars.faceAmount * (bond.cleanPrice(yield.rate(),
                                                         yield.dayCounter(),
                                                         yield.compounding(),
                                                         yield.frequency(),
                                                         today) + bond.accruedAmount(today)) / 100;
            if (Math.Abs(price - cachedPrice) > tolerance)
            {
               Assert.Fail("failed to reproduce cached price:\n"
                           + "    calculated: " + price + "\n"
                           + "    expected:   " + cachedPrice + "\n"
                           + "    error:      " + (price - cachedPrice) + "\n"
                           );
            }
             }
        }
      ////! Internal rate of return.
      ///*! The IRR is the interest rate at which the NPV of the cash flows equals the given market price. The function verifies
      //      the theoretical existance of an IRR and numerically establishes the IRR to the desired precision. */
      //public static double irr(List<CashFlow> cashflows, double marketPrice, DayCounter dayCounter, Compounding compounding,
      //                        Frequency frequency, Date settlementDate, double accuracy, int maxIterations, double guess) {
      //      if (settlementDate == null)
      //          settlementDate = Settings.evaluationDate();

      //      // depending on the sign of the market price, check that cash flows of the opposite sign have been specified (otherwise
      //      // IRR is nonsensical.)

      //      int lastSign = Math.Sign(-marketPrice),
      //          signChanges = 0;

      //      foreach (CashFlow cf in cashflows.Where(cf => !cf.hasOccurred(settlementDate))) {
      //          int thisSign = Math.Sign(cf.amount());
      //          if (lastSign * thisSign < 0) // sign change
      //              signChanges++;

      //          if (thisSign != 0)
      //              lastSign = thisSign;
      //      }
      //      if (!(signChanges > 0))
      //          throw new ApplicationException("the given cash flows cannot result in the given market price due to their sign");

      //      /* The following is commented out due to the lack of a QL_WARN macro
      //      if (signChanges > 1) {    // Danger of non-unique solution
      //                                // Check the aggregate cash flows (Norstrom)
      //          Real aggregateCashFlow = marketPrice;
      //          signChanges = 0;
      //          for (Size i = 0; i < cashflows.size(); ++i) {
      //              Real nextAggregateCashFlow =
      //                  aggregateCashFlow + cashflows[i]->amount();

      //              if (aggregateCashFlow * nextAggregateCashFlow < 0.0)
      //                  signChanges++;

      //              aggregateCashFlow = nextAggregateCashFlow;
      //          }
      //          if (signChanges > 1)
      //              QL_WARN( "danger of non-unique solution");
      //      };
      //      */

      //      //Brent solver;
      //      NewtonSafe solver = new NewtonSafe();
      //      solver.setMaxEvaluations(maxIterations);
      //      return solver.solve(new IrrFinder(cashflows, marketPrice, dayCounter, compounding, frequency, settlementDate),
      //                          accuracy, guess, guess / 10.0);
      //  }

      //! Cash-flow duration.
      /*! The simple duration of a string of cash flows is defined as
                \f[
                D_{\mathrm{simple}} = \frac{\sum t_i c_i B(t_i)}{\sum c_i B(t_i)}
                \f]
                where \f$ c_i \f$ is the amount of the \f$ i \f$-th cash
                flow, \f$ t_i \f$ is its payment time, and \f$ B(t_i) \f$ is the corresponding discount according to the passed yield.

                The modified duration is defined as
                \f[
                D_{\mathrm{modified}} = -\frac{1}{P} \frac{\partial P}{\partial y}
                \f]
                where \f$ P \f$ is the present value of the cash flows according to the given IRR \f$ y \f$.

                The Macaulay duration is defined for a compounded IRR as
                \f[
                D_{\mathrm{Macaulay}} = \left( 1 + \frac{y}{N} \right)
                                        D_{\mathrm{modified}}
                \f]
                where \f$ y \f$ is the IRR and \f$ N \f$ is the number of cash flows per year.
            */
      public static double duration(List<CashFlow> cashflows, InterestRate rate, Duration.Type type = Duration.Type.Modified, 
                                    Date settlementDate = null) 
        {

           if (cashflows.Count == 0)
              return 0.0;

           if (settlementDate == null) settlementDate = Settings.evaluationDate();
           
           switch (type) 
           {
              case Duration.Type.Simple:
                 return simpleDuration(cashflows, rate, settlementDate);
                
              case Duration.Type.Modified:
                 return modifiedDuration(cashflows, rate, settlementDate);
                
              case Duration.Type.Macaulay:
                 return macaulayDuration(cashflows, rate, settlementDate);
                
              default:
                 throw new ArgumentException("unknown duration type");
           }
        }
      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;
        }
Пример #31
0
      //! Yield value of a basis point
      /*! The yield value of a one basis point change in price is
          the derivative of the yield with respect to the price
          multiplied by 0.01
      */
      public static double yieldValueBasisPoint(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 = CashFlows.npv(leg, yield, includeSettlementDateFlows, settlementDate, npvDate);
         double modifiedDuration = CashFlows.duration(leg, yield, Duration.Type.Modified, includeSettlementDateFlows,
                                                      settlementDate, npvDate);

         double shift = 0.01;
         return (1.0/(-npv*modifiedDuration))*shift;
      }
      //! Basis-point value
      /*! Obtained by setting dy = 0.0001 in the 2nd-order Taylor
            series expansion.
        */
      public static double basisPointValue(List<CashFlow> leg, InterestRate y, Date settlementDate) 
      {
         if (leg.Count == 0)
           return 0.0;


         double shift = 0.0001;
         double dirtyPrice = CashFlows.npv(leg, y, settlementDate);
         double modifiedDuration = CashFlows.duration(leg, y, Duration.Type.Modified, settlementDate);
         double convexity = CashFlows.convexity(leg, y, settlementDate);

         double delta = -modifiedDuration*dirtyPrice;

         double gamma = (convexity/100.0)*dirtyPrice;

         delta *= shift;
         gamma *= shift*shift;

         return delta + 0.5*gamma;
      }
Пример #33
0
      public static double macaulayDuration(Leg leg,InterestRate y, bool includeSettlementDateFlows,
                                            Date settlementDate, Date npvDate) 
      {
         Utils.QL_REQUIRE( y.compounding() == Compounding.Compounded, () => "compounded rate required" );

         return (1.0+y.rate()/(int)y.frequency()) *
               modifiedDuration(leg, y, includeSettlementDateFlows, settlementDate, npvDate);
      }
      //! Yield value of a basis point
      /*! The yield value of a one basis point change in price is
            the derivative of the yield with respect to the price
            multiplied by 0.01
        */
      public static double yieldValueBasisPoint(List<CashFlow> leg, InterestRate y, Date settlementDate) 
      {
         if (leg.Count == 0)
            return 0.0;

         double shift = 0.01;
         double dirtyPrice = CashFlows.npv(leg, y, settlementDate);
         double modifiedDuration = CashFlows.duration(leg, y, Duration.Type.Modified, settlementDate);
         
         return (1.0/(-dirtyPrice*modifiedDuration))*shift;
      }
Пример #35
0
 public override double derivative(double y) 
 {
    InterestRate yield = new InterestRate(y, dayCounter_, compounding_, frequency_);
        return modifiedDuration(leg_, yield,includeSettlementDateFlows_,settlementDate_, npvDate_);
 }
Пример #36
0
 protected override void performCalculations()
 {
     Date fixingDate = calendar_.advance(valueDate_, -settlementDays_, TimeUnit.Days);
     forwardRate_ = new InterestRate(index_.fixing(fixingDate), index_.dayCounter(),
                                     Compounding.Simple, Frequency.Once);
     underlyingSpotValue_ = spotValue();
     underlyingIncome_    = 0.0;
     base.performCalculations();
 }
Пример #37
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;
      }
Пример #38
0
        // Handle<YieldTermStructure> discountCurve = Handle<YieldTermStructure>());
        public ForwardRateAgreement(Date valueDate, Date maturityDate, Position.Type type, double strikeForwardRate,
                                  double notionalAmount, IborIndex index, Handle<YieldTermStructure> discountCurve)
            : base(index.dayCounter(), index.fixingCalendar(), index.businessDayConvention(), index.fixingDays(), new Payoff(),
                 valueDate, maturityDate, discountCurve)
        {
            fraType_ = type;
             notionalAmount_ = notionalAmount;
             index_ = index;

             if (notionalAmount <= 0.0)
            throw new ApplicationException("notional Amount must be positive");

             // do I adjust this ?
             // valueDate_ = calendar_.adjust(valueDate_,businessDayConvention_);
             Date fixingDate = calendar_.advance(valueDate_, -settlementDays_, TimeUnit.Days);
             forwardRate_ = new InterestRate(index.fixing(fixingDate), index.dayCounter(), Compounding.Simple, Frequency.Once);
             strikeForwardRate_ = new InterestRate(strikeForwardRate, index.dayCounter(), Compounding.Simple, Frequency.Once);
             double strike = notionalAmount_ * strikeForwardRate_.compoundFactor(valueDate_, maturityDate_);
             payoff_ = new ForwardTypePayoff(fraType_, strike);
             // incomeDiscountCurve_ is irrelevant to an FRA
             incomeDiscountCurve_ = discountCurve_;
             // income is irrelevant to FRA - set it to zero
             underlyingIncome_ = 0.0;

             index_.registerWith(update);
        }
Пример #39
0
      //! Cash-flow duration.
      /*! The simple duration of a string of cash flows is defined as
         \f[
         D_{\mathrm{simple}} = \frac{\sum t_i c_i B(t_i)}{\sum c_i B(t_i)}
         \f]
         where \f$ c_i \f$ is the amount of the \f$ i \f$-th cash
         flow, \f$ t_i \f$ is its payment time, and \f$ B(t_i) \f$ is the corresponding discount according to the passed yield.

         The modified duration is defined as
         \f[
         D_{\mathrm{modified}} = -\frac{1}{P} \frac{\partial P}{\partial y}
         \f]
         where \f$ P \f$ is the present value of the cash flows according to the given IRR \f$ y \f$.

         The Macaulay duration is defined for a compounded IRR as
         \f[
         D_{\mathrm{Macaulay}} = \left( 1 + \frac{y}{N} \right)
                                 D_{\mathrm{modified}}
         \f]
         where \f$ y \f$ is the IRR and \f$ N \f$ is the number of cash flows per year.
   
      */
      public static double duration(Leg leg, InterestRate rate, Duration.Type type, 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;

        switch (type) 
        {
            case Duration.Type.Simple:
               return simpleDuration(leg, rate, includeSettlementDateFlows, settlementDate, npvDate);
            case Duration.Type.Modified:
               return modifiedDuration(leg, rate, includeSettlementDateFlows, settlementDate, npvDate);
            case Duration.Type.Macaulay:
               return macaulayDuration(leg, rate, includeSettlementDateFlows, settlementDate, npvDate);
            default:
               Utils.QL_FAIL("unknown duration type");
               break;
         }
         return 0.0;
      }
Пример #40
0
            public override double derivative(double x)
            {
                InterestRate y = new InterestRate(x, dayCounter_, compounding_, frequency_);

                return(modifiedDuration(cashflows_, y, settlementDate_));
            }