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 FdmHestonVarianceMesher(int size, HestonProcess process, double maturity, int tAvgSteps = 10, double epsilon = 0.0001) : base(size) { List <double> vGrid = new InitializedList <double>(size, 0.0); List <double> pGrid = new InitializedList <double>(size, 0.0); double df = 4.0 * process.theta() * process.kappa() / Math.Pow(process.sigma(), 2); try { List <pair_double> grid = new List <pair_double>(); for (int l = 1; l <= tAvgSteps; ++l) { double t = (maturity * l) / tAvgSteps; double ncp = 4 * process.kappa() * Math.Exp(-process.kappa() * t) / (Math.Pow(process.sigma(), 2) * (1 - Math.Exp(-process.kappa() * t))) * process.v0(); double k = Math.Pow(process.sigma(), 2) * (1 - Math.Exp(-process.kappa() * t)) / (4 * process.kappa()); double qMin = 0.0; // v_min = 0.0; double qMax = Math.Max(process.v0(), k * new InverseNonCentralCumulativeChiSquareDistribution( df, ncp, 100, 1e-8).value(1 - epsilon)); double minVStep = (qMax - qMin) / (50 * size); double ps, p = 0.0; double vTmp = qMin; grid.Add(new pair_double(qMin, epsilon)); for (int i = 1; i < size; ++i) { ps = (1 - epsilon - p) / (size - i); p += ps; double tmp = k * new InverseNonCentralCumulativeChiSquareDistribution( df, ncp, 100, 1e-8).value(p); double vx = Math.Max(vTmp + minVStep, tmp); p = new NonCentralCumulativeChiSquareDistribution(df, ncp).value(vx / k); vTmp = vx; grid.Add(new pair_double(vx, p)); } } Utils.QL_REQUIRE(grid.Count == size * tAvgSteps, () => "something wrong with the grid size"); grid.Sort(); List <Pair <double, double> > tp = new List <Pair <double, double> >(grid); for (int i = 0; i < size; ++i) { int b = (i * tp.Count) / size; int e = ((i + 1) * tp.Count) / size; for (int j = b; j < e; ++j) { vGrid[i] += tp[j].first / (e - b); pGrid[i] += tp[j].second / (e - b); } } } catch (Exception) { // use default mesh double vol = process.sigma() * Math.Sqrt(process.theta() / (2 * process.kappa())); double mean = process.theta(); double upperBound = Math.Max(process.v0() + 4 * vol, mean + 4 * vol); double lowerBound = Math.Max(0.0, Math.Min(process.v0() - 4 * vol, mean - 4 * vol)); for (int i = 0; i < size; ++i) { pGrid[i] = i / (size - 1.0); vGrid[i] = lowerBound + i * (upperBound - lowerBound) / (size - 1.0); } } double skewHint = ((process.kappa() != 0.0) ? Math.Max(1.0, process.sigma() / process.kappa()) : 1.0); pGrid.Sort(); volaEstimate_ = new GaussLobattoIntegral(100000, 1e-4).value( new interpolated_volatility(pGrid, vGrid).value, pGrid.First(), pGrid.Last()) * Math.Pow(skewHint, 1.5); double v0 = process.v0(); for (int i = 1; i < vGrid.Count; ++i) { if (vGrid[i - 1] <= v0 && vGrid[i] >= v0) { if (Math.Abs(vGrid[i - 1] - v0) < Math.Abs(vGrid[i] - v0)) { vGrid[i - 1] = v0; } else { vGrid[i] = v0; } } } locations_ = vGrid.Select(x => x).ToList(); for (int i = 0; i < size - 1; ++i) { dminus_[i + 1] = dplus_[i] = vGrid[i + 1] - vGrid[i]; } dplus_[dplus_.Count - 1] = null; dminus_[0] = null; }