Exemplo n.º 1
0
        //@}
        //! \name Results
        //@{

        /*! Returns the upfront spread that, given the running spread
         *  and the quoted recovery rate, will make the instrument
         *  have an NPV of 0.
         */
        public double fairUpfront()
        {
            calculate();
            Utils.QL_REQUIRE(fairUpfront_ != null, () => "fair upfront not available");
            return(fairUpfront_.Value);
        }
Exemplo n.º 2
0
 public DateGeneration.Rule rule()
 {
     Utils.QL_REQUIRE(rule_.HasValue, () => "full interface (rule) not available");
     return(rule_.Value);
 }
Exemplo n.º 3
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");
                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");
            }

            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);
        }
Exemplo n.º 4
0
 public bool isRegular(int i)
 {
     Utils.QL_REQUIRE(isRegular_.Count > 0, () => "full interface (isRegular) not available");
     Utils.QL_REQUIRE(i <= isRegular_.Count && i > 0, () => "index (" + i + ") must be in [1, " + isRegular_.Count + "]");
     return(isRegular_[i - 1]);
 }
Exemplo n.º 5
0
 public Period tenor()
 {
     Utils.QL_REQUIRE(tenor_ != null, () => "full interface (tenor) not available");
     return(tenor_);
 }
Exemplo n.º 6
0
        protected override double localVolImpl(double t, double underlyingLevel)
        {
            double dr           = riskFreeTS_.currentLink().discount(t, true);
            double dq           = dividendTS_.currentLink().discount(t, true);
            double forwardValue = underlying_.currentLink().value() * dq / dr;

            // strike derivatives
            double strike, y, dy, strikep, strikem;
            double w, wp, wm, dwdy, d2wdy2;

            strike  = underlyingLevel;
            y       = Math.Log(strike / forwardValue);
            dy      = ((Math.Abs(y) > 0.001) ? y * 0.0001 : 0.000001);
            strikep = strike * Math.Exp(dy);
            strikem = strike / Math.Exp(dy);
            w       = blackTS_.link.blackVariance(t, strike, true);
            wp      = blackTS_.link.blackVariance(t, strikep, true);
            wm      = blackTS_.link.blackVariance(t, strikem, true);
            dwdy    = (wp - wm) / (2.0 * dy);
            d2wdy2  = (wp - 2.0 * w + wm) / (dy * dy);

            // time derivative
            double dt, wpt, wmt, dwdt;

            if (t.IsEqual(0.0))
            {
                dt = 0.0001;
                double drpt     = riskFreeTS_.currentLink().discount(t + dt, true);
                double dqpt     = dividendTS_.currentLink().discount(t + dt, true);
                double strikept = strike * dr * dqpt / (drpt * dq);

                wpt = blackTS_.link.blackVariance(t + dt, strikept, true);

                Utils.QL_REQUIRE(wpt >= w, () =>
                                 "decreasing variance at strike " + strike + " between time " + t + " and time " + (t + dt));
                dwdt = (wpt - w) / dt;
            }
            else
            {
                dt = Math.Min(0.0001, t / 2.0);
                double drpt = riskFreeTS_.currentLink().discount(t + dt, true);
                double drmt = riskFreeTS_.currentLink().discount(t - dt, true);
                double dqpt = dividendTS_.currentLink().discount(t + dt, true);
                double dqmt = dividendTS_.currentLink().discount(t - dt, true);

                double strikept = strike * dr * dqpt / (drpt * dq);
                double strikemt = strike * dr * dqmt / (drmt * dq);

                wpt = blackTS_.link.blackVariance(t + dt, strikept, true);
                wmt = blackTS_.link.blackVariance(t - dt, strikemt, true);
                Utils.QL_REQUIRE(wpt >= w, () =>
                                 "decreasing variance at strike " + strike + " between time " + t + " and time " + (t + dt));
                Utils.QL_REQUIRE(w >= wmt, () =>
                                 "decreasing variance at strike " + strike + " between time " + (t - dt) + " and time " + t);
                dwdt = (wpt - wmt) / (2.0 * dt);
            }

            if (dwdy.IsEqual(0.0) && d2wdy2.IsEqual(0.0)) // avoid /w where w might be 0.0
            {
                return(Math.Sqrt(dwdt));
            }
            else
            {
                double den1   = 1.0 - y / w * dwdy;
                double den2   = 0.25 * (-0.25 - 1.0 / w + y * y / w / w) * dwdy * dwdy;
                double den3   = 0.5 * d2wdy2;
                double den    = den1 + den2 + den3;
                double result = dwdt / den;
                Utils.QL_REQUIRE(result >= 0.0, () =>
                                 "negative local vol^2 at strike " + strike + " and time " + t + "; the black vol surface is not smooth enough");
                return(Math.Sqrt(result));
            }
        }
Exemplo n.º 7
0
        public override double swapletRate()
        {
            OvernightIndex index = coupon_.index() as OvernightIndex;

            List <Date>   fixingDates = coupon_.fixingDates();
            List <double> dt          = coupon_.dt();

            int n = dt.Count;
            int i = 0;

            double compoundFactor = 1.0;

            // already fixed part
            Date today = Settings.evaluationDate();

            while (fixingDates[i] < today && i < n)
            {
                // rate must have been fixed
                double?pastFixing = IndexManager.instance().getHistory(index.name())[fixingDates[i]];

                Utils.QL_REQUIRE(pastFixing != null, () => "Missing " + index.name() + " fixing for " + fixingDates[i].ToString());

                compoundFactor *= (1.0 + pastFixing.GetValueOrDefault() * dt[i]);
                ++i;
            }

            // today is a border case
            if (fixingDates[i] == today && i < n)
            {
                // might have been fixed
                try
                {
                    double?pastFixing = IndexManager.instance().getHistory(index.name())[fixingDates[i]];

                    if (pastFixing != null)
                    {
                        compoundFactor *= (1.0 + pastFixing.GetValueOrDefault() * dt[i]);
                        ++i;
                    }
                    else
                    {
                        // fall through and forecast
                    }
                }
                catch (Exception)
                {
                    // fall through and forecast
                }
            }

            // forward part using telescopic property in order
            // to avoid the evaluation of multiple forward fixings
            if (i < n)
            {
                Handle <YieldTermStructure> curve = index.forwardingTermStructure();
                Utils.QL_REQUIRE(!curve.empty(), () => "null term structure set to this instance of" + index.name());

                List <Date> dates         = coupon_.valueDates();
                double      startDiscount = curve.link.discount(dates[i]);
                double      endDiscount   = curve.link.discount(dates[n]);

                compoundFactor *= startDiscount / endDiscount;
            }

            double rate = (compoundFactor - 1.0) / coupon_.accrualPeriod();

            return(coupon_.gearing() * rate + coupon_.spread());
        }
Exemplo n.º 8
0
        public override void calculate(IPricingEngineResults r)
        {
            OneAssetOption.Results results = r as OneAssetOption.Results;
            Utils.QL_REQUIRE(results != null, () => "incorrect results type");

            double beginDate, endDate;
            int    dateNumber        = stoppingTimes_.Count;
            bool   lastDateIsResTime = false;
            int    firstIndex        = -1;
            int    lastIndex         = dateNumber - 1;
            bool   firstDateIsZero   = false;
            double firstNonZeroDate  = getResidualTime();

            double dateTolerance = 1e-6;
            int    j;

            if (dateNumber > 0)
            {
                Utils.QL_REQUIRE(getDividendTime(0) >= 0, () => "first date (" + getDividendTime(0) + ") cannot be negative");
                if (getDividendTime(0) < getResidualTime() * dateTolerance)
                {
                    firstDateIsZero = true;
                    firstIndex      = 0;
                    if (dateNumber >= 2)
                    {
                        firstNonZeroDate = getDividendTime(1);
                    }
                }

                if (Math.Abs(getDividendTime(lastIndex) - getResidualTime()) < dateTolerance)
                {
                    lastDateIsResTime = true;
                    lastIndex         = dateNumber - 2;
                }

                if (!firstDateIsZero)
                {
                    firstNonZeroDate = getDividendTime(0);
                }

                if (dateNumber >= 2)
                {
                    for (j = 1; j < dateNumber; j++)
                    {
                        Utils.QL_REQUIRE(getDividendTime(j - 1) < getDividendTime(j), () =>
                                         "dates must be in increasing order: " + getDividendTime(j - 1) +
                                         " is not strictly smaller than " + getDividendTime(j));
                    }
                }
            }

            double dt = getResidualTime() / (timeStepPerPeriod_ * (dateNumber + 1));

            // Ensure that dt is always smaller than the first non-zero date
            if (firstNonZeroDate <= dt)
            {
                dt = firstNonZeroDate / 2.0;
            }

            setGridLimits();
            initializeInitialCondition();
            initializeOperator();
            initializeBoundaryConditions();
            initializeModel();
            initializeStepCondition();

            prices_ = (SampledCurve)intrinsicValues_.Clone();
            if (lastDateIsResTime)
            {
                executeIntermediateStep(dateNumber - 1);
            }

            j = lastIndex;
            object temp;

            do
            {
                if (j == dateNumber - 1)
                {
                    beginDate = getResidualTime();
                }
                else
                {
                    beginDate = getDividendTime(j + 1);
                }

                if (j >= 0)
                {
                    endDate = getDividendTime(j);
                }
                else
                {
                    endDate = dt;
                }

                temp = prices_.values();
                model_.rollback(ref temp, beginDate, endDate, timeStepPerPeriod_, stepCondition_);
                prices_.setValues((Vector)temp);

                if (j >= 0)
                {
                    executeIntermediateStep(j);
                }
            } while (--j >= firstIndex);

            temp = prices_.values();
            model_.rollback(ref temp, dt, 0, 1, stepCondition_);
            prices_.setValues((Vector)temp);

            if (firstDateIsZero)
            {
                executeIntermediateStep(0);
            }

            results.value = prices_.valueAtCenter();
            results.delta = prices_.firstDerivativeAtCenter();
            results.gamma = prices_.secondDerivativeAtCenter();
            results.additionalResults["priceCurve"] = prices_;
        }
Exemplo n.º 9
0
            public override void setupArguments(IPricingEngineArguments args)
            {
                base.setupArguments(args);

                ConvertibleBond.option.arguments moreArgs = args as ConvertibleBond.option.arguments;
                Utils.QL_REQUIRE(moreArgs != null, "wrong argument type");

                moreArgs.conversionRatio = conversionRatio_;

                Date settlement = bond_.settlementDate();

                int n = callability_.Count;

                moreArgs.callabilityDates.Clear();
                moreArgs.callabilityTypes.Clear();
                moreArgs.callabilityPrices.Clear();
                moreArgs.callabilityTriggers.Clear();
                moreArgs.callabilityDates.Capacity    = n;
                moreArgs.callabilityTypes.Capacity    = n;
                moreArgs.callabilityPrices.Capacity   = n;
                moreArgs.callabilityTriggers.Capacity = n;
                for (int i = 0; i < n; i++)
                {
                    if (!callability_[i].hasOccurred(settlement, false))
                    {
                        moreArgs.callabilityTypes.Add(callability_[i].type());
                        moreArgs.callabilityDates.Add(callability_[i].date());

                        if (callability_[i].price().type() == Callability.Price.Type.Clean)
                        {
                            moreArgs.callabilityPrices.Add(callability_[i].price().amount() + bond_.accruedAmount(callability_[i].date()));
                        }
                        else
                        {
                            moreArgs.callabilityPrices.Add(callability_[i].price().amount());
                        }

                        SoftCallability softCall = callability_[i] as SoftCallability;
                        if (softCall != null)
                        {
                            moreArgs.callabilityTriggers.Add(softCall.trigger());
                        }
                        else
                        {
                            moreArgs.callabilityTriggers.Add(null);
                        }
                    }
                }

                List <CashFlow> cashflows = bond_.cashflows();

                moreArgs.couponDates.Clear();
                moreArgs.couponAmounts.Clear();
                for (int i = 0; i < cashflows.Count - 1; i++)
                {
                    if (!cashflows[i].hasOccurred(settlement, false))
                    {
                        moreArgs.couponDates.Add(cashflows[i].date());
                        moreArgs.couponAmounts.Add(cashflows[i].amount());
                    }
                }

                moreArgs.dividends.Clear();
                moreArgs.dividendDates.Clear();
                for (int i = 0; i < dividends_.Count; i++)
                {
                    if (!dividends_[i].hasOccurred(settlement, false))
                    {
                        moreArgs.dividends.Add(dividends_[i]);
                        moreArgs.dividendDates.Add(dividends_[i].date());
                    }
                }

                moreArgs.creditSpread   = creditSpread_;
                moreArgs.issueDate      = issueDate_;
                moreArgs.settlementDate = settlement;
                moreArgs.settlementDays = settlementDays_;
                moreArgs.redemption     = redemption_;
            }
Exemplo n.º 10
0
 public double upfrontNPV()
 {
     calculate();
     Utils.QL_REQUIRE(upfrontNPV_ != null, () => "upfront NPV not available");
     return(upfrontNPV_.Value);
 }
Exemplo n.º 11
0
        public override void calculate()
        {
            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () => "not an European Option");

            EuropeanExercise exercise = arguments_.exercise as EuropeanExercise;

            Utils.QL_REQUIRE(exercise != null, () => "not an European Option");

            BasketPayoff basket_payoff = arguments_.payoff as BasketPayoff;

            MinBasketPayoff min_basket = arguments_.payoff as MinBasketPayoff;

            MaxBasketPayoff max_basket = arguments_.payoff as MaxBasketPayoff;

            Utils.QL_REQUIRE(min_basket != null || max_basket != null, () => "unknown basket type");

            PlainVanillaPayoff payoff = basket_payoff.basePayoff() as PlainVanillaPayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-plain payoff given");

            double strike = payoff.strike();

            double variance1 = process1_.blackVolatility().link.blackVariance(exercise.lastDate(), strike);
            double variance2 = process2_.blackVolatility().link.blackVariance(exercise.lastDate(), strike);

            double riskFreeDiscount = process1_.riskFreeRate().link.discount(exercise.lastDate());

            // cannot handle non zero dividends, so don't believe this...
            double dividendDiscount1 = process1_.dividendYield().link.discount(exercise.lastDate());
            double dividendDiscount2 = process2_.dividendYield().link.discount(exercise.lastDate());

            double forward1 = process1_.stateVariable().link.value() * dividendDiscount1 / riskFreeDiscount;
            double forward2 = process2_.stateVariable().link.value() * dividendDiscount2 / riskFreeDiscount;

            if (max_basket != null)
            {
                switch (payoff.optionType())
                {
                // euro call on a two asset max basket
                case Option.Type.Call:
                    results_.value = euroTwoAssetMaxBasketCall(forward1, forward2, strike,
                                                               riskFreeDiscount,
                                                               variance1, variance2,
                                                               rho_);

                    break;

                // euro put on a two asset max basket
                case Option.Type.Put:
                    results_.value = strike * riskFreeDiscount -
                                     euroTwoAssetMaxBasketCall(forward1, forward2, 0.0,
                                                               riskFreeDiscount,
                                                               variance1, variance2, rho_) +
                                     euroTwoAssetMaxBasketCall(forward1, forward2, strike,
                                                               riskFreeDiscount,
                                                               variance1, variance2, rho_);
                    break;

                default:
                    Utils.QL_FAIL("unknown option type");
                    break;
                }
            }
            else if (min_basket != null)
            {
                switch (payoff.optionType())
                {
                // euro call on a two asset min basket
                case Option.Type.Call:
                    results_.value = euroTwoAssetMinBasketCall(forward1, forward2, strike,
                                                               riskFreeDiscount,
                                                               variance1, variance2,
                                                               rho_);
                    break;

                // euro put on a two asset min basket
                case Option.Type.Put:
                    results_.value = strike * riskFreeDiscount -
                                     euroTwoAssetMinBasketCall(forward1, forward2, 0.0,
                                                               riskFreeDiscount,
                                                               variance1, variance2, rho_) +
                                     euroTwoAssetMinBasketCall(forward1, forward2, strike,
                                                               riskFreeDiscount,
                                                               variance1, variance2, rho_);
                    break;

                default:
                    Utils.QL_FAIL("unknown option type");
                    break;
                }
            }
            else
            {
                Utils.QL_FAIL("unknown type");
            }
        }
Exemplo n.º 12
0
 public double defaultLegNPV()
 {
     calculate();
     Utils.QL_REQUIRE(defaultLegNPV_ != null, () => "default-leg NPV not available");
     return(defaultLegNPV_.Value);
 }
Exemplo n.º 13
0
 public double couponLegNPV()
 {
     calculate();
     Utils.QL_REQUIRE(couponLegNPV_ != null, () => "coupon-leg NPV not available");
     return(couponLegNPV_.Value);
 }
Exemplo n.º 14
0
 /*! Returns the running spread that, given the quoted recovery
  *  rate, will make the running-only CDS have an NPV of 0.
  *
  *  \note This calculation does not take any upfront into
  *        account, even if one was given.
  */
 public double fairSpread()
 {
     calculate();
     Utils.QL_REQUIRE(fairSpread_ != null, () => "fair spread not available");
     return(fairSpread_.Value);
 }
Exemplo n.º 15
0
 /*! returns the mean, defined as
  *  \f[ \langle x \rangle = \frac{\sum w_i x_i}{\sum w_i}. \f]
  */
 public double mean()
 {
     Utils.QL_REQUIRE(sampleWeight_ > 0.0, () => "sampleWeight_=0, insufficient");
     return(sum_ / sampleWeight_);
 }
Exemplo n.º 16
0
 public virtual int dayCount(Date d1, Date d2)
 {
     Utils.QL_REQUIRE(!empty(), () => "No implementation provided");
     return(dayCounter_.dayCount(d1, d2));
 }
Exemplo n.º 17
0
        public override void calculate()
        {
            Utils.QL_REQUIRE(arguments_.averageType == Average.Type.Geometric, () => "not a geometric average option");
            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () => "not an European Option");

            Date exercise = arguments_.exercise.lastDate();

            PlainVanillaPayoff payoff = arguments_.payoff as PlainVanillaPayoff;

            Utils.QL_REQUIRE(payoff != null, () => "non-plain payoff given");

            double volatility       = process_.blackVolatility().link.blackVol(exercise, payoff.strike());
            double variance         = process_.blackVolatility().link.blackVariance(exercise, payoff.strike());
            double riskFreeDiscount = process_.riskFreeRate().link.discount(exercise);

            DayCounter rfdc  = process_.riskFreeRate().link.dayCounter();
            DayCounter divdc = process_.dividendYield().link.dayCounter();
            DayCounter voldc = process_.blackVolatility().link.dayCounter();

            double dividendYield = 0.5 * (
                process_.riskFreeRate().link.zeroRate(exercise, rfdc,
                                                      Compounding.Continuous,
                                                      Frequency.NoFrequency).rate() +
                process_.dividendYield().link.zeroRate(exercise, divdc,
                                                       Compounding.Continuous,
                                                       Frequency.NoFrequency).rate() +
                volatility * volatility / 6.0);

            double t_q = divdc.yearFraction(process_.dividendYield().link.referenceDate(), exercise);
            double dividendDiscount = Math.Exp(-dividendYield * t_q);

            double spot = process_.stateVariable().link.value();

            Utils.QL_REQUIRE(spot > 0.0, () => "negative or null underlying");

            double forward = spot * dividendDiscount / riskFreeDiscount;

            BlackCalculator black = new BlackCalculator(payoff, forward, Math.Sqrt(variance / 3.0), riskFreeDiscount);

            results_.value = black.value();
            results_.delta = black.delta(spot);
            results_.gamma = black.gamma(spot);

            results_.dividendRho = black.dividendRho(t_q) / 2.0;

            double t_r = rfdc.yearFraction(process_.riskFreeRate().link.referenceDate(), arguments_.exercise.lastDate());

            results_.rho = black.rho(t_r) + 0.5 * black.dividendRho(t_q);

            double t_v = voldc.yearFraction(process_.blackVolatility().link.referenceDate(), arguments_.exercise.lastDate());

            results_.vega = black.vega(t_v) / Math.Sqrt(3.0) +
                            black.dividendRho(t_q) * volatility / 6.0;
            try
            {
                results_.theta = black.theta(spot, t_v);
            }
            catch (Exception /*Error*/)
            {
                results_.theta = null; //Null<Real>();
            }
        }
Exemplo n.º 18
0
 public virtual double yearFraction(Date d1, Date d2, Date refPeriodStart, Date refPeriodEnd)
 {
     Utils.QL_REQUIRE(!empty(), () => "No implementation provided");
     return(dayCounter_.yearFraction(d1, d2, refPeriodStart, refPeriodEnd));
 }
Exemplo n.º 19
0
 public override void initialize(FloatingRateCoupon coupon)
 {
     coupon_ = coupon as OvernightIndexedCoupon;
     Utils.QL_REQUIRE(coupon_ != null, () => "wrong coupon type");
 }
Exemplo n.º 20
0
        public AssetSwap(bool parAssetSwap,
                         Bond bond,
                         double bondCleanPrice,
                         double nonParRepayment,
                         double gearing,
                         IborIndex iborIndex,
                         double spread = 0.0,
                         DayCounter floatingDayCount = null,
                         Date dealMaturity           = null,
                         bool payBondCoupon          = false)
            : base(2)
        {
            bond_            = bond;
            bondCleanPrice_  = bondCleanPrice;
            nonParRepayment_ = nonParRepayment;
            spread_          = spread;
            parSwap_         = parAssetSwap;

            Schedule tempSch = new Schedule(bond_.settlementDate(),
                                            bond_.maturityDate(),
                                            iborIndex.tenor(),
                                            iborIndex.fixingCalendar(),
                                            iborIndex.businessDayConvention(),
                                            iborIndex.businessDayConvention(),
                                            DateGeneration.Rule.Backward,
                                            false); // endOfMonth

            if (dealMaturity == null)
            {
                dealMaturity = bond_.maturityDate();
            }

            Utils.QL_REQUIRE(dealMaturity <= tempSch.dates().Last(), () =>
                             "deal maturity " + dealMaturity +
                             " cannot be later than (adjusted) bond maturity " +
                             tempSch.dates().Last());
            Utils.QL_REQUIRE(dealMaturity > tempSch.dates()[0], () =>
                             "deal maturity " + dealMaturity +
                             " must be later than swap start date " +
                             tempSch.dates()[0]);

            // the following might become an input parameter
            BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following;

            Date     finalDate = tempSch.calendar().adjust(dealMaturity, paymentAdjustment);
            Schedule schedule  = tempSch.until(finalDate);

            // bondCleanPrice must be the (forward) clean price
            // at the floating schedule start date
            upfrontDate_ = schedule.startDate();
            double dirtyPrice = bondCleanPrice_ +
                                bond_.accruedAmount(upfrontDate_);

            double notional = bond_.notional(upfrontDate_);

            /* In the market asset swap, the bond is purchased in return for
             * payment of the full price. The notional of the floating leg is
             * then scaled by the full price. */
            if (!parSwap_)
            {
                notional *= dirtyPrice / 100.0;
            }

            if (floatingDayCount == null)
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withGearings(gearing)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }
            else
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withGearings(gearing)
                           .withPaymentDayCounter(floatingDayCount)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }

            foreach (CashFlow c in legs_[1])
            {
                c.registerWith(update);
            }


            List <CashFlow> bondLeg = bond_.cashflows();
            // skip bond redemption
            int i;

            for (i = 0; i < bondLeg.Count && bondLeg[i].date() <= dealMaturity; ++i)
            {
                // whatever might be the choice for the discounting engine
                // bond flows on upfrontDate_ must be discarded
                bool upfrontDateBondFlows = false;
                if (!bondLeg[i].hasOccurred(upfrontDate_, upfrontDateBondFlows))
                {
                    legs_[0].Add(bondLeg[i]);
                }
            }
            // if the first skipped cashflow is not the redemption
            // and it is a coupon then add the accrued coupon
            if (i < bondLeg.Count - 1)
            {
                Coupon c = bondLeg[i] as Coupon;
                if (c != null)
                {
                    CashFlow accruedCoupon = new SimpleCashFlow(c.accruedAmount(dealMaturity), finalDate);
                    legs_[0].Add(accruedCoupon);
                }
            }
            // add the nonParRepayment_
            CashFlow nonParRepaymentFlow = new SimpleCashFlow(nonParRepayment_, finalDate);

            legs_[0].Add(nonParRepaymentFlow);

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with");

            // special flows
            if (parSwap_)
            {
                // upfront on the floating leg
                double   upfront         = (dirtyPrice - 100.0) / 100.0 * notional;
                CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_);
                legs_[1].Insert(0, upfrontCashFlow);
                // backpayment on the floating leg
                // (accounts for non-par redemption, if any)
                double   backPayment         = notional;
                CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate);
                legs_[1].Add(backPaymentCashFlow);
            }
            else
            {
                // final notional exchange
                CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate);
                legs_[1].Add(finalCashFlow);
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg");

            foreach (CashFlow c in legs_[0])
            {
                c.registerWith(update);
            }

            if (payBondCoupon)
            {
                payer_[0] = -1.0;
                payer_[1] = +1.0;
            }
            else
            {
                payer_[0] = +1.0;
                payer_[1] = -1.0;
            }
        }
Exemplo n.º 21
0
 public InverseCumulativePoisson(double lambda)
 {
     lambda_ = lambda;
     Utils.QL_REQUIRE(lambda_ > 0.0, () => "lambda must be positive");
 }
Exemplo n.º 22
0
 public double floatingLegNPV()
 {
     calculate();
     Utils.QL_REQUIRE(legNPV_.Count > 1 && legNPV_[1] != null, () => "floating-leg NPV not available");
     return(legNPV_[1].GetValueOrDefault());
 }
Exemplo n.º 23
0
 public IList <bool> isRegular()
 {
     Utils.QL_REQUIRE(isRegular_.Count > 0, () => "full interface (isRegular) not available");
     return(isRegular_);
 }
Exemplo n.º 24
0
        public AssetSwap(bool payBondCoupon,
                         Bond bond,
                         double bondCleanPrice,
                         IborIndex iborIndex,
                         double spread,
                         Schedule floatSchedule      = null,
                         DayCounter floatingDayCount = null,
                         bool parAssetSwap           = true)
            : base(2)
        {
            bond_            = bond;
            bondCleanPrice_  = bondCleanPrice;
            nonParRepayment_ = 100;
            spread_          = spread;
            parSwap_         = parAssetSwap;

            Schedule schedule = floatSchedule;

            if (floatSchedule == null)
            {
                schedule = new Schedule(bond_.settlementDate(),
                                        bond_.maturityDate(),
                                        iborIndex.tenor(),
                                        iborIndex.fixingCalendar(),
                                        iborIndex.businessDayConvention(),
                                        iborIndex.businessDayConvention(),
                                        DateGeneration.Rule.Backward,
                                        false); // endOfMonth
            }
            // the following might become an input parameter
            BusinessDayConvention paymentAdjustment = BusinessDayConvention.Following;

            Date finalDate           = schedule.calendar().adjust(schedule.endDate(), paymentAdjustment);
            Date adjBondMaturityDate = schedule.calendar().adjust(bond_.maturityDate(), paymentAdjustment);

            Utils.QL_REQUIRE(finalDate == adjBondMaturityDate, () =>
                             "adjusted schedule end date (" +
                             finalDate +
                             ") must be equal to adjusted bond maturity date (" +
                             adjBondMaturityDate + ")");

            // bondCleanPrice must be the (forward) clean price
            // at the floating schedule start date
            upfrontDate_ = schedule.startDate();
            double dirtyPrice = bondCleanPrice_ +
                                bond_.accruedAmount(upfrontDate_);

            double notional = bond_.notional(upfrontDate_);

            /* In the market asset swap, the bond is purchased in return for
             * payment of the full price. The notional of the floating leg is
             * then scaled by the full price. */
            if (!parSwap_)
            {
                notional *= dirtyPrice / 100.0;
            }

            if (floatingDayCount == null)
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }
            else
            {
                legs_[1] = new IborLeg(schedule, iborIndex)
                           .withSpreads(spread)
                           .withPaymentDayCounter(floatingDayCount)
                           .withNotionals(notional)
                           .withPaymentAdjustment(paymentAdjustment);
            }

            foreach (CashFlow c in legs_[1])
            {
                c.registerWith(update);
            }

            List <CashFlow> bondLeg = bond_.cashflows();

            foreach (CashFlow c in bondLeg)
            {
                // whatever might be the choice for the discounting engine
                // bond flows on upfrontDate_ must be discarded
                bool upfrontDateBondFlows = false;
                if (!(c.hasOccurred(upfrontDate_, upfrontDateBondFlows)))
                {
                    legs_[0].Add(c);
                }
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg to start with");

            // special flows
            if (parSwap_)
            {
                // upfront on the floating leg
                double   upfront         = (dirtyPrice - 100.0) / 100.0 * notional;
                CashFlow upfrontCashFlow = new SimpleCashFlow(upfront, upfrontDate_);
                legs_[1].Insert(0, upfrontCashFlow);
                // backpayment on the floating leg
                // (accounts for non-par redemption, if any)
                double   backPayment         = notional;
                CashFlow backPaymentCashFlow = new SimpleCashFlow(backPayment, finalDate);
                legs_[1].Add(backPaymentCashFlow);
            }
            else
            {
                // final notional exchange
                CashFlow finalCashFlow = new SimpleCashFlow(notional, finalDate);
                legs_[1].Add(finalCashFlow);
            }

            Utils.QL_REQUIRE(!legs_[0].empty(), () => "empty bond leg");

            foreach (CashFlow c in legs_[0])
            {
                c.registerWith(update);
            }

            if (payBondCoupon)
            {
                payer_[0] = -1.0;
                payer_[1] = +1.0;
            }
            else
            {
                payer_[0] = +1.0;
                payer_[1] = -1.0;
            }
        }
Exemplo n.º 25
0
 public BusinessDayConvention terminationDateBusinessDayConvention()
 {
     Utils.QL_REQUIRE(terminationDateConvention_.HasValue, () => "full interface (termination date business day convention) not available");
     return(terminationDateConvention_.Value);
 }
Exemplo n.º 26
0
        public TqrEigenDecomposition(Vector diag, Vector sub, EigenVectorCalculation calc = EigenVectorCalculation.WithEigenVector,
                                     ShiftStrategy strategy = ShiftStrategy.CloseEigenValue)
        {
            iter_ = 0;
            d_    = new Vector(diag);

            int row = calc == EigenVectorCalculation.WithEigenVector ? d_.size() :
                      calc == EigenVectorCalculation.WithoutEigenVector ? 0 : 1;

            ev_ = new Matrix(row, d_.size(), 0.0);

            int n = diag.size();

            Utils.QL_REQUIRE(n == sub.size() + 1, () => "Wrong dimensions");

            Vector e = new Vector(n, 0.0);
            int    i;

            for (i = 1; i < e.Count; ++i)
            {
                e[i] = sub[i - 1];
            }


            for (i = 0; i < ev_.rows(); ++i)
            {
                ev_[i, i] = 1.0;
            }

            for (int k = n - 1; k >= 1; --k)
            {
                while (!offDiagIsZero(k, e))
                {
                    int l = k;
                    while (--l > 0 && !offDiagIsZero(l, e))
                    {
                        ;
                    }
                    iter_++;

                    double q = d_[l];
                    if (strategy != ShiftStrategy.NoShift)
                    {
                        // calculated eigenvalue of 2x2 sub matrix of
                        // [ d_[k-1] e_[k] ]
                        // [  e_[k]  d_[k] ]
                        // which is closer to d_[k+1].
                        // FLOATING_POINT_EXCEPTION
                        double t1 = Math.Sqrt(
                            0.25 * (d_[k] * d_[k] + d_[k - 1] * d_[k - 1])
                            - 0.5 * d_[k - 1] * d_[k] + e[k] * e[k]);
                        double t2 = 0.5 * (d_[k] + d_[k - 1]);

                        double lambda = (Math.Abs(t2 + t1 - d_[k]) < Math.Abs(t2 - t1 - d_[k]))?
                                        t2 + t1 : t2 - t1;

                        if (strategy == ShiftStrategy.CloseEigenValue)
                        {
                            q -= lambda;
                        }
                        else
                        {
                            q -= ((k == n - 1) ? 1.25 : 1.0) * lambda;
                        }
                    }

                    // the QR transformation
                    double sine   = 1.0;
                    double cosine = 1.0;
                    double u      = 0.0;

                    bool recoverUnderflow = false;
                    for (i = l + 1; i <= k && !recoverUnderflow; ++i)
                    {
                        double h = cosine * e[i];
                        double p = sine * e[i];

                        e[i - 1] = Math.Sqrt(p * p + q * q);
                        if (e[i - 1].IsNotEqual(0.0))
                        {
                            sine   = p / e[i - 1];
                            cosine = q / e[i - 1];

                            double g = d_[i - 1] - u;
                            double t = (d_[i] - g) * sine + 2 * cosine * h;

                            u         = sine * t;
                            d_[i - 1] = g + u;
                            q         = cosine * t - h;

                            for (int j = 0; j < ev_.rows(); ++j)
                            {
                                double tmp = ev_[j, i - 1];
                                ev_[j, i - 1] = sine * ev_[j, i] + cosine * tmp;
                                ev_[j, i]     = cosine * ev_[j, i] - sine * tmp;
                            }
                        }
                        else
                        {
                            // recover from underflow
                            d_[i - 1]       -= u;
                            e[l]             = 0.0;
                            recoverUnderflow = true;
                        }
                    }

                    if (!recoverUnderflow)
                    {
                        d_[k] -= u;
                        e[k]   = q;
                        e[l]   = 0.0;
                    }
                }
            }

            // sort (eigenvalues, eigenvectors),
            // code taken from symmetricSchureDecomposition.cpp
            List <KeyValuePair <double, List <double> > > temp = new  InitializedList <KeyValuePair <double, List <double> > >(n);
            List <double> eigenVector = new InitializedList <double>(ev_.rows());

            for (i = 0; i < n; i++)
            {
                if (ev_.rows() > 0)
                {
                    eigenVector = ev_.column(i);
                }

                temp[i] = new KeyValuePair <double, List <double> >(d_[i], eigenVector);
            }

            temp.Sort(KeyValuePairCompare);

            // first element is positive
            for (i = 0; i < n; i++)
            {
                d_[i] = temp[i].Key;
                double sign = 1.0;
                if (ev_.rows() > 0 && temp[i].Value[0] < 0.0)
                {
                    sign = -1.0;
                }
                for (int j = 0; j < ev_.rows(); ++j)
                {
                    ev_[j, i] = sign * temp[i].Value[j];
                }
            }
        }
Exemplo n.º 27
0
 public bool endOfMonth()
 {
     Utils.QL_REQUIRE(endOfMonth_.HasValue, () => "full interface (end of month) not available");
     return(endOfMonth_.Value);
 }
Exemplo n.º 28
0
 /*! returns the maximum sample value */
 public double max()
 {
     Utils.QL_REQUIRE(samples() > 0, () => "empty sample set");
     return(max_);
 }
Exemplo n.º 29
0
 //! the settlementDays used for reference date calculation
 public virtual int settlementDays()
 {
     Utils.QL_REQUIRE(settlementDays_ != null, () => "settlement days not provided for this instance");
     return(settlementDays_.Value);
 }
Exemplo n.º 30
0
 public virtual Date referenceDate()
 {
     Utils.QL_REQUIRE(referenceDate_ != null, () => "referenceDate not available for this instance");
     return(referenceDate_);
 }