void FDVanillaEngine::initializeOperator() const { finiteDifferenceOperator_ = OperatorFactory::getOperator(process_, intrinsicValues_.grid(), getResidualTime(), timeDependent_); }
void FDEuropeanEngine<Scheme>::calculate() const { setupArguments(&arguments_); setGridLimits(); initializeInitialCondition(); initializeOperator(); initializeBoundaryConditions(); FiniteDifferenceModel<Scheme<TridiagonalOperator> > model( finiteDifferenceOperator_, BCs_); prices_ = intrinsicValues_; model.rollback(prices_.values(), getResidualTime(), 0, timeSteps_); results_.value = prices_.valueAtCenter(); results_.delta = prices_.firstDerivativeAtCenter(); results_.gamma = prices_.secondDerivativeAtCenter(); results_.theta = blackScholesTheta(process_, results_.value, results_.delta, results_.gamma); results_.additionalResults["priceCurve"] = prices_; }
void FDStepConditionEngine<Scheme>::calculate( PricingEngine::results* r) const { OneAssetOption::results * results = dynamic_cast<OneAssetOption::results *>(r); setGridLimits(); initializeInitialCondition(); initializeOperator(); initializeBoundaryConditions(); initializeStepCondition(); typedef FiniteDifferenceModel<ParallelEvolver< Scheme<TridiagonalOperator> > > model_type; typename model_type::operator_type operatorSet; typename model_type::array_type arraySet; typename model_type::bc_set bcSet; typename model_type::condition_type conditionSet; prices_ = intrinsicValues_; controlPrices_ = intrinsicValues_; controlOperator_ = finiteDifferenceOperator_; controlBCs_[0] = BCs_[0]; controlBCs_[1] = BCs_[1]; operatorSet.push_back(finiteDifferenceOperator_); operatorSet.push_back(controlOperator_); arraySet.push_back(prices_.values()); arraySet.push_back(controlPrices_.values()); bcSet.push_back(BCs_); bcSet.push_back(controlBCs_); conditionSet.push_back(stepCondition_); conditionSet.push_back(boost::shared_ptr<StandardStepCondition>( new NullCondition<Array>)); model_type model(operatorSet, bcSet); model.rollback(arraySet, getResidualTime(), 0.0, timeSteps_, conditionSet); prices_.values() = arraySet[0]; controlPrices_.values() = arraySet[1]; boost::shared_ptr<StrikedTypePayoff> striked_payoff = boost::dynamic_pointer_cast<StrikedTypePayoff>(payoff_); QL_REQUIRE(striked_payoff, "non-striked payoff given"); Real variance = process_->blackVolatility()->blackVariance( exerciseDate_, striked_payoff->strike()); DiscountFactor dividendDiscount = process_->dividendYield()->discount(exerciseDate_); DiscountFactor riskFreeDiscount = process_->riskFreeRate()->discount(exerciseDate_); Real spot = process_->stateVariable()->value(); Real forwardPrice = spot * dividendDiscount / riskFreeDiscount; BlackCalculator black(striked_payoff, forwardPrice, std::sqrt(variance), riskFreeDiscount); results->value = prices_.valueAtCenter() - controlPrices_.valueAtCenter() + black.value(); results->delta = prices_.firstDerivativeAtCenter() - controlPrices_.firstDerivativeAtCenter() + black.delta(spot); results->gamma = prices_.secondDerivativeAtCenter() - controlPrices_.secondDerivativeAtCenter() + black.gamma(spot); results->additionalResults["priceCurve"] = prices_; }
void FDVanillaEngine::setGridLimits() const { setGridLimits(process_->stateVariable()->value(), getResidualTime()); ensureStrikeInGrid(); }
void FDMultiPeriodEngine<Scheme>::calculate( PricingEngine::results* r) const { OneAssetOption::results *results = dynamic_cast<OneAssetOption::results *>(r); QL_REQUIRE(results, "incorrect argument type"); Time beginDate, endDate; Size dateNumber = stoppingTimes_.size(); bool lastDateIsResTime = false; Integer firstIndex = -1; Integer lastIndex = dateNumber - 1; bool firstDateIsZero = false; Time firstNonZeroDate = getResidualTime(); Real dateTolerance = 1e-6; if (dateNumber > 0) { QL_REQUIRE(getDividendTime(0) >= 0, "first date (" << getDividendTime(0) << ") cannot be negative"); if(getDividendTime(0) < getResidualTime() * dateTolerance ){ firstDateIsZero = true; firstIndex = 0; if(dateNumber >= 2) firstNonZeroDate = getDividendTime(1); } if (std::fabs(getDividendTime(lastIndex) - getResidualTime()) < dateTolerance) { lastDateIsResTime = true; lastIndex = Integer(dateNumber) - 2; } if (!firstDateIsZero) firstNonZeroDate = getDividendTime(0); if (dateNumber >= 2) { for (Size j = 1; j < dateNumber; j++) QL_REQUIRE(getDividendTime(j-1) < getDividendTime(j), "dates must be in increasing order: " << getDividendTime(j-1) << " is not strictly smaller than " << getDividendTime(j)); } } Time dt = getResidualTime()/(timeStepPerPeriod_*(dateNumber+1)); // Ensure that dt is always smaller than the first non-zero date if (firstNonZeroDate <= dt) dt = firstNonZeroDate/2.0; setGridLimits(); initializeInitialCondition(); initializeOperator(); initializeBoundaryConditions(); initializeModel(); initializeStepCondition(); prices_ = intrinsicValues_; if(lastDateIsResTime) executeIntermediateStep(dateNumber - 1); Integer j = lastIndex; do { if (j == Integer(dateNumber) - 1) beginDate = getResidualTime(); else beginDate = getDividendTime(j+1); if (j >= 0) endDate = getDividendTime(j); else endDate = dt; model_->rollback(prices_.values(), beginDate, endDate, timeStepPerPeriod_, *stepCondition_); if (j >= 0) executeIntermediateStep(j); } while (--j >= firstIndex); model_->rollback(prices_.values(), dt, 0, 1, *stepCondition_); if(firstDateIsZero) executeIntermediateStep(0); results->value = prices_.valueAtCenter(); results->delta = prices_.firstDerivativeAtCenter(); results->gamma = prices_.secondDerivativeAtCenter(); results->additionalResults["priceCurve"] = prices_; }