private Sample <IPath> next(bool antithetic) { Sample <List <double> > sequence_ = antithetic ? generator_.lastSequence() : generator_.nextSequence(); if (brownianBridge_) { bb_.transform(sequence_.value, temp_); } else { temp_ = new List <double>(sequence_.value); } next_.weight = sequence_.weight; Path path = (Path)next_.value; path.setFront(process_.x0()); for (int i = 1; i < path.length(); i++) { double t = timeGrid_[i - 1]; double dt = timeGrid_.dt(i - 1); path[i] = process_.evolve(t, path[i - 1], dt, antithetic ? -temp_[i - 1] : temp_[i - 1]); } return(next_); }
public TrinomialTree(StochasticProcess1D process, TimeGrid timeGrid, bool isPositive /*= false*/) : base(timeGrid.size()) { branchings_ = new List <Branching>(); dx_ = new InitializedList <double>(1); timeGrid_ = timeGrid; x0_ = process.x0(); int nTimeSteps = timeGrid.size() - 1; int jMin = 0; int jMax = 0; for (int i = 0; i < nTimeSteps; i++) { double t = timeGrid[i]; double dt = timeGrid.dt(i); //Variance must be independent of x double v2 = process.variance(t, 0.0, dt); double v = Math.Sqrt(v2); dx_.Add(v * Math.Sqrt(3.0)); Branching branching = new Branching(); for (int j = jMin; j <= jMax; j++) { double x = x0_ + j * dx_[i]; double m = process.expectation(t, x, dt); int temp = (int)(Math.Floor((m - x0_) / dx_[i + 1] + 0.5)); if (isPositive) { while (x0_ + (temp - 1) * dx_[i + 1] <= 0) { temp++; } } double e = m - (x0_ + temp * dx_[i + 1]); double e2 = e * e; double e3 = e * Math.Sqrt(3.0); double p1 = (1.0 + e2 / v2 - e3 / v) / 6.0; double p2 = (2.0 - e2 / v2) / 3.0; double p3 = (1.0 + e2 / v2 + e3 / v) / 6.0; branching.add(temp, p1, p2, p3); } branchings_.Add(branching); jMin = branching.jMin(); jMax = branching.jMax(); } }
private Sample <IPath> next(bool antithetic) { if (brownianBridge_) { Utils.QL_FAIL("Brownian bridge not supported"); return(null); } Sample <List <double> > sequence_ = antithetic ? generator_.lastSequence() : generator_.nextSequence(); int m = process_.size(); int n = process_.factors(); MultiPath path = (MultiPath)next_.value; Vector asset = process_.initialValues(); for (int j = 0; j < m; j++) { path[j].setFront(asset[j]); } Vector temp; next_.weight = sequence_.weight; TimeGrid timeGrid = path[0].timeGrid(); double t, dt; for (int i = 1; i < path.pathSize(); i++) { int offset = (i - 1) * n; t = timeGrid[i - 1]; dt = timeGrid.dt(i - 1); if (antithetic) { temp = -1 * new Vector(sequence_.value.GetRange(offset, n)); } else { temp = new Vector(sequence_.value.GetRange(offset, n)); } asset = process_.evolve(t, asset, dt, temp); for (int j = 0; j < m; j++) { path[j][i] = asset[j]; } } return(next_); }
public double value(IPath path) { int n = path.length(); Utils.QL_REQUIRE(n > 1, () => "the path cannot be empty"); bool isOptionActive = false; int? knockNode = null; double asset_price = (path as Path).front(); double new_asset_price; double x, y; double vol; TimeGrid timeGrid = (path as Path).timeGrid(); double dt; List <double> u = sequenceGen_.nextSequence().value; int i; switch (barrierType_) { case Barrier.Type.DownIn: isOptionActive = false; for (i = 0; i < n - 1; i++) { new_asset_price = (path as Path)[i + 1]; // terminal or initial vol? vol = diffProcess_.diffusion(timeGrid[i], asset_price); dt = timeGrid.dt(i); x = Math.Log(new_asset_price / asset_price); y = 0.5 * (x - Math.Sqrt(x * x - 2 * vol * vol * dt * Math.Log(u[i]))); y = asset_price * Math.Exp(y); if (y <= barrier_) { isOptionActive = true; if (knockNode == null) { knockNode = i + 1; } } asset_price = new_asset_price; } break; case Barrier.Type.UpIn: isOptionActive = false; for (i = 0; i < n - 1; i++) { new_asset_price = (path as Path)[i + 1]; // terminal or initial vol? vol = diffProcess_.diffusion(timeGrid[i], asset_price); dt = timeGrid.dt(i); x = Math.Log(new_asset_price / asset_price); y = 0.5 * (x + Math.Sqrt(x * x - 2 * vol * vol * dt * Math.Log((1 - u[i])))); y = asset_price * Math.Exp(y); if (y >= barrier_) { isOptionActive = true; if (knockNode == null) { knockNode = i + 1; } } asset_price = new_asset_price; } break; case Barrier.Type.DownOut: isOptionActive = true; for (i = 0; i < n - 1; i++) { new_asset_price = (path as Path)[i + 1]; // terminal or initial vol? vol = diffProcess_.diffusion(timeGrid[i], asset_price); dt = timeGrid.dt(i); x = Math.Log(new_asset_price / asset_price); y = 0.5 * (x - Math.Sqrt(x * x - 2 * vol * vol * dt * Math.Log(u[i]))); y = asset_price * Math.Exp(y); if (y <= barrier_) { isOptionActive = false; if (knockNode == null) { knockNode = i + 1; } } asset_price = new_asset_price; } break; case Barrier.Type.UpOut: isOptionActive = true; for (i = 0; i < n - 1; i++) { new_asset_price = (path as Path)[i + 1]; // terminal or initial vol? vol = diffProcess_.diffusion(timeGrid[i], asset_price); dt = timeGrid.dt(i); x = Math.Log(new_asset_price / asset_price); y = 0.5 * (x + Math.Sqrt(x * x - 2 * vol * vol * dt * Math.Log((1 - u[i])))); y = asset_price * Math.Exp(y); if (y >= barrier_) { isOptionActive = false; if (knockNode == null) { knockNode = i + 1; } } asset_price = new_asset_price; } break; default: Utils.QL_FAIL("unknown barrier type"); break; } if (isOptionActive) { return(payoff_.value(asset_price) * discounts_.Last()); } else { switch (barrierType_) { case Barrier.Type.UpIn: case Barrier.Type.DownIn: return(rebate_.GetValueOrDefault() * discounts_.Last()); case Barrier.Type.UpOut: case Barrier.Type.DownOut: return(rebate_.GetValueOrDefault() * discounts_[(int)knockNode]); default: Utils.QL_FAIL("unknown barrier type"); return(-1); } } }