//! fixed reference date, fixed market data
        public CapFloorTermVolCurve(Date settlementDate,
                                    Calendar calendar,
                                    BusinessDayConvention bdc,
                                    List <Period> optionTenors,
                                    List <double> vols,
                                    DayCounter dc = null) // Actual365Fixed()
            : base(settlementDate, calendar, bdc, dc ?? new Actual365Fixed())
        {
            nOptionTenors_ = optionTenors.Count;
            optionTenors_  = optionTenors;
            optionDates_   = new InitializedList <Date>(nOptionTenors_);
            optionTimes_   = new InitializedList <double>(nOptionTenors_);
            volHandles_    = new InitializedList <Handle <Quote> >(vols.Count);
            vols_          = vols; // do not initialize with nOptionTenors_

            checkInputs();
            initializeOptionDatesAndTimes();
            // fill dummy handles to allow generic handle-based computations later
            for (int i = 0; i < nOptionTenors_; ++i)
            {
                volHandles_[i] = new Handle <Quote>(new SimpleQuote(vols_[i]));
            }
            interpolate();
        }
        public MersenneTwisterUniformRng(List <ulong> seeds)
        {
            mt = new InitializedList <ulong>(N);

            seedInitialization(19650218UL);
            int i = 1, j = 0, k = (N > seeds.Count ? N : seeds.Count);

            for (; k != 0; k--)
            {
                mt[i]  = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL)) + seeds[j] + (ulong)j; /* non linear */
                mt[i] &= 0xffffffffUL;                                                                  /* for WORDSIZE > 32 machines */
                i++; j++;
                if (i >= N)
                {
                    mt[0] = mt[N - 1];
                    i     = 1;
                }
                if (j >= seeds.Count)
                {
                    j = 0;
                }
            }
            for (k = N - 1; k != 0; k--)
            {
                mt[i]  = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1566083941UL)) - (ulong)i; /* non linear */
                mt[i] &= 0xffffffffUL;                                                          /* for WORDSIZE > 32 machines */
                i++;
                if (i >= N)
                {
                    mt[0] = mt[N - 1];
                    i     = 1;
                }
            }

            mt[0] = 0x80000000UL; /*MSB is 1; assuring non-zero initial array*/
        }
            public Fj_Helper(Handle <PiecewiseTimeDependentHestonModel> model, double term, double strike, int j)
            {
                j_        = j;
                term_     = term;
                v0_       = model.link.v0();
                x_        = Math.Log(model.link.s0());
                sx_       = Math.Log(strike);
                r_        = new InitializedList <double>(model.link.timeGrid().size() - 1);
                q_        = new InitializedList <double>(model.link.timeGrid().size() - 1);
                model_    = model;
                timeGrid_ = model.link.timeGrid();

                for (int i = 0; i < timeGrid_.size() - 1; ++i)
                {
                    double begin = Math.Min(term_, timeGrid_[i]);
                    double end   = Math.Min(term_, timeGrid_[i + 1]);
                    r_[i] = model.link.riskFreeRate().link.forwardRate(begin, end,
                                                                       Compounding.Continuous, Frequency.NoFrequency).rate();
                    q_[i] = model.link.dividendYield().link.forwardRate(begin, end,
                                                                        Compounding.Continuous, Frequency.NoFrequency).rate();
                }

                Utils.QL_REQUIRE(term_ < model_.link.timeGrid().Last(), () => "maturity is too large");
            }
示例#4
0
        public override List <SparseMatrix> toMatrixDecomp()
        {
            List <SparseMatrix> retVal = new InitializedList <SparseMatrix>(1, mapT_.toMatrix());

            return(retVal);
        }
示例#5
0
        public static List <Func <Vector, double> > multiPathBasisSystem(int dim, int order, PolynomType polynomType)
        {
            List <Func <double, double> > b = pathBasisSystem(order, polynomType);

            List <Func <Vector, double> > ret = new List <Func <Vector, double> >();

            ret.Add((xx) => 1.0);

            for (int i = 1; i <= order; ++i)
            {
                List <Func <Vector, double> > a = w(dim, i, polynomType, b);

                foreach (var iter in a)
                {
                    ret.Add(iter);
                }
            }

            // remove-o-zap: now remove redundant functions.
            // usually we do have a lot of them due to the construction schema.
            // We use a more "hands on" method here.
            List <bool> rm = new InitializedList <bool>(ret.Count, true);

            Vector x = new Vector(dim), v = new Vector(ret.Count);
            MersenneTwisterUniformRng rng = new MersenneTwisterUniformRng(1234UL);

            for (int i = 0; i < 10; ++i)
            {
                int k;

                // calculate random x vector
                for (k = 0; k < dim; ++k)
                {
                    x[k] = rng.next().value;
                }

                // get return values for all basis functions
                for (k = 0; k < ret.Count; ++k)
                {
                    v[k] = ret[k](x);
                }

                // find duplicates
                for (k = 0; k < ret.Count; ++k)
                {
                    if (v.First(xx => (Math.Abs(v[k] - xx) <= 10 * v[k] * Const.QL_EPSILON)).IsEqual(v.First() + k))
                    {
                        // don't remove this item, it's unique!
                        rm[k] = false;
                    }
                }
            }

            int iter2 = 0;

            for (int i = 0; i < rm.Count; ++i)
            {
                if (rm[i])
                {
                    ret.RemoveAt(iter2);
                }
                else
                {
                    ++iter2;
                }
            }

            return(ret);
        }
示例#6
0
 public AmericanExercise(Date latest, bool payoffAtExpiry = false) : base(Type.American, payoffAtExpiry)
 {
     dates_    = new InitializedList <Date>(2);
     dates_[0] = Date.minDate();
     dates_[1] = latest;
 }
示例#7
0
        protected void calculateNextGeneration(List <Candidate> population,
                                               CostFunction costFunction)
        {
            List <Candidate> mirrorPopulation = null;
            List <Candidate> oldPopulation    = (List <Candidate>)population.Clone();

            switch (configuration().strategy)
            {
            case Strategy.Rand1Standard:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();
                List <Candidate> shuffledPop2 = (List <Candidate>)population.Clone();
                population.Shuffle();
                mirrorPopulation = (List <Candidate>)shuffledPop1.Clone();

                for (int popIter = 0; popIter < population.Count; popIter++)
                {
                    population[popIter].values = population[popIter].values
                                                 + configuration().stepsizeWeight
                                                 *(shuffledPop1[popIter].values - shuffledPop2[popIter].values);
                }
            }
            break;

            case Strategy.BestMemberWithJitter:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();
                Vector jitter = new Vector(population[0].values.size(), 0.0);

                for (int popIter = 0; popIter < population.Count; popIter++)
                {
                    for (int jitterIter = 0; jitterIter < jitter.Count; jitterIter++)
                    {
                        jitter[jitterIter] = rng_.nextReal();
                    }

                    population[popIter].values = bestMemberEver_.values
                                                 + Vector.DirectMultiply(
                        shuffledPop1[popIter].values - population[popIter].values
                        , 0.0001 * jitter + configuration().stepsizeWeight);
                }

                mirrorPopulation = new InitializedList <Candidate>(population.Count);
                mirrorPopulation.ForEach((ii, vv) => mirrorPopulation[ii] = (Candidate)bestMemberEver_.Clone());
            }
            break;

            case Strategy.CurrentToBest2Diffs:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();

                for (int popIter = 0; popIter < population.Count; popIter++)
                {
                    population[popIter].values = oldPopulation[popIter].values
                                                 + configuration().stepsizeWeight
                                                 *(bestMemberEver_.values - oldPopulation[popIter].values)
                                                 + configuration().stepsizeWeight
                                                 *(population[popIter].values - shuffledPop1[popIter].values);
                }

                mirrorPopulation = (List <Candidate>)shuffledPop1.Clone();
            }
            break;

            case Strategy.Rand1DiffWithPerVectorDither:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();
                List <Candidate> shuffledPop2 = (List <Candidate>)population.Clone();
                population.Shuffle();
                mirrorPopulation = (List <Candidate>)shuffledPop1.Clone();
                Vector FWeight = new Vector(population.First().values.size(), 0.0);
                for (int fwIter = 0; fwIter < FWeight.Count; fwIter++)
                {
                    FWeight[fwIter] = (1.0 - configuration().stepsizeWeight)
                                      * rng_.nextReal() + configuration().stepsizeWeight;
                }
                for (int popIter = 0; popIter < population.Count; popIter++)
                {
                    population[popIter].values = population[popIter].values
                                                 + Vector.DirectMultiply(FWeight,
                                                                         shuffledPop1[popIter].values - shuffledPop2[popIter].values);
                }
            }
            break;

            case Strategy.Rand1DiffWithDither:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();
                List <Candidate> shuffledPop2 = (List <Candidate>)population.Clone();
                population.Shuffle();
                mirrorPopulation = (List <Candidate>)shuffledPop1.Clone();
                double FWeight = (1.0 - configuration().stepsizeWeight) * rng_.nextReal()
                                 + configuration().stepsizeWeight;
                for (int popIter = 0; popIter < population.Count; popIter++)
                {
                    population[popIter].values = population[popIter].values
                                                 + FWeight * (shuffledPop1[popIter].values -
                                                              shuffledPop2[popIter].values);
                }
            }
            break;

            case Strategy.EitherOrWithOptimalRecombination:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();
                List <Candidate> shuffledPop2 = (List <Candidate>)population.Clone();
                population.Shuffle();
                mirrorPopulation = (List <Candidate>)shuffledPop1.Clone();
                double probFWeight = 0.5;
                if (rng_.nextReal() < probFWeight)
                {
                    for (int popIter = 0; popIter < population.Count; popIter++)
                    {
                        population[popIter].values = oldPopulation[popIter].values
                                                     + configuration().stepsizeWeight
                                                     *(shuffledPop1[popIter].values - shuffledPop2[popIter].values);
                    }
                }
                else
                {
                    double K = 0.5 * (configuration().stepsizeWeight + 1); // invariant with respect to probFWeight used
                    for (int popIter = 0; popIter < population.Count; popIter++)
                    {
                        population[popIter].values = oldPopulation[popIter].values
                                                     + K
                                                     * (shuffledPop1[popIter].values - shuffledPop2[popIter].values
                                                        - 2.0 * population[popIter].values);
                    }
                }
            }
            break;

            case Strategy.Rand1SelfadaptiveWithRotation:
            {
                population.Shuffle();
                List <Candidate> shuffledPop1 = (List <Candidate>)population.Clone();
                population.Shuffle();
                List <Candidate> shuffledPop2 = (List <Candidate>)population.Clone();
                population.Shuffle();
                mirrorPopulation = (List <Candidate>)shuffledPop1.Clone();

                adaptSizeWeights();

                for (int popIter = 0; popIter < population.Count; popIter++)
                {
                    if (rng_.nextReal() < 0.1)
                    {
                        population[popIter].values = rotateArray(bestMemberEver_.values);
                    }
                    else
                    {
                        population[popIter].values = bestMemberEver_.values
                                                     + currGenSizeWeights_[popIter]
                                                     * (shuffledPop1[popIter].values - shuffledPop2[popIter].values);
                    }
                }
            }
            break;

            default:
                Utils.QL_FAIL("Unknown strategy ("
                              + Convert.ToInt32(configuration().strategy) + ")");
                break;
            }

            // in order to avoid unnecessary copying we use the same population object for mutants
            crossover(oldPopulation, population, population, mirrorPopulation,
                      costFunction);
        }
示例#8
0
        public override void calculate()
        {
            // copy black version then adapt to others

            double        value      = 0.0;
            int           optionlets = arguments_.startDates.Count;
            List <double> values     = new InitializedList <double>(optionlets, 0.0);
            List <double> stdDevs    = new InitializedList <double>(optionlets, 0.0);
            List <double> forwards   = new InitializedList <double> (optionlets, 0.0);
            CapFloorType  type       = arguments_.type;

            Handle <YoYInflationTermStructure> yoyTS
                = index().yoyInflationTermStructure();
            Handle <YieldTermStructure> nominalTS
                = yoyTS.link.nominalTermStructure();
            Date settlement = nominalTS.link.referenceDate();


            for (int i = 0; i < optionlets; ++i)
            {
                Date paymentDate = arguments_.payDates[i];
                if (paymentDate > settlement)
                {
                    // discard expired caplets
                    double d = arguments_.nominals[i] *
                               arguments_.gearings[i] *
                               nominalTS.link.discount(paymentDate) *
                               arguments_.accrualTimes[i];

                    // We explicitly have the index and assume that
                    // the fixing is natural, i.e. no convexity adjustment.
                    // If that was required then we would also need
                    // nominal vols in the pricing engine, i.e. a different engine.
                    // This also means that we do not need the coupon to have
                    // a pricing engine to return the swaplet rate and then
                    // the adjusted fixing in the instrument.
                    forwards[i] = yoyTS.link.yoyRate(arguments_.fixingDates[i], new Period(0, TimeUnit.Days));
                    double forward = forwards[i];

                    Date   fixingDate = arguments_.fixingDates[i];
                    double sqrtTime   = 0.0;
                    if (fixingDate > volatility_.link.baseDate())
                    {
                        sqrtTime = Math.Sqrt(volatility_.link.timeFromBase(fixingDate));
                    }

                    if (type == CapFloorType.Cap || type == CapFloorType.Collar)
                    {
                        double strike = arguments_.capRates[i].Value;
                        if (sqrtTime > 0.0)
                        {
                            stdDevs[i] = Math.Sqrt(volatility_.link.totalVariance(fixingDate, strike, new Period(0, TimeUnit.Days)));
                        }

                        // sttDev=0 for already-fixed dates so everything on forward
                        values[i] = optionletImpl(Option.Type.Call, strike, forward, stdDevs[i], d);
                    }
                    if (type == CapFloorType.Floor || type == CapFloorType.Collar)
                    {
                        double strike = arguments_.floorRates[i].Value;
                        if (sqrtTime > 0.0)
                        {
                            stdDevs[i] = Math.Sqrt(volatility_.link.totalVariance(fixingDate, strike, new Period(0, TimeUnit.Days)));
                        }
                        double floorlet = optionletImpl(Option.Type.Put, strike, forward, stdDevs[i], d);
                        if (type == CapFloorType.Floor)
                        {
                            values[i] = floorlet;
                        }
                        else
                        {
                            // a collar is long a cap and short a floor
                            values[i] -= floorlet;
                        }
                    }
                    value += values[i];
                }
            }
            results_.value = value;

            results_.additionalResults["optionletsPrice"]      = values;
            results_.additionalResults["optionletsAtmForward"] = forwards;
            if (type != CapFloorType.Collar)
            {
                results_.additionalResults["optionletsStdDev"] = stdDevs;
            }
        }
        public override void calculate()
        {
            Utils.QL_REQUIRE(arguments_.settlementMethod != Settlement.Method.ParYieldCurve, () =>
                             "cash-settled (ParYieldCurve) swaptions not priced with tree engine");

            Utils.QL_REQUIRE(model_ != null, () => "no model specified");

            Date       referenceDate;
            DayCounter dayCounter;

            ITermStructureConsistentModel tsmodel =
                (ITermStructureConsistentModel)base.model_.link;

            try
            {
                if (tsmodel != null)
                {
                    referenceDate = tsmodel.termStructure().link.referenceDate();
                    dayCounter    = tsmodel.termStructure().link.dayCounter();
                }
                else
                {
                    referenceDate = termStructure_.link.referenceDate();
                    dayCounter    = termStructure_.link.dayCounter();
                }
            }
            catch
            {
                referenceDate = termStructure_.link.referenceDate();
                dayCounter    = termStructure_.link.dayCounter();
            }

            DiscretizedSwaption swaption = new DiscretizedSwaption(arguments_, referenceDate, dayCounter);
            Lattice             lattice;

            if (lattice_ != null)
            {
                lattice = lattice_;
            }
            else
            {
                List <double> times    = swaption.mandatoryTimes();
                TimeGrid      timeGrid = new TimeGrid(times, times.Count, timeSteps_);
                lattice = model_.link.tree(timeGrid);
            }

            List <double> stoppingTimes = new InitializedList <double>(arguments_.exercise.dates().Count);

            for (int i = 0; i < stoppingTimes.Count; ++i)
            {
                stoppingTimes[i] =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.exercise.date(i));
            }

            swaption.initialize(lattice, stoppingTimes.Last());

            double nextExercise;

            List <double> listExercise = new List <double>();

            listExercise.AddRange(stoppingTimes.FindAll(x => x >= 0));
            nextExercise = listExercise[0];
            swaption.rollback(nextExercise);

            results_.value = swaption.presentValue();
        }
示例#10
0
        private void initialize()
        {
            sqrtdt_[0] = Math.Sqrt(t_[0]);
            for (int i = 1; i < size_; ++i)
            {
                sqrtdt_[i] = Math.Sqrt(t_[i] - t_[i - 1]);
            }

            // map is used to indicate which points are already constructed.
            // If map[i] is zero, path point i is yet unconstructed.
            // map[i]-1 is the index of the variate that constructs
            // the path point # i.
            List <int> map = new InitializedList <int>(size_);

            //  The first point in the construction is the global step.
            map[size_ - 1] = 1;
            //  The global step is constructed from the first variate.
            bridgeIndex_[0] = size_ - 1;
            //  The variance of the global step
            stdDev_[0] = Math.Sqrt(t_[size_ - 1]);
            //  The global step to the last point in time is special.
            leftWeight_[0] = rightWeight_[0] = 0.0;
            for (int j = 0, i = 1; i < size_; ++i)
            {
                // Find the next unpopulated entry in the map.
                while (map[j] != 0)
                {
                    ++j;
                }
                int k = j;
                // Find the next populated entry in the map from there.
                while (map[k] == 0)
                {
                    ++k;
                }
                // l-1 is now the index of the point to be constructed next.
                int l = j + ((k - 1 - j) >> 1);
                map[l] = i;
                // The i-th Gaussian variate will be used to set point l-1.
                bridgeIndex_[i] = l;
                leftIndex_[i]   = j;
                rightIndex_[i]  = k;
                if (j != 0)
                {
                    leftWeight_[i]  = (t_[k] - t_[l]) / (t_[k] - t_[j - 1]);
                    rightWeight_[i] = (t_[l] - t_[j - 1]) / (t_[k] - t_[j - 1]);
                    stdDev_[i]      =
                        Math.Sqrt(((t_[l] - t_[j - 1]) * (t_[k] - t_[l]))
                                  / (t_[k] - t_[j - 1]));
                }
                else
                {
                    leftWeight_[i]  = (t_[k] - t_[l]) / t_[k];
                    rightWeight_[i] = t_[l] / t_[k];
                    stdDev_[i]      = Math.Sqrt(t_[l] * (t_[k] - t_[l]) / t_[k]);
                }
                j = k + 1;
                if (j >= size_)
                {
                    j = 0; //  wrap around
                }
            }
        }
示例#11
0
        public void calculate()
        {
            // we might have to call initialize even if the curve is initialized
            // and not moving, just because helpers might be date relative and change
            // with evaluation date change.
            // anyway it makes little sense to use date relative helpers with a
            // non-moving curve if the evaluation date changes
            if (!initialized_ || ts_.moving_)
            {
                initialize();
            }

            // setup helpers
            for (int j = firstAliveHelper_; j < n_; ++j)
            {
                BootstrapHelper <U> helper = ts_.instruments_[j];
                // check for valid quote
                Utils.QL_REQUIRE(helper.quote().link.isValid(), () =>
                                 (j + 1) + " instrument (maturity: " +
                                 helper.pillarDate() + ") has an invalid quote");
                // don't try this at home!
                // This call creates helpers, and removes "const".
                // There is a significant interaction with observability.
                ts_.setTermStructure(ts_.instruments_[j]);
            }

            List <double> times         = ts_.times_;
            List <double> data          = ts_.data_;
            double        accuracy      = accuracy_ != null ? accuracy_.Value : ts_.accuracy_;
            int           maxIterations = ts_.maxIterations() - 1;

            // there might be a valid curve state to use as guess
            bool validData = validCurve_;

            for (int iteration = 0; ; ++iteration)
            {
                previousData_ = new List <double>(ts_.data_);

                List <double?> minValues = new InitializedList <double?>(alive_ + 1, null);
                List <double?> maxValues = new InitializedList <double?>(alive_ + 1, null);
                List <int>     attempts  = new InitializedList <int>(alive_ + 1, 1);

                for (int i = 1; i <= alive_; ++i)
                {
                    // shorter aliases for readability and to avoid duplication
                    double?min = minValues[i];
                    double?max = maxValues[i];

                    // bracket root and calculate guess
                    if (min == null)
                    {
                        min = (minValue_ != null ? minValue_ :
                               ts_.minValueAfter(i, ts_, validData, firstAliveHelper_));
                        max = (maxValue_ != null ? maxValue_ :
                               ts_.maxValueAfter(i, ts_, validData, firstAliveHelper_));
                    }
                    else
                    {
                        min = (min.Value < 0.0 ? min.Value * minFactor_ : min.Value / minFactor_);
                        max = (max.Value > 0.0 ? max.Value * maxFactor_ : max.Value / maxFactor_);
                    }
                    double guess = ts_.guess(i, ts_, validData, firstAliveHelper_);

                    // adjust guess if needed
                    if (guess >= max.Value)
                    {
                        guess = max.Value - (max.Value - min.Value) / 5.0;
                    }
                    else if (guess <= min.Value)
                    {
                        guess = min.Value + (max.Value - min.Value) / 5.0;
                    }

                    // extend interpolation if needed
                    if (!validData)
                    {
                        try
                        {
                            // extend interpolation a point at a time
                            // including the pillar to be boostrapped
                            ts_.interpolation_ = ts_.interpolator_.interpolate(ts_.times_, i + 1, ts_.data_);
                        }
                        catch (Exception)
                        {
                            if (!ts_.interpolator_.global)
                            {
                                throw; // no chance to fix it in a later iteration
                            }
                            // otherwise use Linear while the target
                            // interpolation is not usable yet
                            ts_.interpolation_ = new Linear().interpolate(ts_.times_, i + 1, ts_.data_);
                        }
                        ts_.interpolation_.update();
                    }

                    try
                    {
                        var error = new BootstrapError <T, U>(ts_, ts_.instruments_[i - 1], i);
                        if (validData)
                        {
                            ts_.data_[i] = solver_.solve(error, accuracy, guess, min.Value, max.Value);
                        }
                        else
                        {
                            ts_.data_[i] = firstSolver_.solve(error, accuracy, guess, min.Value, max.Value);
                        }
                    }
                    catch (Exception e)
                    {
                        if (validCurve_)
                        {
                            // the previous curve state might have been a
                            // bad guess, so we retry without using it.
                            // This would be tricky to do here (we're
                            // inside multiple nested for loops, we need
                            // to re-initialize...), so we invalidate the
                            // curve, make a recursive call and then exit.
                            validCurve_ = initialized_ = false;
                            calculate();
                            return;
                        }

                        // If we have more attempts left on this iteration, try again. Note that the max and min
                        // bounds will be widened on the retry.
                        if (attempts[i] < maxAttempts_)
                        {
                            attempts[i]++;
                            i--;
                            continue;
                        }

                        if (dontThrow_)
                        {
                            // Use the fallback value
                            var error = new BootstrapError <T, U>(ts_, ts_.instruments_[i - 1], i);
                            ts_.data_[i] = dontThrowFallback(error, min.Value, max.Value, dontThrowSteps_);

                            // Remember to update the interpolation. If we don't and we are on the last "i", we will still
                            // have the last attempted value in the solver being used in ts_->interpolation_.
                            ts_.interpolation_.update();
                        }
                        else
                        {
                            Utils.QL_FAIL((iteration + 1) + " iteration: failed " +
                                          "at " + (i) + " alive instrument, " +
                                          "pillar " + ts_.instruments_[i - 1].pillarDate() + ", " +
                                          "maturity " + ts_.instruments_[i - 1].maturityDate() +
                                          ", reference date " + ts_.dates_[0] +
                                          ": " + e.Message);
                        }
                    }
                }

                if (!loopRequired_)
                {
                    break; // no need for convergence loop
                }
                // exit condition
                double change = Math.Abs(data[1] - previousData_[1]);
                for (int i = 2; i <= alive_; ++i)
                {
                    change = Math.Max(change, Math.Abs(data[i] - previousData_[i]));
                }
                if (change <= accuracy) // convergence reached
                {
                    break;
                }

                Utils.QL_REQUIRE(iteration < maxIterations, () =>
                                 "convergence not reached after " + iteration +
                                 " iterations; last improvement " + change +
                                 ", required accuracy " + accuracy);
                validData = true;
            }
            validCurve_ = true;
        }
        public DiscretizedConvertible(ConvertibleBond.option.Arguments args,
                                      GeneralizedBlackScholesProcess process, TimeGrid grid)
        {
            arguments_ = args;
            process_   = process;

            dividendValues_ = new Vector(arguments_.dividends.Count, 0.0);

            Date settlementDate = process.riskFreeRate().link.referenceDate();

            for (int i = 0; i < arguments_.dividends.Count; i++)
            {
                if (arguments_.dividends[i].date() >= settlementDate)
                {
                    dividendValues_[i] = arguments_.dividends[i].amount() *
                                         process.riskFreeRate().link.discount(arguments_.dividends[i].date());
                }
            }

            DayCounter dayCounter     = process.riskFreeRate().currentLink().dayCounter();
            Date       bondSettlement = arguments_.settlementDate;

            stoppingTimes_ = new InitializedList <double>(arguments_.exercise.dates().Count, 0.0);
            for (var i = 0; i < stoppingTimes_.Count; i++)
            {
                stoppingTimes_[i] = dayCounter.yearFraction(bondSettlement, arguments_.exercise.date(i));
            }

            callabilityTimes_ = new InitializedList <double>(arguments_.callabilityDates.Count, 0.0);
            for (var i = 0; i < callabilityTimes_.Count; i++)
            {
                callabilityTimes_[i] = dayCounter.yearFraction(bondSettlement, arguments_.callabilityDates[i]);
            }

            couponTimes_ = new InitializedList <double>(arguments_.couponDates.Count, 0.0);
            for (var i = 0; i < couponTimes_.Count; i++)
            {
                couponTimes_[i] = dayCounter.yearFraction(bondSettlement, arguments_.couponDates[i]);
            }

            dividendTimes_ = new InitializedList <double>(arguments_.dividendDates.Count, 0.0);
            for (var i = 0; i < dividendTimes_.Count; i++)
            {
                dividendTimes_[i] = dayCounter.yearFraction(bondSettlement, arguments_.dividendDates[i]);
            }

            if (!grid.empty())
            {
                // adjust times to grid
                for (var i = 0; i < stoppingTimes_.Count; i++)
                {
                    stoppingTimes_[i] = grid.closestTime(stoppingTimes_[i]);
                }

                for (var i = 0; i < couponTimes_.Count; i++)
                {
                    couponTimes_[i] = grid.closestTime(couponTimes_[i]);
                }

                for (var i = 0; i < dividendTimes_.Count; i++)
                {
                    dividendTimes_[i] = grid.closestTime(dividendTimes_[i]);
                }

                for (var i = 0; i < callabilityTimes_.Count; i++)
                {
                    callabilityTimes_[i] = grid.closestTime(callabilityTimes_[i]);
                }
            }
        }
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            int stationaryStateIterations_ = 0;

            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x = P.currentValue();

            iteration_ = 0;
            n_         = x.size();
            ptry_      = new Vector(n_, 0.0);

            // build vertices

            vertices_ = new InitializedList <Vector>(n_ + 1, x);
            for (i_ = 0; i_ < n_; i_++)
            {
                Vector direction = new Vector(n_, 0.0);
                direction[i_] = 1.0;
                Vector tmp = vertices_[i_ + 1];
                P.constraint().update(ref tmp, direction, lambda_);
                vertices_[i_ + 1] = tmp;
            }

            values_ = new Vector(n_ + 1, 0.0);
            for (i_ = 0; i_ <= n_; i_++)
            {
                if (!P.constraint().test(vertices_[i_]))
                {
                    values_[i_] = Double.MaxValue;
                }
                else
                {
                    values_[i_] = P.value(vertices_[i_]);
                }
                if (Double.IsNaN(ytry_))
                {
                    // handle NAN
                    values_[i_] = Double.MaxValue;
                }
            }

            // minimize

            T_  = T0_;
            yb_ = Double.MaxValue;
            pb_ = new Vector(n_, 0.0);
            do
            {
                iterationT_ = iteration_;
                do
                {
                    sum_ = new Vector(n_, 0.0);
                    for (i_ = 0; i_ <= n_; i_++)
                    {
                        sum_ += vertices_[i_];
                    }
                    tt_   = -T_;
                    ilo_  = 0;
                    ihi_  = 1;
                    ynhi_ = values_[0] + tt_ * Math.Log(rng_.next().value);
                    ylo_  = ynhi_;
                    yhi_  = values_[1] + tt_ * Math.Log(rng_.next().value);
                    if (ylo_ > yhi_)
                    {
                        ihi_  = 0;
                        ilo_  = 1;
                        ynhi_ = yhi_;
                        yhi_  = ylo_;
                        ylo_  = ynhi_;
                    }

                    for (i_ = 2; i_ < n_ + 1; i_++)
                    {
                        yt_ = values_[i_] + tt_ * Math.Log(rng_.next().value);
                        if (yt_ <= ylo_)
                        {
                            ilo_ = i_;
                            ylo_ = yt_;
                        }

                        if (yt_ > yhi_)
                        {
                            ynhi_ = yhi_;
                            ihi_  = i_;
                            yhi_  = yt_;
                        }
                        else
                        {
                            if (yt_ > ynhi_)
                            {
                                ynhi_ = yt_;
                            }
                        }
                    }

                    // GSL end criterion in x (cf. above)
                    if (endCriteria.checkStationaryPoint(simplexSize(), 0.0,
                                                         ref stationaryStateIterations_,
                                                         ref ecType) ||
                        endCriteria.checkMaxIterations(iteration_, ref ecType))
                    {
                        // no matter what, we return the best ever point !
                        P.setCurrentValue(pb_);
                        P.setFunctionValue(yb_);
                        return(ecType);
                    }

                    iteration_ += 2;
                    amotsa(P, -1.0);
                    if (ytry_ <= ylo_)
                    {
                        amotsa(P, 2.0);
                    }
                    else
                    {
                        if (ytry_ >= ynhi_)
                        {
                            ysave_ = yhi_;
                            amotsa(P, 0.5);
                            if (ytry_ >= ysave_)
                            {
                                for (i_ = 0; i_ < n_ + 1; i_++)
                                {
                                    if (i_ != ilo_)
                                    {
                                        for (j_ = 0; j_ < n_; j_++)
                                        {
                                            sum_[j_] = 0.5 * (vertices_[i_][j_] +
                                                              vertices_[ilo_][j_]);
                                            vertices_[i_][j_] = sum_[j_];
                                        }

                                        values_[i_] = P.value(sum_);
                                    }
                                }

                                iteration_ += n_;
                                for (i_ = 0; i_ < n_; i_++)
                                {
                                    sum_[i_] = 0.0;
                                }
                                for (i_ = 0; i_ <= n_; i_++)
                                {
                                    sum_ += vertices_[i_];
                                }
                            }
                        }
                        else
                        {
                            iteration_ += 1;
                        }
                    }
                }while (iteration_ <
                        iterationT_ + (scheme_ == Scheme.ConstantFactor ? m_ : 1));

                switch (scheme_)
                {
                case Scheme.ConstantFactor:
                    T_ *= (1.0 - epsilon_);
                    break;

                case Scheme.ConstantBudget:
                    if (iteration_ <= K_)
                    {
                        T_ = T0_ *
                             Math.Pow(1.0 - Convert.ToDouble(iteration_) / Convert.ToDouble(K_), alpha_);
                    }
                    else
                    {
                        T_ = 0.0;
                    }
                    break;
                }
            }while (true);
        }
        public override void calculate()
        {
            Utils.QL_REQUIRE(arguments_.settlementMethod != Settlement.Method.ParYieldCurve, () =>
                             "cash-settled (ParYieldCurve) swaptions not priced by Jamshidian engine");

            Utils.QL_REQUIRE(arguments_.exercise.type() == Exercise.Type.European, () =>
                             "cannot use the Jamshidian decomposition on exotic swaptions");

            Utils.QL_REQUIRE(arguments_.swap.spread.IsEqual(0.0), () =>
                             "non zero spread (" + arguments_.swap.spread + ") not allowed");

            Date       referenceDate;
            DayCounter dayCounter;

            ITermStructureConsistentModel tsmodel = (ITermStructureConsistentModel)base.model_.link;

            try
            {
                if (tsmodel != null)
                {
                    referenceDate = tsmodel.termStructure().link.referenceDate();
                    dayCounter    = tsmodel.termStructure().link.dayCounter();
                }
                else
                {
                    referenceDate = termStructure_.link.referenceDate();
                    dayCounter    = termStructure_.link.dayCounter();
                }
            }
            catch
            {
                referenceDate = termStructure_.link.referenceDate();
                dayCounter    = termStructure_.link.dayCounter();
            }

            List <double> amounts = new InitializedList <double>(arguments_.fixedCoupons.Count);

            for (int i = 0; i < amounts.Count; i++)
            {
                amounts[i] = arguments_.fixedCoupons[i];
            }
            amounts[amounts.Count - 1] = amounts.Last() + arguments_.nominal;

            double maturity = dayCounter.yearFraction(referenceDate,
                                                      arguments_.exercise.date(0));

            List <double> fixedPayTimes = new InitializedList <double>(arguments_.fixedPayDates.Count);

            for (int i = 0; i < fixedPayTimes.Count; i++)
            {
                fixedPayTimes[i] =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.fixedPayDates[i]);
            }

            rStarFinder finder = new rStarFinder(model_, arguments_.nominal, maturity,
                                                 fixedPayTimes, amounts);
            Brent  s1d       = new Brent();
            double minStrike = -10.0;
            double maxStrike = 10.0;

            s1d.setMaxEvaluations(10000);
            s1d.setLowerBound(minStrike);
            s1d.setUpperBound(maxStrike);
            double rStar = s1d.solve(finder, 1e-8, 0.05, minStrike, maxStrike);

            Option.Type w = arguments_.type == VanillaSwap.Type.Payer ?
                            Option.Type.Put : Option.Type.Call;
            int size = arguments_.fixedCoupons.Count;

            double value = 0.0;

            for (int i = 0; i < size; i++)
            {
                double fixedPayTime =
                    dayCounter.yearFraction(referenceDate,
                                            arguments_.fixedPayDates[i]);
                double strike = model_.link.discountBond(maturity,
                                                         fixedPayTime,
                                                         rStar);
                double dboValue = model_.link.discountBondOption(
                    w, strike, maturity,
                    fixedPayTime);
                value += amounts[i] * dboValue;
            }
            results_.value = value;
        }
示例#15
0
 protected LmCorrelationModel(int size, int nArguments)
 {
     size_      = size;
     arguments_ = new InitializedList <Parameter>(nArguments);
 }
            public List <double> value(double x, List <double> y)
            {
                List <double> res = new InitializedList <double>(1, ode1d_(x, y[0]));

                return(res);
            }
示例#17
0
 public FdmLinearOpIterator(List <int> dim)
 {
     index_       = 0;
     dim_         = dim;
     coordinates_ = new InitializedList <int>(dim.Count, 0);
 }
示例#18
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            // set up of the problem
            //double ftol = endCriteria.functionEpsilon();    // end criteria on f(x) (see Numerical Recipes in C++, p.410)
            double xtol = endCriteria.rootEpsilon(); // end criteria on x (see GSL v. 1.9, http://www.gnu.org/software/gsl/)
            int    maxStationaryStateIterations_ = endCriteria.maxStationaryStateIterations();

            EndCriteria.Type ecType = EndCriteria.Type.None;
            P.reset();
            Vector x_ = P.currentValue();
            int    iterationNumber_ = 0;

            // Initialize vertices of the simplex
            bool end = false;
            int  n   = x_.Count;

            vertices_ = new InitializedList <Vector>(n + 1, x_);
            for (int i = 0; i < n; i++)
            {
                Vector direction = new Vector(n, 0.0);
                Vector vertice   = vertices_[i + 1];
                direction[i] = 1.0;
                P.constraint().update(ref vertice, direction, lambda_);
                vertices_[i + 1] = vertice;
            }
            // Initialize function values at the vertices of the simplex
            values_ = new Vector(n + 1, 0.0);
            for (int i = 0; i <= n; i++)
            {
                values_[i] = P.value(vertices_[i]);
            }
            // Loop looking for minimum
            do
            {
                sum_ = new Vector(n, 0.0);
                for (int i = 0; i <= n; i++)
                {
                    sum_ += vertices_[i];
                }
                // Determine the best (iLowest), worst (iHighest)
                // and 2nd worst (iNextHighest) vertices
                int iLowest = 0;
                int iHighest;
                int iNextHighest;
                if (values_[0] < values_[1])
                {
                    iHighest     = 1;
                    iNextHighest = 0;
                }
                else
                {
                    iHighest     = 0;
                    iNextHighest = 1;
                }
                for (int i = 1; i <= n; i++)
                {
                    if (values_[i] > values_[iHighest])
                    {
                        iNextHighest = iHighest;
                        iHighest     = i;
                    }
                    else
                    {
                        if ((values_[i] > values_[iNextHighest]) && i != iHighest)
                        {
                            iNextHighest = i;
                        }
                    }
                    if (values_[i] < values_[iLowest])
                    {
                        iLowest = i;
                    }
                }
                // Now compute accuracy, update iteration number and check end criteria
                // GSL exit strategy on x (see GSL v. 1.9, http://www.gnu.org/software/gsl
                double simplexSize = Utils.computeSimplexSize(vertices_);
                ++iterationNumber_;
                if (simplexSize < xtol || endCriteria.checkMaxIterations(iterationNumber_, ref ecType))
                {
                    endCriteria.checkStationaryPoint(0.0, 0.0, ref maxStationaryStateIterations_, ref ecType);
                    endCriteria.checkMaxIterations(iterationNumber_, ref ecType);
                    x_ = vertices_[iLowest];
                    double low = values_[iLowest];
                    P.setFunctionValue(low);
                    P.setCurrentValue(x_);
                    return(ecType);
                }
                // If end criteria is not met, continue
                double factor = -1.0;
                double vTry   = extrapolate(ref P, iHighest, ref factor);
                if ((vTry <= values_[iLowest]) && (factor.IsEqual(-1.0)))
                {
                    factor = 2.0;
                    extrapolate(ref P, iHighest, ref factor);
                }
                else if (Math.Abs(factor) > Const.QL_EPSILON)
                {
                    if (vTry >= values_[iNextHighest])
                    {
                        double vSave = values_[iHighest];
                        factor = 0.5;
                        vTry   = extrapolate(ref P, iHighest, ref factor);
                        if (vTry >= vSave && Math.Abs(factor) > Const.QL_EPSILON)
                        {
                            for (int i = 0; i <= n; i++)
                            {
                                if (i != iLowest)
                                {
#if QL_ARRAY_EXPRESSIONS
                                    vertices_[i] = 0.5 * (vertices_[i] + vertices_[iLowest]);
#else
                                    vertices_[i] += vertices_[iLowest];
                                    vertices_[i] *= 0.5;
#endif
                                    values_[i] = P.value(vertices_[i]);
                                }
                            }
                        }
                    }
                }
                // If can't extrapolate given the constraints, exit
                if (Math.Abs(factor) <= Const.QL_EPSILON)
                {
                    x_ = vertices_[iLowest];
                    double low = values_[iLowest];
                    P.setFunctionValue(low);
                    P.setCurrentValue(x_);
                    return(EndCriteria.Type.StationaryFunctionValue);
                }
            }while (end == false);
            Utils.QL_FAIL("optimization failed: unexpected behaviour");
            return(0);
        }
示例#19
0
        public SobolRsg(int dimensionality, ulong seed, DirectionIntegers directionIntegers)
        {
            dimensionality_  = dimensionality;
            sequenceCounter_ = 0;
            firstDraw_       = true;

            sequence_        = new Sample <List <double> >(new InitializedList <double>(dimensionality), 1.0);
            integerSequence_ = new InitializedList <ulong>(dimensionality);

            directionIntegers_ = new InitializedList <List <ulong> >(dimensionality);
            for (int i = 0; i < dimensionality; i++)
            {
                directionIntegers_[i] = new InitializedList <ulong>(bits_);
            }

            Utils.QL_REQUIRE(dimensionality > 0, () => "dimensionality must be greater than 0");
            Utils.QL_REQUIRE(dimensionality <= PPMT_MAX_DIM, () =>
                             "dimensionality " + dimensionality + " exceeds the number of available " +
                             "primitive polynomials modulo two (" + PPMT_MAX_DIM + ")");

            // initializes coefficient array of the k-th primitive polynomial
            // and degree of the k-th primitive polynomial
            List <uint> degree = new InitializedList <uint>(dimensionality_);
            List <long> ppmt   = new InitializedList <long>(dimensionality_);

            bool useAltPolynomials = false;

            if (directionIntegers == DirectionIntegers.Kuo || directionIntegers == DirectionIntegers.Kuo2 ||
                directionIntegers == DirectionIntegers.Kuo3 || directionIntegers == DirectionIntegers.SobolLevitan ||
                directionIntegers == DirectionIntegers.SobolLevitanLemieux)
            {
                useAltPolynomials = true;
            }

            // degree 0 is not used
            ppmt[0]   = 0;
            degree[0] = 0;
            int  k, index;
            uint currentDegree = 1;

            k     = 1;
            index = 0;

            uint altDegree = useAltPolynomials ? maxAltDegree : 0;

            for (; k < Math.Min(dimensionality_, altDegree); k++, index++)
            {
                ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index];
                if (ppmt[k] == -1)
                {
                    ++currentDegree;
                    index   = 0;
                    ppmt[k] = AltPrimitivePolynomials[currentDegree - 1][index];
                }

                degree[k] = currentDegree;
            }

            for (; k < dimensionality_; k++, index++)
            {
                ppmt[k] = PrimitivePolynomials[currentDegree - 1][index];
                if (ppmt[k] == -1)
                {
                    ++currentDegree;
                    index   = 0;
                    ppmt[k] = PrimitivePolynomials[currentDegree - 1][index];
                }
                degree[k] = currentDegree;
            }

            // initializes bits_ direction integers for each dimension
            // and store them into directionIntegers_[dimensionality_][bits_]
            //
            // In each dimension k with its associated primitive polynomial,
            // the first degree_[k] direction integers can be chosen freely
            // provided that only the l leftmost bits can be non-zero, and
            // that the l-th leftmost bit must be set

            // degenerate (no free direction integers) first dimension
            int j;

            for (j = 0; j < bits_; j++)
            {
                directionIntegers_[0][j] = (1UL << (bits_ - j - 1));
            }

            int maxTabulated = 0;

            // dimensions from 2 (k=1) to maxTabulated (k=maxTabulated-1) included
            // are initialized from tabulated coefficients
            switch (directionIntegers)
            {
            case DirectionIntegers.Unit:
                maxTabulated = dimensionality_;
                for (k = 1; k < maxTabulated; k++)
                {
                    for (int l = 1; l <= degree[k]; l++)
                    {
                        directionIntegers_[k][l - 1]   = 1UL;
                        directionIntegers_[k][l - 1] <<= (bits_ - l);
                    }
                }
                break;

            case DirectionIntegers.Jaeckel:
                // maxTabulated=32
                maxTabulated = initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.SobolLevitan:
                // maxTabulated=40
                maxTabulated = SLinitializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (SLinitializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = SLinitializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.SobolLevitanLemieux:
                // maxTabulated=360
                maxTabulated = Linitializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Linitializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Linitializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.JoeKuoD5:
                // maxTabulated=1898
                maxTabulated = JoeKuoD5initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (JoeKuoD5initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = JoeKuoD5initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.JoeKuoD6:
                // maxTabulated=1799
                maxTabulated = JoeKuoD6initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (JoeKuoD6initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = JoeKuoD6initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.JoeKuoD7:
                // maxTabulated=1898
                maxTabulated = JoeKuoD7initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (JoeKuoD7initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = JoeKuoD7initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;



            case DirectionIntegers.Kuo:
                // maxTabulated=4925
                maxTabulated = Kuoinitializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Kuoinitializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Kuoinitializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.Kuo2:
                // maxTabulated=3946
                maxTabulated = Kuo2initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Kuo2initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Kuo2initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            case DirectionIntegers.Kuo3:
                // maxTabulated=4585
                maxTabulated = Kuo3initializers.Length + 1;
                for (k = 1; k < Math.Min(dimensionality_, maxTabulated); k++)
                {
                    j = 0;
                    // 0UL marks coefficients' end for a given dimension
                    while (Kuo3initializers[k - 1][j] != 0UL)
                    {
                        directionIntegers_[k][j]   = Kuo3initializers[k - 1][j];
                        directionIntegers_[k][j] <<= (bits_ - j - 1);
                        j++;
                    }
                }
                break;

            default:
                break;
            }

            // random initialization for higher dimensions
            if (dimensionality_ > maxTabulated)
            {
                MersenneTwisterUniformRng uniformRng = new MersenneTwisterUniformRng(seed);
                for (k = maxTabulated; k < dimensionality_; k++)
                {
                    for (int l = 1; l <= degree[k]; l++)
                    {
                        do
                        {
                            // u is in (0,1)
                            double u = uniformRng.next().value;
                            // the direction integer has at most the
                            // rightmost l bits non-zero
                            directionIntegers_[k][l - 1] = (ulong)(u * (1UL << l));
                        }while ((directionIntegers_[k][l - 1] & 1UL) == 0);
                        // iterate until the direction integer is odd
                        // that is it has the rightmost bit set

                        // shifting bits_-l bits to the left
                        // we are guaranteed that the l-th leftmost bit
                        // is set, and only the first l leftmost bit
                        // can be non-zero
                        directionIntegers_[k][l - 1] <<= (bits_ - l);
                    }
                }
            }

            // computation of directionIntegers_[k][l] for l>=degree_[k]
            // by recurrence relation
            for (k = 1; k < dimensionality_; k++)
            {
                uint gk = degree[k];
                for (int l = (int)gk; l < bits_; l++)
                {
                    // eq. 8.19 "Monte Carlo Methods in Finance" by P. Jдckel
                    ulong n = (directionIntegers_[k][(int)(l - gk)] >> (int)gk);
                    // a[k][j] are the coefficients of the monomials in ppmt[k]
                    // The highest order coefficient a[k][0] is not actually
                    // used in the recurrence relation, and the lowest order
                    // coefficient a[k][gk] is always set: this is the reason
                    // why the highest and lowest coefficient of
                    // the polynomial ppmt[k] are not included in its encoding,
                    // provided that its degree is known.
                    // That is: a[k][j] = ppmt[k] >> (gk-j-1)
                    for (uint z = 1; z < gk; z++)
                    {
                        // XORed with a selection of (unshifted) direction
                        // integers controlled by which of the a[k][j] are set
                        if ((((ulong)ppmt[k] >> (int)(gk - z - 1)) & 1UL) != 0)
                        {
                            n ^= directionIntegers_[k][(int)(l - z)];
                        }
                    }
                    // a[k][gk] is always set, so directionIntegers_[k][l-gk]
                    // will always enter
                    n ^= directionIntegers_[k][(int)(l - gk)];
                    directionIntegers_[k][l] = n;
                }
            }

            // initialize the Sobol integer/double vectors
            // first draw
            for (k = 0; k < dimensionality_; k++)
            {
                integerSequence_[k] = directionIntegers_[k][0];
            }
        }
示例#20
0
        protected GMRESResult solveImpl(Vector b, Vector x0)
        {
            double      bn = Vector.Norm2(b);
            GMRESResult result;

            if (bn.IsEqual(0.0))
            {
                result = new GMRESResult(new InitializedList <double>(1, 0.0), b);
                return(result);
            }

            Vector x = !x0.empty() ? x0 : new Vector(b.size(), 0.0);
            Vector r = b - A_(x);

            double g = Vector.Norm2(r);

            if (g / bn < relTol_)
            {
                result = new GMRESResult(new InitializedList <double>(1, g / bn), x);
                return(result);
            }

            List <Vector> v = new InitializedList <Vector>(1, r / g);
            List <Vector> h = new InitializedList <Vector>(1, new Vector(maxIter_, 0.0));
            List <double> c = new List <double>(maxIter_ + 1),
                          s = new List <double>(maxIter_ + 1),
                          z = new List <double>(maxIter_ + 1);

            z[0] = g;

            List <double> errors = new InitializedList <double>(1, g / bn);

            for (int j = 0; j < maxIter_ && errors.Last() >= relTol_; ++j)
            {
                h.Add(new Vector(maxIter_, 0.0));
                Vector w = A_((M_ != null) ? M_(v[j]) : v[j]);

                for (int i = 0; i <= j; ++i)
                {
                    h[i][j] = Vector.DotProduct(w, v[i]);
                    w      -= h[i][j] * v[i];
                }

                h[j + 1][j] = Vector.Norm2(w);

                if (h[j + 1][j] < Const.QL_EPSILON * Const.QL_EPSILON)
                {
                    break;
                }

                v.Add(w / h[j + 1][j]);

                for (int i = 0; i < j; ++i)
                {
                    double h0 = c[i] * h[i][j] + s[i] * h[i + 1][j];
                    double h1 = -s[i] * h[i][j] + c[i] * h[i + 1][j];

                    h[i][j]     = h0;
                    h[i + 1][j] = h1;
                }

                double nu = Math.Sqrt((h[j][j]) * (h[j][j])
                                      + (h[j + 1][j]) * (h[j + 1][j]));

                c[j] = h[j][j] / nu;
                s[j] = h[j + 1][j] / nu;

                h[j][j]     = nu;
                h[j + 1][j] = 0.0;

                z[j + 1] = -s[j] * z[j];
                z[j]     = c[j] * z[j];

                errors.Add(Math.Abs(z[j + 1] / bn));
            }

            int k = v.Count - 1;

            Vector y = new Vector(k, 0.0);

            y[k - 1] = z[k - 1] / h[k - 1][k - 1];

            for (int i = k - 2; i >= 0; --i)
            {
                y[i] = (z[i] - h[i].inner_product(
                            i + 1, k, i + 1, y, 0.0)) / h[i][i];
            }

            Vector xm = new Vector(x.Count, 0.0);

            for (int i = 0; i < x.Count; i++)
            {
                xm[i] = v[i].inner_product(0, k, 0, y, 0.0);
            }

            xm = x + ((M_ != null) ? M_(xm) : xm);

            result = new GMRESResult(errors, xm);
            return(result);
        }
示例#21
0
        public override void update()
        {
            Vector        tmp = new Vector(size_);
            List <double> dx  = new InitializedList <double>(size_ - 1),
                          S   = new InitializedList <double>(size_ - 1);

            for (int i = 0; i < size_ - 1; ++i)
            {
                dx[i] = xBegin_[i + 1] - xBegin_[i];
                S[i]  = (yBegin_[i + 1] - yBegin_[i]) / dx[i];
            }

            // first derivative approximation
            if (da_ == CubicInterpolation.DerivativeApprox.Spline)
            {
                TridiagonalOperator L = new TridiagonalOperator(size_);
                for (int i = 1; i < size_ - 1; ++i)
                {
                    L.setMidRow(i, dx[i], 2.0 * (dx[i] + dx[i - 1]), dx[i - 1]);
                    tmp[i] = 3.0 * (dx[i] * S[i - 1] + dx[i - 1] * S[i]);
                }

                // left boundary condition
                switch (leftType_)
                {
                case CubicInterpolation.BoundaryCondition.NotAKnot:
                    // ignoring end condition value
                    L.setFirstRow(dx[1] * (dx[1] + dx[0]), (dx[0] + dx[1]) * (dx[0] + dx[1]));
                    tmp[0] = S[0] * dx[1] * (2.0 * dx[1] + 3.0 * dx[0]) + S[1] * dx[0] * dx[0];
                    break;

                case CubicInterpolation.BoundaryCondition.FirstDerivative:
                    L.setFirstRow(1.0, 0.0);
                    tmp[0] = leftValue_;
                    break;

                case CubicInterpolation.BoundaryCondition.SecondDerivative:
                    L.setFirstRow(2.0, 1.0);
                    tmp[0] = 3.0 * S[0] - leftValue_ * dx[0] / 2.0;
                    break;

                case CubicInterpolation.BoundaryCondition.Periodic:
                    // ignoring end condition value
                    throw new NotImplementedException("this end condition is not implemented yet");

                case CubicInterpolation.BoundaryCondition.Lagrange:
                    L.setFirstRow(1.0, 0.0);
                    tmp[0] = cubicInterpolatingPolynomialDerivative(
                        this.xBegin_[0], this.xBegin_[1],
                        this.xBegin_[2], this.xBegin_[3],
                        this.yBegin_[0], this.yBegin_[1],
                        this.yBegin_[2], this.yBegin_[3],
                        this.xBegin_[0]);
                    break;

                default:
                    throw new ArgumentException("unknown end condition");
                }

                // right boundary condition
                switch (rightType_)
                {
                case CubicInterpolation.BoundaryCondition.NotAKnot:
                    // ignoring end condition value
                    L.setLastRow(-(dx[size_ - 2] + dx[size_ - 3]) * (dx[size_ - 2] + dx[size_ - 3]),
                                 -dx[size_ - 3] * (dx[size_ - 3] + dx[size_ - 2]));
                    tmp[size_ - 1] = -S[size_ - 3] * dx[size_ - 2] * dx[size_ - 2] -
                                     S[size_ - 2] * dx[size_ - 3] * (3.0 * dx[size_ - 2] + 2.0 * dx[size_ - 3]);
                    break;

                case CubicInterpolation.BoundaryCondition.FirstDerivative:
                    L.setLastRow(0.0, 1.0);
                    tmp[size_ - 1] = rightValue_;
                    break;

                case CubicInterpolation.BoundaryCondition.SecondDerivative:
                    L.setLastRow(1.0, 2.0);
                    tmp[size_ - 1] = 3.0 * S[size_ - 2] + rightValue_ * dx[size_ - 2] / 2.0;
                    break;

                case CubicInterpolation.BoundaryCondition.Periodic:
                    // ignoring end condition value
                    throw new NotImplementedException("this end condition is not implemented yet");

                case CubicInterpolation.BoundaryCondition.Lagrange:
                    L.setLastRow(0.0, 1.0);
                    tmp[size_ - 1] = cubicInterpolatingPolynomialDerivative(
                        this.xBegin_[size_ - 4], this.xBegin_[size_ - 3],
                        this.xBegin_[size_ - 2], this.xBegin_[size_ - 1],
                        this.yBegin_[size_ - 4], this.yBegin_[size_ - 3],
                        this.yBegin_[size_ - 2], this.yBegin_[size_ - 1],
                        this.xBegin_[size_ - 1]);
                    break;

                default:
                    throw new ArgumentException("unknown end condition");
                }

                // solve the system
                tmp = L.solveFor(tmp);
            }
            else if (da_ == CubicInterpolation.DerivativeApprox.SplineOM1)
            {
                Matrix T_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    T_[i, i]     = dx[i] / 6.0;
                    T_[i, i + 1] = (dx[i + 1] + dx[i]) / 3.0;
                    T_[i, i + 2] = dx[i + 1] / 6.0;
                }
                Matrix S_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    S_[i, i]     = 1.0 / dx[i];
                    S_[i, i + 1] = -(1.0 / dx[i + 1] + 1.0 / dx[i]);
                    S_[i, i + 2] = 1.0 / dx[i + 1];
                }
                Matrix Up_ = new Matrix(size_, 2, 0.0);
                Up_[0, 0]         = 1;
                Up_[size_ - 1, 1] = 1;
                Matrix Us_ = new Matrix(size_, size_ - 2, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    Us_[i + 1, i] = 1;
                }
                Matrix Z_ = Us_ * Matrix.inverse(T_ * Us_);
                Matrix I_ = new Matrix(size_, size_, 0.0);
                for (int i = 0; i < size_; ++i)
                {
                    I_[i, i] = 1;
                }
                Matrix V_ = (I_ - Z_ * T_) * Up_;
                Matrix W_ = Z_ * S_;
                Matrix Q_ = new Matrix(size_, size_, 0.0);
                Q_[0, 0] = 1.0 / (size_ - 1) * dx[0] * dx[0] * dx[0];
                Q_[0, 1] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[0] * dx[0] * dx[0];
                for (int i = 1; i < size_ - 1; ++i)
                {
                    Q_[i, i - 1] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[i - 1] * dx[i - 1] * dx[i - 1];
                    Q_[i, i]     = 1.0 / (size_ - 1) * dx[i] * dx[i] * dx[i] + 1.0 / (size_ - 1) * dx[i - 1] * dx[i - 1] * dx[i - 1];
                    Q_[i, i + 1] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[i] * dx[i] * dx[i];
                }
                Q_[size_ - 1, size_ - 2] = 7.0 / 8 * 1.0 / (size_ - 1) * dx[size_ - 2] * dx[size_ - 2] * dx[size_ - 2];
                Q_[size_ - 1, size_ - 1] = 1.0 / (size_ - 1) * dx[size_ - 2] * dx[size_ - 2] * dx[size_ - 2];
                Matrix J_ = (I_ - V_ * Matrix.inverse(Matrix.transpose(V_) * Q_ * V_) * Matrix.transpose(V_) * Q_) * W_;
                Vector Y_ = new Vector(size_);
                for (int i = 0; i < size_; ++i)
                {
                    Y_[i] = this.yBegin_[i];
                }
                Vector D_ = J_ * Y_;
                for (int i = 0; i < size_ - 1; ++i)
                {
                    tmp[i] = (Y_[i + 1] - Y_[i]) / dx[i] - (2.0 * D_[i] + D_[i + 1]) * dx[i] / 6.0;
                }
                tmp[size_ - 1] = tmp[size_ - 2] + D_[size_ - 2] * dx[size_ - 2] + (D_[size_ - 1] - D_[size_ - 2]) * dx[size_ - 2] / 2.0;
            }
            else if (da_ == CubicInterpolation.DerivativeApprox.SplineOM2)
            {
                Matrix T_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    T_[i, i]     = dx[i] / 6.0;
                    T_[i, i + 1] = (dx[i] + dx[i + 1]) / 3.0;
                    T_[i, i + 2] = dx[i + 1] / 6.0;
                }
                Matrix S_ = new Matrix(size_ - 2, size_, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    S_[i, i]     = 1.0 / dx[i];
                    S_[i, i + 1] = -(1.0 / dx[i + 1] + 1.0 / dx[i]);
                    S_[i, i + 2] = 1.0 / dx[i + 1];
                }
                Matrix Up_ = new Matrix(size_, 2, 0.0);
                Up_[0, 0]         = 1;
                Up_[size_ - 1, 1] = 1;
                Matrix Us_ = new Matrix(size_, size_ - 2, 0.0);
                for (int i = 0; i < size_ - 2; ++i)
                {
                    Us_[i + 1, i] = 1;
                }
                Matrix Z_ = Us_ * Matrix.inverse(T_ * Us_);
                Matrix I_ = new Matrix(size_, size_, 0.0);
                for (int i = 0; i < size_; ++i)
                {
                    I_[i, i] = 1;
                }
                Matrix V_ = (I_ - Z_ * T_) * Up_;
                Matrix W_ = Z_ * S_;
                Matrix Q_ = new Matrix(size_, size_, 0.0);
                Q_[0, 0] = 1.0 / (size_ - 1) * dx[0];
                Q_[0, 1] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[0];
                for (int i = 1; i < size_ - 1; ++i)
                {
                    Q_[i, i - 1] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[i - 1];
                    Q_[i, i]     = 1.0 / (size_ - 1) * dx[i] + 1.0 / (size_ - 1) * dx[i - 1];
                    Q_[i, i + 1] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[i];
                }
                Q_[size_ - 1, size_ - 2] = 1.0 / 2 * 1.0 / (size_ - 1) * dx[size_ - 2];
                Q_[size_ - 1, size_ - 1] = 1.0 / (size_ - 1) * dx[size_ - 2];
                Matrix J_ = (I_ - V_ * Matrix.inverse(Matrix.transpose(V_) * Q_ * V_) * Matrix.transpose(V_) * Q_) * W_;
                Vector Y_ = new Vector(size_);
                for (int i = 0; i < size_; ++i)
                {
                    Y_[i] = this.yBegin_[i];
                }
                Vector D_ = J_ * Y_;
                for (int i = 0; i < size_ - 1; ++i)
                {
                    tmp[i] = (Y_[i + 1] - Y_[i]) / dx[i] - (2.0 * D_[i] + D_[i + 1]) * dx[i] / 6.0;
                }
                tmp[size_ - 1] = tmp[size_ - 2] + D_[size_ - 2] * dx[size_ - 2] + (D_[size_ - 1] - D_[size_ - 2]) * dx[size_ - 2] / 2.0;
            }
            else
            {
                // local schemes
                if (size_ == 2)
                {
                    tmp[0] = tmp[1] = S[0];
                }
                else
                {
                    switch (da_)
                    {
                    case CubicInterpolation.DerivativeApprox.FourthOrder:
                        throw new NotImplementedException("FourthOrder not implemented yet");

                    case CubicInterpolation.DerivativeApprox.Parabolic:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            tmp[i] = (dx[i - 1] * S[i] + dx[i] * S[i - 1]) / (dx[i] + dx[i - 1]);
                        }
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] -
                                          dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;

                    case CubicInterpolation.DerivativeApprox.FritschButland:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            double Smin = Math.Min(S[i - 1], S[i]);
                            double Smax = Math.Max(S[i - 1], S[i]);
                            tmp[i] = 3.0 * Smin * Smax / (Smax + 2.0 * Smin);
                        }
                        // end points
                        tmp[0]         = ((2.0 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[0] + dx[1]);
                        tmp[size_ - 1] = ((2.0 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] -
                                          dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 2] + dx[size_ - 3]);
                        break;

                    case CubicInterpolation.DerivativeApprox.Akima:
                        tmp[0] = (Math.Abs(S[1] - S[0]) * 2 * S[0] * S[1] +
                                  Math.Abs(2 * S[0] * S[1] - 4 * S[0] * S[0] * S[1]) * S[0]) /
                                 (Math.Abs(S[1] - S[0]) + Math.Abs(2 * S[0] * S[1] - 4 * S[0] * S[0] * S[1]));
                        tmp[1] = (Math.Abs(S[2] - S[1]) * S[0] + Math.Abs(S[0] - 2 * S[0] * S[1]) * S[1]) /
                                 (Math.Abs(S[2] - S[1]) + Math.Abs(S[0] - 2 * S[0] * S[1]));
                        for (int i = 2; i < size_ - 2; ++i)
                        {
                            if ((S[i - 2].IsEqual(S[i - 1])) && (S[i].IsNotEqual(S[i + 1])))
                            {
                                tmp[i] = S[i - 1];
                            }
                            else if ((S[i - 2].IsNotEqual(S[i - 1])) && (S[i].IsEqual(S[i + 1])))
                            {
                                tmp[i] = S[i];
                            }
                            else if (S[i].IsEqual(S[i - 1]))
                            {
                                tmp[i] = S[i];
                            }
                            else if ((S[i - 2].IsEqual(S[i - 1])) && (S[i - 1].IsNotEqual(S[i])) && (S[i].IsEqual(S[i + 1])))
                            {
                                tmp[i] = (S[i - 1] + S[i]) / 2.0;
                            }
                            else
                            {
                                tmp[i] = (Math.Abs(S[i + 1] - S[i]) * S[i - 1] + Math.Abs(S[i - 1] - S[i - 2]) * S[i]) /
                                         (Math.Abs(S[i + 1] - S[i]) + Math.Abs(S[i - 1] - S[i - 2]));
                            }
                        }
                        tmp[size_ - 2] = (Math.Abs(2 * S[size_ - 2] * S[size_ - 3] - S[size_ - 2]) * S[size_ - 3] +
                                          Math.Abs(S[size_ - 3] - S[size_ - 4]) * S[size_ - 2]) /
                                         (Math.Abs(2 * S[size_ - 2] * S[size_ - 3] - S[size_ - 2]) +
                                          Math.Abs(S[size_ - 3] - S[size_ - 4]));
                        tmp[size_ - 1] =
                            (Math.Abs(4 * S[size_ - 2] * S[size_ - 2] * S[size_ - 3] - 2 * S[size_ - 2] * S[size_ - 3]) *
                             S[size_ - 2] + Math.Abs(S[size_ - 2] - S[size_ - 3]) * 2 * S[size_ - 2] * S[size_ - 3]) /
                            (Math.Abs(4 * S[size_ - 2] * S[size_ - 2] * S[size_ - 3] - 2 * S[size_ - 2] * S[size_ - 3]) +
                             Math.Abs(S[size_ - 2] - S[size_ - 3]));
                        break;

                    case CubicInterpolation.DerivativeApprox.Kruger:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            if (S[i - 1] * S[i] < 0.0)
                            {
                                // slope changes sign at point
                                tmp[i] = 0.0;
                            }
                            else
                            {
                                // slope will be between the slopes of the adjacent
                                // straight lines and should approach zero if the
                                // slope of either line approaches zero
                                tmp[i] = 2.0 / (1.0 / S[i - 1] + 1.0 / S[i]);
                            }
                        }
                        // end points
                        tmp[0]         = (3.0 * S[0] - tmp[1]) / 2.0;
                        tmp[size_ - 1] = (3.0 * S[size_ - 2] - tmp[size_ - 2]) / 2.0;
                        break;

                    case CubicInterpolation.DerivativeApprox.Harmonic:
                        // intermediate points
                        for (int i = 1; i < size_ - 1; ++i)
                        {
                            double w1 = 2 * dx[i] + dx[i - 1];
                            double w2 = dx[i] + 2 * dx[i - 1];
                            if (S[i - 1] * S[i] <= 0.0)
                            {
                                // slope changes sign at point
                                tmp[i] = 0.0;
                            }
                            else
                            {
                                // weighted harmonic mean of S[i] and S[i-1] if they
                                // have the same sign; otherwise 0
                                tmp[i] = (w1 + w2) / (w1 / S[i - 1] + w2 / S[i]);
                            }
                        }
                        // end points [0]
                        tmp[0] = ((2 * dx[0] + dx[1]) * S[0] - dx[0] * S[1]) / (dx[1] + dx[0]);
                        if (tmp[0] * S[0] < 0.0)
                        {
                            tmp[0] = 0;
                        }
                        else if (S[0] * S[1] < 0)
                        {
                            if (Math.Abs(tmp[0]) > Math.Abs(3 * S[0]))
                            {
                                tmp[0] = 3 * S[0];
                            }
                        }
                        // end points [n-1]
                        tmp[size_ - 1] = ((2 * dx[size_ - 2] + dx[size_ - 3]) * S[size_ - 2] - dx[size_ - 2] * S[size_ - 3]) / (dx[size_ - 3] + dx[size_ - 2]);
                        if (tmp[size_ - 1] * S[size_ - 2] < 0.0)
                        {
                            tmp[size_ - 1] = 0;
                        }
                        else if (S[size_ - 2] * S[size_ - 3] < 0)
                        {
                            if (Math.Abs(tmp[size_ - 1]) > Math.Abs(3 * S[size_ - 2]))
                            {
                                tmp[size_ - 1] = 3 * S[size_ - 2];
                            }
                        }
                        break;

                    default:
                        throw new ArgumentException("unknown scheme");
                    }
                }
            }

            monotonicityAdjustments_.Erase();

            // Hyman monotonicity constrained filter
            if (monotonic_)
            {
                double correction;
                double pm, pu, pd, M;
                for (int i = 0; i < size_; ++i)
                {
                    if (i == 0)
                    {
                        if (tmp[i] * S[0] > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]),
                                                  Math.Abs(3.0 * S[0]));
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction.IsNotEqual(tmp[i]))
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                    else if (i == size_ - 1)
                    {
                        if (tmp[i] * S[size_ - 2] > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]), Math.Abs(3.0 * S[size_ - 2]));
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction.IsNotEqual(tmp[i]))
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                    else
                    {
                        pm = (S[i - 1] * dx[i] + S[i] * dx[i - 1]) /
                             (dx[i - 1] + dx[i]);
                        M = 3.0 * Math.Min(Math.Min(Math.Abs(S[i - 1]), Math.Abs(S[i])),
                                           Math.Abs(pm));
                        if (i > 1)
                        {
                            if ((S[i - 1] - S[i - 2]) * (S[i] - S[i - 1]) > 0.0)
                            {
                                pd = (S[i - 1] * (2.0 * dx[i - 1] + dx[i - 2])
                                      - S[i - 2] * dx[i - 1]) /
                                     (dx[i - 2] + dx[i - 1]);
                                if (pm * pd > 0.0 && pm * (S[i - 1] - S[i - 2]) > 0.0)
                                {
                                    M = Math.Max(M, 1.5 * Math.Min(
                                                     Math.Abs(pm), Math.Abs(pd)));
                                }
                            }
                        }
                        if (i < size_ - 2)
                        {
                            if ((S[i] - S[i - 1]) * (S[i + 1] - S[i]) > 0.0)
                            {
                                pu = (S[i] * (2.0 * dx[i] + dx[i + 1]) - S[i + 1] * dx[i]) /
                                     (dx[i] + dx[i + 1]);
                                if (pm * pu > 0.0 && -pm * (S[i] - S[i - 1]) > 0.0)
                                {
                                    M = Math.Max(M, 1.5 * Math.Min(
                                                     Math.Abs(pm), Math.Abs(pu)));
                                }
                            }
                        }
                        if (tmp[i] * pm > 0.0)
                        {
                            correction = tmp[i] / Math.Abs(tmp[i]) *
                                         Math.Min(Math.Abs(tmp[i]), M);
                        }
                        else
                        {
                            correction = 0.0;
                        }
                        if (correction.IsNotEqual(tmp[i]))
                        {
                            tmp[i] = correction;
                            monotonicityAdjustments_[i] = true;
                        }
                    }
                }
            }

            // cubic coefficients
            for (int i = 0; i < size_ - 1; ++i)
            {
                a_[i] = tmp[i];
                b_[i] = (3.0 * S[i] - tmp[i + 1] - 2.0 * tmp[i]) / dx[i];
                c_[i] = (tmp[i + 1] + tmp[i] - 2.0 * S[i]) / (dx[i] * dx[i]);
            }

            primitiveConst_[0] = 0.0;
            for (int i = 1; i < size_ - 1; ++i)
            {
                primitiveConst_[i] = primitiveConst_[i - 1]
                                     + dx[i - 1] *
                                     (yBegin_[i - 1] + dx[i - 1] *
                                      (a_[i - 1] / 2.0 + dx[i - 1] *
                                       (b_[i - 1] / 3.0 + dx[i - 1] * c_[i - 1] / 4.0)));
            }
        }
示例#22
0
        public void sabrCalibrationSection(Cube marketVolCube, Cube parametersCube, Period swapTenor)
        {
            List <double> optionTimes = marketVolCube.optionTimes();
            List <double> swapLengths = marketVolCube.swapLengths();
            List <Date>   optionDates = marketVolCube.optionDates();
            List <Period> swapTenors  = marketVolCube.swapTenors();

            int k = swapTenors.IndexOf(swapTenors.First(x => x == swapTenor));

            Utils.QL_REQUIRE(k != swapTenors.Count, () => "swap tenor not found");

            List <double> calibrationResult = new InitializedList <double>(8, 0.0);
            List <Matrix> tmpMarketVolCube  = marketVolCube.points();

            List <double> strikes      = new List <double>(strikeSpreads_.Count);
            List <double> volatilities = new List <double>(strikeSpreads_.Count);

            for (int j = 0; j < optionTimes.Count; j++)
            {
                double atmForward = atmStrike(optionDates[j], swapTenors[k]);
                double shiftTmp   = atmVol_.link.shift(optionTimes[j], swapLengths[k]);
                strikes.Clear();
                volatilities.Clear();
                for (int i = 0; i < nStrikes_; i++)
                {
                    double strike = atmForward + strikeSpreads_[i];
                    if (strike + shiftTmp >= cutoffStrike_)
                    {
                        strikes.Add(strike);
                        volatilities.Add(tmpMarketVolCube[i][j, k]);
                    }
                }

                List <double> guess = parametersGuess_.value(optionTimes[j], swapLengths[k]);

                var sabrInterpolation = new SABRInterpolation(strikes,
                                                              strikes.Count,
                                                              volatilities,
                                                              optionTimes[j], atmForward,
                                                              guess[0], guess[1],
                                                              guess[2], guess[3],
                                                              isParameterFixed_[0],
                                                              isParameterFixed_[1],
                                                              isParameterFixed_[2],
                                                              isParameterFixed_[3],
                                                              vegaWeightedSmileFit_,
                                                              endCriteria_,
                                                              optMethod_,
                                                              errorAccept_,
                                                              useMaxError_,
                                                              maxGuesses_,
                                                              shiftTmp,
                                                              volatilityType());//shiftTmp

                sabrInterpolation.update();
                double interpolationError = sabrInterpolation.rmsError();
                calibrationResult[0] = sabrInterpolation.alpha();
                calibrationResult[1] = sabrInterpolation.beta();
                calibrationResult[2] = sabrInterpolation.nu();
                calibrationResult[3] = sabrInterpolation.rho();
                calibrationResult[4] = atmForward;
                calibrationResult[5] = interpolationError;
                calibrationResult[6] = sabrInterpolation.maxError();
                calibrationResult[7] = (double)sabrInterpolation.endCriteria();

                Utils.QL_REQUIRE(calibrationResult[7].IsNotEqual((double)EndCriteria.Type.MaxIterations), () =>
                                 "section calibration failed: " +
                                 "option tenor " + optionDates[j] +
                                 ", swap tenor " + swapTenors[k] +
                                 ": max iteration (" +
                                 endCriteria_.maxIterations() + ")" +
                                 ", alpha " + calibrationResult[0] +
                                 ", beta " + calibrationResult[1] +
                                 ", nu " + calibrationResult[2] +
                                 ", rho " + calibrationResult[3] +
                                 ", max error " + calibrationResult[6] +
                                 ", error " + calibrationResult[5]
                                 );

                Utils.QL_REQUIRE(useMaxError_ ? calibrationResult[6] > 0 : calibrationResult[5] < maxErrorTolerance_, () =>
                                 "section calibration failed: " +
                                 "option tenor " + optionDates[j] +
                                 ", swap tenor " + swapTenors[k] +
                                 (useMaxError_ ? ": max error " : ": error ") +
                                 (useMaxError_ ? calibrationResult[6] : calibrationResult[5]) +
                                 ", alpha " + calibrationResult[0] +
                                 ", beta " + calibrationResult[1] +
                                 ", nu " + calibrationResult[2] +
                                 ", rho " + calibrationResult[3] +
                                 (useMaxError_ ? ": error" : ": max error ") +
                                 (useMaxError_ ? calibrationResult[5] : calibrationResult[6])
                                 );

                parametersCube.setPoint(optionDates[j], swapTenors[k], optionTimes[j], swapLengths[k], calibrationResult);
                parametersCube.updateInterpolators();
            }
        }
示例#23
0
        protected void crossover(List <Candidate> oldPopulation,
                                 List <Candidate> population,
                                 List <Candidate> mutantPopulation,
                                 List <Candidate> mirrorPopulation,
                                 CostFunction costFunction)
        {
            if (configuration().crossoverIsAdaptive)
            {
                adaptCrossover();
            }

            Vector mutationProbabilities = getMutationProbabilities(population);

            List <Vector> crossoverMask = new InitializedList <Vector>(population.Count);

            crossoverMask.ForEach((ii, vv) => crossoverMask[ii] = new Vector(population.First().values.size(), 1.0));

            List <Vector> invCrossoverMask = new InitializedList <Vector>(population.Count);

            invCrossoverMask.ForEach((ii, vv) => invCrossoverMask[ii] = new Vector(population.First().values.size(), 1.0));

            getCrossoverMask(crossoverMask, invCrossoverMask, mutationProbabilities);

            // crossover of the old and mutant population
            for (int popIter = 0; popIter < population.Count; popIter++)
            {
                population[popIter].values = Vector.DirectMultiply(oldPopulation[popIter].values, invCrossoverMask[popIter])
                                             + Vector.DirectMultiply(mutantPopulation[popIter].values,
                                                                     crossoverMask[popIter]);
                // immediately apply bounds if specified
                if (configuration().applyBounds)
                {
                    for (int memIter = 0; memIter < population[popIter].values.size(); memIter++)
                    {
                        if (population[popIter].values[memIter] > upperBound_[memIter])
                        {
                            population[popIter].values[memIter] = upperBound_[memIter]
                                                                  + rng_.nextReal()
                                                                  * (mirrorPopulation[popIter].values[memIter]
                                                                     - upperBound_[memIter]);
                        }
                        if (population[popIter].values[memIter] < lowerBound_[memIter])
                        {
                            population[popIter].values[memIter] = lowerBound_[memIter]
                                                                  + rng_.nextReal()
                                                                  * (mirrorPopulation[popIter].values[memIter]
                                                                     - lowerBound_[memIter]);
                        }
                    }
                }

                // evaluate objective function as soon as possible to avoid unnecessary loops
                try
                {
                    population[popIter].cost = costFunction.value(population[popIter].values);

                    if (Double.IsNaN(population[popIter].cost))
                    {
                        population[popIter].cost = Double.MaxValue;
                    }
                }
                catch
                {
                    population[popIter].cost = Double.MaxValue;
                }
            }
        }
示例#24
0
        public void recalibration(double beta, Period swapTenor)
        {
            List <double> betaVector = new InitializedList <double>(nOptionTenors_, beta);

            recalibration(betaVector, swapTenor);
        }
示例#25
0
 public EuropeanExercise(Date date) : base(Type.European)
 {
     dates_ = new InitializedList <Date>(1, date);
 }
示例#26
0
        protected Cube sabrCalibration(Cube marketVolCube)
        {
            List <double> optionTimes = marketVolCube.optionTimes();
            List <double> swapLengths = marketVolCube.swapLengths();
            List <Date>   optionDates = marketVolCube.optionDates();
            List <Period> swapTenors  = marketVolCube.swapTenors();
            Matrix        alphas      = new Matrix(optionTimes.Count, swapLengths.Count, 0.0);
            Matrix        betas       = new Matrix(alphas);
            Matrix        nus         = new Matrix(alphas);
            Matrix        rhos        = new Matrix(alphas);
            Matrix        forwards    = new Matrix(alphas);
            Matrix        errors      = new Matrix(alphas);
            Matrix        maxErrors   = new Matrix(alphas);
            Matrix        endCriteria = new Matrix(alphas);

            List <Matrix> tmpMarketVolCube = marketVolCube.points();

            List <double> strikes      = new InitializedList <double>(strikeSpreads_.Count);
            List <double> volatilities = new InitializedList <double>(strikeSpreads_.Count);

            for (int j = 0; j < optionTimes.Count; j++)
            {
                for (int k = 0; k < swapLengths.Count; k++)
                {
                    double atmForward = atmStrike(optionDates[j], swapTenors[k]);
                    double shiftTmp   = atmVol_.link.shift(optionTimes[j], swapLengths[k]);
                    strikes.Clear();
                    volatilities.Clear();
                    for (int i = 0; i < nStrikes_; i++)
                    {
                        double strike = atmForward + strikeSpreads_[i];
                        if (strike + shiftTmp >= cutoffStrike_)
                        {
                            strikes.Add(strike);
                            Matrix matrix = tmpMarketVolCube[i];
                            volatilities.Add(matrix[j, k]);
                        }
                    }

                    List <double> guess = parametersGuess_.value(optionTimes[j], swapLengths[k]);


                    SABRInterpolation sabrInterpolation = new SABRInterpolation(strikes, strikes.Count,
                                                                                volatilities,
                                                                                optionTimes[j], atmForward,
                                                                                guess[0], guess[1],
                                                                                guess[2], guess[3],
                                                                                isParameterFixed_[0],
                                                                                isParameterFixed_[1],
                                                                                isParameterFixed_[2],
                                                                                isParameterFixed_[3],
                                                                                vegaWeightedSmileFit_,
                                                                                endCriteria_,
                                                                                optMethod_,
                                                                                errorAccept_,
                                                                                useMaxError_,
                                                                                maxGuesses_,
                                                                                shiftTmp,
                                                                                volatilityType());// shiftTmp
                    sabrInterpolation.update();

                    double rmsError = sabrInterpolation.rmsError();
                    double maxError = sabrInterpolation.maxError();
                    alphas     [j, k] = sabrInterpolation.alpha();
                    betas      [j, k] = sabrInterpolation.beta();
                    nus        [j, k] = sabrInterpolation.nu();
                    rhos       [j, k] = sabrInterpolation.rho();
                    forwards   [j, k] = atmForward;
                    errors     [j, k] = rmsError;
                    maxErrors  [j, k] = maxError;
                    endCriteria[j, k] = (double)sabrInterpolation.endCriteria();

                    Utils.QL_REQUIRE(endCriteria[j, k].IsNotEqual((double)EndCriteria.Type.MaxIterations), () =>
                                     "global swaptions calibration failed: " +
                                     "MaxIterations reached: " + "\n" +
                                     "option maturity = " + optionDates[j] + ", \n" +
                                     "swap tenor = " + swapTenors[k] + ", \n" +
                                     "error = " + (errors[j, k]) + ", \n" +
                                     "max error = " + (maxErrors[j, k]) + ", \n" +
                                     "   alpha = " + alphas[j, k] + "n" +
                                     "   beta = " + betas[j, k] + "\n" +
                                     "   nu = " + nus[j, k] + "\n" +
                                     "   rho = " + rhos[j, k] + "\n"
                                     );

                    Utils.QL_REQUIRE(useMaxError_ ? maxError > 0 : rmsError < maxErrorTolerance_, () =>
                                     "global swaptions calibration failed: " +
                                     "option tenor " + optionDates[j] +
                                     ", swap tenor " + swapTenors[k] +
                                     (useMaxError_ ? ": max error " : ": error") +
                                     (useMaxError_ ? maxError : rmsError) +
                                     "   alpha = " + alphas[j, k] + "\n" +
                                     "   beta = " + betas[j, k] + "\n" +
                                     "   nu = " + nus[j, k] + "\n" +
                                     "   rho = " + rhos[j, k] + "\n" +
                                     (useMaxError_ ? ": error" : ": max error ") +
                                     (useMaxError_ ? rmsError : maxError)

                                     );
                }
            }
            Cube sabrParametersCube = new Cube(optionDates, swapTenors, optionTimes, swapLengths, 8, true, backwardFlat_);

            sabrParametersCube.setLayer(0, alphas);
            sabrParametersCube.setLayer(1, betas);
            sabrParametersCube.setLayer(2, nus);
            sabrParametersCube.setLayer(3, rhos);
            sabrParametersCube.setLayer(4, forwards);
            sabrParametersCube.setLayer(5, errors);
            sabrParametersCube.setLayer(6, maxErrors);
            sabrParametersCube.setLayer(7, endCriteria);

            return(sabrParametersCube);
        }
        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];
                }
            }
        }
示例#28
0
        protected List <double> spreadVolInterpolation(Date atmOptionDate, Period atmSwapTenor)
        {
            double atmOptionTime = timeFromReference(atmOptionDate);
            double atmTimeLength = swapLength(atmSwapTenor);

            List <double> result      = new List <double>();
            List <double> optionTimes = sparseParameters_.optionTimes();
            List <double> swapLengths = sparseParameters_.swapLengths();
            List <Date>   optionDates = sparseParameters_.optionDates();
            List <Period> swapTenors  = sparseParameters_.swapTenors();

            double optionTimesPreviousNode, swapLengthsPreviousNode;

            optionTimesPreviousNode = optionTimes_.First(x => x >= Math.Min(atmOptionTime, optionTimes_.Max()));
            int optionTimesPreviousIndex = optionTimes_.IndexOf(optionTimesPreviousNode);

            swapLengthsPreviousNode = swapLengths_.First(x => x >= Math.Min(atmTimeLength, swapLengths_.Max()));
            int swapLengthsPreviousIndex = swapLengths_.IndexOf(swapLengthsPreviousNode);

            if (optionTimesPreviousIndex > 0)
            {
                optionTimesPreviousIndex--;
            }

            if (swapLengthsPreviousIndex > 0)
            {
                swapLengthsPreviousIndex--;
            }

            List <List <SmileSection> > smiles = new List <List <SmileSection> >();
            List <SmileSection>         smilesOnPreviousExpiry = new List <SmileSection>();
            List <SmileSection>         smilesOnNextExpiry     = new List <SmileSection>();

            Utils.QL_REQUIRE(optionTimesPreviousIndex + 1 < sparseSmiles_.Count, () =>
                             "optionTimesPreviousIndex+1 >= sparseSmiles_.size()");
            Utils.QL_REQUIRE(swapLengthsPreviousIndex + 1 < sparseSmiles_[0].Count, () =>
                             "swapLengthsPreviousIndex+1 >= sparseSmiles_[0].size()");
            smilesOnPreviousExpiry.Add(sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex]);
            smilesOnPreviousExpiry.Add(sparseSmiles_[optionTimesPreviousIndex][swapLengthsPreviousIndex + 1]);
            smilesOnNextExpiry.Add(sparseSmiles_[optionTimesPreviousIndex + 1][swapLengthsPreviousIndex]);
            smilesOnNextExpiry.Add(sparseSmiles_[optionTimesPreviousIndex + 1][swapLengthsPreviousIndex + 1]);

            smiles.Add(smilesOnPreviousExpiry);
            smiles.Add(smilesOnNextExpiry);

            List <double> optionsNodes = new InitializedList <double>(2);

            optionsNodes[0] = optionTimes[optionTimesPreviousIndex];
            optionsNodes[1] = optionTimes[optionTimesPreviousIndex + 1];

            List <Date> optionsDateNodes = new InitializedList <Date>(2);

            optionsDateNodes[0] = optionDates[optionTimesPreviousIndex];
            optionsDateNodes[1] = optionDates[optionTimesPreviousIndex + 1];

            List <double> swapLengthsNodes = new InitializedList <double>(2);

            swapLengthsNodes[0] = swapLengths[swapLengthsPreviousIndex];
            swapLengthsNodes[1] = swapLengths[swapLengthsPreviousIndex + 1];

            List <Period> swapTenorNodes = new InitializedList <Period>(2);

            swapTenorNodes[0] = swapTenors[swapLengthsPreviousIndex];
            swapTenorNodes[1] = swapTenors[swapLengthsPreviousIndex + 1];

            double atmForward = atmStrike(atmOptionDate, atmSwapTenor);
            double shift      = atmVol_.link.shift(atmOptionTime, atmTimeLength);

            Matrix atmForwards = new Matrix(2, 2, 0.0);
            Matrix atmShifts   = new Matrix(2, 2, 0.0);
            Matrix atmVols     = new Matrix(2, 2, 0.0);

            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    atmForwards[i, j] = atmStrike(optionsDateNodes[i], swapTenorNodes[j]);
                    atmShifts[i, j]   = atmVol_.link.shift(optionsNodes[i], swapLengthsNodes[j]);
                    atmVols[i, j]     = atmVol_.link.volatility(optionsDateNodes[i], swapTenorNodes[j], atmForwards[i, j]);

                    /* With the old implementation the interpolated spreads on ATM
                     * volatilities were null even if the spreads on ATM volatilities to be
                     * interpolated were non-zero. The new implementation removes
                     * this behaviour, but introduces a small ERROR in the cube:
                     * even if no spreads are applied on any cube ATM volatility corresponding
                     * to quoted smile sections (that is ATM volatilities in sparse cube), the
                     * cube ATM volatilities corresponding to not quoted smile sections (that
                     * is ATM volatilities in dense cube) are no more exactly the quoted values,
                     * but that ones PLUS the linear interpolation of the fit errors on the ATM
                     * volatilities in sparse cube whose spreads are used in the calculation.
                     * A similar imprecision is introduced to the volatilities in dense cube
                     * whith moneyness near to 1.
                     * (See below how spreadVols are calculated).
                     * The extent of this error depends on the quality of the fit: in case of
                     * good fits it is negligibile.
                     */
                }
            }

            for (int k = 0; k < nStrikes_; k++)
            {
                double strike    = Math.Max(atmForward + strikeSpreads_[k], cutoffStrike_ - shift);
                double moneyness = (atmForward + shift) / (strike + shift);

                Matrix strikes    = new Matrix(2, 2, 0.0);
                Matrix spreadVols = new Matrix(2, 2, 0.0);
                for (int i = 0; i < 2; i++)
                {
                    for (int j = 0; j < 2; j++)
                    {
                        strikes[i, j]    = (atmForwards[i, j] + atmShifts[i, j]) / moneyness - atmShifts[i, j];
                        spreadVols[i, j] = smiles[i][j].volatility(strikes[i, j]) - atmVols[i, j];
                    }
                }
                Cube localInterpolator = new Cube(optionsDateNodes, swapTenorNodes, optionsNodes, swapLengthsNodes, 1);
                localInterpolator.setLayer(0, spreadVols);
                localInterpolator.updateInterpolators();

                result.Add(localInterpolator.value(atmOptionTime, atmTimeLength)[0]);
            }
            return(result);
        }
示例#29
0
 public LinearInterpolationImpl(List <double> xBegin, int size, List <double> yBegin)
     : base(xBegin, size, yBegin)
 {
     primitiveConst_ = new InitializedList <double>(size_);
     s_ = new InitializedList <double>(size_);
 }
        protected void rkqs(List <double> y,
                            List <double> dydx,
                            ref double x,
                            double htry,
                            double eps,
                            List <double> yScale,
                            ref double hdid,
                            ref double hnext,
                            OdeFct derivs)
        {
            int           n = y.Count;
            double        errmax, xnew;
            List <double> yerr = new InitializedList <double>(n), ytemp = new InitializedList <double>(n);

            double h = htry;

            for (;;)
            {
                rkck(y, dydx, ref x, h, ref ytemp, ref yerr, derivs);
                errmax = 0.0;
                for (int i = 0; i < n; i++)
                {
                    errmax = Math.Max(errmax, Math.Abs(yerr[i] / yScale[i]));
                }
                errmax /= eps;
                if (errmax > 1.0)
                {
                    double htemp1 = ADAPTIVERK_SAFETY * h * Math.Pow(errmax, ADAPTIVERK_PSHRINK);
                    double htemp2 = h / 10;
                    // These would be std::min and std::max, of course,
                    // but VC++14 had problems inlining them and caused
                    // the wrong results to be calculated.  The problem
                    // seems to be fixed in update 3, but let's keep this
                    // implementation for compatibility.
                    double max_positive = htemp1 > htemp2 ? htemp1 : htemp2;
                    double max_negative = htemp1 < htemp2 ? htemp1 : htemp2;
                    h    = ((h >= 0.0) ? max_positive : max_negative);
                    xnew = x + h;
                    if (xnew.IsEqual(x))
                    {
                        Utils.QL_FAIL("Stepsize underflow (" + h + " at x = " + x
                                      + ") in AdaptiveRungeKutta::rkqs");
                    }
                    continue;
                }
                else
                {
                    if (errmax > ADAPTIVERK_ERRCON)
                    {
                        hnext = ADAPTIVERK_SAFETY * h * Math.Pow(errmax, ADAPTIVERK_PGROW);
                    }
                    else
                    {
                        hnext = 5.0 * h;
                    }
                    x += (hdid = h);
                    for (int i = 0; i < n; i++)
                    {
                        y[i] = ytemp[i];
                    }
                    break;
                }
            }
        }