boost::shared_ptr<FdmStepConditionComposite> FdmStepConditionComposite::vanillaComposite( const DividendSchedule& cashFlow, const boost::shared_ptr<Exercise>& exercise, const boost::shared_ptr<FdmMesher>& mesher, const boost::shared_ptr<FdmInnerValueCalculator>& calculator, const Date& refDate, const DayCounter& dayCounter) { std::list<std::vector<Time> > stoppingTimes; std::list<boost::shared_ptr<StepCondition<Array> > > stepConditions; if(!cashFlow.empty()) { boost::shared_ptr<FdmDividendHandler> dividendCondition( new FdmDividendHandler(cashFlow, mesher, refDate, dayCounter, 0)); stepConditions.push_back(dividendCondition); stoppingTimes.push_back(dividendCondition->dividendTimes()); } QL_REQUIRE( exercise->type() == Exercise::American || exercise->type() == Exercise::European || exercise->type() == Exercise::Bermudan, "exercise type is not supported"); if (exercise->type() == Exercise::American) { stepConditions.push_back(boost::shared_ptr<StepCondition<Array> >( new FdmAmericanStepCondition(mesher,calculator))); } else if (exercise->type() == Exercise::Bermudan) { boost::shared_ptr<FdmBermudanStepCondition> bermudanCondition( new FdmBermudanStepCondition(exercise->dates(), refDate, dayCounter, mesher, calculator)); stepConditions.push_back(bermudanCondition); stoppingTimes.push_back(bermudanCondition->exerciseTimes()); } return boost::shared_ptr<FdmStepConditionComposite>( new FdmStepConditionComposite(stoppingTimes, stepConditions)); }
void FdBlackScholesRebateEngine::calculate() const { // 1. Layout std::vector<Size> dim; dim.push_back(xGrid_); const boost::shared_ptr<FdmLinearOpLayout> layout( new FdmLinearOpLayout(dim)); // 2. Mesher const boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); const Time maturity = process_->time(arguments_.exercise->lastDate()); Real xMin=Null<Real>(); Real xMax=Null<Real>(); if ( arguments_.barrierType == Barrier::DownIn || arguments_.barrierType == Barrier::DownOut) { xMin = std::log(arguments_.barrier); } if ( arguments_.barrierType == Barrier::UpIn || arguments_.barrierType == Barrier::UpOut) { xMax = std::log(arguments_.barrier); } const boost::shared_ptr<Fdm1dMesher> equityMesher( new FdmBlackScholesMesher(xGrid_, process_, maturity, payoff->strike(), xMin, xMax)); std::vector<boost::shared_ptr<Fdm1dMesher> > meshers; meshers.push_back(equityMesher); boost::shared_ptr<FdmMesher> mesher ( new FdmMesherComposite(layout, meshers)); // 3. Calculator boost::shared_ptr<StrikedTypePayoff> rebatePayoff( new CashOrNothingPayoff(Option::Call, 0.0, arguments_.rebate)); boost::shared_ptr<FdmInnerValueCalculator> calculator( new FdmLogInnerValue(rebatePayoff, mesher, 0)); // 4. Step conditions std::list<boost::shared_ptr<StepCondition<Array> > > stepConditions; std::list<std::vector<Time> > stoppingTimes; // 4.1 Step condition if discrete dividends boost::shared_ptr<FdmDividendHandler> dividendCondition( new FdmDividendHandler(arguments_.cashFlow, mesher, process_->riskFreeRate()->referenceDate(), process_->riskFreeRate()->dayCounter(), 0)); if(!arguments_.cashFlow.empty()) { stepConditions.push_back(dividendCondition); stoppingTimes.push_back(dividendCondition->dividendTimes()); } QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "only european style option are supported"); boost::shared_ptr<FdmStepConditionComposite> conditions( new FdmStepConditionComposite(stoppingTimes, stepConditions)); // 5. Boundary conditions std::vector<boost::shared_ptr<FdmDirichletBoundary> > boundaries; if ( arguments_.barrierType == Barrier::DownIn || arguments_.barrierType == Barrier::DownOut) { boundaries.push_back(boost::shared_ptr<FdmDirichletBoundary>( new FdmDirichletBoundary(layout, arguments_.rebate, 0, FdmDirichletBoundary::Lower))); } if ( arguments_.barrierType == Barrier::UpIn || arguments_.barrierType == Barrier::UpOut) { boundaries.push_back(boost::shared_ptr<FdmDirichletBoundary>( new FdmDirichletBoundary(layout, arguments_.rebate, 0, FdmDirichletBoundary::Upper))); } // 6. Solver boost::shared_ptr<FdmBlackScholesSolver> solver( new FdmBlackScholesSolver( Handle<GeneralizedBlackScholesProcess>(process_), mesher, boundaries, conditions, calculator, payoff->strike(), maturity, tGrid_, dampingSteps_, theta_, localVol_, illegalLocalVolOverwrite_)); const Real spot = process_->x0(); results_.value = solver->valueAt(spot); results_.delta = solver->deltaAt(spot); results_.gamma = solver->gammaAt(spot); results_.theta = solver->thetaAt(spot); }
void FdBlackScholesVanillaEngine::calculate() const { // 1. Layout std::vector<Size> dim; dim.push_back(xGrid_); const boost::shared_ptr<FdmLinearOpLayout> layout( new FdmLinearOpLayout(dim)); const boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); // 2. Mesher const Time maturity = process_->time(arguments_.exercise->lastDate()); const boost::shared_ptr<Fdm1dMesher> equityMesher( new FdmBlackScholesMesher( xGrid_, process_, maturity, payoff->strike(), Null<Real>(), Null<Real>(), 0.0001, 1.5, std::pair<Real, Real>(payoff->strike(), 0.1))); std::vector<boost::shared_ptr<Fdm1dMesher> > meshers; meshers.push_back(equityMesher); boost::shared_ptr<FdmMesher> mesher ( new FdmMesherComposite(layout, meshers)); // 3. Calculator boost::shared_ptr<FdmInnerValueCalculator> calculator( new FdmLogInnerValue(payoff, mesher, 0)); // 4. Step conditions std::list<boost::shared_ptr<StepCondition<Array> > > stepConditions; std::list<std::vector<Time> > stoppingTimes; // 4.1 Step condition if discrete dividends if(!arguments_.cashFlow.empty()) { boost::shared_ptr<FdmDividendHandler> dividendCondition( new FdmDividendHandler(arguments_.cashFlow, mesher, process_->riskFreeRate()->referenceDate(), process_->riskFreeRate()->dayCounter(), 0)); stepConditions.push_back(dividendCondition); stoppingTimes.push_back(dividendCondition->dividendTimes()); } // 4.2 Step condition if american or bermudan exercise QL_REQUIRE( arguments_.exercise->type() == Exercise::American || arguments_.exercise->type() == Exercise::European || arguments_.exercise->type() == Exercise::Bermudan, "exercise type is not supported"); if (arguments_.exercise->type() == Exercise::American) { stepConditions.push_back(boost::shared_ptr<StepCondition<Array> >( new FdmAmericanStepCondition(mesher,calculator))); } else if (arguments_.exercise->type() == Exercise::Bermudan) { boost::shared_ptr<FdmBermudanStepCondition> bermudanCondition( new FdmBermudanStepCondition( arguments_.exercise->dates(), process_->riskFreeRate()->referenceDate(), process_->riskFreeRate()->dayCounter(), mesher, calculator)); stepConditions.push_back(bermudanCondition); stoppingTimes.push_back(bermudanCondition->exerciseTimes()); } boost::shared_ptr<FdmStepConditionComposite> conditions( new FdmStepConditionComposite(stoppingTimes, stepConditions)); // 5. Boundary conditions std::vector<boost::shared_ptr<FdmDirichletBoundary> > boundaries; // 6. Solver boost::shared_ptr<FdmBlackScholesSolver> solver( new FdmBlackScholesSolver( Handle<GeneralizedBlackScholesProcess>(process_), mesher, boundaries, conditions, calculator, payoff->strike(), maturity, tGrid_, dampingSteps_, schemeDesc_, localVol_, illegalLocalVolOverwrite_)); const Real spot = process_->x0(); results_.value = solver->valueAt(spot); results_.delta = solver->deltaAt(spot); results_.gamma = solver->gammaAt(spot); results_.theta = solver->thetaAt(spot); }
void FdHestonBarrierEngine::calculate() const { // 1. Mesher const boost::shared_ptr<HestonProcess>& process = model_->process(); const Time maturity = process->time(arguments_.exercise->lastDate()); // 1.1 The variance mesher const Size tGridMin = 5; const boost::shared_ptr<FdmHestonVarianceMesher> varianceMesher( new FdmHestonVarianceMesher(vGrid_, process, maturity, std::max(tGridMin, tGrid_/50))); // 1.2 The equity mesher const boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff); Real xMin=Null<Real>(); Real xMax=Null<Real>(); if ( arguments_.barrierType == Barrier::DownIn || arguments_.barrierType == Barrier::DownOut) { xMin = std::log(arguments_.barrier); } if ( arguments_.barrierType == Barrier::UpIn || arguments_.barrierType == Barrier::UpOut) { xMax = std::log(arguments_.barrier); } const boost::shared_ptr<Fdm1dMesher> equityMesher( new FdmBlackScholesMesher( xGrid_, FdmBlackScholesMesher::processHelper( process->s0(), process->dividendYield(), process->riskFreeRate(), varianceMesher->volaEstimate()), maturity, payoff->strike(), xMin, xMax)); const boost::shared_ptr<FdmMesher> mesher ( new FdmMesherComposite(equityMesher, varianceMesher)); // 2. Calculator boost::shared_ptr<FdmInnerValueCalculator> calculator( new FdmLogInnerValue(payoff, mesher, 0)); // 3. Step conditions std::list<boost::shared_ptr<StepCondition<Array> > > stepConditions; std::list<std::vector<Time> > stoppingTimes; // 3.1 Step condition if discrete dividends boost::shared_ptr<FdmDividendHandler> dividendCondition( new FdmDividendHandler(arguments_.cashFlow, mesher, process->riskFreeRate()->referenceDate(), process->riskFreeRate()->dayCounter(), 0)); if(!arguments_.cashFlow.empty()) { stepConditions.push_back(dividendCondition); stoppingTimes.push_back(dividendCondition->dividendTimes()); } QL_REQUIRE(arguments_.exercise->type() == Exercise::European, "only european style option are supported"); boost::shared_ptr<FdmStepConditionComposite> conditions( new FdmStepConditionComposite(stoppingTimes, stepConditions)); // 4. Boundary conditions FdmBoundaryConditionSet boundaries; if ( arguments_.barrierType == Barrier::DownIn || arguments_.barrierType == Barrier::DownOut) { boundaries.push_back(FdmBoundaryConditionSet::value_type( new FdmDirichletBoundary(mesher, arguments_.rebate, 0, FdmDirichletBoundary::Lower))); } if ( arguments_.barrierType == Barrier::UpIn || arguments_.barrierType == Barrier::UpOut) { boundaries.push_back(FdmBoundaryConditionSet::value_type( new FdmDirichletBoundary(mesher, arguments_.rebate, 0, FdmDirichletBoundary::Upper))); } // 5. Solver FdmSolverDesc solverDesc = { mesher, boundaries, conditions, calculator, maturity, tGrid_, dampingSteps_ }; boost::shared_ptr<FdmHestonSolver> solver(new FdmHestonSolver( Handle<HestonProcess>(process), solverDesc, schemeDesc_, Handle<FdmQuantoHelper>(), leverageFct_)); const Real spot = process->s0()->value(); results_.value = solver->valueAt(spot, process->v0()); results_.delta = solver->deltaAt(spot, process->v0()); results_.gamma = solver->gammaAt(spot, process->v0()); results_.theta = solver->thetaAt(spot, process->v0()); // 6. Calculate vanilla option and rebate for in-barriers if ( arguments_.barrierType == Barrier::DownIn || arguments_.barrierType == Barrier::UpIn) { // Cast the payoff boost::shared_ptr<StrikedTypePayoff> payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>( arguments_.payoff); // Calculate the vanilla option boost::shared_ptr<DividendVanillaOption> vanillaOption( new DividendVanillaOption(payoff,arguments_.exercise, dividendCondition->dividendDates(), dividendCondition->dividends())); vanillaOption->setPricingEngine(boost::shared_ptr<PricingEngine>( new FdHestonVanillaEngine(*model_, tGrid_, xGrid_, vGrid_, dampingSteps_, schemeDesc_))); // Calculate the rebate value boost::shared_ptr<DividendBarrierOption> rebateOption( new DividendBarrierOption(arguments_.barrierType, arguments_.barrier, arguments_.rebate, payoff, arguments_.exercise, dividendCondition->dividendDates(), dividendCondition->dividends())); const Size xGridMin = 20; const Size vGridMin = 10; const Size rebateDampingSteps = (dampingSteps_ > 0) ? std::min(Size(1), dampingSteps_/2) : 0; rebateOption->setPricingEngine(boost::shared_ptr<PricingEngine>( new FdHestonRebateEngine(*model_, tGrid_, std::max(xGridMin, xGrid_/4), std::max(vGridMin, vGrid_/4), rebateDampingSteps, schemeDesc_))); results_.value = vanillaOption->NPV() + rebateOption->NPV() - results_.value; results_.delta = vanillaOption->delta() + rebateOption->delta() - results_.delta; results_.gamma = vanillaOption->gamma() + rebateOption->gamma() - results_.gamma; results_.theta = vanillaOption->theta() + rebateOption->theta() - results_.theta; } }