const Handle<LocalVolTermStructure>& GeneralizedBlackScholesProcess::localVolatility() const { if (hasExternalLocalVol_) return externalLocalVolTS_; if (!updated_) { isStrikeIndependent_=true; // constant Black vol? ext::shared_ptr<BlackConstantVol> constVol = ext::dynamic_pointer_cast<BlackConstantVol>( *blackVolatility()); if (constVol) { // ok, the local vol is constant too. localVolatility_.linkTo(ext::make_shared<LocalConstantVol>( constVol->referenceDate(), constVol->blackVol(0.0, x0_->value()), constVol->dayCounter())); updated_ = true; return localVolatility_; } // ok, so it's not constant. Maybe it's strike-independent? ext::shared_ptr<BlackVarianceCurve> volCurve = ext::dynamic_pointer_cast<BlackVarianceCurve>( *blackVolatility()); if (volCurve) { // ok, we can use the optimized algorithm localVolatility_.linkTo(ext::make_shared<LocalVolCurve>( Handle<BlackVarianceCurve>(volCurve))); updated_ = true; return localVolatility_; } // ok, so it's strike-dependent. Never mind. localVolatility_.linkTo( ext::make_shared<LocalVolSurface>(blackVolatility_, riskFreeRate_, dividendYield_, x0_->value())); updated_ = true; isStrikeIndependent_ = false; return localVolatility_; } else { return localVolatility_; } }
void ForwardVanillaEngine<Engine>::setup() const { ext::shared_ptr<StrikedTypePayoff> argumentsPayoff = ext::dynamic_pointer_cast<StrikedTypePayoff>( this->arguments_.payoff); QL_REQUIRE(argumentsPayoff, "wrong payoff given"); ext::shared_ptr<StrikedTypePayoff> payoff( new PlainVanillaPayoff(argumentsPayoff->optionType(), this->arguments_.moneyness * process_->x0())); // maybe the forward value is "better", in some fashion // the right level is needed in order to interpolate // the vol Handle<Quote> spot = process_->stateVariable(); QL_REQUIRE(spot->value() >= 0.0, "negative or null underlting given"); Handle<YieldTermStructure> dividendYield( ext::shared_ptr<YieldTermStructure>( new ImpliedTermStructure(process_->dividendYield(), this->arguments_.resetDate))); Handle<YieldTermStructure> riskFreeRate( ext::shared_ptr<YieldTermStructure>( new ImpliedTermStructure(process_->riskFreeRate(), this->arguments_.resetDate))); // The following approach is ok if the vol is at most // time dependant. It is plain wrong if it is asset dependant. // In the latter case the right solution would be stochastic // volatility or at least local volatility (which unfortunately // implies an unrealistic time-decreasing smile) Handle<BlackVolTermStructure> blackVolatility( ext::shared_ptr<BlackVolTermStructure>( new ImpliedVolTermStructure(process_->blackVolatility(), this->arguments_.resetDate))); ext::shared_ptr<GeneralizedBlackScholesProcess> fwdProcess( new GeneralizedBlackScholesProcess(spot, dividendYield, riskFreeRate, blackVolatility)); originalEngine_ = ext::shared_ptr<Engine>(new Engine(fwdProcess)); originalEngine_->reset(); originalArguments_ = dynamic_cast<VanillaOption::arguments*>( originalEngine_->getArguments()); QL_REQUIRE(originalArguments_, "wrong engine type"); originalResults_ = dynamic_cast<const VanillaOption::results*>( originalEngine_->getResults()); QL_REQUIRE(originalResults_, "wrong engine type"); originalArguments_->payoff = payoff; originalArguments_->exercise = this->arguments_.exercise; originalArguments_->validate(); }
const Handle<LocalVolTermStructure>& VarianceGammaProcess::localVolatility() const{ if(!updated_) { // Constant Volatility boost::shared_ptr<BlackConstantVol> constant = boost::dynamic_pointer_cast<BlackConstantVol>(*blackVolatility()); if(constant) { localVolatility_.linkTo(boost::shared_ptr<LocalVolTermStructure>(new LocalConstantVol(constant->referenceDate(), constant->blackVol(0.0, s0_->value()), constant->dayCounter()))); updated_ = true; return localVolatility_; } boost::shared_ptr<BlackVarianceCurve> volCurve = boost::dynamic_pointer_cast<BlackVarianceCurve>(*blackVolatility()); if(volCurve) { localVolatility_.linkTo(boost::shared_ptr<LocalVolTermStructure>(new LocalVolCurve(Handle<BlackVarianceCurve>(volCurve)))); updated_ = true; return localVolatility_; } // ok, so it's strike-dependent. Never mind. localVolatility_.linkTo(boost::shared_ptr<LocalVolTermStructure>(new LocalVolSurface(blackVolatility_,riskFreeRate_,dividendYield_, s0_->value()))); updated_ = true; return localVolatility_; } else { return localVolatility_; } }