Пример #1
0
        public static IList <T> Clone <T>(this IList <T> input) where T : ICloneable, new ()
        {
            IList <T> c = new InitializedList <T>(input.Count);

            c.ForEach((ii, vv) => c[ii] = (T)input[ii].Clone());
            return(c);
        }
Пример #2
0
        public override EndCriteria.Type minimize(Problem P, EndCriteria endCriteria)
        {
            EndCriteria.Type ecType = EndCriteria.Type.None;

            upperBound_         = P.constraint().upperBound(P.currentValue());
            lowerBound_         = P.constraint().lowerBound(P.currentValue());
            currGenSizeWeights_ = new Vector(configuration().populationMembers,
                                             configuration().stepsizeWeight);
            currGenCrossover_ = new Vector(configuration().populationMembers,
                                           configuration().crossoverProbability);

            List <Candidate> population = new InitializedList <Candidate>(configuration().populationMembers);

            population.ForEach((ii, vv) => population[ii] = new Candidate(P.currentValue().size()));

            fillInitialPopulation(population, P);

            //original quantlib use partial_sort as only first elements is needed
            double fxOld = population.Min(x => x.cost);

            bestMemberEver_ = (Candidate)population.First(x => x.cost.IsEqual(fxOld)).Clone();
            int iteration = 0, stationaryPointIteration = 0;

            // main loop - calculate consecutive emerging populations
            while (!endCriteria.checkMaxIterations(iteration++, ref ecType))
            {
                calculateNextGeneration(population, P.costFunction());

                double    fxNew = population.Min(x => x.cost);
                Candidate tmp   = (Candidate)population.First(x => x.cost.IsEqual(fxNew)).Clone();

                if (fxNew < bestMemberEver_.cost)
                {
                    bestMemberEver_ = tmp;
                }

                if (endCriteria.checkStationaryFunctionValue(fxOld, fxNew, ref stationaryPointIteration,
                                                             ref ecType))
                {
                    break;
                }
                fxOld = fxNew;
            }

            P.setCurrentValue(bestMemberEver_.values);
            P.setFunctionValue(bestMemberEver_.cost);
            return(ecType);
        }
        public override void calculate()
        {
            /* this engine cannot really check for the averageType==Geometric
             * since it can be used as control variate for the Arithmetic version
             *  QL_REQUIRE(arguments_.averageType == Average::Geometric,
             *             "not a geometric average option");
             */

            if (!(arguments_.exercise.type() == Exercise.Type.European))
            {
                throw new ApplicationException("not an European Option");
            }

            double runningLog;
            int    pastFixings;

            if (arguments_.averageType == Average.Type.Geometric)
            {
                if (!(arguments_.runningAccumulator > 0.0))
                {
                    throw new ApplicationException("positive running product required: "
                                                   + arguments_.runningAccumulator + " not allowed");
                }
                runningLog =
                    Math.Log(arguments_.runningAccumulator.GetValueOrDefault());
                pastFixings = arguments_.pastFixings.GetValueOrDefault();
            }
            else      // it is being used as control variate
            {
                runningLog  = 1.0;
                pastFixings = 0;
            }

            PlainVanillaPayoff payoff = (PlainVanillaPayoff)(arguments_.payoff);

            if (payoff == null)
            {
                throw new ApplicationException("non-plain payoff given");
            }

            Date          referenceDate = process_.riskFreeRate().link.referenceDate();
            DayCounter    rfdc          = process_.riskFreeRate().link.dayCounter();
            DayCounter    divdc         = process_.dividendYield().link.dayCounter();
            DayCounter    voldc         = process_.blackVolatility().link.dayCounter();
            List <double> fixingTimes   = new InitializedList <double>(arguments_.fixingDates.Count());
            int           i;

            for (i = 0; i < arguments_.fixingDates.Count(); i++)
            {
                if (arguments_.fixingDates[i] >= referenceDate)
                {
                    double t = voldc.yearFraction(referenceDate,
                                                  arguments_.fixingDates[i]);
                    fixingTimes.Add(t);
                }
            }

            int    remainingFixings = fixingTimes.Count();
            int    numberOfFixings  = pastFixings + remainingFixings;
            double N = numberOfFixings;

            double pastWeight   = pastFixings / N;
            double futureWeight = 1.0 - pastWeight;

            /*double timeSum = std::accumulate(fixingTimes.begin(),
             *                             fixingTimes.end(), 0.0);*/
            double timeSum = 0;

            fixingTimes.ForEach((ii, vv) => timeSum += fixingTimes[ii]);

            double vola = process_.blackVolatility().link.blackVol(
                arguments_.exercise.lastDate(),
                payoff.strike());
            double temp = 0.0;

            for (i = pastFixings + 1; i < numberOfFixings; i++)
            {
                temp += fixingTimes[i - pastFixings - 1] * (N - i);
            }
            double variance   = vola * vola / N / N * (timeSum + 2.0 * temp);
            double dsigG_dsig = Math.Sqrt((timeSum + 2.0 * temp)) / N;
            double sigG       = vola * dsigG_dsig;
            double dmuG_dsig  = -(vola * timeSum) / N;

            Date   exDate       = arguments_.exercise.lastDate();
            double dividendRate = process_.dividendYield().link.
                                  zeroRate(exDate, divdc, Compounding.Continuous, Frequency.NoFrequency).rate();
            double riskFreeRate = process_.riskFreeRate().link.
                                  zeroRate(exDate, rfdc, Compounding.Continuous, Frequency.NoFrequency).rate();
            double nu = riskFreeRate - dividendRate - 0.5 * vola * vola;

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

            if (!(s > 0.0))
            {
                throw new ApplicationException("positive underlying value required");
            }

            int    M   = (pastFixings == 0 ? 1 : pastFixings);
            double muG = pastWeight * runningLog / M +
                         futureWeight * Math.Log(s) + nu * timeSum / N;
            double forwardPrice = Math.Exp(muG + variance / 2.0);

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

            BlackCalculator black = new BlackCalculator(payoff, forwardPrice, Math.Sqrt(variance),
                                                        riskFreeDiscount);

            results_.value = black.value();
            results_.delta = futureWeight * black.delta(forwardPrice) * forwardPrice / s;
            results_.gamma = forwardPrice * futureWeight / (s * s)
                             * (black.gamma(forwardPrice) * futureWeight * forwardPrice
                                - pastWeight * black.delta(forwardPrice));

            double Nx_1, nx_1;
            CumulativeNormalDistribution CND = new CumulativeNormalDistribution();
            NormalDistribution           ND  = new NormalDistribution();

            if (sigG > Const.QL_Epsilon)
            {
                double x_1 = (muG - Math.Log(payoff.strike()) + variance) / sigG;
                Nx_1 = CND.value(x_1);
                nx_1 = ND.value(x_1);
            }
            else
            {
                Nx_1 = (muG > Math.Log(payoff.strike()) ? 1.0 : 0.0);
                nx_1 = 0.0;
            }
            results_.vega = forwardPrice * riskFreeDiscount *
                            ((dmuG_dsig + sigG * dsigG_dsig) * Nx_1 + nx_1 * dsigG_dsig);

            if (payoff.optionType() == Option.Type.Put)
            {
                results_.vega -= riskFreeDiscount * forwardPrice *
                                 (dmuG_dsig + sigG * dsigG_dsig);
            }

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

            results_.rho = black.rho(tRho) * timeSum / (N * tRho)
                           - (tRho - timeSum / N) * results_.value;

            double tDiv = divdc.yearFraction(
                process_.dividendYield().link.referenceDate(),
                arguments_.exercise.lastDate());

            results_.dividendRho = black.dividendRho(tDiv) * timeSum / (N * tDiv);

            results_.strikeSensitivity = black.strikeSensitivity();

            results_.theta = Utils.blackScholesTheta(process_,
                                                     results_.value.GetValueOrDefault(),
                                                     results_.delta.GetValueOrDefault(),
                                                     results_.gamma.GetValueOrDefault());
        }
Пример #4
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;
                }
            }
        }
Пример #5
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);
        }