Real ExponentialJump1dMesher::jumpSizeDistribution(Real x, Time t) const { const Real xmin = std::min(x, 1.0e-100); return GaussLobattoIntegral(1000000, 1e-12)( boost::bind(&ExponentialJump1dMesher::jumpSizeDensity, this, _1, t), xmin, std::max(x, xmin)); }
Real ExtendedOrnsteinUhlenbeckProcess::expectation( Time t0, Real x0, Time dt) const { switch (discretization_) { case MidPoint: return ouProcess_->expectation(t0, x0, dt) + b_(t0+0.5*dt)*(1.0 - std::exp(-speed_*dt)); break; case Trapezodial: { const Time t = t0+dt; const Time u = t0; const Real bt = b_(t); const Real bu = b_(u); const Real ex = std::exp(-speed_*dt); return ouProcess_->expectation(t0, x0, dt) + bt-ex*bu - (bt-bu)/(speed_*dt)*(1-ex); } break; case GaussLobatto: return ouProcess_->expectation(t0, x0, dt) + speed_*std::exp(-speed_*(t0+dt)) * GaussLobattoIntegral(100000, intEps_)( boost::lambda::bind(b_, boost::lambda::_1) *boost::lambda::bind(std::ptr_fun<Real, Real>(std::exp), speed_*boost::lambda::_1), t0, t0+dt); break; default: QL_FAIL("unknown discretization scheme"); } }
Real HestonRNDCalculator::cdf(Real x, Time t) const { return GaussLobattoIntegral( maxIntegrationIterations_, 0.1*integrationEps_)( boost::bind(&CpxPv_Helper::p0, CpxPv_Helper(getHestonParams(hestonProcess_), x_t(x,t),t),_1), 0.0, 1.0)/M_TWOPI + 0.5; }
Real ExponentialJump1dMesher::jumpSizeDistribution(Real x) const { const Real a = jumpIntensity_/beta_; const Real xmin = std::min(x, QL_EPSILON); const Real gammaValue = std::exp(GammaFunction().logValue(jumpIntensity_/beta_)); const Real lowerEps = (std::pow(xmin, a)/a - std::pow(xmin, a+1)/(a+1))/gammaValue; return lowerEps + GaussLobattoIntegral(10000, 1e-12)( boost::bind(&ExponentialJump1dMesher::jumpSizeDensity, this, _1), xmin/eta_, std::max(x, xmin/eta_)); }
Real AnalyticPDFHestonEngine::Pv(Real x_t, Time t) const { const Hestonp p = { model_->v0(), model_->kappa(), model_->theta(), model_->sigma(), model_->rho() }; Real xMax = (xMax_ != Null<Real>()) ? xMax_ : Brent().solve(boost::bind(&zero_pv, p, _1, x_t, t), 0.01, 1.0, 1.0); return GaussLobattoIntegral(nIterations_, 0.1*eps_) (boost::bind(&pv, p, _1, x_t, t), -xMax, xMax)/M_TWOPI; }
void AnalyticPDFHestonEngine::calculate() const { // this is an European option pricer QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "not an European option"); const boost::shared_ptr<HestonProcess>& process = model_->process(); const Time t = process->time(arguments_.exercise->lastDate()); const Real xMax = 10 * std::sqrt(process->theta()*t); results_.value = GaussLobattoIntegral(nIterations_, eps_) (boost::bind(&AnalyticPDFHestonEngine::weightedPayoff, this,_1, t), -xMax, xMax); }
FdmHestonVarianceMesher::FdmHestonVarianceMesher( Size size, const boost::shared_ptr<HestonProcess> & process, Time maturity, Size tAvgSteps, Real epsilon) : Fdm1dMesher(size) { std::vector<Real> vGrid(size, 0.0), pGrid(size, 0.0); const Real df = 4*process->theta()*process->kappa()/ square<Real>()(process->sigma()); try { std::multiset<std::pair<Real, Real> > grid; for (Size l=1; l<=tAvgSteps; ++l) { const Real t = (maturity*l)/tAvgSteps; const Real ncp = 4*process->kappa()*std::exp(-process->kappa()*t) /(square<Real>()(process->sigma()) *(1-std::exp(-process->kappa()*t)))*process->v0(); const Real k = square<Real>()(process->sigma()) *(1-std::exp(-process->kappa()*t))/(4*process->kappa()); const Real qMin = 0.0; // v_min = 0.0; const Real qMax = std::max(process->v0(), k*InverseNonCentralChiSquareDistribution( df, ncp, 1000, 1e-8)(1-epsilon)); const Real minVStep=(qMax-qMin)/(50*size); Real ps,p = 0.0; Real vTmp = qMin; grid.insert(std::pair<Real, Real>(qMin, epsilon)); for (Size i=1; i < size; ++i) { ps = (1 - epsilon - p)/(size-i); p += ps; const Real tmp = k*InverseNonCentralChiSquareDistribution( df, ncp, 1000, 1e-8)(p); const Real vx = std::max(vTmp+minVStep, tmp); p = NonCentralChiSquareDistribution(df, ncp)(vx/k); vTmp=vx; grid.insert(std::pair<Real, Real>(vx, p)); } } QL_REQUIRE(grid.size() == size*tAvgSteps, "something wrong with the grid size"); std::vector<std::pair<Real, Real> > tp(grid.begin(), grid.end()); for (Size i=0; i < size; ++i) { const Size b = (i*tp.size())/size; const Size e = ((i+1)*tp.size())/size; for (Size j=b; j < e; ++j) { vGrid[i]+=tp[j].first/(e-b); pGrid[i]+=tp[j].second/(e-b); } } } catch (const Error&) { // use default mesh const Real vol = process->sigma()* std::sqrt(process->theta()/(2*process->kappa())); const Real mean = process->theta(); const Real upperBound = std::max(process->v0()+4*vol, mean+4*vol); const Real lowerBound = std::max(0.0, std::min(process->v0()-4*vol, mean-4*vol)); for (Size i=0; i < size; ++i) { pGrid[i] = i/(size-1.0); vGrid[i] = lowerBound + i*(upperBound-lowerBound)/(size-1.0); } } Real skewHint = ((process->kappa() != 0.0) ? std::max(1.0, process->sigma()/process->kappa()) : 1.0); std::sort(pGrid.begin(), pGrid.end()); volaEstimate_ = GaussLobattoIntegral(100000, 1e-4)( boost::function1<Real, Real>( compose(std::ptr_fun<Real, Real>(std::sqrt), LinearInterpolation(pGrid.begin(), pGrid.end(), vGrid.begin()))), pGrid.front(), pGrid.back())*std::pow(skewHint, 1.5); const Real v0 = process->v0(); for (Size i=1; i<vGrid.size(); ++i) { if (vGrid[i-1] <= v0 && vGrid[i] >= v0) { if (std::fabs(vGrid[i-1] - v0) < std::fabs(vGrid[i] - v0)) vGrid[i-1] = v0; else vGrid[i] = v0; } } std::copy(vGrid.begin(), vGrid.end(), locations_.begin()); for (Size i=0; i < size-1; ++i) { dminus_[i+1] = dplus_[i] = vGrid[i+1] - vGrid[i]; } dplus_.back() = dminus_.front() = Null<Real>(); }