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); }
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()); }
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; } } }
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); }