示例#1
0
        // to constrained <- from unconstrained
        public AbcdCalibration(List <double> t,
                               List <double> blackVols,
                               double aGuess             = -0.06,
                               double bGuess             = 0.17,
                               double cGuess             = 0.54,
                               double dGuess             = 0.17,
                               bool aIsFixed             = false,
                               bool bIsFixed             = false,
                               bool cIsFixed             = false,
                               bool dIsFixed             = false,
                               bool vegaWeighted         = false,
                               EndCriteria endCriteria   = null,
                               OptimizationMethod method = null)
        {
            aIsFixed_        = aIsFixed;
            bIsFixed_        = bIsFixed;
            cIsFixed_        = cIsFixed;
            dIsFixed_        = dIsFixed;
            a_               = aGuess;
            b_               = bGuess;
            c_               = cGuess;
            d_               = dGuess;
            abcdEndCriteria_ = QLCore.EndCriteria.Type.None;
            endCriteria_     = endCriteria;
            optMethod_       = method;
            weights_         = new InitializedList <double>(blackVols.Count, 1.0 / blackVols.Count);
            vegaWeighted_    = vegaWeighted;
            times_           = t;
            blackVols_       = blackVols;


            AbcdMathFunction.validate(aGuess, bGuess, cGuess, dGuess);

            Utils.QL_REQUIRE(blackVols.Count == t.Count, () =>
                             "mismatch between number of times (" + t.Count + ") and blackVols (" + blackVols.Count + ")");

            // if no optimization method or endCriteria is provided, we provide one
            if (optMethod_ == null)
            {
                double epsfcn = 1.0e-8;
                double xtol   = 1.0e-8;
                double gtol   = 1.0e-8;
                bool   useCostFunctionsJacobian = false;
                optMethod_ = new LevenbergMarquardt(epsfcn, xtol, gtol, useCostFunctionsJacobian);
            }

            if (endCriteria_ == null)
            {
                int    maxIterations = 10000;
                int    maxStationaryStateIterations = 1000;
                double rootEpsilon         = 1.0e-8;
                double functionEpsilon     = 0.3e-4; // Why 0.3e-4 ?
                double gradientNormEpsilon = 0.3e-4; // Why 0.3e-4 ?
                endCriteria_ = new EndCriteria(maxIterations, maxStationaryStateIterations, rootEpsilon, functionEpsilon,
                                               gradientNormEpsilon);
            }
        }
示例#2
0
        public void calculate()
        {
            validCurve_ = false;
            int nInsts = ts_.instruments_.Count, i;

            // ensure rate helpers are sorted
            ts_.instruments_.Sort((x, y) => x.latestDate().CompareTo(y.latestDate()));

            // check that there is no instruments with the same maturity
            for (i = 1; i < nInsts; ++i)
            {
                Date m1 = ts_.instruments_[i - 1].latestDate(),
                     m2 = ts_.instruments_[i].latestDate();
                Utils.QL_REQUIRE(m1 != m2, () => "two instruments have the same maturity (" + m1 + ")");
            }

            // check that there is no instruments with invalid quote
            Utils.QL_REQUIRE((i = ts_.instruments_.FindIndex(x => !x.quoteIsValid())) == -1, () =>
                             "instrument " + i + " (maturity: " + ts_.instruments_[i].latestDate() + ") has an invalid quote");

            // setup instruments and register with them
            ts_.instruments_.ForEach((x, j) => ts_.setTermStructure(j));

            // set initial guess only if the current curve cannot be used as guess
            if (validCurve_)
            {
                Utils.QL_REQUIRE(ts_.data_.Count == nInsts + 1, () =>
                                 "dimension mismatch: expected " + nInsts + 1 + ", actual " + ts_.data_.Count);
            }
            else
            {
                ts_.data_    = new InitializedList <double>(nInsts + 1);
                ts_.data_[0] = ts_.initialValue();
            }

            // calculate dates and times
            ts_.dates_    = new InitializedList <Date>(nInsts + 1);
            ts_.times_    = new InitializedList <double>(nInsts + 1);
            ts_.dates_[0] = ts_.initialDate();
            ts_.times_[0] = ts_.timeFromReference(ts_.dates_[0]);
            for (i = 0; i < nInsts; ++i)
            {
                ts_.dates_[i + 1] = ts_.instruments_[i].latestDate();
                ts_.times_[i + 1] = ts_.timeFromReference(ts_.dates_[i + 1]);
                if (!validCurve_)
                {
                    ts_.data_[i + 1] = ts_.data_[i];
                }
            }

            LevenbergMarquardt solver           = new LevenbergMarquardt(ts_.accuracy_, ts_.accuracy_, ts_.accuracy_);
            EndCriteria        endCriteria      = new EndCriteria(100, 10, 0.00, ts_.accuracy_, 0.00);
            PositiveConstraint posConstraint    = new PositiveConstraint();
            NoConstraint       noConstraint     = new NoConstraint();
            Constraint         solverConstraint = forcePositive_ ? (Constraint)posConstraint : (Constraint)noConstraint;

            // now start the bootstrapping.
            int iInst = localisation_ - 1;

            int dataAdjust = (ts_.interpolator_ as ConvexMonotone).dataSizeAdjustment;

            do
            {
                int    initialDataPt = iInst + 1 - localisation_ + dataAdjust;
                Vector startArray    = new Vector(localisation_ + 1 - dataAdjust);
                for (int j = 0; j < startArray.size() - 1; ++j)
                {
                    startArray[j] = ts_.data_[initialDataPt + j];
                }

                // here we are extending the interpolation a point at a
                // time... but the local interpolator can make an
                // approximation for the final localisation period.
                // e.g. if the localisation is 2, then the first section
                // of the curve will be solved using the first 2
                // instruments... with the local interpolator making
                // suitable boundary conditions.
                ts_.interpolation_ = (ts_.interpolator_ as ConvexMonotone).localInterpolate(ts_.times_, iInst + 2, ts_.data_,
                                                                                            localisation_, ts_.interpolation_ as ConvexMonotoneInterpolation, nInsts + 1);

                if (iInst >= localisation_)
                {
                    startArray[localisation_ - dataAdjust] = ts_.guess(iInst, ts_, false, 0);
                }
                else
                {
                    startArray[localisation_ - dataAdjust] = ts_.data_[0];
                }

                var currentCost = new PenaltyFunction <T, U>(ts_, initialDataPt, ts_.instruments_,
                                                             iInst - localisation_ + 1, iInst + 1);
                Problem          toSolve = new Problem(currentCost, solverConstraint, startArray);
                EndCriteria.Type endType = solver.minimize(toSolve, endCriteria);

                // check the end criteria
                Utils.QL_REQUIRE(endType == EndCriteria.Type.StationaryFunctionAccuracy ||
                                 endType == EndCriteria.Type.StationaryFunctionValue, () =>
                                 "Unable to strip yieldcurve to required accuracy ");
                ++iInst;
            }while (iInst < nInsts);

            validCurve_ = true;
        }