void FdSimpleExtOUJumpSwingEngine::calculate() const { boost::shared_ptr<SwingExercise> swingExercise( boost::dynamic_pointer_cast<SwingExercise>(arguments_.exercise)); QL_REQUIRE(swingExercise, "Swing exercise supported only"); // 1. Layout std::vector<Size> dim; dim.push_back(xGrid_); dim.push_back(yGrid_); dim.push_back(arguments_.maxExerciseRights+1); const boost::shared_ptr<FdmLinearOpLayout> layout( new FdmLinearOpLayout(dim)); // 2. Mesher const std::vector<Time> exerciseTimes = swingExercise->exerciseTimes(rTS_->dayCounter(), rTS_->referenceDate()); const Time maturity = exerciseTimes.back(); const boost::shared_ptr<StochasticProcess1D> ouProcess( process_->getExtendedOrnsteinUhlenbeckProcess()); const boost::shared_ptr<Fdm1dMesher> xMesher( new FdmSimpleProcess1dMesher(xGrid_, ouProcess,maturity)); const boost::shared_ptr<Fdm1dMesher> yMesher( new ExponentialJump1dMesher(yGrid_, process_->beta(), process_->jumpIntensity(), process_->eta())); const boost::shared_ptr<Fdm1dMesher> exerciseMesher( new Uniform1dMesher(0, arguments_.maxExerciseRights, arguments_.maxExerciseRights+1)); std::vector<boost::shared_ptr<Fdm1dMesher> > meshers; meshers.push_back(xMesher); meshers.push_back(yMesher); meshers.push_back(exerciseMesher); const boost::shared_ptr<FdmMesher> mesher ( new FdmMesherComposite(layout, meshers)); // 3. Calculator boost::shared_ptr<FdmInnerValueCalculator> calculator( new FdmZeroInnerValue()); // 4. Step conditions std::list<boost::shared_ptr<StepCondition<Array> > > stepConditions; std::list<std::vector<Time> > stoppingTimes; // 4.1 Bermudan step conditions stoppingTimes.push_back(exerciseTimes); const boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); boost::shared_ptr<FdmInnerValueCalculator> exerciseCalculator( new FdmExtOUJumpModelInnerValue(payoff, mesher, shape_)); stepConditions.push_back(boost::shared_ptr<StepCondition<Array> >( new FdmSimpleSwingCondition(exerciseTimes, mesher, exerciseCalculator, 2))); boost::shared_ptr<FdmStepConditionComposite> conditions( new FdmStepConditionComposite(stoppingTimes, stepConditions)); // 5. Boundary conditions const std::vector<boost::shared_ptr<FdmDirichletBoundary> > boundaries; // 6. set-up solver FdmSolverDesc solverDesc = { mesher, boundaries, conditions, calculator, maturity, tGrid_, 0 }; const boost::shared_ptr<FdmSimple3dExtOUJumpSolver> solver( new FdmSimple3dExtOUJumpSolver( Handle<ExtOUWithJumpsProcess>(process_), rTS_, solverDesc, schemeDesc_)); const Real x = process_->initialValues()[0]; const Real y = process_->initialValues()[1]; std::vector< std::pair<Real, Real> > exerciseValues; for (Size i=arguments_.minExerciseRights; i <= arguments_.maxExerciseRights; ++i) { const Real z = Real(i); exerciseValues.push_back(std::pair<Real, Real>( solver->valueAt(x, y, z), z)); } const Real z = std::max_element(exerciseValues.begin(), exerciseValues.end())->second; results_.value = solver->valueAt(x, y, z); }
void FdSimpleBSSwingEngine::calculate() const { QL_REQUIRE(arguments_.exercise->type() == Exercise::Bermudan, "Bermudan exercise supported only"); // 1. Mesher const boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); const Time maturity = process_->time(arguments_.exercise->lastDate()); const boost::shared_ptr<Fdm1dMesher> equityMesher( new FdmBlackScholesMesher(xGrid_, process_, maturity, payoff->strike())); const boost::shared_ptr<Fdm1dMesher> exerciseMesher( new Uniform1dMesher(0, arguments_.maxExerciseRights, arguments_.maxExerciseRights+1)); const boost::shared_ptr<FdmMesher> mesher ( new FdmMesherComposite(equityMesher, exerciseMesher)); // 2. Calculator boost::shared_ptr<FdmInnerValueCalculator> calculator( new FdmZeroInnerValue()); // 3. Step conditions std::list<boost::shared_ptr<StepCondition<Array> > > stepConditions; std::list<std::vector<Time> > stoppingTimes; // 3.1 Bermudan step conditions std::vector<Time> exerciseTimes; for (Size i=0; i<arguments_.exercise->dates().size(); ++i) { Time t = process_->time(arguments_.exercise->dates()[i]); QL_REQUIRE(t >= 0, "exercise dates must not contain past date"); exerciseTimes.push_back(t); } stoppingTimes.push_back(exerciseTimes); boost::shared_ptr<FdmInnerValueCalculator> exerciseCalculator( new FdmLogInnerValue(payoff, mesher, 0)); stepConditions.push_back(boost::shared_ptr<StepCondition<Array> >( new FdmSimpleSwingCondition(exerciseTimes, mesher, exerciseCalculator, 1))); boost::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 }; boost::shared_ptr<FdmSimple2dBSSolver> solver( new FdmSimple2dBSSolver( Handle<GeneralizedBlackScholesProcess>(process_), payoff->strike(), solverDesc, schemeDesc_)); const Real spot = process_->x0(); std::vector< std::pair<Real, Real> > exerciseValues; for (Size i=arguments_.minExerciseRights; i <= arguments_.maxExerciseRights; ++i) { const Real y = std::exp(Real(i)); exerciseValues.push_back( std::pair<Real, Real>(solver->valueAt(spot, y), y)); } const Real y = std::max_element(exerciseValues.begin(), exerciseValues.end())->second; results_.value = solver->valueAt(spot, y); results_.delta = solver->deltaAt(spot, y, spot*0.01); results_.gamma = solver->gammaAt(spot, y, spot*0.01); results_.theta = solver->thetaAt(spot, y); }