SobolBrownianGenerator::SobolBrownianGenerator( Size factors, Size steps, Ordering ordering, unsigned long seed, SobolRsg::DirectionIntegers integers) : factors_(factors), steps_(steps), ordering_(ordering), generator_(SobolRsg(factors*steps, seed, integers), InverseCumulativeNormal()), bridge_(steps), lastStep_(0), orderedIndices_(factors, std::vector<Size>(steps)), bridgedVariates_(factors, std::vector<Real>(steps)) { switch (ordering_) { case Factors: fillByFactor(orderedIndices_, factors_, steps_); break; case Steps: fillByStep(orderedIndices_, factors_, steps_); break; case Diagonal: fillByDiagonal(orderedIndices_, factors_, steps_); break; default: QL_FAIL("unknown ordering"); } }
FdmBlackScholesMultiStrikeMesher::FdmBlackScholesMultiStrikeMesher( Size size, const boost::shared_ptr<GeneralizedBlackScholesProcess>& process, Time maturity, const std::vector<Real>& strikes, Real eps, Real scaleFactor, const std::pair<Real, Real>& cPoint) : Fdm1dMesher(size) { const Real spot = process->x0(); QL_REQUIRE(spot > 0.0, "negative or null underlying given"); const DiscountFactor d = process->dividendYield()->discount(maturity) / process->riskFreeRate()->discount(maturity); const Real minStrike= *std::min_element(strikes.begin(), strikes.end()); const Real maxStrike= *std::max_element(strikes.begin(), strikes.end()); const Real Fmin = spot*spot/maxStrike*d; const Real Fmax = spot*spot/minStrike*d; QL_REQUIRE(Fmin > 0.0, "negative forward given"); // Set the grid boundaries const Real normInvEps = InverseCumulativeNormal()(1-eps); const Real sigmaSqrtTmin = process->blackVolatility()->blackVol(maturity, minStrike) *std::sqrt(maturity); const Real sigmaSqrtTmax = process->blackVolatility()->blackVol(maturity, maxStrike) *std::sqrt(maturity); const Real xMin = std::min(0.8*std::log(0.8*spot*spot/maxStrike), std::log(Fmin) - sigmaSqrtTmin*normInvEps*scaleFactor - sigmaSqrtTmin*sigmaSqrtTmin/2.0); const Real xMax = std::max(1.2*std::log(0.8*spot*spot/minStrike), std::log(Fmax) + sigmaSqrtTmax*normInvEps*scaleFactor - sigmaSqrtTmax*sigmaSqrtTmax/2.0); boost::shared_ptr<Fdm1dMesher> helper; if ( cPoint.first != Null<Real>() && std::log(cPoint.first) >=xMin && std::log(cPoint.first) <=xMax) { helper = boost::shared_ptr<Fdm1dMesher>( new Concentrating1dMesher(xMin, xMax, size, std::pair<Real,Real>(std::log(cPoint.first),cPoint.second))); } else { helper = boost::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); } }
void RandomBase::GetGaussian(std::vector<double>& variates) { GetUniforms(variates); for (unsigned long i = 0; i < Dimensionality; i++) { double x = variates[i]; variates[i] = InverseCumulativeNormal(x); } }
FdmBlackScholesMesher::FdmBlackScholesMesher( Size size, const boost::shared_ptr<GeneralizedBlackScholesProcess>& process, Time maturity, Real strike, Real xMinConstraint, Real xMaxConstraint, Real eps, Real scaleFactor, const std::pair<Real, Real>& cPoint) : Fdm1dMesher(size) { const Real S = process->x0(); QL_REQUIRE(S > 0.0, "negative or null underlying given"); // 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(S) - sigmaSqrtT*normInvEps*scaleFactor; Real xMax = std::log(S) + sigmaSqrtT*normInvEps*scaleFactor; if (xMinConstraint != Null<Real>()) { xMin = xMinConstraint; } if (xMaxConstraint != Null<Real>()) { xMax = xMaxConstraint; } boost::shared_ptr<Fdm1dMesher> helper; if ( cPoint.first != Null<Real>() && std::log(cPoint.first) >=xMin && std::log(cPoint.first) <=xMax) { helper = boost::shared_ptr<Fdm1dMesher>( new Concentrating1dMesher(xMin, xMax, size, std::pair<Real,Real>(std::log(cPoint.first),cPoint.second))); } else { helper = boost::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); } }
void FdBlackScholesAsianEngine::calculate() const { QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "European exercise supported only"); QL_REQUIRE(arguments_.averageType == Average::Arithmetic, "Arithmetic averaging supported only"); QL_REQUIRE( arguments_.runningAccumulator == 0 || arguments_.pastFixings > 0, "Running average requires at least one past fixing"); // 1. Mesher const ext::shared_ptr<StrikedTypePayoff> payoff = ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); const Time maturity = process_->time(arguments_.exercise->lastDate()); const ext::shared_ptr<Fdm1dMesher> equityMesher( new FdmBlackScholesMesher(xGrid_, process_, maturity, payoff->strike())); const Real spot = process_->x0(); QL_REQUIRE(spot > 0.0, "negative or null underlying given"); const Real avg = (arguments_.runningAccumulator == 0) ? spot : arguments_.runningAccumulator/arguments_.pastFixings; const Real normInvEps = InverseCumulativeNormal()(1-0.0001); const Real sigmaSqrtT = process_->blackVolatility()->blackVol(maturity, payoff->strike()) *std::sqrt(maturity); const Real r = sigmaSqrtT*normInvEps; Real xMin = std::min(std::log(avg) - 0.25*r, std::log(spot) - 1.5*r); Real xMax = std::max(std::log(avg) + 0.25*r, std::log(spot) + 1.5*r); const ext::shared_ptr<Fdm1dMesher> averageMesher( new FdmBlackScholesMesher(aGrid_, process_, maturity, payoff->strike(), xMin, xMax)); const ext::shared_ptr<FdmMesher> mesher ( new FdmMesherComposite(equityMesher, averageMesher)); // 2. Calculator ext::shared_ptr<FdmInnerValueCalculator> calculator( new FdmLogInnerValue(payoff, mesher, 1)); // 3. Step conditions std::list<ext::shared_ptr<StepCondition<Array> > > stepConditions; std::list<std::vector<Time> > stoppingTimes; // 3.1 Arithmetic average step conditions std::vector<Time> averageTimes; for (Size i=0; i<arguments_.fixingDates.size(); ++i) { Time t = process_->time(arguments_.fixingDates[i]); QL_REQUIRE(t >= 0, "Fixing dates must not contain past date"); averageTimes.push_back(t); } stoppingTimes.push_back(std::vector<Time>(averageTimes)); stepConditions.push_back(ext::shared_ptr<StepCondition<Array> >( new FdmArithmeticAverageCondition( averageTimes, arguments_.runningAccumulator, arguments_.pastFixings, mesher, 0))); ext::shared_ptr<FdmStepConditionComposite> conditions( new FdmStepConditionComposite(stoppingTimes, stepConditions)); // 4. Boundary conditions const FdmBoundaryConditionSet boundaries; // 5. Solver FdmSolverDesc solverDesc = { mesher, boundaries, conditions, calculator, maturity, tGrid_, 0 }; ext::shared_ptr<FdmSimple2dBSSolver> solver( new FdmSimple2dBSSolver( Handle<GeneralizedBlackScholesProcess>(process_), payoff->strike(), solverDesc, schemeDesc_)); results_.value = solver->valueAt(spot, avg); results_.delta = solver->deltaAt(spot, avg, spot*0.01); results_.gamma = solver->gammaAt(spot, avg, spot*0.01); }
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); } }