//! 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"); }
public override List <SparseMatrix> toMatrixDecomp() { List <SparseMatrix> retVal = new InitializedList <SparseMatrix>(1, mapT_.toMatrix()); return(retVal); }
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); }
public AmericanExercise(Date latest, bool payoffAtExpiry = false) : base(Type.American, payoffAtExpiry) { dates_ = new InitializedList <Date>(2); dates_[0] = Date.minDate(); dates_[1] = latest; }
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); }
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(); }
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 } } }
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; }
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); }
public FdmLinearOpIterator(List <int> dim) { index_ = 0; dim_ = dim; coordinates_ = new InitializedList <int>(dim.Count, 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); }
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]; } }
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); }
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))); } }
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(); } }
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; } } }
public void recalibration(double beta, Period swapTenor) { List <double> betaVector = new InitializedList <double>(nOptionTenors_, beta); recalibration(betaVector, swapTenor); }
public EuropeanExercise(Date date) : base(Type.European) { dates_ = new InitializedList <Date>(1, date); }
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]; } } }
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); }
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; } } }