length() private method

private length ( ) : int
return int
Ejemplo n.º 1
0
        public AmortizingFixedRateBond(
            int settlementDays,
            Calendar calendar,
            double faceAmount,
            Date startDate,
            Period bondTenor,
            Frequency sinkingFrequency,
            double coupon,
            DayCounter accrualDayCounter,
            BusinessDayConvention paymentConvention = BusinessDayConvention.Following,
            Date issueDate = null)
            : base(settlementDays, calendar, issueDate)
        {
            frequency_  = sinkingFrequency;
            dayCounter_ = accrualDayCounter;

            Utils.QL_REQUIRE(bondTenor.length() > 0, () =>
                             "bond tenor must be positive. "
                             + bondTenor + " is not allowed.");

            maturityDate_ = startDate + bondTenor;
            schedule_     = sinkingSchedule(startDate, bondTenor, sinkingFrequency, calendar);
            cashflows_    = new FixedRateLeg(schedule_)
                            .withCouponRates(coupon, accrualDayCounter)
                            .withNotionals(sinkingNotionals(bondTenor, sinkingFrequency, coupon, faceAmount))
                            .withPaymentAdjustment(paymentConvention).value();

            addRedemptionsToCashflows();
        }
Ejemplo n.º 2
0
        //! implements the conversion between swap tenor and swap (time) length
        public double swapLength(Period swapTenor)
        {
            Utils.QL_REQUIRE(swapTenor.length() > 0, () => "non-positive swap tenor (" + swapTenor + ") given");
            switch (swapTenor.units())
            {
            case TimeUnit.Months:
                return(swapTenor.length() / 12.0);

            case TimeUnit.Years:
                return(swapTenor.length());

            default:
                Utils.QL_FAIL("invalid Time Unit (" + swapTenor.units() + ") for swap length");
                return(0);
            }
        }
Ejemplo n.º 3
0
      //! The factor returned is NOT normalized relative to ANYTHING.
      public virtual double seasonalityFactor(Date to)
      {
         Date from = seasonalityBaseDate();
         Frequency factorFrequency = frequency();
         int nFactors = seasonalityFactors().Count;
         Period factorPeriod = new Period(factorFrequency);
         int which = 0;
         if (from==to) 
         {
            which = 0;
         } 
         else 
         {
            // days, weeks, months, years are the only time unit possibilities
            int diffDays = Math.Abs(to - from);  // in days
            int dir = 1;
            if(from > to)dir = -1;
            int diff;
            if (factorPeriod.units() == TimeUnit.Days)
            {
                diff = dir*diffDays;
            }
            else if (factorPeriod.units() == TimeUnit.Weeks)
            {
                diff = dir * (diffDays / 7);
            }
            else if (factorPeriod.units() == TimeUnit.Months)
            {
                KeyValuePair<Date,Date> lim = Utils.inflationPeriod(to, factorFrequency);
                diff = diffDays / (31*factorPeriod.length());
                Date go = from + dir*diff*factorPeriod;
                while ( !(lim.Key <= go && go <= lim.Value) ) 
                {
                    go += dir*factorPeriod;
                    diff++;
                }
                diff=dir*diff;
            }
            else if (factorPeriod.units() == TimeUnit.Years) 
            {
                throw new ApplicationException(
                   "seasonality period time unit is not allowed to be : " + factorPeriod.units());
            } 
            else 
            {
                throw new ApplicationException("Unknown time unit: " + factorPeriod.units());
            }
            // now adjust to the available number of factors, direction dependent

            if (dir==1) 
            {
                which = diff % nFactors;
            } 
            else 
            {
                which = (nFactors - (-diff % nFactors)) % nFactors;
            }
        }
        return seasonalityFactors()[which];
      }
Ejemplo n.º 4
0
      public AmortizingFixedRateBond(
                          int settlementDays,
                          Calendar calendar,
                          double faceAmount,
                          Date startDate,
                          Period bondTenor,
                          Frequency sinkingFrequency,
                          double coupon,
                          DayCounter accrualDayCounter,
                          BusinessDayConvention paymentConvention = BusinessDayConvention.Following,
                          Date issueDate = null)
         :base(settlementDays, calendar, issueDate)
      {
         frequency_ = sinkingFrequency;
         dayCounter_ = accrualDayCounter;

         Utils.QL_REQUIRE( bondTenor.length() > 0,() =>
                  "bond tenor must be positive. "
                  + bondTenor + " is not allowed." );

         maturityDate_ = startDate + bondTenor;
         maturityDate_ = startDate + bondTenor;
         schedule_ = sinkingSchedule(startDate, bondTenor, sinkingFrequency, calendar);
         cashflows_ = new FixedRateLeg(schedule_)
                        .withCouponRates(coupon, accrualDayCounter)
                        .withNotionals(sinkingNotionals(bondTenor, sinkingFrequency, coupon, faceAmount))        
                        .withPaymentAdjustment(paymentConvention).value();

         addRedemptionsToCashflows();

      }
        protected void checkSwapTenor(Period swapTenor, bool extrapolate)
        {
            if (!(swapTenor.length() > 0))
            {
                throw new ApplicationException("non-positive swap tenor (" + swapTenor + ") given");
            }

            if (!(extrapolate || allowsExtrapolation() || swapTenor <= maxSwapTenor()))
            {
                throw new ApplicationException("swap tenor (" + swapTenor + ") is past max tenor (" + maxSwapTenor() + ")");
            }
        }
        //@}
        //! implements the conversion between swap tenor and swap (time) length
        public double swapLength(Period p)
        {
            if (!(p.length() > 0))
            {
                throw new ApplicationException("non-positive swap tenor (" + p + ") given");
            }

            //         while using the reference date is arbitrary it is coherent between
            //           different swaption structures defined on the same reference date.
            //
            Date start = referenceDate();
            Date end   = start + p;

            return(swapLength(start, end));
        }
 protected void checkRange(Date optionDate, Period bondTenor, double k, bool extrapolate)
 {
     base.checkRange(timeFromReference(optionDate),
                     extrapolate);
     Utils.QL_REQUIRE(bondTenor.length() > 0, () =>
                      "negative bond tenor (" + bondTenor + ") given");
     Utils.QL_REQUIRE(extrapolate || allowsExtrapolation() ||
                      bondTenor <= maxBondTenor(), () =>
                      "bond tenor (" + bondTenor + ") is past max tenor ("
                      + maxBondTenor() + ")");
     Utils.QL_REQUIRE(extrapolate || allowsExtrapolation() ||
                      (k >= minStrike() && k <= maxStrike()), () =>
                      "strike (" + k + ") is outside the curve domain ["
                      + minStrike() + "," + maxStrike() + "]");
 }
        KeyValuePair <int, int> daysMinMax(Period p)
        {
            switch (p.units())
            {
            case TimeUnit.Days:
                return(new KeyValuePair <int, int>(p.length(), p.length()));

            case TimeUnit.Weeks:
                return(new KeyValuePair <int, int>(7 * p.length(), 7 * p.length()));

            case TimeUnit.Months:
                return(new KeyValuePair <int, int>(28 * p.length(), 31 * p.length()));

            case TimeUnit.Years:
                return(new KeyValuePair <int, int>(365 * p.length(), 366 * p.length()));

            default:
                throw new ApplicationException("unknown time unit (" + p.units() + ")");
            }
        }
Ejemplo n.º 9
0
Archivo: Period.cs Proyecto: qed-/qlnet
            public pair(Period p)
            {
                switch (p.units())
                {
                case TimeUnit.Days:
                    lo = hi = p.length(); break;

                case TimeUnit.Weeks:
                    lo = hi = 7 * p.length(); break;

                case TimeUnit.Months:
                    lo = 28 * p.length(); hi = 31 * p.length(); break;

                case TimeUnit.Years:
                    lo = 365 * p.length(); hi = 366 * p.length(); break;

                default:
                    throw new ArgumentException("Unknown TimeUnit: " + p.units());
                }
            }
Ejemplo n.º 10
0
            public pair(Period p)
            {
                switch (p.units())
                {
                case TimeUnit.Days:
                    lo = hi = p.length(); break;

                case TimeUnit.Weeks:
                    lo = hi = 7 * p.length(); break;

                case TimeUnit.Months:
                    lo = 28 * p.length(); hi = 31 * p.length(); break;

                case TimeUnit.Years:
                    lo = 365 * p.length(); hi = 366 * p.length(); break;

                default:
                    Utils.QL_FAIL("Unknown TimeUnit: " + p.units());
                    lo = hi = 0;
                    break;
                }
            }
Ejemplo n.º 11
0
        public OvernightIndexedSwap value()
        {
            Date startDate;

            if (effectiveDate_ != null)
            {
                startDate = effectiveDate_;
            }
            else
            {
                Date refDate = Settings.evaluationDate();
                // if the evaluation date is not a business day
                // then move to the next business day
                refDate = calendar_.adjust(refDate);
                Date spotDate = calendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days));
                startDate = spotDate + forwardStart_;
                if (forwardStart_.length() < 0)
                {
                    startDate = calendar_.adjust(startDate, BusinessDayConvention.Preceding);
                }
                else
                {
                    startDate = calendar_.adjust(startDate, BusinessDayConvention.Following);
                }
            }

            // OIS end of month default
            bool usedEndOfMonth =
                isDefaultEOM_ ? calendar_.isEndOfMonth(startDate) : endOfMonth_;

            Date endDate = terminationDate_;

            if (endDate == null)
            {
                if (usedEndOfMonth)
                {
                    endDate = calendar_.advance(startDate,
                                                swapTenor_,
                                                BusinessDayConvention.ModifiedFollowing,
                                                usedEndOfMonth);
                }
                else
                {
                    endDate = startDate + swapTenor_;
                }
            }



            Schedule schedule = new Schedule(startDate, endDate,
                                             new Period(paymentFrequency_),
                                             calendar_,
                                             BusinessDayConvention.ModifiedFollowing,
                                             BusinessDayConvention.ModifiedFollowing,
                                             rule_,
                                             usedEndOfMonth);

            double?usedFixedRate = fixedRate_;

            if (fixedRate_ == null)
            {
                OvernightIndexedSwap temp = new OvernightIndexedSwap(type_, nominal_,
                                                                     schedule,
                                                                     0.0, // fixed rate
                                                                     fixedDayCount_,
                                                                     overnightIndex_, overnightSpread_);
                if (engine_ == null)
                {
                    Handle <YieldTermStructure> disc = overnightIndex_.forwardingTermStructure();
                    Utils.QL_REQUIRE(!disc.empty(), () => "null term structure set to this instance of " +
                                     overnightIndex_.name());
                    bool           includeSettlementDateFlows = false;
                    IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                    temp.setPricingEngine(engine);
                }
                else
                {
                    temp.setPricingEngine(engine_);
                }

                usedFixedRate = temp.fairRate();
            }

            OvernightIndexedSwap ois = new OvernightIndexedSwap(type_, nominal_,
                                                                schedule,
                                                                usedFixedRate.Value, fixedDayCount_,
                                                                overnightIndex_, overnightSpread_);

            if (engine_ == null)
            {
                Handle <YieldTermStructure> disc          = overnightIndex_.forwardingTermStructure();
                bool           includeSettlementDateFlows = false;
                IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                ois.setPricingEngine(engine);
            }
            else
            {
                ois.setPricingEngine(engine_);
            }

            return(ois);
        }
Ejemplo n.º 12
0
        //! set up the interpolations for capPrice_ and floorPrice_
        //! since we know ATM, and we have single flows,
        //! we can use put/call parity to extend the surfaces
        //! across all strikes
        protected override void performCalculations()
        {
            allStrikes_ = new List <double>();
            int nMat  = cfMaturities_.Count,
                ncK   = cStrikes_.Count,
                nfK   = fStrikes_.Count,
                nK    = ncK + nfK;
            Matrix cP = new Matrix(nK, nMat),
                   fP = new Matrix(nK, nMat);
            Handle <ZeroInflationTermStructure> zts = zii_.link.zeroInflationTermStructure();
            Handle <YieldTermStructure>         yts = this.nominalTermStructure();

            Utils.QL_REQUIRE(!zts.empty(), () => "Zts is empty!!!");
            Utils.QL_REQUIRE(!yts.empty(), () => "Yts is empty!!!");

            for (int i = 0; i < nfK; i++)
            {
                allStrikes_.Add(fStrikes_[i]);
                for (int j = 0; j < nMat; j++)
                {
                    Period mat       = cfMaturities_[j];
                    double df        = yts.link.discount(cpiOptionDateFromTenor(mat));
                    double atm_quote = zts.link.zeroRate(cpiOptionDateFromTenor(mat));
                    double atm       = Math.Pow(1.0 + atm_quote, mat.length());
                    double S         = atm * df;
                    double K_quote   = fStrikes_[i] / 100.0;
                    double K         = Math.Pow(1.0 + K_quote, mat.length());
                    cP[i, j] = fPrice_[i, j] + S - K * df;
                    fP[i, j] = fPrice_[i, j];
                }
            }
            for (int i = 0; i < ncK; i++)
            {
                allStrikes_.Add(cStrikes_[i]);
                for (int j = 0; j < nMat; j++)
                {
                    Period mat       = cfMaturities_[j];
                    double df        = yts.link.discount(cpiOptionDateFromTenor(mat));
                    double atm_quote = zts.link.zeroRate(cpiOptionDateFromTenor(mat));
                    double atm       = Math.Pow(1.0 + atm_quote, mat.length());
                    double S         = atm * df;
                    double K_quote   = cStrikes_[i] / 100.0;
                    double K         = Math.Pow(1.0 + K_quote, mat.length());
                    cP[i + nfK, j] = cPrice_[i, j];
                    fP[i + nfK, j] = cPrice_[i, j] + K * df - S;
                }
            }

            // copy to store
            cPriceB_ = cP;
            fPriceB_ = fP;

            cfMaturityTimes_ = new List <double>();
            for (int i = 0; i < cfMaturities_.Count; i++)
            {
                cfMaturityTimes_.Add(timeFromReference(cpiOptionDateFromTenor(cfMaturities_[i])));
            }

            capPrice_ = interpolator2d_.interpolate(cfMaturityTimes_, cfMaturityTimes_.Count,
                                                    allStrikes_, allStrikes_.Count, cPriceB_);

            capPrice_.enableExtrapolation();

            floorPrice_ = interpolator2d_.interpolate(cfMaturityTimes_, cfMaturityTimes_.Count,
                                                      allStrikes_, allStrikes_.Count, fPriceB_);

            floorPrice_.enableExtrapolation();
        }
Ejemplo n.º 13
0
 protected void checkSwapTenor(Period swapTenor, bool extrapolate)
 {
     Utils.QL_REQUIRE(swapTenor.length() > 0, () => "non-positive swap tenor (" + swapTenor + ") given");
     Utils.QL_REQUIRE(extrapolate || allowsExtrapolation() || swapTenor <= maxSwapTenor(), () =>
                      "swap tenor (" + swapTenor + ") is past max tenor (" + maxSwapTenor() + ")");
 }
Ejemplo n.º 14
0
 KeyValuePair<int, int> daysMinMax(Period p) 
 {
       switch (p.units()) {
         case TimeUnit.Days:
           return new KeyValuePair<int, int>(p.length(), p.length());
         case TimeUnit.Weeks:
           return new KeyValuePair<int, int>(7*p.length(), 7*p.length());
         case TimeUnit.Months:
           return new KeyValuePair<int, int>(28*p.length(), 31*p.length());
         case TimeUnit.Years:
           return new KeyValuePair<int, int>(365 * p.length(), 366 * p.length());
         default:
           throw new ApplicationException("unknown time unit (" + p.units() + ")");
       }
   }
Ejemplo n.º 15
0
 protected void checkSwapTenor(Period swapTenor, bool extrapolate)
 {
     Utils.QL_REQUIRE(swapTenor.length() > 0, "non-positive swap tenor ("  + swapTenor + ") given");
      Utils.QL_REQUIRE(extrapolate || allowsExtrapolation() || swapTenor <= maxSwapTenor(),
             "swap tenor (" + swapTenor + ") is past max tenor (" + maxSwapTenor() + ")");
 }
Ejemplo n.º 16
0
        public Schedule(Date effectiveDate__, Date terminationDate__, Period tenor__, Calendar calendar__,
                        BusinessDayConvention convention__, BusinessDayConvention terminationDateConvention__,
                        DateGeneration.Rule rule__, bool endOfMonth__,
                        Date firstDate__, Date nextToLastDate__)
        {
            // first save the properties
            fullInterface_             = true;
            tenor_                     = tenor__;
            calendar_                  = calendar__;
            convention_                = convention__;
            terminationDateConvention_ = terminationDateConvention__;
            rule_           = rule__;
            endOfMonth_     = endOfMonth__;
            firstDate_      = firstDate__;
            nextToLastDate_ = nextToLastDate__;

            // sanity checks
            if (effectiveDate__ == null)
            {
                throw new ArgumentException("Null effective date");
            }
            if (terminationDate__ == null)
            {
                throw new ArgumentException("Null termination  date");
            }
            if (effectiveDate__ >= terminationDate__)
            {
                throw new ArgumentException("Effective date (" + effectiveDate__ +
                                            ") is later than or equal to termination date (" + terminationDate__ + ")");
            }

            if (tenor_.length() == 0)
            {
                rule_ = DateGeneration.Rule.Zero;
            }
            else if (tenor_.length() < 0)
            {
                throw new ArgumentException("Non positive tenor (" + tenor_ + ") is not allowed");
            }

            if (firstDate_ != null)
            {
                switch (rule_)
                {
                case DateGeneration.Rule.Backward:
                case DateGeneration.Rule.Forward:
                    if (!(firstDate_ > effectiveDate__ && firstDate_ < terminationDate__))
                    {
                        throw new ArgumentException("First date (" + firstDate_ + ") is out of range [effective date (" + effectiveDate__
                                                    + "), termination date (" + terminationDate__ + ")]");
                    }
                    // we should ensure that the above condition is still verified after adjustment
                    break;

                case DateGeneration.Rule.ThirdWednesday:
                    if (!IMM.isIMMdate(firstDate_, false))
                    {
                        throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date");
                    }
                    break;

                case DateGeneration.Rule.Zero:
                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                    throw new ArgumentException("First date is incompatible with " + rule_ + " date generation rule");

                default:
                    throw new ArgumentException("Unknown DateGeneration rule: " + rule_);
                }
            }

            if (nextToLastDate_ != null)
            {
                switch (rule_)
                {
                case DateGeneration.Rule.Backward:
                case DateGeneration.Rule.Forward:
                    if (!(nextToLastDate_ > effectiveDate__ && nextToLastDate_ < terminationDate__))
                    {
                        throw new ArgumentException("Next to last date (" + nextToLastDate_ + ") out of range [effective date (" + effectiveDate__
                                                    + "), termination date (" + terminationDate__ + ")]");
                    }
                    // we should ensure that the above condition is still verified after adjustment
                    break;

                case DateGeneration.Rule.ThirdWednesday:
                    if (!IMM.isIMMdate(firstDate_, false))
                    {
                        throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date");
                    }
                    break;

                case DateGeneration.Rule.Zero:
                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                    throw new ArgumentException("next to last is incompatible with " + rule_ + " date generation rule");

                default:
                    throw new ArgumentException("Unknown DateGeneration rule: " + rule_);
                }
            }

            // calendar needed for endOfMonth adjustment
            Calendar nullCalendar = new NullCalendar();
            int      periods = 1;
            Date     seed = new Date(), exitDate;

            switch (rule_)
            {
            case DateGeneration.Rule.Zero:
                tenor_ = new Period(0, TimeUnit.Years);
                originalDates_.Add(effectiveDate__);
                originalDates_.Add(terminationDate__);
                isRegular_.Add(true);
                break;

            case DateGeneration.Rule.Backward:
                originalDates_.Add(terminationDate__);
                seed = terminationDate__;
                if (nextToLastDate_ != null)
                {
                    originalDates_.Insert(0, nextToLastDate_);
                    Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                    isRegular_.Insert(0, temp == nextToLastDate_);
                    seed = nextToLastDate_;
                }
                exitDate = effectiveDate__;
                if (firstDate_ != null)
                {
                    exitDate = firstDate_;
                }
                while (true)
                {
                    Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                    if (temp < exitDate)
                    {
                        if (firstDate_ != null && (calendar_.adjust(originalDates_.First(), convention_) !=
                                                   calendar_.adjust(firstDate_, convention_)))
                        {
                            originalDates_.Insert(0, firstDate_);
                            isRegular_.Insert(0, false);
                        }
                        break;
                    }
                    else
                    {
                        originalDates_.Insert(0, temp);
                        isRegular_.Insert(0, true);
                        ++periods;
                    }
                }
                if (endOfMonth_ && calendar_.isEndOfMonth(seed))
                {
                    convention_ = BusinessDayConvention.Preceding;
                }
                if (calendar_.adjust(originalDates_[0], convention_) != calendar_.adjust(effectiveDate__, convention_))
                {
                    originalDates_.Insert(0, effectiveDate__);
                    isRegular_.Insert(0, false);
                }
                break;

            case DateGeneration.Rule.Twentieth:
            case DateGeneration.Rule.TwentiethIMM:
            case DateGeneration.Rule.ThirdWednesday:
            case DateGeneration.Rule.OldCDS:
            case DateGeneration.Rule.CDS:
                if (endOfMonth_)
                {
                    throw new ArgumentException("endOfMonth convention is incompatible with " + rule_ + " date generation rule");
                }
                goto case DateGeneration.Rule.Forward;                          // fall through

            case DateGeneration.Rule.Forward:
                if (rule_ == DateGeneration.Rule.CDS)
                {
                    originalDates_.Add(previousTwentieth(effectiveDate__, DateGeneration.Rule.CDS));
                }
                else
                {
                    originalDates_.Add(effectiveDate__);
                }

                seed = effectiveDate__;
                if (firstDate_ != null)
                {
                    originalDates_.Add(firstDate_);
                    Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                    isRegular_.Add(temp == firstDate_);
                    seed = firstDate_;
                }
                else if (rule_ == DateGeneration.Rule.Twentieth ||
                         rule_ == DateGeneration.Rule.TwentiethIMM ||
                         rule_ == DateGeneration.Rule.OldCDS ||
                         rule_ == DateGeneration.Rule.CDS)
                {
                    Date next20th = nextTwentieth(effectiveDate__, rule_);
                    if (rule_ == DateGeneration.Rule.OldCDS)
                    {
                        // distance rule inforced in natural days
                        long stubDays = 30;
                        if (next20th - effectiveDate__ < stubDays)
                        {
                            // +1 will skip this one and get the next
                            next20th = nextTwentieth(next20th + 1, rule_);
                        }
                    }
                    if (next20th != effectiveDate__)
                    {
                        originalDates_.Add(next20th);
                        isRegular_.Add(false);
                        seed = next20th;
                    }
                }

                exitDate = terminationDate__;
                if (nextToLastDate_ != null)
                {
                    exitDate = nextToLastDate_;
                }
                while (true)
                {
                    Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                    if (temp > exitDate)
                    {
                        if (nextToLastDate_ != null &&
                            (calendar_.adjust(originalDates_.Last(), convention_) !=
                             calendar_.adjust(nextToLastDate_, convention_)))
                        {
                            originalDates_.Add(nextToLastDate_);
                            isRegular_.Add(false);
                        }
                        break;
                    }
                    else
                    {
                        originalDates_.Add(temp);
                        isRegular_.Add(true);
                        ++periods;
                    }
                }
                if (endOfMonth_ && calendar_.isEndOfMonth(seed))
                {
                    convention_ = BusinessDayConvention.Preceding;
                }

                if (calendar_.adjust(originalDates_.Last(), terminationDateConvention_) != calendar_.adjust(terminationDate__, terminationDateConvention_))
                {
                    if (rule_ == DateGeneration.Rule.Twentieth ||
                        rule_ == DateGeneration.Rule.TwentiethIMM ||
                        rule_ == DateGeneration.Rule.OldCDS ||
                        rule_ == DateGeneration.Rule.CDS)
                    {
                        originalDates_.Add(nextTwentieth(terminationDate__, rule_));
                        isRegular_.Add(true);
                    }
                    else
                    {
                        originalDates_.Add(terminationDate__);
                        isRegular_.Add(false);
                    }
                }
                break;

            default:
                throw new ArgumentException("Unknown DateGeneration rule: " + rule_);
            }

            // adjustments to holidays, etc.
            if (rule_ == DateGeneration.Rule.ThirdWednesday)
            {
                for (int i = 1; i < originalDates_.Count; ++i)
                {
                    originalDates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, originalDates_[i].Month, originalDates_[i].Year);
                }
            }

            if (endOfMonth && calendar_.isEndOfMonth(seed))
            {
                // adjust to end of month
                if (convention_ == BusinessDayConvention.Unadjusted)
                {
                    for (int i = 0; i < originalDates_.Count; ++i)
                    {
                        originalDates_[i] = Date.endOfMonth(originalDates_[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < originalDates_.Count; ++i)
                    {
                        originalDates_[i] = calendar_.endOfMonth(originalDates_[i]);
                    }
                }
                if (terminationDateConvention_ == BusinessDayConvention.Unadjusted)
                {
                    originalDates_[originalDates_.Count - 1] = Date.endOfMonth(originalDates_.Last());
                }
                else
                {
                    originalDates_[originalDates_.Count - 1] = calendar_.endOfMonth(originalDates_.Last());
                }
            }
            else
            {
                // first date not adjusted for CDS schedules
                if (rule_ != DateGeneration.Rule.OldCDS)
                {
                    originalDates_[0] = calendar_.adjust(originalDates_[0], convention_);
                }
                for (int i = 1; i < originalDates_.Count; ++i)
                {
                    originalDates_[i] = calendar_.adjust(originalDates_[i], convention_);
                }

                foreach (Date d in originalDates_)
                {
                    adjustedDates_.Add(d);
                }

                // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the
                // confirmation of the deal or unless we're creating a CDS schedule
                if (terminationDateConvention_ != BusinessDayConvention.Unadjusted ||
                    rule_ == DateGeneration.Rule.Twentieth ||
                    rule_ == DateGeneration.Rule.TwentiethIMM ||
                    rule_ == DateGeneration.Rule.OldCDS ||
                    rule_ == DateGeneration.Rule.CDS)
                {
                    adjustedDates_[adjustedDates_.Count - 1] = calendar_.adjust(originalDates_.Last(), terminationDateConvention_);
                }
            }
        }
Ejemplo n.º 17
0
        public override void initialize(FloatingRateCoupon coupon)
        {
            coupon_ = coupon as CmsCoupon;
            Utils.QL_REQUIRE( coupon_ != null, () => "CMS coupon needed" );
            gearing_ = coupon_.gearing();
            spread_ = coupon_.spread();

            fixingDate_ = coupon_.fixingDate();
            paymentDate_ = coupon_.date();
            SwapIndex swapIndex = coupon_.swapIndex();
            rateCurve_ = swapIndex.forwardingTermStructure().link;

            Date today = Settings.evaluationDate();

            if (paymentDate_ > today)
                discount_ = rateCurve_.discount(paymentDate_);
            else
                discount_ = 1.0;

            spreadLegValue_ = spread_ * coupon_.accrualPeriod() * discount_;

            if (fixingDate_ > today) {
                swapTenor_ = swapIndex.tenor();
                VanillaSwap swap = swapIndex.underlyingSwap(fixingDate_);

                swapRateValue_ = swap.fairRate();

                double bp = 1.0e-4;
                annuity_ = (swap.floatingLegBPS() / bp);

                int q = (int)swapIndex.fixedLegTenor().frequency();
                Schedule schedule = swap.fixedSchedule();
                DayCounter dc = swapIndex.dayCounter();
                //DayCounter dc = coupon.dayCounter();
                double startTime = dc.yearFraction(rateCurve_.referenceDate(), swap.startDate());
                double swapFirstPaymentTime = dc.yearFraction(rateCurve_.referenceDate(), schedule.date(1));
                double paymentTime = dc.yearFraction(rateCurve_.referenceDate(), paymentDate_);
                double delta = (paymentTime - startTime) / (swapFirstPaymentTime - startTime);

                switch (modelOfYieldCurve_) {
                    case GFunctionFactory.YieldCurveModel.Standard:
                        gFunction_ = GFunctionFactory.newGFunctionStandard(q, delta, swapTenor_.length());
                        break;
                    case GFunctionFactory.YieldCurveModel.ExactYield:
                        gFunction_ = GFunctionFactory.newGFunctionExactYield(coupon_);
                        break;
                    case GFunctionFactory.YieldCurveModel.ParallelShifts: {
                            Handle<Quote> nullMeanReversionQuote = new Handle<Quote>(new SimpleQuote(0.0));
                            gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, nullMeanReversionQuote);
                        }
                        break;
                    case GFunctionFactory.YieldCurveModel.NonParallelShifts:
                        gFunction_ = GFunctionFactory.newGFunctionWithShifts(coupon_, meanReversion_);
                        break;
                    default:
                        throw new ApplicationException("unknown/illegal gFunction type");
                }
                vanillaOptionPricer_ = new BlackVanillaOptionPricer(swapRateValue_, fixingDate_, swapTenor_, swaptionVolatility().link);
            }
        }
Ejemplo n.º 18
0
 /// <summary>
 /// Advances the given date as specified by the given period and
 /// returns the result.
 /// </summary>
 /// <remarks>The input date is not modified.</remarks>
 public Date advance(Date d, Period p, BusinessDayConvention c = BusinessDayConvention.Following, bool endOfMonth = false)
 {
     return(advance(d, p.length(), p.units(), c, endOfMonth));
 }
 public Date advance(Date d, Period p, BusinessDayConvention c, bool endOfMonth)
 {
     return advance(d, p.length(), p.units(), c, endOfMonth);
 }
      //! The factor returned is NOT normalized relative to ANYTHING.
      public virtual double seasonalityFactor(Date to)
      {
         Date from = seasonalityBaseDate();
         Frequency factorFrequency = frequency();
         int nFactors = seasonalityFactors().Count;
         Period factorPeriod = new Period(factorFrequency);
         int which = 0;
         if (from==to) 
         {
            which = 0;
         } 
         else 
         {
            // days, weeks, months, years are the only time unit possibilities
            int diffDays = Math.Abs(to - from);  // in days
            int dir = 1;
            if(from > to)dir = -1;
            int diff;
            if (factorPeriod.units() == TimeUnit.Days)
            {
                diff = dir*diffDays;
            }
            else if (factorPeriod.units() == TimeUnit.Weeks)
            {
                diff = dir * (diffDays / 7);
            }
            else if (factorPeriod.units() == TimeUnit.Months)
            {
                KeyValuePair<Date,Date> lim = Utils.inflationPeriod(to, factorFrequency);
                diff = diffDays / (31*factorPeriod.length());
                Date go = from + dir*diff*factorPeriod;
                while ( !(lim.Key <= go && go <= lim.Value) ) 
                {
                    go += dir*factorPeriod;
                    diff++;
                }
                diff=dir*diff;
            }
            else if (factorPeriod.units() == TimeUnit.Years) 
            {
                throw new ApplicationException(
                   "seasonality period time unit is not allowed to be : " + factorPeriod.units());
            } 
            else 
            {
                throw new ApplicationException("Unknown time unit: " + factorPeriod.units());
            }
            // now adjust to the available number of factors, direction dependent

            if (dir==1) 
            {
                which = diff % nFactors;
            } 
            else 
            {
                which = (nFactors - (-diff % nFactors)) % nFactors;
            }
        }
        return seasonalityFactors()[which];
      }
Ejemplo n.º 21
0
        public VanillaSwap value()
        {
            Date startDate;

            if (effectiveDate_ != null)
            {
                startDate = effectiveDate_;
            }
            else
            {
                //int fixingDays = iborIndex_.fixingDays();
                Date refDate = Settings.evaluationDate();
                // if the evaluation date is not a business day
                // then move to the next business day
                refDate = floatCalendar_.adjust(refDate);
                Date spotDate = floatCalendar_.advance(refDate, new Period(settlementDays_, TimeUnit.Days));
                startDate = spotDate + forwardStart_;
                if (forwardStart_.length() < 0)
                {
                    startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Preceding);
                }
                else
                {
                    startDate = floatCalendar_.adjust(startDate, BusinessDayConvention.Following);
                }
            }

            Date endDate = terminationDate_;

            if (endDate == null)
            {
                if (floatEndOfMonth_)
                {
                    endDate = floatCalendar_.advance(startDate,
                                                     swapTenor_,
                                                     BusinessDayConvention.ModifiedFollowing,
                                                     floatEndOfMonth_);
                }
                else
                {
                    endDate = startDate + swapTenor_;
                }
            }

            Currency curr       = iborIndex_.currency();
            Period   fixedTenor = null;

            if (fixedTenor_ != null)
            {
                fixedTenor = fixedTenor_;
            }
            else
            {
                if ((curr == new EURCurrency()) ||
                    (curr == new USDCurrency()) ||
                    (curr == new CHFCurrency()) ||
                    (curr == new SEKCurrency()) ||
                    (curr == new GBPCurrency() && swapTenor_ <= new Period(1, TimeUnit.Years)))
                {
                    fixedTenor = new Period(1, TimeUnit.Years);
                }
                else if ((curr == new GBPCurrency() && swapTenor_ > new Period(1, TimeUnit.Years) ||
                          (curr == new JPYCurrency()) ||
                          (curr == new AUDCurrency() && swapTenor_ >= new Period(4, TimeUnit.Years))))
                {
                    fixedTenor = new Period(6, TimeUnit.Months);
                }
                else if ((curr == new HKDCurrency() ||
                          (curr == new AUDCurrency() && swapTenor_ < new Period(4, TimeUnit.Years))))
                {
                    fixedTenor = new Period(3, TimeUnit.Months);
                }
                else
                {
                    Utils.QL_FAIL("unknown fixed leg default tenor for " + curr);
                }
            }

            Schedule fixedSchedule = new Schedule(startDate, endDate,
                                                  fixedTenor, fixedCalendar_,
                                                  fixedConvention_, fixedTerminationDateConvention_,
                                                  fixedRule_, fixedEndOfMonth_,
                                                  fixedFirstDate_, fixedNextToLastDate_);

            Schedule floatSchedule = new Schedule(startDate, endDate,
                                                  floatTenor_, floatCalendar_,
                                                  floatConvention_, floatTerminationDateConvention_,
                                                  floatRule_, floatEndOfMonth_,
                                                  floatFirstDate_, floatNextToLastDate_);

            DayCounter fixedDayCount = null;

            if (fixedDayCount_ != null)
            {
                fixedDayCount = fixedDayCount_;
            }
            else
            {
                if (curr == new USDCurrency())
                {
                    fixedDayCount = new Actual360();
                }
                else if (curr == new EURCurrency() || curr == new CHFCurrency() || curr == new SEKCurrency())
                {
                    fixedDayCount = new Thirty360(Thirty360.Thirty360Convention.BondBasis);
                }
                else if (curr == new GBPCurrency() || curr == new JPYCurrency() || curr == new AUDCurrency() ||
                         curr == new HKDCurrency())
                {
                    fixedDayCount = new Actual365Fixed();
                }
                else
                {
                    Utils.QL_FAIL("unknown fixed leg day counter for " + curr);
                }
            }

            double?usedFixedRate = fixedRate_;

            if (fixedRate_ == null)
            {
                VanillaSwap temp = new VanillaSwap(type_, nominal_, fixedSchedule, 0.0, fixedDayCount,
                                                   floatSchedule, iborIndex_, floatSpread_, floatDayCount_);

                if (engine_ == null)
                {
                    Handle <YieldTermStructure> disc = iborIndex_.forwardingTermStructure();
                    Utils.QL_REQUIRE(!disc.empty(), () =>
                                     "null term structure set to this instance of " + iborIndex_.name());
                    bool           includeSettlementDateFlows = false;
                    IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                    temp.setPricingEngine(engine);
                }
                else
                {
                    temp.setPricingEngine(engine_);
                }

                usedFixedRate = temp.fairRate();
            }

            VanillaSwap swap = new VanillaSwap(type_, nominal_, fixedSchedule, usedFixedRate.Value, fixedDayCount,
                                               floatSchedule, iborIndex_, floatSpread_, floatDayCount_);

            if (engine_ == null)
            {
                Handle <YieldTermStructure> disc          = iborIndex_.forwardingTermStructure();
                bool           includeSettlementDateFlows = false;
                IPricingEngine engine = new DiscountingSwapEngine(disc, includeSettlementDateFlows);
                swap.setPricingEngine(engine);
            }
            else
            {
                swap.setPricingEngine(engine_);
            }

            return(swap);
        }
Ejemplo n.º 22
0
        /// <summary>
        /// rule based constructor
        /// </summary>
        /// <param name="effectiveDate"></param>
        /// <param name="terminationDate"></param>
        /// <param name="tenor"></param>
        /// <param name="calendar"></param>
        /// <param name="convention"></param>
        /// <param name="terminationDateConvention"></param>
        /// <param name="rule"></param>
        /// <param name="endOfMonth"></param>
        /// <param name="firstDate"></param>
        /// <param name="nextToLastDate"></param>
        public Schedule(Date effectiveDate,
                        Date terminationDate,
                        Period tenor,
                        Calendar calendar,
                        BusinessDayConvention convention,
                        BusinessDayConvention terminationDateConvention,
                        DateGeneration.Rule rule,
                        bool endOfMonth,
                        Date firstDate      = null,
                        Date nextToLastDate = null)
        {
            calendar_       = calendar ?? new NullCalendar();
            firstDate_      = firstDate == effectiveDate ? null : firstDate;
            nextToLastDate_ = nextToLastDate == terminationDate ? null : nextToLastDate;

            tenor_      = tenor;
            convention_ = convention;
            terminationDateConvention_ = terminationDateConvention;
            rule_       = rule;
            endOfMonth_ = allowsEndOfMonth(tenor) && endOfMonth;

            // sanity checks
            Utils.QL_REQUIRE(terminationDate != null, () => "null termination date");

            // in many cases (e.g. non-expired bonds) the effective date is not
            // really necessary. In these cases a decent placeholder is enough
            if (effectiveDate == null && firstDate == null && rule == DateGeneration.Rule.Backward)
            {
                Date evalDate = Settings.evaluationDate();
                Utils.QL_REQUIRE(evalDate < terminationDate, () => "null effective date", QLNetExceptionEnum.NullEffectiveDate);
                int y;
                if (nextToLastDate != null)
                {
                    y             = (nextToLastDate - evalDate) / 366 + 1;
                    effectiveDate = nextToLastDate - new Period(y, TimeUnit.Years);
                }
                else
                {
                    y             = (terminationDate - evalDate) / 366 + 1;
                    effectiveDate = terminationDate - new Period(y, TimeUnit.Years);
                }
                // More accurate , is the previous coupon date
                if (effectiveDate > evalDate)
                {
                    effectiveDate = effectiveDate - new Period(tenor_.length(), TimeUnit.Months);
                }
                else if (effectiveDate + new Period(tenor_.length(), TimeUnit.Months) < evalDate)
                {
                    effectiveDate = effectiveDate + new Period(tenor_.length(), TimeUnit.Months);
                }
            }
            else
            {
                Utils.QL_REQUIRE(effectiveDate != null, () => "null effective date", QLNetExceptionEnum.NullEffectiveDate);
            }

            Utils.QL_REQUIRE(effectiveDate < terminationDate, () =>
                             "effective date (" + effectiveDate +
                             ") later than or equal to termination date (" +
                             terminationDate + ")"
                             );

            if (tenor_.length() == 0)
            {
                rule_ = DateGeneration.Rule.Zero;
            }
            else
            {
                Utils.QL_REQUIRE(tenor.length() > 0, () => "non positive tenor (" + tenor + ") not allowed");
            }

            if (firstDate_ != null)
            {
                switch (rule_.Value)
                {
                case DateGeneration.Rule.Backward:
                case DateGeneration.Rule.Forward:
                    Utils.QL_REQUIRE(firstDate_ > effectiveDate &&
                                     firstDate_ < terminationDate, () =>
                                     "first date (" + firstDate_ + ") out of effective-termination date range [" +
                                     effectiveDate + ", " + terminationDate + ")");
                    // we should ensure that the above condition is still verified after adjustment
                    break;

                case DateGeneration.Rule.ThirdWednesday:
                    Utils.QL_REQUIRE(IMM.isIMMdate(firstDate_, false), () => "first date (" + firstDate_ + ") is not an IMM date");
                    break;

                case DateGeneration.Rule.Zero:
                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                case DateGeneration.Rule.CDS2015:
                    Utils.QL_FAIL("first date incompatible with " + rule_.Value + " date generation rule");
                    break;

                default:
                    Utils.QL_FAIL("unknown rule (" + rule_.Value + ")");
                    break;
                }
            }

            if (nextToLastDate_ != null)
            {
                switch (rule_.Value)
                {
                case DateGeneration.Rule.Backward:
                case DateGeneration.Rule.Forward:
                    Utils.QL_REQUIRE(nextToLastDate_ > effectiveDate && nextToLastDate_ < terminationDate, () =>
                                     "next to last date (" + nextToLastDate_ + ") out of effective-termination date range (" +
                                     effectiveDate + ", " + terminationDate + "]");
                    // we should ensure that the above condition is still verified after adjustment
                    break;

                case DateGeneration.Rule.ThirdWednesday:
                    Utils.QL_REQUIRE(IMM.isIMMdate(nextToLastDate_, false), () => "next-to-last date (" + nextToLastDate_ +
                                     ") is not an IMM date");
                    break;

                case DateGeneration.Rule.Zero:
                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                case DateGeneration.Rule.CDS2015:
                    Utils.QL_FAIL("next to last date incompatible with " + rule_.Value + " date generation rule");
                    break;

                default:
                    Utils.QL_FAIL("unknown rule (" + rule_.Value + ")");
                    break;
                }
            }

            // calendar needed for endOfMonth adjustment
            Calendar nullCalendar = new NullCalendar();
            int      periods = 1;
            Date     seed = new Date(), exitDate = new Date();

            switch (rule_.Value)
            {
            case DateGeneration.Rule.Zero:
                tenor_ = new Period(0, TimeUnit.Years);
                dates_.Add(effectiveDate);
                dates_.Add(terminationDate);
                isRegular_.Add(true);
                break;

            case DateGeneration.Rule.Backward:
                dates_.Add(terminationDate);

                seed = terminationDate;
                if (nextToLastDate_ != null)
                {
                    dates_.Insert(0, nextToLastDate_);
                    Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_.Value);
                    if (temp != nextToLastDate_)
                    {
                        isRegular_.Insert(0, false);
                    }
                    else
                    {
                        isRegular_.Insert(0, true);
                    }
                    seed = nextToLastDate_;
                }
                exitDate = effectiveDate;
                if (firstDate_ != null)
                {
                    exitDate = firstDate_;
                }

                while (true)
                {
                    Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_.Value);
                    if (temp < exitDate)
                    {
                        if (firstDate_ != null && (calendar_.adjust(dates_.First(), convention_) !=
                                                   calendar_.adjust(firstDate_, convention_)))
                        {
                            dates_.Insert(0, firstDate_);
                            isRegular_.Insert(0, false);
                        }
                        break;
                    }
                    else
                    {
                        // skip dates that would result in duplicates
                        // after adjustment
                        if (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(temp, convention_))
                        {
                            dates_.Insert(0, temp);
                            isRegular_.Insert(0, true);
                        }
                        ++periods;
                    }
                }

                if (calendar_.adjust(dates_.First(), convention) != calendar_.adjust(effectiveDate, convention))
                {
                    dates_.Insert(0, effectiveDate);
                    isRegular_.Insert(0, false);
                }

                break;

            case DateGeneration.Rule.Twentieth:
            case DateGeneration.Rule.TwentiethIMM:
            case DateGeneration.Rule.ThirdWednesday:
            case DateGeneration.Rule.OldCDS:
            case DateGeneration.Rule.CDS:
            case DateGeneration.Rule.CDS2015:
                Utils.QL_REQUIRE(!endOfMonth, () => "endOfMonth convention incompatible with " + rule_.Value + " date generation rule");
                goto case DateGeneration.Rule.Forward;   // fall through

            case DateGeneration.Rule.Forward:
                if (rule_.Value == DateGeneration.Rule.CDS ||
                    rule_.Value == DateGeneration.Rule.CDS2015)
                {
                    dates_.Add(previousTwentieth(effectiveDate, rule_.Value));
                }
                else
                {
                    dates_.Add(effectiveDate);
                }

                seed = dates_.Last();
                if (firstDate_ != null)
                {
                    dates_.Add(firstDate_);
                    Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_.Value);
                    if (temp != firstDate_)
                    {
                        isRegular_.Add(false);
                    }
                    else
                    {
                        isRegular_.Add(true);
                    }
                    seed = firstDate_;
                }
                else if (rule_.Value == DateGeneration.Rule.Twentieth ||
                         rule_.Value == DateGeneration.Rule.TwentiethIMM ||
                         rule_.Value == DateGeneration.Rule.OldCDS ||
                         rule_.Value == DateGeneration.Rule.CDS ||
                         rule_.Value == DateGeneration.Rule.CDS2015)
                {
                    Date next20th = nextTwentieth(effectiveDate, rule_.Value);
                    if (rule_ == DateGeneration.Rule.OldCDS)
                    {
                        // distance rule inforced in natural days
                        long stubDays = 30;
                        if (next20th - effectiveDate < stubDays)
                        {
                            // +1 will skip this one and get the next
                            next20th = nextTwentieth(next20th + 1, rule_.Value);
                        }
                    }
                    if (next20th != effectiveDate)
                    {
                        dates_.Add(next20th);
                        isRegular_.Add(false);
                        seed = next20th;
                    }
                }

                exitDate = terminationDate;
                if (nextToLastDate_ != null)
                {
                    exitDate = nextToLastDate_;
                }
                if (rule_ == DateGeneration.Rule.CDS2015 &&
                    nextTwentieth(terminationDate, rule_.Value) == terminationDate &&
                    terminationDate.month() % 2 == 1)
                {
                    exitDate = nextTwentieth(terminationDate + 1, rule_.Value);
                }
                while (true)
                {
                    Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_.Value);
                    if (temp > exitDate)
                    {
                        if (nextToLastDate_ != null &&
                            (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(nextToLastDate_, convention_)))
                        {
                            dates_.Add(nextToLastDate_);
                            isRegular_.Add(false);
                        }
                        break;
                    }
                    else
                    {
                        // skip dates that would result in duplicates
                        // after adjustment
                        if (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(temp, convention_))
                        {
                            dates_.Add(temp);
                            isRegular_.Add(true);
                        }
                        ++periods;
                    }
                }

                if (calendar_.adjust(dates_.Last(), terminationDateConvention_.Value) !=
                    calendar_.adjust(terminationDate, terminationDateConvention_.Value))
                {
                    if (rule_.Value == DateGeneration.Rule.Twentieth ||
                        rule_.Value == DateGeneration.Rule.TwentiethIMM ||
                        rule_.Value == DateGeneration.Rule.OldCDS ||
                        rule_.Value == DateGeneration.Rule.CDS)
                    {
                        dates_.Add(nextTwentieth(terminationDate, rule_.Value));
                        isRegular_.Add(true);
                    }
                    else if (rule_ == DateGeneration.Rule.CDS2015)
                    {
                        Date tentativeTerminationDate = nextTwentieth(terminationDate, rule_.Value);
                        if (tentativeTerminationDate.month() % 2 == 0)
                        {
                            dates_.Add(tentativeTerminationDate);
                            isRegular_.Add(true);
                        }
                    }
                    else
                    {
                        dates_.Add(terminationDate);
                        isRegular_.Add(false);
                    }
                }
                break;

            default:
                Utils.QL_FAIL("unknown rule (" + rule_.Value + ")");
                break;
            }

            // adjustments
            if (rule_ == DateGeneration.Rule.ThirdWednesday)
            {
                for (int i = 1; i < dates_.Count - 1; ++i)
                {
                    dates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, dates_[i].Month, dates_[i].Year);
                }
            }

            if (endOfMonth && calendar_.isEndOfMonth(seed))
            {
                // adjust to end of month
                if (convention_ == BusinessDayConvention.Unadjusted)
                {
                    for (int i = 1; i < dates_.Count - 1; ++i)
                    {
                        dates_[i] = Date.endOfMonth(dates_[i]);
                    }
                }
                else
                {
                    for (int i = 1; i < dates_.Count - 1; ++i)
                    {
                        dates_[i] = calendar_.endOfMonth(dates_[i]);
                    }
                }
                if (terminationDateConvention_ != BusinessDayConvention.Unadjusted)
                {
                    dates_[0] = calendar_.endOfMonth(dates_.First());
                    dates_[dates_.Count - 1] = calendar_.endOfMonth(dates_.Last());
                }
                else
                {
                    // the termination date is the first if going backwards,
                    // the last otherwise.
                    if (rule_ == DateGeneration.Rule.Backward)
                    {
                        dates_[dates_.Count - 1] = Date.endOfMonth(dates_.Last());
                    }
                    else
                    {
                        dates_[0] = Date.endOfMonth(dates_.First());
                    }
                }
            }
            else
            {
                // first date not adjusted for CDS schedules
                if (rule_ != DateGeneration.Rule.OldCDS)
                {
                    dates_[0] = calendar_.adjust(dates_[0], convention_);
                }
                for (int i = 1; i < dates_.Count - 1; ++i)
                {
                    dates_[i] = calendar_.adjust(dates_[i], convention_);
                }

                // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the
                // confirmation of the deal or unless we're creating a CDS schedule
                if (terminationDateConvention_.Value != BusinessDayConvention.Unadjusted &&
                    rule_.Value != DateGeneration.Rule.CDS &&
                    rule_.Value != DateGeneration.Rule.CDS2015)
                {
                    dates_[dates_.Count - 1] = calendar_.adjust(dates_.Last(), terminationDateConvention_.Value);
                }
            }

            // Final safety checks to remove extra next-to-last date, if
            // necessary.  It can happen to be equal or later than the end
            // date due to EOM adjustments (see the Schedule test suite
            // for an example).
            if (dates_.Count >= 2 && dates_[dates_.Count - 2] >= dates_.Last())
            {
                isRegular_[isRegular_.Count - 2] = (dates_[dates_.Count - 2] == dates_.Last());
                dates_[dates_.Count - 2]         = dates_.Last();

                dates_.RemoveAt(dates_.Count - 1);
                isRegular_.RemoveAt(isRegular_.Count - 1);
            }

            if (dates_.Count >= 2 && dates_[1] <= dates_.First())
            {
                isRegular_[1] = (dates_[1] == dates_.First());
                dates_[1]     = dates_.First();
                dates_.RemoveAt(0);
                isRegular_.RemoveAt(0);
            }

            Utils.QL_REQUIRE(dates_.Count > 1,
                             () => "degenerate single date (" + dates_[0] + ") schedule" +
                             "\n seed date: " + seed +
                             "\n exit date: " + exitDate +
                             "\n effective date: " + effectiveDate +
                             "\n first date: " + firstDate +
                             "\n next to last date: " + nextToLastDate +
                             "\n termination date: " + terminationDate +
                             "\n generation rule: " + rule_.Value +
                             "\n end of month: " + endOfMonth_.Value);
        }
        public Schedule(Date effectiveDate, Date terminationDate, Period tenor, Calendar calendar,
                        BusinessDayConvention convention, BusinessDayConvention terminationDateConvention,
                        DateGeneration.Rule rule, bool endOfMonth, Date firstDate, Date nextToLastDate)
        {
            // first save the properties
            fullInterface_             = true;
            tenor_                     = tenor;
            calendar_                  = calendar;
            convention_                = convention;
            terminationDateConvention_ = terminationDateConvention;
            rule_       = rule;
            endOfMonth_ = endOfMonth;

            if (firstDate == effectiveDate)
            {
                firstDate_ = null;
            }
            else
            {
                firstDate_ = firstDate;
            }

            if (nextToLastDate == terminationDate)
            {
                nextToLastDate_ = null;
            }
            else
            {
                nextToLastDate_ = nextToLastDate;
            }

            // sanity checks
            Utils.QL_REQUIRE(terminationDate != null, "null termination date");

            // in many cases (e.g. non-expired bonds) the effective date is not
            // really necessary. In these cases a decent placeholder is enough
            if (effectiveDate == null && firstDate == null && rule == DateGeneration.Rule.Backward)
            {
                Date evalDate = Settings.evaluationDate();
                Utils.QL_REQUIRE(evalDate < terminationDate, "null effective date");
                int y;
                if (nextToLastDate != null)
                {
                    y             = (nextToLastDate - evalDate) / 366 + 1;
                    effectiveDate = nextToLastDate - new Period(y, TimeUnit.Years);
                }
                else
                {
                    y             = (terminationDate - evalDate) / 366 + 1;
                    effectiveDate = terminationDate - new Period(y, TimeUnit.Years);
                }
            }
            else
            {
                Utils.QL_REQUIRE(effectiveDate != null, "null effective date");
            }

            if (tenor_.length() == 0)
            {
                rule_ = DateGeneration.Rule.Zero;
            }
            else
            {
                Utils.QL_REQUIRE(tenor.length() > 0, "non positive tenor (" + tenor + ") not allowed");
            }

            if (firstDate_ != null)
            {
                switch (rule_)
                {
                case DateGeneration.Rule.Backward:
                case DateGeneration.Rule.Forward:
                    Utils.QL_REQUIRE(firstDate_ > effectiveDate &&
                                     firstDate_ < terminationDate,
                                     "first date (" + firstDate_ + ") out of effective-termination date range [" +
                                     effectiveDate + ", " + terminationDate + ")");
                    // we should ensure that the above condition is still verified after adjustment
                    break;

                case DateGeneration.Rule.ThirdWednesday:
                    Utils.QL_REQUIRE(IMM.isIMMdate(firstDate_, false), "first date (" + firstDate_ + ") is not an IMM date");
                    break;

                case DateGeneration.Rule.Zero:
                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                    Utils.QL_FAIL("first date incompatible with " + rule_ + " date generation rule");
                    break;

                default:
                    Utils.QL_FAIL("unknown rule (" + rule_ + ")");
                    break;
                }
            }

            if (nextToLastDate_ != null)
            {
                switch (rule_)
                {
                case DateGeneration.Rule.Backward:
                case DateGeneration.Rule.Forward:
                    Utils.QL_REQUIRE(nextToLastDate_ > effectiveDate && nextToLastDate_ < terminationDate,
                                     "next to last date (" + nextToLastDate_ + ") out of effective-termination date range (" +
                                     effectiveDate + ", " + terminationDate + "]");
                    // we should ensure that the above condition is still verified after adjustment
                    break;

                case DateGeneration.Rule.ThirdWednesday:
                    Utils.QL_REQUIRE(IMM.isIMMdate(nextToLastDate_, false), "next-to-last date (" + nextToLastDate_ +
                                     ") is not an IMM date");
                    break;

                case DateGeneration.Rule.Zero:
                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                    Utils.QL_FAIL("next to last date incompatible with " + rule_ + " date generation rule");
                    break;

                default:
                    Utils.QL_FAIL("unknown rule (" + rule_ + ")");
                    break;
                }
            }

            // calendar needed for endOfMonth adjustment
            Calendar nullCalendar = new NullCalendar();
            int      periods = 1;
            Date     seed = new Date(), exitDate;

            switch (rule_)
            {
            case DateGeneration.Rule.Zero:
                tenor_ = new Period(0, TimeUnit.Years);
                dates_.Add(effectiveDate);
                dates_.Add(terminationDate);
                isRegular_.Add(true);
                break;

            case DateGeneration.Rule.Backward:
                dates_.Add(terminationDate);

                seed = terminationDate;
                if (nextToLastDate_ != null)
                {
                    dates_.Insert(0, nextToLastDate_);
                    Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                    if (temp != nextToLastDate_)
                    {
                        isRegular_.Insert(0, false);
                    }
                    else
                    {
                        isRegular_.Insert(0, true);
                    }
                    seed = nextToLastDate_;
                }
                exitDate = effectiveDate;
                if (firstDate_ != null)
                {
                    exitDate = firstDate_;
                }

                while (true)
                {
                    Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                    if (temp < exitDate)
                    {
                        if (firstDate_ != null && (calendar_.adjust(dates_.First(), convention_) !=
                                                   calendar_.adjust(firstDate_, convention_)))
                        {
                            dates_.Insert(0, firstDate_);
                            isRegular_.Insert(0, false);
                        }
                        break;
                    }
                    else
                    {
                        // skip dates that would result in duplicates
                        // after adjustment
                        if (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(temp, convention_))
                        {
                            dates_.Insert(0, temp);
                            isRegular_.Insert(0, true);
                        }
                        ++periods;
                    }
                }

                if (calendar_.adjust(dates_.First(), convention) != calendar_.adjust(effectiveDate, convention))
                {
                    dates_.Insert(0, effectiveDate);
                    isRegular_.Insert(0, false);
                }

                break;

            case DateGeneration.Rule.Twentieth:
            case DateGeneration.Rule.TwentiethIMM:
            case DateGeneration.Rule.ThirdWednesday:
            case DateGeneration.Rule.OldCDS:
            case DateGeneration.Rule.CDS:
                Utils.QL_REQUIRE(!endOfMonth, "endOfMonth convention incompatible with " + rule_ + " date generation rule");
                goto case DateGeneration.Rule.Forward;                  // fall through

            case DateGeneration.Rule.Forward:
                if (rule_ == DateGeneration.Rule.CDS)
                {
                    dates_.Add(previousTwentieth(effectiveDate, DateGeneration.Rule.CDS));
                }
                else
                {
                    dates_.Add(effectiveDate);
                }

                seed = dates_.Last();
                if (firstDate_ != null)
                {
                    dates_.Add(firstDate_);
                    Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                    if (temp != firstDate_)
                    {
                        isRegular_.Add(false);
                    }
                    else
                    {
                        isRegular_.Add(true);
                    }
                    seed = firstDate_;
                }
                else if (rule_ == DateGeneration.Rule.Twentieth ||
                         rule_ == DateGeneration.Rule.TwentiethIMM ||
                         rule_ == DateGeneration.Rule.OldCDS ||
                         rule_ == DateGeneration.Rule.CDS)
                {
                    Date next20th = nextTwentieth(effectiveDate, rule_);
                    if (rule_ == DateGeneration.Rule.OldCDS)
                    {
                        // distance rule inforced in natural days
                        long stubDays = 30;
                        if (next20th - effectiveDate < stubDays)
                        {
                            // +1 will skip this one and get the next
                            next20th = nextTwentieth(next20th + 1, rule_);
                        }
                    }
                    if (next20th != effectiveDate)
                    {
                        dates_.Add(next20th);
                        isRegular_.Add(false);
                        seed = next20th;
                    }
                }

                exitDate = terminationDate;
                if (nextToLastDate_ != null)
                {
                    exitDate = nextToLastDate_;
                }
                while (true)
                {
                    Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                    if (temp > exitDate)
                    {
                        if (nextToLastDate_ != null &&
                            (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(nextToLastDate_, convention_)))
                        {
                            dates_.Add(nextToLastDate_);
                            isRegular_.Add(false);
                        }
                        break;
                    }
                    else
                    {
                        // skip dates that would result in duplicates
                        // after adjustment
                        if (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(temp, convention_))
                        {
                            dates_.Add(temp);
                            isRegular_.Add(true);
                        }
                        ++periods;
                    }
                }

                if (calendar_.adjust(dates_.Last(), terminationDateConvention_) !=
                    calendar_.adjust(terminationDate, terminationDateConvention_))
                {
                    if (rule_ == DateGeneration.Rule.Twentieth ||
                        rule_ == DateGeneration.Rule.TwentiethIMM ||
                        rule_ == DateGeneration.Rule.OldCDS ||
                        rule_ == DateGeneration.Rule.CDS)
                    {
                        dates_.Add(nextTwentieth(terminationDate, rule_));
                        isRegular_.Add(true);
                    }
                    else
                    {
                        dates_.Add(terminationDate);
                        isRegular_.Add(false);
                    }
                }
                break;

            default:
                Utils.QL_FAIL("unknown rule (" + rule_ + ")");
                break;
            }

            // adjustments
            if (rule_ == DateGeneration.Rule.ThirdWednesday)
            {
                for (int i = 1; i < dates_.Count - 1; ++i)
                {
                    dates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, dates_[i].Month, dates_[i].Year);
                }
            }

            if (endOfMonth && calendar_.isEndOfMonth(seed))
            {
                // adjust to end of month
                if (convention_ == BusinessDayConvention.Unadjusted)
                {
                    for (int i = 0; i < dates_.Count - 1; ++i)
                    {
                        dates_[i] = Date.endOfMonth(dates_[i]);
                    }
                }
                else
                {
                    for (int i = 0; i < dates_.Count - 1; ++i)
                    {
                        dates_[i] = calendar_.endOfMonth(dates_[i]);
                    }
                }
                if (terminationDateConvention_ != BusinessDayConvention.Unadjusted)
                {
                    dates_[dates_.Count - 1] = calendar_.endOfMonth(dates_.Last());
                }
            }
            else
            {
                // first date not adjusted for CDS schedules
                if (rule_ != DateGeneration.Rule.OldCDS)
                {
                    dates_[0] = calendar_.adjust(dates_[0], convention_);
                }
                for (int i = 1; i < dates_.Count - 1; ++i)
                {
                    dates_[i] = calendar_.adjust(dates_[i], convention_);
                }

                // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the
                // confirmation of the deal or unless we're creating a CDS schedule
                if (terminationDateConvention_ != BusinessDayConvention.Unadjusted ||
                    rule_ == DateGeneration.Rule.Twentieth ||
                    rule_ == DateGeneration.Rule.TwentiethIMM ||
                    rule_ == DateGeneration.Rule.OldCDS ||
                    rule_ == DateGeneration.Rule.CDS)
                {
                    dates_[dates_.Count - 1] = calendar_.adjust(dates_.Last(), terminationDateConvention_);
                }
            }

            // final safety check to remove duplicated last dates, if any
            // it can happen if EOM is applied to two near dates
            if (dates_.Count >= 2 && dates_[dates_.Count - 2] >= dates_.Last())
            {
                isRegular_[dates_.Count() - 2] = (dates_[dates_.Count() - 2] == dates_.Last());
                dates_[dates_.Count() - 2]     = dates_.Last();

                dates_.RemoveAt(dates_.Count - 1);
                isRegular_.RemoveAt(isRegular_.Count - 1);
            }
        }
 protected void checkRange(Date optionDate, Period bondTenor, double k, bool extrapolate)
 {
     base.checkRange(timeFromReference(optionDate),
                           extrapolate);
      Utils.QL_REQUIRE( bondTenor.length() > 0, () =>
            "negative bond tenor (" + bondTenor + ") given");
      Utils.QL_REQUIRE(extrapolate || allowsExtrapolation() ||
            bondTenor <= maxBondTenor(), () =>
            "bond tenor (" + bondTenor + ") is past max tenor ("
            + maxBondTenor() + ")");
      Utils.QL_REQUIRE(extrapolate || allowsExtrapolation() ||
            ( k >= minStrike() && k <= maxStrike() ), () =>
            "strike (" + k + ") is outside the curve domain ["
            + minStrike() + "," + maxStrike()+ "]");
 }
Ejemplo n.º 25
0
 /// <summary>
 /// Advances the given date as specified by the given period and
 /// returns the result.
 /// </summary>
 /// <remarks>The input date is not modified.</remarks>
 public Date advance( Date d, Period p, BusinessDayConvention c = BusinessDayConvention.Following, bool endOfMonth = false)
 {
     return advance(d, p.length(), p.units(), c, endOfMonth);
 }
Ejemplo n.º 26
0
        public Schedule( Date effectiveDate, Date terminationDate, Period tenor, Calendar calendar,
                       BusinessDayConvention convention, BusinessDayConvention terminationDateConvention,
                       DateGeneration.Rule rule, bool endOfMonth, Date firstDate = null, Date nextToLastDate = null)
        {
            // first save the properties
             fullInterface_ = true;
             tenor_ = tenor;
            if ( calendar == null )
                calendar_ = new NullCalendar();
            else
                calendar_ = calendar;
             convention_ = convention;
             terminationDateConvention_ = terminationDateConvention;
             rule_ = rule;
             endOfMonth_ = endOfMonth;

             if ( firstDate == effectiveDate )
            firstDate_ = null;
             else
            firstDate_ = firstDate;

              if ( nextToLastDate == terminationDate )
            nextToLastDate_ = null;
             else
            nextToLastDate_ = nextToLastDate;

             // sanity checks
              Utils.QL_REQUIRE( terminationDate != null, () => "null termination date" );

             // in many cases (e.g. non-expired bonds) the effective date is not
             // really necessary. In these cases a decent placeholder is enough
             if ( effectiveDate == null && firstDate == null && rule== DateGeneration.Rule.Backward)
             {
            Date evalDate = Settings.evaluationDate();
            Utils.QL_REQUIRE( evalDate < terminationDate, () => "null effective date" );
            int y;
            if (nextToLastDate != null)
            {
                y = (nextToLastDate - evalDate)/366 + 1;
                effectiveDate = nextToLastDate - new Period(y,TimeUnit.Years);
            }
            else
            {
                y = (terminationDate - evalDate)/366 + 1;
                effectiveDate = terminationDate - new Period(y,TimeUnit.Years);
            }
             }
             else
            Utils.QL_REQUIRE( effectiveDate != null, () => "null effective date" );

             if (tenor_.length() == 0)
            rule_ = DateGeneration.Rule.Zero;
             else
            Utils.QL_REQUIRE( tenor.length() > 0, () => "non positive tenor (" + tenor + ") not allowed" );

             if (firstDate_ != null)
             {
            switch (rule_)
            {
               case DateGeneration.Rule.Backward:
               case DateGeneration.Rule.Forward:
                  Utils.QL_REQUIRE(firstDate_ > effectiveDate &&
                                   firstDate_ < terminationDate, () =>
                                   "first date (" + firstDate_ + ") out of effective-termination date range [" +
                                   effectiveDate + ", " + terminationDate + ")");
                  // we should ensure that the above condition is still verified after adjustment
                  break;
               case DateGeneration.Rule.ThirdWednesday:
                  Utils.QL_REQUIRE( IMM.isIMMdate( firstDate_, false ), () => "first date (" + firstDate_ + ") is not an IMM date" );
                  break;
               case DateGeneration.Rule.Zero:
               case DateGeneration.Rule.Twentieth:
               case DateGeneration.Rule.TwentiethIMM:
               case DateGeneration.Rule.OldCDS:
               case DateGeneration.Rule.CDS:
                  Utils.QL_FAIL("first date incompatible with " + rule_ + " date generation rule");
                  break;
               default:
                  Utils.QL_FAIL("unknown rule (" + rule_ + ")");
                  break;
            }
             }

             if (nextToLastDate_ != null)
             {
            switch (rule_)
            {
               case DateGeneration.Rule.Backward:
               case DateGeneration.Rule.Forward:
                  Utils.QL_REQUIRE( nextToLastDate_ > effectiveDate && nextToLastDate_ < terminationDate, () =>
                                   "next to last date (" + nextToLastDate_ + ") out of effective-termination date range (" +
                                   effectiveDate + ", " + terminationDate + "]");
                  // we should ensure that the above condition is still verified after adjustment
                  break;
               case DateGeneration.Rule.ThirdWednesday:
                  Utils.QL_REQUIRE( IMM.isIMMdate( nextToLastDate_, false ), () => "next-to-last date (" + nextToLastDate_ +
                                    ") is not an IMM date");
                  break;
               case DateGeneration.Rule.Zero:
               case DateGeneration.Rule.Twentieth:
               case DateGeneration.Rule.TwentiethIMM:
               case DateGeneration.Rule.OldCDS:
               case DateGeneration.Rule.CDS:
                  Utils.QL_FAIL("next to last date incompatible with " + rule_ + " date generation rule");
                  break;
               default:
                  Utils.QL_FAIL("unknown rule (" + rule_ + ")");
                  break;
            }
             }

             // calendar needed for endOfMonth adjustment
             Calendar nullCalendar = new NullCalendar();
             int periods = 1;
             Date seed = new Date() , exitDate;
             switch (rule_)
             {
            case DateGeneration.Rule.Zero:
               tenor_ = new Period(0, TimeUnit.Years);
               dates_.Add(effectiveDate);
               dates_.Add(terminationDate);
               isRegular_.Add(true);
               break;

            case DateGeneration.Rule.Backward:
               dates_.Add(terminationDate);

               seed = terminationDate;
               if (nextToLastDate_ != null)
               {
                  dates_.Insert(0, nextToLastDate_);
                  Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                  if (temp != nextToLastDate_)
                     isRegular_.Insert(0, false);
                  else
                     isRegular_.Insert(0, true);
                  seed = nextToLastDate_;
               }
               exitDate = effectiveDate;
               if (firstDate_ != null)
                  exitDate = firstDate_;

               while (true)
               {
                  Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                  if (temp < exitDate)
                  {
                     if (firstDate_ != null && (calendar_.adjust(dates_.First(), convention_) !=
                          calendar_.adjust(firstDate_, convention_)))
                     {
                        dates_.Insert(0, firstDate_);
                        isRegular_.Insert(0, false);
                     }
                     break;
                  }
                  else
                  {
                     // skip dates that would result in duplicates
                     // after adjustment
                     if (calendar_.adjust(dates_.First(), convention_) != calendar_.adjust(temp, convention_))
                     {
                        dates_.Insert(0, temp);
                        isRegular_.Insert(0, true);
                     }
                     ++periods;
                  }
               }

               if (calendar_.adjust(dates_.First(), convention) != calendar_.adjust(effectiveDate, convention))
               {
                  dates_.Insert(0, effectiveDate);
                  isRegular_.Insert(0, false);
               }

               break;

            case DateGeneration.Rule.Twentieth:
            case DateGeneration.Rule.TwentiethIMM:
            case DateGeneration.Rule.ThirdWednesday:
            case DateGeneration.Rule.OldCDS:
            case DateGeneration.Rule.CDS:
               Utils.QL_REQUIRE( !endOfMonth, () => "endOfMonth convention incompatible with " + rule_ + " date generation rule" );
               goto case DateGeneration.Rule.Forward;			// fall through

            case DateGeneration.Rule.Forward:
               if (rule_ == DateGeneration.Rule.CDS)
               {
                  dates_.Add(previousTwentieth(effectiveDate, DateGeneration.Rule.CDS));
               }
               else
               {
                  dates_.Add(effectiveDate);
               }

               seed = dates_.Last();
               if (firstDate_ != null)
               {
                  dates_.Add(firstDate_);
                  Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                  if (temp != firstDate_)
                     isRegular_.Add(false);
                  else
                     isRegular_.Add(true);
                  seed = firstDate_;
               }
               else if (rule_ == DateGeneration.Rule.Twentieth ||
                        rule_ == DateGeneration.Rule.TwentiethIMM ||
                        rule_ == DateGeneration.Rule.OldCDS ||
                        rule_ == DateGeneration.Rule.CDS)
               {
                  Date next20th = nextTwentieth(effectiveDate, rule_);
                  if (rule_ == DateGeneration.Rule.OldCDS)
                  {
                     // distance rule inforced in natural days
                     long stubDays = 30;
                     if (next20th - effectiveDate < stubDays)
                     {
                        // +1 will skip this one and get the next
                        next20th = nextTwentieth(next20th + 1, rule_);
                     }
                  }
                  if (next20th != effectiveDate)
                  {
                     dates_.Add(next20th);
                     isRegular_.Add(false);
                     seed = next20th;
                  }
               }

               exitDate = terminationDate;
               if (nextToLastDate_ != null)
                  exitDate = nextToLastDate_;
               while (true)
               {
                  Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                  if (temp > exitDate)
                  {
                     if (nextToLastDate_ != null &&
                         (calendar_.adjust(dates_.Last(), convention_) !=  calendar_.adjust(nextToLastDate_, convention_)))
                     {
                        dates_.Add(nextToLastDate_);
                        isRegular_.Add(false);
                     }
                     break;
                  }
                  else
                  {
                     // skip dates that would result in duplicates
                     // after adjustment
                     if (calendar_.adjust(dates_.Last(), convention_) != calendar_.adjust(temp, convention_))
                     {
                        dates_.Add(temp);
                        isRegular_.Add(true);
                     }
                     ++periods;
                  }
               }

               if (calendar_.adjust(dates_.Last(), terminationDateConvention_) !=
                   calendar_.adjust(terminationDate, terminationDateConvention_))
               {
                  if (rule_ == DateGeneration.Rule.Twentieth ||
                      rule_ == DateGeneration.Rule.TwentiethIMM ||
                      rule_ == DateGeneration.Rule.OldCDS ||
                      rule_ == DateGeneration.Rule.CDS)
                  {
                     dates_.Add(nextTwentieth(terminationDate, rule_));
                     isRegular_.Add(true);
                  }
                  else
                  {
                     dates_.Add(terminationDate);
                     isRegular_.Add(false);
                  }
               }
               break;

            default:
               Utils.QL_FAIL("unknown rule (" + rule_ + ")");
               break;
             }

             // adjustments
             if (rule_ == DateGeneration.Rule.ThirdWednesday)
            for (int i = 1; i < dates_.Count-1; ++i)
               dates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, dates_[i].Month, dates_[i].Year);

             if (endOfMonth && calendar_.isEndOfMonth(seed))
             {
            // adjust to end of month
            if (convention_ == BusinessDayConvention.Unadjusted)
            {
               for (int i = 0; i < dates_.Count-1; ++i)
                  dates_[i] = Date.endOfMonth(dates_[i]);
            }
            else
            {
               for (int i = 0; i < dates_.Count-1; ++i)
                  dates_[i] = calendar_.endOfMonth(dates_[i]);
            }
            if (terminationDateConvention_ != BusinessDayConvention.Unadjusted)
               dates_[dates_.Count - 1] = calendar_.endOfMonth(dates_.Last());
             }
             else
             {
            // first date not adjusted for CDS schedules
            if (rule_ != DateGeneration.Rule.OldCDS)
               dates_[0] = calendar_.adjust(dates_[0], convention_);
            for (int i = 1; i < dates_.Count-1; ++i)
               dates_[i] = calendar_.adjust(dates_[i], convention_);

            // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the
            // confirmation of the deal or unless we're creating a CDS schedule
            if (terminationDateConvention_ != BusinessDayConvention.Unadjusted
                || rule_ == DateGeneration.Rule.Twentieth
                || rule_ == DateGeneration.Rule.TwentiethIMM
                || rule_ == DateGeneration.Rule.OldCDS
                || rule_ == DateGeneration.Rule.CDS)
               dates_[dates_.Count - 1] = calendar_.adjust(dates_.Last(), terminationDateConvention_);
             }

             // final safety check to remove duplicated last dates, if any
             // it can happen if EOM is applied to two near dates
             if (dates_.Count >= 2 &&  dates_[dates_.Count - 2] >= dates_.Last())
             {
            isRegular_[dates_.Count() - 2] = (dates_[dates_.Count() - 2] == dates_.Last());
            dates_[dates_.Count() - 2] = dates_.Last();

            dates_.RemoveAt(dates_.Count - 1);
            isRegular_.RemoveAt(isRegular_.Count - 1);
             }
        }
Ejemplo n.º 27
0
 public pair(Period p)
 {
     switch (p.units()) {
         case TimeUnit.Days:
             lo = hi = p.length(); break;
         case TimeUnit.Weeks:
             lo = hi = 7 * p.length(); break;
         case TimeUnit.Months:
             lo = 28 * p.length(); hi = 31 * p.length(); break;
         case TimeUnit.Years:
             lo = 365 * p.length(); hi = 366 * p.length(); break;
         default:
             throw new ArgumentException("Unknown TimeUnit: " + p.units());
     }
 }
 public Date advance(Date d, Period p, BusinessDayConvention c, bool endOfMonth)
 {
     return(advance(d, p.length(), p.units(), c, endOfMonth));
 }
		//@}
		//! implements the conversion between swap tenor and swap (time) length
		public double swapLength(Period p)
		{
			if (!(p.length()>0))
                throw new ApplicationException("non-positive swap tenor (" + p + ") given");

	//         while using the reference date is arbitrary it is coherent between
	//           different swaption structures defined on the same reference date.
	//        
			Date start = referenceDate();
			Date end = start + p;
			return swapLength(start, end);
		}
Ejemplo n.º 30
0
 //! implements the conversion between swap tenor and swap (time) length
 public double swapLength(Period swapTenor)
 {
     Utils.QL_REQUIRE(swapTenor.length() > 0, "non-positive swap tenor (" + swapTenor + ") given");
      switch (swapTenor.units())
      {
     case TimeUnit.Months:
        return swapTenor.length() / 12.0;
     case TimeUnit.Years:
        return swapTenor.length();
     default:
        Utils.QL_FAIL("invalid Time Unit (" + swapTenor.units() + ") for swap length");
        return 0;
      }
 }
		protected void checkSwapTenor(Period swapTenor, bool extrapolate)
		{
			if (!(swapTenor.length() > 0))
                throw new ApplicationException("non-positive swap tenor (" + swapTenor + ") given");

			if (!(extrapolate || allowsExtrapolation() || swapTenor <= maxSwapTenor()))
                throw new ApplicationException("swap tenor (" + swapTenor + ") is past max tenor (" + maxSwapTenor() + ")");
		}
Ejemplo n.º 32
0
        public Schedule(Date effectiveDate__, Date terminationDate__, Period tenor__, Calendar calendar__,
            BusinessDayConvention convention__, BusinessDayConvention terminationDateConvention__,
            DateGeneration.Rule rule__, bool endOfMonth__,
            Date firstDate__, Date nextToLastDate__)
        {
            // first save the properties
            fullInterface_ = true;
            tenor_ = tenor__;
            calendar_ = calendar__;
            convention_ = convention__;
            terminationDateConvention_ = terminationDateConvention__;
            rule_ = rule__;
            endOfMonth_ = endOfMonth__;
            firstDate_ = firstDate__;
            nextToLastDate_ = nextToLastDate__;

            // sanity checks
            if (effectiveDate__ == null) throw new ArgumentException("Null effective date");
            if (terminationDate__ == null) throw new ArgumentException("Null termination  date");
            if (effectiveDate__ >= terminationDate__) throw new ArgumentException("Effective date (" + effectiveDate__ +
                       ") is later than or equal to termination date (" + terminationDate__ + ")");

            if (tenor_.length() == 0)
                rule_ = DateGeneration.Rule.Zero;
            else if (tenor_.length() < 0)
                throw new ArgumentException("Non positive tenor (" + tenor_ + ") is not allowed");

            if (firstDate_ != null) {
                switch (rule_) {
                    case DateGeneration.Rule.Backward:
                    case DateGeneration.Rule.Forward:
                        if (!(firstDate_ > effectiveDate__ && firstDate_ < terminationDate__))
                            throw new ArgumentException("First date (" + firstDate_ + ") is out of range [effective date (" + effectiveDate__
                                                        + "), termination date (" + terminationDate__ + ")]");
                        // we should ensure that the above condition is still verified after adjustment
                        break;
                    case DateGeneration.Rule.ThirdWednesday:
                        if (!IMM.isIMMdate(firstDate_, false))
                            throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date");
                        break;
                    case DateGeneration.Rule.Zero:
                    case DateGeneration.Rule.Twentieth:
                    case DateGeneration.Rule.TwentiethIMM:
                    case DateGeneration.Rule.OldCDS:
                    case DateGeneration.Rule.CDS:
                        throw new ArgumentException("First date is incompatible with " + rule_ + " date generation rule");
                    default:
                        throw new ArgumentException("Unknown DateGeneration rule: " + rule_);
                }
            }

            if (nextToLastDate_ != null) {
                switch (rule_) {
                    case DateGeneration.Rule.Backward:
                    case DateGeneration.Rule.Forward:
                        if (!(nextToLastDate_ > effectiveDate__ && nextToLastDate_ < terminationDate__))
                            throw new ArgumentException("Next to last date (" + nextToLastDate_ + ") out of range [effective date (" + effectiveDate__
                               + "), termination date (" + terminationDate__ + ")]");
                        // we should ensure that the above condition is still verified after adjustment
                        break;
                    case DateGeneration.Rule.ThirdWednesday:
                        if (!IMM.isIMMdate(firstDate_, false))
                            throw new ArgumentException("first date (" + firstDate_ + ") is not an IMM date");
                        break;
                    case DateGeneration.Rule.Zero:
                    case DateGeneration.Rule.Twentieth:
                    case DateGeneration.Rule.TwentiethIMM:
                    case DateGeneration.Rule.OldCDS:
                    case DateGeneration.Rule.CDS:
                        throw new ArgumentException("next to last is incompatible with " + rule_ + " date generation rule");
                    default:
                        throw new ArgumentException("Unknown DateGeneration rule: " + rule_);
                }
            }

            // calendar needed for endOfMonth adjustment
            Calendar nullCalendar = new NullCalendar();
            int periods = 1;
            Date seed = new Date(), exitDate;
            switch (rule_) {
                case DateGeneration.Rule.Zero:
                    tenor_ = new Period(0, TimeUnit.Years);
                    originalDates_.Add(effectiveDate__);
                    originalDates_.Add(terminationDate__);
                    isRegular_.Add(true);
                    break;

                case DateGeneration.Rule.Backward:
                    originalDates_.Add(terminationDate__);
                    seed = terminationDate__;
                    if (nextToLastDate_ != null) {
                        originalDates_.Insert(0, nextToLastDate_);
                        Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                        isRegular_.Insert(0, temp == nextToLastDate_);
                        seed = nextToLastDate_;
                    }
                    exitDate = effectiveDate__;
                    if (firstDate_ != null)
                        exitDate = firstDate_;
                    while (true) {
                        Date temp = nullCalendar.advance(seed, -periods * tenor_, convention_, endOfMonth_);
                        if (temp < exitDate) {
                            if (firstDate_ != null && (calendar_.adjust(originalDates_.First(), convention_) !=
                                 calendar_.adjust(firstDate_, convention_))) {
                                originalDates_.Insert(0, firstDate_);
                                isRegular_.Insert(0, false);
                            }
                            break;
                        } else {
                            originalDates_.Insert(0, temp);
                            isRegular_.Insert(0, true);
                            ++periods;
                        }
                    }
                    if (endOfMonth_ && calendar_.isEndOfMonth(seed))
                        convention_ = BusinessDayConvention.Preceding;
                    if (calendar_.adjust(originalDates_[0], convention_) != calendar_.adjust(effectiveDate__, convention_)) {
                        originalDates_.Insert(0, effectiveDate__);
                        isRegular_.Insert(0, false);
                    }
                    break;

                case DateGeneration.Rule.Twentieth:
                case DateGeneration.Rule.TwentiethIMM:
                case DateGeneration.Rule.ThirdWednesday:
                case DateGeneration.Rule.OldCDS:
                case DateGeneration.Rule.CDS:
                    if (endOfMonth_)
                        throw new ArgumentException("endOfMonth convention is incompatible with " + rule_ + " date generation rule");
                    goto case DateGeneration.Rule.Forward;			// fall through

                case DateGeneration.Rule.Forward:
                    if (rule_ == DateGeneration.Rule.CDS) {
                       originalDates_.Add(previousTwentieth(effectiveDate__,DateGeneration.Rule.CDS));
                    } else {
                       originalDates_.Add(effectiveDate__);
                    }

                    seed = effectiveDate__;
                    if (firstDate_ != null) {
                        originalDates_.Add(firstDate_);
                        Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                        isRegular_.Add(temp == firstDate_);
                        seed = firstDate_;
                    } else if (rule_ == DateGeneration.Rule.Twentieth ||
                               rule_ == DateGeneration.Rule.TwentiethIMM ||
                               rule_ == DateGeneration.Rule.OldCDS ||
                               rule_ == DateGeneration.Rule.CDS)
                    {
                        Date next20th = nextTwentieth(effectiveDate__, rule_);
                        if (rule_ == DateGeneration.Rule.OldCDS) {
                           // distance rule inforced in natural days
                           long stubDays = 30;
                           if (next20th - effectiveDate__ < stubDays) {
                              // +1 will skip this one and get the next
                              next20th = nextTwentieth(next20th + 1, rule_);
                           }
                        }
                        if (next20th != effectiveDate__) {
                            originalDates_.Add(next20th);
                            isRegular_.Add(false);
                            seed = next20th;
                        }
                    }

                    exitDate = terminationDate__;
                    if (nextToLastDate_ != null)
                        exitDate = nextToLastDate_;
                    while (true) {
                        Date temp = nullCalendar.advance(seed, periods * tenor_, convention_, endOfMonth_);
                        if (temp > exitDate) {
                            if (nextToLastDate_ != null &&
                                (calendar_.adjust(originalDates_.Last(), convention_) !=
                                 calendar_.adjust(nextToLastDate_, convention_))) {
                                originalDates_.Add(nextToLastDate_);
                                isRegular_.Add(false);
                            }
                            break;
                        } else {
                            originalDates_.Add(temp);
                            isRegular_.Add(true);
                            ++periods;
                        }
                    }
                    if (endOfMonth_ && calendar_.isEndOfMonth(seed))
                        convention_ = BusinessDayConvention.Preceding;

                    if (calendar_.adjust(originalDates_.Last(), terminationDateConvention_) != calendar_.adjust(terminationDate__, terminationDateConvention_)) {
                        if (rule_ == DateGeneration.Rule.Twentieth ||
                            rule_ == DateGeneration.Rule.TwentiethIMM ||
                            rule_ == DateGeneration.Rule.OldCDS ||
                            rule_ == DateGeneration.Rule.CDS ) {
                            originalDates_.Add(nextTwentieth(terminationDate__, rule_));
                            isRegular_.Add(true);
                        } else {
                            originalDates_.Add(terminationDate__);
                            isRegular_.Add(false);
                        }
                    }
                    break;

                default:
                    throw new ArgumentException("Unknown DateGeneration rule: " + rule_);
            }

            // adjustments to holidays, etc.
            if (rule_ == DateGeneration.Rule.ThirdWednesday)
                for (int i = 1; i < originalDates_.Count; ++i)
                    originalDates_[i] = Date.nthWeekday(3, DayOfWeek.Wednesday, originalDates_[i].Month, originalDates_[i].Year);

            if (endOfMonth && calendar_.isEndOfMonth(seed))
            {
               // adjust to end of month
               if (convention_ == BusinessDayConvention.Unadjusted)
               {
                  for (int i = 0; i < originalDates_.Count; ++i)
                     originalDates_[i] = Date.endOfMonth(originalDates_[i]);
               }
               else
               {
                  for (int i = 0; i < originalDates_.Count; ++i)
                     originalDates_[i] = calendar_.endOfMonth(originalDates_[i]);
               }
               if (terminationDateConvention_ == BusinessDayConvention.Unadjusted)
                  originalDates_[originalDates_.Count - 1] = Date.endOfMonth(originalDates_.Last());
               else
                  originalDates_[originalDates_.Count - 1] = calendar_.endOfMonth(originalDates_.Last());
            }
            else
            {
               // first date not adjusted for CDS schedules
               if (rule_ != DateGeneration.Rule.OldCDS)
                  originalDates_[0] = calendar_.adjust(originalDates_[0], convention_);
               for (int i = 1; i < originalDates_.Count; ++i)
                  originalDates_[i] = calendar_.adjust(originalDates_[i], convention_);

               foreach (Date d in originalDates_)
                  adjustedDates_.Add(d);

               // termination date is NOT adjusted as per ISDA specifications, unless otherwise specified in the
               // confirmation of the deal or unless we're creating a CDS schedule
               if (terminationDateConvention_ != BusinessDayConvention.Unadjusted
                   || rule_ == DateGeneration.Rule.Twentieth
                   || rule_ == DateGeneration.Rule.TwentiethIMM
                   || rule_ == DateGeneration.Rule.OldCDS
                   || rule_ == DateGeneration.Rule.CDS)
                  adjustedDates_[adjustedDates_.Count - 1] = calendar_.adjust(originalDates_.Last(), terminationDateConvention_);
            }
        }