public FdmDividendHandler(DividendSchedule schedule, FdmMesher mesher, Date referenceDate, DayCounter dayCounter, int equityDirection) { x_ = new Vector(mesher.layout().dim()[equityDirection]); mesher_ = mesher; equityDirection_ = equityDirection; dividends_ = new List <double>(); dividendDates_ = new List <Date>(); dividendTimes_ = new List <double>(); foreach (Dividend iter in schedule) { dividends_.Add(iter.amount()); dividendDates_.Add(iter.date()); dividendTimes_.Add( dayCounter.yearFraction(referenceDate, iter.date())); } Vector tmp = mesher_.locations(equityDirection); int spacing = mesher_.layout().spacing()[equityDirection]; for (int i = 0; i < x_.size(); ++i) { x_[i] = Math.Exp(tmp[i * spacing]); } }
public Fdm1DimSolver(FdmSolverDesc solverDesc, FdmSchemeDesc schemeDesc, FdmLinearOpComposite op) { solverDesc_ = solverDesc; schemeDesc_ = schemeDesc; op_ = op; thetaCondition_ = new FdmSnapshotCondition( 0.99 * Math.Min(1.0 / 365.0, solverDesc.condition.stoppingTimes().empty() ? solverDesc.maturity : solverDesc.condition.stoppingTimes().First())); conditions_ = FdmStepConditionComposite.joinConditions(thetaCondition_, solverDesc.condition); x_ = new InitializedList <double>(solverDesc.mesher.layout().size()); initialValues_ = new InitializedList <double>(solverDesc.mesher.layout().size()); resultValues_ = new Vector(solverDesc.mesher.layout().size()); FdmMesher mesher = solverDesc.mesher; FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { initialValues_[iter.index()] = solverDesc_.calculator.avgInnerValue(iter, solverDesc.maturity); x_[iter.index()] = mesher.location(iter, 0); } }
public FdmHestonEquityPart(FdmMesher mesher, YieldTermStructure rTS, YieldTermStructure qTS, FdmQuantoHelper quantoHelper = null, LocalVolTermStructure leverageFct = null) { varianceValues_ = new Vector(0.5 * mesher.locations(1)); dxMap_ = new FirstDerivativeOp(0, mesher); dxxMap_ = new SecondDerivativeOp(0, mesher).mult(0.5 * mesher.locations(1)); mapT_ = new TripleBandLinearOp(0, mesher); mesher_ = mesher; rTS_ = rTS; qTS_ = qTS; quantoHelper_ = quantoHelper; leverageFct_ = leverageFct; // on the boundary s_min and s_max the second derivative // d^2V/dS^2 is zero and due to Ito's Lemma the variance term // in the drift should vanish. FdmLinearOpLayout layout = mesher_.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { if (iter.coordinates()[0] == 0 || iter.coordinates()[0] == layout.dim()[0] - 1) { varianceValues_[iter.index()] = 0.0; } } volatilityValues_ = Vector.Sqrt(2 * varianceValues_); }
public SecondDerivativeOp(int direction, FdmMesher mesher) : base(direction, mesher) { FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); double?hm = mesher.dminus(iter, direction_); double?hp = mesher.dplus(iter, direction_); double?zetam1 = hm * (hm + hp); double?zeta0 = hm * hp; double?zetap1 = hp * (hm + hp); int co = iter.coordinates()[direction_]; if (co == 0 || co == layout.dim()[direction] - 1) { lower_[i] = diag_[i] = upper_[i] = 0.0; } else { lower_[i] = 2.0 / zetam1.Value; diag_[i] = -2.0 / zeta0.Value; upper_[i] = 2.0 / zetap1.Value; } } }
public FdmDirichletBoundary(FdmMesher mesher, double valueOnBoundary, int direction, Side side) { side_ = side; valueOnBoundary_ = valueOnBoundary; indices_ = new FdmIndicesOnBoundary(mesher.layout(), direction, side).getIndices(); if (side_ == Side.Lower) { xExtreme_ = mesher.locations(direction)[0]; } else if (side_ == Side.Upper) { xExtreme_ = mesher .locations(direction)[mesher.layout().dim()[direction] - 1]; } else { Utils.QL_FAIL("internal error"); } }
public TripleBandLinearOp(int direction, FdmMesher mesher) { direction_ = direction; i0_ = new InitializedList <int>(mesher.layout().size()); i2_ = new InitializedList <int>(mesher.layout().size()); reverseIndex_ = new InitializedList <int>(mesher.layout().size()); lower_ = new InitializedList <double>(mesher.layout().size()); diag_ = new InitializedList <double>(mesher.layout().size()); upper_ = new InitializedList <double>(mesher.layout().size()); mesher_ = mesher; FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); int tmp; List <int> newDim = new List <int>(layout.dim()); tmp = newDim[direction_]; newDim[direction_] = newDim[0]; newDim[0] = tmp; List <int> newSpacing = new FdmLinearOpLayout(newDim).spacing(); tmp = newSpacing[direction_]; newSpacing[direction_] = newSpacing[0]; newSpacing[0] = tmp; for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); i0_[i] = layout.neighbourhood(iter, direction, -1); i2_[i] = layout.neighbourhood(iter, direction, 1); List <int> coordinates = iter.coordinates(); int newIndex = coordinates.inner_product(0, coordinates.Count, 0, newSpacing, 0); reverseIndex_[newIndex] = i; } }
public FirstDerivativeOp(int direction, FdmMesher mesher) : base(direction, mesher) { FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); double?hm = mesher.dminus(iter, direction_); double?hp = mesher.dplus(iter, direction_); double?zetam1 = hm * (hm + hp); double?zeta0 = hm * hp; double?zetap1 = hp * (hm + hp); if (iter.coordinates()[direction_] == 0) { //upwinding scheme lower_[i] = 0.0; diag_[i] = -(upper_[i] = 1 / hp.Value); } else if (iter.coordinates()[direction_] == layout.dim()[direction] - 1) { // downwinding scheme lower_[i] = -(diag_[i] = 1 / hm.Value); upper_[i] = 0.0; } else { lower_[i] = -hp.Value / zetam1.Value; diag_[i] = (hp.Value - hm.Value) / zeta0.Value; upper_[i] = hm.Value / zetap1.Value; } } }
public SecondOrderMixedDerivativeOp(int d0, int d1, FdmMesher mesher) : base(d0, d1, mesher) { FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); double?hm_d0 = mesher.dminus(iter, d0_); double?hp_d0 = mesher.dplus(iter, d0_); double?hm_d1 = mesher.dminus(iter, d1_); double?hp_d1 = mesher.dplus(iter, d1_); double?zetam1 = hm_d0 * (hm_d0 + hp_d0); double?zeta0 = hm_d0 * hp_d0; double?zetap1 = hp_d0 * (hm_d0 + hp_d0); double?phim1 = hm_d1 * (hm_d1 + hp_d1); double?phi0 = hm_d1 * hp_d1; double?phip1 = hp_d1 * (hm_d1 + hp_d1); int c0 = iter.coordinates()[d0_]; int c1 = iter.coordinates()[d1_]; if (c0 == 0 && c1 == 0) { // lower left corner a00_[i] = a01_[i] = a02_[i] = a10_[i] = a20_[i] = 0.0; a11_[i] = a22_[i] = 1.0 / (hp_d0.Value * hp_d1.Value); a21_[i] = a12_[i] = -a11_[i]; } else if (c0 == layout.dim()[d0_] - 1 && c1 == 0) { // upper left corner a22_[i] = a21_[i] = a20_[i] = a10_[i] = a00_[i] = 0.0; a01_[i] = a12_[i] = 1.0 / (hm_d0.Value * hp_d1.Value); a11_[i] = a02_[i] = -a01_[i]; } else if (c0 == 0 && c1 == layout.dim()[d1_] - 1) { // lower right corner a00_[i] = a01_[i] = a02_[i] = a12_[i] = a22_[i] = 0.0; a10_[i] = a21_[i] = 1.0 / (hp_d0.Value * hm_d1.Value); a20_[i] = a11_[i] = -a10_[i]; } else if (c0 == layout.dim()[d0_] - 1 && c1 == layout.dim()[d1_] - 1) { // upper right corner a20_[i] = a21_[i] = a22_[i] = a12_[i] = a02_[i] = 0.0; a00_[i] = a11_[i] = 1.0 / (hm_d0.Value * hm_d1.Value); a10_[i] = a01_[i] = -a00_[i]; } else if (c0 == 0) { // lower side a00_[i] = a01_[i] = a02_[i] = 0.0; a10_[i] = hp_d1.Value / (hp_d0.Value * phim1.Value); a20_[i] = -a10_[i]; a21_[i] = (hp_d1.Value - hm_d1.Value) / (hp_d0.Value * phi0.Value); a11_[i] = -a21_[i]; a22_[i] = hm_d1.Value / (hp_d0.Value * phip1.Value); a12_[i] = -a22_[i]; } else if (c0 == layout.dim()[d0_] - 1) { // upper side a20_[i] = a21_[i] = a22_[i] = 0.0; a00_[i] = hp_d1.Value / (hm_d0.Value * phim1.Value); a10_[i] = -a00_[i]; a11_[i] = (hp_d1.Value - hm_d1.Value) / (hm_d0.Value * phi0.Value); a01_[i] = -a11_[i]; a12_[i] = hm_d1.Value / (hm_d0.Value * phip1.Value); a02_[i] = -a12_[i]; } else if (c1 == 0) { // left side a00_[i] = a10_[i] = a20_[i] = 0.0; a01_[i] = hp_d0.Value / (zetam1.Value * hp_d1.Value); a02_[i] = -a01_[i]; a12_[i] = (hp_d0.Value - hm_d0.Value) / (zeta0.Value * hp_d1.Value); a11_[i] = -a12_[i]; a22_[i] = hm_d0.Value / (zetap1.Value * hp_d1.Value); a21_[i] = -a22_[i]; } else if (c1 == layout.dim()[d1_] - 1) { // right side a22_[i] = a12_[i] = a02_[i] = 0.0; a00_[i] = hp_d0.Value / (zetam1.Value * hm_d1.Value); a01_[i] = -a00_[i]; a11_[i] = (hp_d0.Value - hm_d0.Value) / (zeta0.Value * hm_d1.Value); a10_[i] = -a11_[i]; a21_[i] = hm_d0.Value / (zetap1.Value * hm_d1.Value); a20_[i] = -a21_[i]; } else { a00_[i] = hp_d0.Value * hp_d1.Value / (zetam1.Value * phim1.Value); a10_[i] = -(hp_d0.Value - hm_d0.Value) * hp_d1.Value / (zeta0.Value * phim1.Value); a20_[i] = -hm_d0.Value * hp_d1.Value / (zetap1.Value * phim1.Value); a01_[i] = -hp_d0.Value * (hp_d1.Value - hm_d1.Value) / (zetam1.Value * phi0.Value); a11_[i] = (hp_d0.Value - hm_d0.Value) * (hp_d1.Value - hm_d1.Value) / (zeta0.Value * phi0.Value); a21_[i] = hm_d0.Value * (hp_d1.Value - hm_d1.Value) / (zetap1.Value * phi0.Value); a02_[i] = -hp_d0.Value * hm_d1.Value / (zetam1.Value * phip1.Value); a12_[i] = hm_d1.Value * (hp_d0.Value - hm_d0.Value) / (zeta0.Value * phip1.Value); a22_[i] = hm_d0.Value * hm_d1.Value / (zetap1.Value * phip1.Value); } } }
public FdmHullWhiteOp(FdmMesher mesher, HullWhite model, int direction) { x_ = mesher.locations(direction); dzMap_ = new TripleBandLinearOp(new FirstDerivativeOp(direction, mesher).mult(-1.0 * x_ * model.a()).add( new SecondDerivativeOp(direction, mesher).mult(0.5 * model.sigma() * model.sigma() * new Vector(mesher.layout().size(), 1.0)))); mapT_ = new TripleBandLinearOp(direction, mesher); direction_ = direction; model_ = model; }
public NinePointLinearOp(int d0, int d1, FdmMesher mesher) { d0_ = d0; d1_ = d1; i00_ = new InitializedList <int>(mesher.layout().size()); i10_ = new InitializedList <int>(mesher.layout().size()); i20_ = new InitializedList <int>(mesher.layout().size()); i01_ = new InitializedList <int>(mesher.layout().size()); i21_ = new InitializedList <int>(mesher.layout().size()); i02_ = new InitializedList <int>(mesher.layout().size()); i12_ = new InitializedList <int>(mesher.layout().size()); i22_ = new InitializedList <int>(mesher.layout().size()); a00_ = new InitializedList <double>(mesher.layout().size()); a10_ = new InitializedList <double>(mesher.layout().size()); a20_ = new InitializedList <double>(mesher.layout().size()); a01_ = new InitializedList <double>(mesher.layout().size()); a11_ = new InitializedList <double>(mesher.layout().size()); a21_ = new InitializedList <double>(mesher.layout().size()); a02_ = new InitializedList <double>(mesher.layout().size()); a12_ = new InitializedList <double>(mesher.layout().size()); a22_ = new InitializedList <double>(mesher.layout().size()); mesher_ = mesher; Utils.QL_REQUIRE(d0_ != d1_ && d0_ < mesher.layout().dim().Count && d1_ < mesher.layout().dim().Count, () => "inconsistent derivative directions"); FdmLinearOpLayout layout = mesher.layout(); FdmLinearOpIterator endIter = layout.end(); for (FdmLinearOpIterator iter = layout.begin(); iter != endIter; ++iter) { int i = iter.index(); i10_[i] = layout.neighbourhood(iter, d1_, -1); i01_[i] = layout.neighbourhood(iter, d0_, -1); i21_[i] = layout.neighbourhood(iter, d0_, 1); i12_[i] = layout.neighbourhood(iter, d1_, 1); i00_[i] = layout.neighbourhood(iter, d0_, -1, d1_, -1); i20_[i] = layout.neighbourhood(iter, d0_, 1, d1_, -1); i02_[i] = layout.neighbourhood(iter, d0_, -1, d1_, 1); i22_[i] = layout.neighbourhood(iter, d0_, 1, d1_, 1); } }