FdmDividendHandler::FdmDividendHandler( const DividendSchedule& schedule, const boost::shared_ptr<FdmMesher>& mesher, const Date& referenceDate, const DayCounter& dayCounter, Size equityDirection) : x_(mesher->layout()->dim()[equityDirection]), mesher_(mesher), equityDirection_(equityDirection) { dividends_.reserve(schedule.size()); dividendDates_.reserve(schedule.size()); dividendTimes_.reserve(schedule.size()); for (DividendSchedule::const_iterator iter=schedule.begin(); iter!=schedule.end(); ++iter) { dividends_.push_back((*iter)->amount()); dividendDates_.push_back((*iter)->date()); dividendTimes_.push_back( dayCounter.yearFraction(referenceDate,(*iter)->date())); } Array tmp = mesher_->locations(equityDirection); Size spacing = mesher_->layout()->spacing()[equityDirection]; for (Size i = 0; i < x_.size(); ++i) { x_[i] = std::exp(tmp[i*spacing]); } }
FdmBlackScholesMesher::FdmBlackScholesMesher( Size size, const ext::shared_ptr<GeneralizedBlackScholesProcess>& process, Time maturity, Real strike, Real xMinConstraint, Real xMaxConstraint, Real eps, Real scaleFactor, const std::pair<Real, Real>& cPoint, const DividendSchedule& dividendSchedule) : Fdm1dMesher(size) { const Real S = process->x0(); QL_REQUIRE(S > 0.0, "negative or null underlying given"); std::vector<std::pair<Time, Real> > intermediateSteps; for (Size i=0; i < dividendSchedule.size() && process->time(dividendSchedule[i]->date()) <= maturity; ++i) intermediateSteps.push_back( std::make_pair( process->time(dividendSchedule[i]->date()), dividendSchedule[i]->amount() ) ); const Size intermediateTimeSteps = std::max<Size>(2, Size(24.0*maturity)); for (Size i=0; i < intermediateTimeSteps; ++i) intermediateSteps.push_back( std::make_pair((i+1)*(maturity/intermediateTimeSteps), 0.0)); std::sort(intermediateSteps.begin(), intermediateSteps.end()); const Handle<YieldTermStructure> rTS = process->riskFreeRate(); const Handle<YieldTermStructure> qTS = process->dividendYield(); Time lastDivTime = 0.0; Real fwd = S, mi = S, ma = S; for (Size i=0; i < intermediateSteps.size(); ++i) { const Time divTime = intermediateSteps[i].first; const Real divAmount = intermediateSteps[i].second; fwd = fwd / rTS->discount(divTime) * rTS->discount(lastDivTime) * qTS->discount(divTime) / qTS->discount(lastDivTime); mi = std::min(mi, fwd); ma = std::max(ma, fwd); fwd-= divAmount; mi = std::min(mi, fwd); ma = std::max(ma, fwd); lastDivTime = divTime; } // Set the grid boundaries const Real normInvEps = InverseCumulativeNormal()(1-eps); const Real sigmaSqrtT = process->blackVolatility()->blackVol(maturity, strike) *std::sqrt(maturity); Real xMin = std::log(mi) - sigmaSqrtT*normInvEps*scaleFactor; Real xMax = std::log(ma) + sigmaSqrtT*normInvEps*scaleFactor; if (xMinConstraint != Null<Real>()) { xMin = xMinConstraint; } if (xMaxConstraint != Null<Real>()) { xMax = xMaxConstraint; } ext::shared_ptr<Fdm1dMesher> helper; if ( cPoint.first != Null<Real>() && std::log(cPoint.first) >=xMin && std::log(cPoint.first) <=xMax) { helper = ext::shared_ptr<Fdm1dMesher>( new Concentrating1dMesher(xMin, xMax, size, std::pair<Real,Real>(std::log(cPoint.first), cPoint.second))); } else { helper = ext::shared_ptr<Fdm1dMesher>( new Uniform1dMesher(xMin, xMax, size)); } locations_ = helper->locations(); for (Size i=0; i < locations_.size(); ++i) { dplus_[i] = helper->dplus(i); dminus_[i] = helper->dminus(i); } }