public override void calculate() { Utils.QL_REQUIRE(arguments_.settlementType == Settlement.Type.Physical, () => "cash-settled 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(); }
public override void calculate() { Utils.QL_REQUIRE(arguments_.settlementType == Settlement.Type.Physical, () => "cash-settled 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 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); }