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 void axpyb(Vector a, TripleBandLinearOp x, TripleBandLinearOp y, Vector b) { int size = mesher_.layout().size(); if (a.empty()) { if (b.empty()) { //#pragma omp parallel for for (int i = 0; i < size; ++i) { diag_[i] = y.diag_[i]; lower_[i] = y.lower_[i]; upper_[i] = y.upper_[i]; } } else { int binc = (b.size() > 1) ? 1 : 0; //#pragma omp parallel for for (int i = 0; i < size; ++i) { diag_[i] = y.diag_[i] + b[i * binc]; lower_[i] = y.lower_[i]; upper_[i] = y.upper_[i]; } } } else if (b.empty()) { int ainc = (a.size() > 1) ? 1 : 0; //#pragma omp parallel for for (int i = 0; i < size; ++i) { double s = a[i * ainc]; diag_[i] = y.diag_[i] + s * x.diag_[i]; lower_[i] = y.lower_[i] + s * x.lower_[i]; upper_[i] = y.upper_[i] + s * x.upper_[i]; } } else { int binc = (b.size() > 1) ? 1 : 0; int ainc = (a.size() > 1) ? 1 : 0; //#pragma omp parallel for for (int i = 0; i < size; ++i) { double s = a[i * ainc]; diag_[i] = y.diag_[i] + s * x.diag_[i] + b[i * binc]; lower_[i] = y.lower_[i] + s * x.lower_[i]; upper_[i] = y.upper_[i] + s * x.upper_[i]; } } }
public void swap(TripleBandLinearOp m) { Utils.swap(ref mesher_, ref m.mesher_); Utils.swap(ref direction_, ref m.direction_); Utils.swap(ref i0_, ref m.i0_); Utils.swap(ref i2_, ref m.i2_); Utils.swap(ref reverseIndex_, ref m.reverseIndex_); Utils.swap(ref lower_, ref m.lower_); Utils.swap(ref diag_, ref m.diag_); Utils.swap(ref upper_, ref m.upper_); }
public FdmHestonVariancePart( FdmMesher mesher, YieldTermStructure rTS, double sigma, double kappa, double theta) { dyMap_ = new SecondDerivativeOp(1, mesher) .mult(0.5 * sigma * sigma * mesher.locations(1)) .add(new FirstDerivativeOp(1, mesher) .mult(kappa * (theta - mesher.locations(1)))); mapT_ = new TripleBandLinearOp(1, mesher); rTS_ = rTS; }
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 TripleBandLinearOp add (TripleBandLinearOp m) { TripleBandLinearOp retVal = new TripleBandLinearOp(direction_, mesher_); int size = mesher_.layout().size(); //#pragma omp parallel for for (int i = 0; i < size; ++i) { retVal.lower_[i] = lower_[i] + m.lower_[i]; retVal.diag_[i] = diag_[i] + m.diag_[i]; retVal.upper_[i] = upper_[i] + m.upper_[i]; } return(retVal); }
public TripleBandLinearOp mult(Vector u) { TripleBandLinearOp retVal = new TripleBandLinearOp(direction_, mesher_); int size = mesher_.layout().size(); //#pragma omp parallel for for (int i = 0; i < size; ++i) { double s = u[i]; retVal.lower_[i] = lower_[i] * s; retVal.diag_[i] = diag_[i] * s; retVal.upper_[i] = upper_[i] * s; } return(retVal); }
public TripleBandLinearOp(TripleBandLinearOp m) { direction_ = m.direction_; i0_ = new InitializedList <int>(m.mesher_.layout().size()); i2_ = new InitializedList <int>(m.mesher_.layout().size()); reverseIndex_ = new InitializedList <int>(m.mesher_.layout().size()); lower_ = new InitializedList <double>(m.mesher_.layout().size()); diag_ = new InitializedList <double>(m.mesher_.layout().size()); upper_ = new InitializedList <double>(m.mesher_.layout().size()); mesher_ = m.mesher_; int len = m.mesher_.layout().size(); m.i0_.copy(0, len, 0, i0_); m.i2_.copy(0, len, 0, i2_); m.reverseIndex_.copy(0, len, 0, reverseIndex_); m.lower_.copy(0, len, 0, lower_); m.diag_.copy(0, len, 0, diag_); m.upper_.copy(0, len, 0, upper_); }
public TripleBandLinearOp multR(Vector u) { FdmLinearOpLayout layout = mesher_.layout(); int size = layout.size(); Utils.QL_REQUIRE(u.size() == size, () => "inconsistent size of rhs"); TripleBandLinearOp retVal = new TripleBandLinearOp(direction_, mesher_); for (int i = 0; i < size; ++i) { double sm1 = i > 0 ? u[i - 1] : 1.0; double s0 = u[i]; double sp1 = i < size - 1 ? u[i + 1] : 1.0; retVal.lower_[i] = lower_[i] * sm1; retVal.diag_[i] = diag_[i] * s0; retVal.upper_[i] = upper_[i] * sp1; } return(retVal); }
public FdmBlackScholesOp(FdmMesher mesher, GeneralizedBlackScholesProcess bsProcess, double strike, bool localVol = false, double?illegalLocalVolOverwrite = null, int direction = 0, FdmQuantoHelper quantoHelper = null) { mesher_ = mesher; rTS_ = bsProcess.riskFreeRate().currentLink(); qTS_ = bsProcess.dividendYield().currentLink(); volTS_ = bsProcess.blackVolatility().currentLink(); localVol_ = (localVol) ? bsProcess.localVolatility().currentLink() : null; x_ = (localVol) ? new Vector(Vector.Exp(mesher.locations(direction))) : null; dxMap_ = new FirstDerivativeOp(direction, mesher); dxxMap_ = new SecondDerivativeOp(direction, mesher); mapT_ = new TripleBandLinearOp(direction, mesher); strike_ = strike; illegalLocalVolOverwrite_ = illegalLocalVolOverwrite; direction_ = direction; quantoHelper_ = quantoHelper; }