Exemple #1
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));
        }
Exemple #2
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.Instance.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));
        }
Exemple #3
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_);
            Date         exCouponDate = null;
            InterestRate rate         = couponRates_[0];
            double       nominal      = notionals_[0];

            if (exCouponPeriod_ != null)
            {
                exCouponDate = exCouponCalendar_.advance(paymentDate,
                                                         -exCouponPeriod_,
                                                         exCouponAdjustment_,
                                                         exCouponEndOfMonth_);
            }
            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(paymentDate, nominal, rate, start, end, start, end, exCouponDate));
            }
            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(paymentDate, nominal, r, start, end, refer, end, exCouponDate));
            }

            // regular periods
            for (int i = 2; i < schedule_.Count - 1; ++i)
            {
                start       = end; end = schedule_[i];
                paymentDate = calendar_.adjust(end, paymentAdjustment_);
                if (exCouponPeriod_ != null)
                {
                    exCouponDate = exCouponCalendar_.advance(paymentDate,
                                                             -exCouponPeriod_,
                                                             exCouponAdjustment_,
                                                             exCouponEndOfMonth_);
                }
                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(paymentDate, nominal, rate, start, end, start, end, exCouponDate));
            }

            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 (exCouponPeriod_ != null)
                {
                    exCouponDate = exCouponCalendar_.advance(paymentDate,
                                                             -exCouponPeriod_,
                                                             exCouponAdjustment_,
                                                             exCouponEndOfMonth_);
                }

                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();
                }

                InterestRate r = new InterestRate(rate.rate(),
                                                  lastPeriodDC_ == null ? rate.dayCounter() : lastPeriodDC_, rate.compounding(), rate.frequency());
                if (schedule_.isRegular(N - 1))
                {
                    leg.Add(new FixedRateCoupon(paymentDate, nominal, r, start, end, start, end, exCouponDate));
                }
                else
                {
                    Date refer = start + schedule_.tenor();
                    refer = schCalendar.adjust(refer, schedule_.businessDayConvention());
                    leg.Add(new FixedRateCoupon(paymentDate, nominal, r, start, end, start, refer, exCouponDate));
                }
            }
            return(leg);
        }
Exemple #4
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.Instance.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
        }
Exemple #5
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.Instance.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);
        }