private void initialize() { Utils.QL_REQUIRE(dates_.Count >= interpolator_.requiredPoints, () => "not enough input dates givesn"); Utils.QL_REQUIRE(this.data_.Count == this.dates_.Count, () => "dates/data count mismatch"); Utils.QL_REQUIRE(this.data_[0].IsEqual(1.0), () => "the first discount must be == 1.0 " + "to flag the corrsponding date as settlement date"); times_ = new InitializedList <double>(dates_.Count - 1); times_.Add(0.0); for (int i = 1; i < dates_.Count; i++) { Utils.QL_REQUIRE(dates_[i] > dates_[i - 1], () => "invalid date (" + dates_[i] + ", vs " + dates_[i - 1] + ")"); times_[i] = dayCounter().yearFraction(dates_[0], dates_[i]); Utils.QL_REQUIRE(!Utils.close(this.times_[i], this.times_[i - 1]), () => "two dates correspond to the same time " + "under this curve's day count convention"); Utils.QL_REQUIRE(this.data_[i] > 0.0, () => "negative discount"); #if !QL_NEGATIVE_RATES Utils.QL_REQUIRE(this.data_[i] <= this.data_[i - 1], () => "negative forward rate implied by the discount " + this.data_[i] + " at " + dates_[i] + " (t=" + this.times_[i] + ") after the discount " + this.data_[i - 1] + " at " + dates_[i - 1] + " (t=" + this.times_[i - 1] + ")"); #endif } setupInterpolation(); interpolation_.update(); }
// McSimulation implementation protected override TimeGrid timeGrid() { Date referenceDate = process_.riskFreeRate().link.referenceDate(); DayCounter voldc = process_.blackVolatility().link.dayCounter(); List <double> fixingTimes = new InitializedList <double>(arguments_.fixingDates.Count); for (int i = 0; i < arguments_.fixingDates.Count; i++) { if (arguments_.fixingDates[i] >= referenceDate) { double t = voldc.yearFraction(referenceDate, arguments_.fixingDates[i]); fixingTimes.Add(t); } } // handle here maxStepsPerYear return(new TimeGrid(fixingTimes.Last(), fixingTimes.Count)); }
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); }
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 Concentrating1dMesher(double start, double end, int size, List <Tuple <double?, double?, bool> > cPoints, double tol = 1e-8) : base(size) { Utils.QL_REQUIRE(end > start, () => "end must be larger than start"); List <double?> points = new List <double?>(), betas = new List <double?>(); foreach (Tuple <double?, double?, bool> iter in cPoints) { points.Add(iter.Item1); betas.Add((iter.Item2 * (end - start)) * (iter.Item2 * (end - start))); } // get scaling factor a so that y(1) = end double aInit = 0.0; for (int i = 0; i < points.Count; ++i) { double c1 = Utils.Asinh((start - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault()); double c2 = Utils.Asinh((end - points[i].GetValueOrDefault()) / betas[i].GetValueOrDefault()); aInit += (c2 - c1) / points.Count; } OdeIntegrationFct fct = new OdeIntegrationFct(points, betas, tol); double a = new Brent().solve( new OdeSolver(fct, start, 0.0, 1.0, end), tol, aInit, 0.1 * aInit); // solve ODE for all grid points Vector x = new Vector(size), y = new Vector(size); x[0] = 0.0; y[0] = start; double dx = 1.0 / (size - 1); for (int i = 1; i < size; ++i) { x[i] = i * dx; y[i] = fct.solve(a, y[i - 1], x[i - 1], x[i]); } // eliminate numerical noise and ensure y(1) = end double dy = y[y.Count - 1] - end; for (int i = 1; i < size; ++i) { y[i] -= i * dx * dy; } LinearInterpolation odeSolution = new LinearInterpolation(x, x.Count, y); // ensure required points are part of the grid List <Pair <double?, double?> > w = new InitializedList <Pair <double?, double?> > (1, new Pair <double?, double?>(0.0, 0.0)); for (int i = 0; i < points.Count; ++i) { if (cPoints[i].Item3 && points[i] > start && points[i] < end) { int j = y.distance(y[0], y.BinarySearch(points[i].Value)); double e = new Brent().solve( new OdeSolver2(odeSolution.value, points[i].Value), Const.QL_EPSILON, x[j], 0.5 / size); w.Add(new Pair <double?, double?>(Math.Min(x[size - 2], x[j]), e)); } } w.Add(new Pair <double?, double?>(1.0, 1.0)); w = w.OrderBy(xx => xx.first).Distinct(new equal_on_first()).ToList(); List <double> u = new List <double>(w.Count), z = new List <double>(w.Count); for (int i = 0; i < w.Count; ++i) { u[i] = w[i].first.GetValueOrDefault(); z[i] = w[i].second.GetValueOrDefault(); } LinearInterpolation transform = new LinearInterpolation(u, u.Count, z); for (int i = 0; i < size; ++i) { locations_[i] = odeSolution.value(transform.value(i * dx)); } for (int i = 0; i < size - 1; ++i) { dplus_[i] = dminus_[i + 1] = locations_[i + 1] - locations_[i]; } dplus_[dplus_.Count] = null; dminus_[0] = null; }