Real HullWhiteSmileSection::volatilityImpl(Rate strike) const { boost::shared_ptr<VanillaSwap> underlying = MakeVanillaSwap(swapLength_,swapIndex_->iborIndex(),strike) .withEffectiveDate(swapIndex_->valueDate(optionDate_)) .withFixedLegCalendar(swapIndex_->fixingCalendar()) .withFixedLegDayCount(swapIndex_->dayCounter()) .withFixedLegTenor(swapIndex_->fixedLegTenor()) .withFixedLegConvention(swapIndex_->fixedLegConvention()) .withFixedLegTerminationDateConvention(swapIndex_->fixedLegConvention()) .withType(VanillaSwap::Payer); underlying->setPricingEngine(discountingEngine_); boost::shared_ptr<Exercise> exercise(new EuropeanExercise(optionDate_)); Swaption swaption(underlying,exercise); swaption.setPricingEngine(jamshidianEngine_); Real npv = swaption.NPV(); Real annuity = fabs(underlying->fixedLegBPS() * 10000.0); //Real blackNpv=blackFormula(Option::Call,strike,atm,0.30*sqrt(exerciseTime())); //std::cout << std::setprecision(8) << "SECTION atm=" << atm_ << " annuity=" << annuity << " npv=" << npv << " strike= " << strike << std::endl; Real vol=0.0; try { vol=blackFormulaImpliedStdDev(Option::Call,strike,atm_,npv,annuity) / sqrt(exerciseTime()); } catch(QuantLib::Error) { //std::cout << " can not imply vol for npv " << npv << " black(300%)=" << blackFormula(Option::Call,strike,atm_,sqrt(exerciseTime())*3.00,annuity) << // " black(1%)=" << blackFormula(Option::Call,strike,atm_,sqrt(exerciseTime())*0.01,annuity) << std::endl; if(npv>blackFormula(Option::Call,strike,atm_,3.00,annuity)) vol =3.0/sqrt(exerciseTime()); else vol=0.0; } return vol; }
Real SmileSection::volatility(Rate strike, VolatilityType volatilityType, Real shift) const { if(volatilityType == volatilityType_ && close(shift,this->shift())) return volatility(strike); Real atm = atmLevel(); QL_REQUIRE(atm != Null<Real>(), "smile section must provide atm level to compute converted volatilties"); Option::Type type = strike >= atm ? Option::Call : Option::Put; Real premium = optionPrice(strike,type); Real premiumAtm = optionPrice(atm,type); if (volatilityType == ShiftedLognormal) { try { return blackFormulaImpliedStdDev(type, strike, atm, premium, 1.0, shift) / std::sqrt(exerciseTime()); } catch(...) { return blackFormulaImpliedStdDevChambers( type, strike, atm, premium, premiumAtm, 1.0, shift) / std::sqrt(exerciseTime()); } } else { return bachelierBlackFormulaImpliedVol(type, strike, atm, exerciseTime(), premium); } }
InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection( const Date& d, const std::vector<Rate>& strikes, const std::vector<Real>& stdDevs, Real atmLevel, const DayCounter& dc, const Interpolator& interpolator, const Date& referenceDate, const Real shift) : SmileSection(d, dc, referenceDate, ShiftedLognormal, shift), exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(strikes), stdDevHandles_(stdDevs.size()), vols_(stdDevs.size()) { //fill dummy handles to allow generic handle-based // computations later on for (Size i=0; i<stdDevs.size(); ++i) stdDevHandles_[i] = Handle<Quote>(boost::shared_ptr<Quote>(new SimpleQuote(stdDevs[i]))); atmLevel_ = Handle<Quote> (boost::shared_ptr<Quote>(new SimpleQuote(atmLevel))); // check strikes!!!!!!!!!!!!!!!!!!!! interpolation_ = interpolator.interpolate(strikes_.begin(), strikes_.end(), vols_.begin()); }
void SabrInterpolatedSmileSection::createInterpolation() const { boost::shared_ptr<SABRInterpolation> tmp(new SABRInterpolation( actualStrikes_.begin(), actualStrikes_.end(), vols_.begin(), exerciseTime(), forwardValue_, alpha_, beta_, nu_, rho_, isAlphaFixed_, isBetaFixed_, isNuFixed_, isRhoFixed_, vegaWeighted_, endCriteria_, method_, 0.0020, false, 50, shift())); swap(tmp, sabrInterpolation_); }
Real SmileSection::vega(Rate strike, Real discount) const { Real atm = atmLevel(); QL_REQUIRE(atm != Null<Real>(), "smile section must provide atm level to compute option vega"); if (volatilityType() == ShiftedLognormal) return blackFormulaVolDerivative(strike,atmLevel(), sqrt(variance(strike)), exerciseTime(),discount,shift())*0.01; else QL_FAIL("vega for normal smilesection not yet implemented"); }
Real Gaussian1dSmileSection::volatilityImpl(Rate strike) const { Real vol = 0.0; try { Option::Type type = strike >= atm_ ? Option::Call : Option::Put; Real o = optionPrice(strike, type); vol = blackFormulaImpliedStdDev(type, strike, atm_, o) / sqrt(exerciseTime()); } catch (...) { } return vol; }
Real KahaleSmileSection::volatilityImpl(Rate strike) const { strike = std::max ( strike, QL_KAHALE_EPS ); int i = index(strike); if(!interpolate_ && !(i==0 || i==(int) (rightIndex_-leftIndex_+1))) return source_->volatility(strike); Real c = cFunctions_[i]->operator()(strike); Real vol=0.0; try { vol = blackFormulaImpliedStdDev(Option::Call,strike,f_,c) / sqrt(exerciseTime()); } catch(...) { } return vol; }
void NoArbSabrSmileSection::init() { QL_REQUIRE(params_.size() >= 4, "sabr expects 4 parameters (alpha,beta,nu,rho) but (" << params_.size() << ") given"); QL_REQUIRE(forward_ > 0.0, "forward (" << forward_ << ") must be positive"); QL_REQUIRE( shift_ == 0.0, "shift (" << shift_ << ") must be zero, other shifts are not implemented yet"); model_ = boost::make_shared<NoArbSabrModel>(exerciseTime(), forward_, params_[0], params_[1], params_[2], params_[3]); }
Real NoArbSabrSmileSection::volatilityImpl(Rate strike) const { Real impliedVol = 0.0; try { Option::Type type; if (strike >= forward_) type = Option::Call; else type = Option::Put; impliedVol = blackFormulaImpliedStdDev(type, strike, forward_, optionPrice(strike, type, 1.0), 1.0) / std::sqrt(exerciseTime()); } catch (...) { } if (impliedVol == 0.0) // fall back on Hagan 2002 expansion impliedVol = unsafeSabrVolatility(strike, forward_, exerciseTime(), params_[0], params_[1], params_[2], params_[3]); return impliedVol; }
Real SplineDensitySmileSection::volatilityImpl(Rate strike) const { strike = std::max(strike,0.00001); // assume only non shifted lognormal // here ... TODO later ... (should be // shifted lognormal with shift equal // to minus lowerBound_ Option::Type type = strike >= f_ ? Option::Call : Option::Put; Real p = optionPrice(strike,type); Real vol = 0.0; try { vol = blackFormulaImpliedStdDev(type, strike, f_, p) / sqrt(exerciseTime()); } catch (...) { } return vol; }
InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection( const Date& d, const std::vector<Rate>& strikes, const std::vector<Handle<Quote> >& stdDevHandles, const Handle<Quote>& atmLevel, const DayCounter& dc, const Interpolator& interpolator, const Date& referenceDate, const Real shift) : SmileSection(d, dc, referenceDate, ShiftedLognormal, shift), exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(strikes), stdDevHandles_(stdDevHandles), atmLevel_(atmLevel), vols_(stdDevHandles.size()) { for (Size i=0; i<stdDevHandles_.size(); ++i) LazyObject::registerWith(stdDevHandles_[i]); LazyObject::registerWith(atmLevel_); // check strikes!!!!!!!!!!!!!!!!!!!! interpolation_ = interpolator.interpolate(strikes_.begin(), strikes_.end(), vols_.begin()); }
InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection( Time timeToExpiry, const std::vector<Rate>& strikes, const std::vector<Handle<Quote> >& stdDevHandles, const Handle<Quote>& atmLevel, const Interpolator& interpolator, const DayCounter& dc, const VolatilityType type, const Real shift) : SmileSection(timeToExpiry, dc, type, shift), exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(strikes), stdDevHandles_(stdDevHandles), atmLevel_(atmLevel), vols_(stdDevHandles.size()) { for (Size i=0; i<stdDevHandles_.size(); ++i) LazyObject::registerWith(stdDevHandles_[i]); LazyObject::registerWith(atmLevel_); // check strikes!!!!!!!!!!!!!!!!!!!! interpolation_ = interpolator.interpolate(strikes_.begin(), strikes_.end(), vols_.begin()); }
Real InterpolatedSmileSection<Interpolator>::varianceImpl(Real strike) const { calculate(); Real v = interpolation_(strike, true); return v*v*exerciseTime(); }
inline Real SmileSection::varianceImpl(Rate strike) const { Volatility v = volatilityImpl(strike); return v*v*exerciseTime(); }
Real SabrInterpolatedSmileSection::varianceImpl(Real strike) const { calculate(); Real v = (*sabrInterpolation_)(strike, true); return v*v*exerciseTime(); }
Real SabrSmileSection::volatilityImpl(Rate strike) const { strike = std::max(0.00001,strike); return unsafeSabrVolatility(strike, forward_, exerciseTime(), alpha_, beta_, nu_, rho_); }
SplineDensitySmileSection::SplineDensitySmileSection( const boost::shared_ptr<SmileSection> source, const Real atm, const Real lowerBound, const Real upperBound, const bool deleteArbitragePoints, const std::vector<Real> &moneynessGrid) : SmileSection(*source), source_(source), lowerBound_(lowerBound), upperBound_(upperBound) { adjustment_ = 1.0; ssutils_ = boost::shared_ptr<SmileSectionUtils>(new SmileSectionUtils( *source, moneynessGrid, atm, deleteArbitragePoints)); std::pair<Size, Size> af = ssutils_->arbitragefreeIndices(); Size leftIndex = af.first; Size rightIndex = af.second; f_ = ssutils_->atmLevel(); const std::vector<Real> &strikes = ssutils_->strikeGrid(); const std::vector<Real> &calls = ssutils_->callPrices(); k_.clear(); c_.clear(); d_.clear(); k_.push_back(lowerBound_); c_.push_back(f_-lowerBound_); d_.push_back(0.0); Real vol = 0.10; // start with a lognormal density Real mu = std::log(f_) - vol*vol*exerciseTime()/2.0; NormalDistribution norm(mu,vol*sqrt(exerciseTime())); std::vector<Real> initialv; for(Size i=leftIndex; i<=rightIndex; i++) { if( strikes[i] > lowerBound_ && strikes[i] < upperBound_ ) { k_.push_back(strikes[i]); c_.push_back(calls[i]); d_.push_back( norm(std::log(strikes[i]))/ strikes[i] ); initialv.push_back(std::sqrt(d_.back())); } } Array initial(initialv.begin(),initialv.end()); k_.push_back(upperBound_); c_.push_back(0.0); d_.push_back(0.0); // density_ = boost::shared_ptr<CubicInterpolation>(new CubicInterpolation(k_.begin(), k_.end(), // d_.begin(), CubicInterpolation::Spline, true, // CubicInterpolation::SecondDerivative, 0.0, // CubicInterpolation::SecondDerivative, 0.0)); density_ = boost::shared_ptr<LinearInterpolation>(new LinearInterpolation(k_.begin(), k_.end(), d_.begin())); // // global calibration // SplineDensityCostFunction cost(this); // NoConstraint constraint; // Problem p(cost,constraint,initial); // LevenbergMarquardt lm; // //Simplex lm(0.01); // //BFGS lm; // EndCriteria ec(5000,100,1e-16,1e-16,1e-16); // EndCriteria::Type ret = lm.minimize(p,ec); // QL_REQUIRE(ret!=EndCriteria::MaxIterations,"Optimizer returns maxiterations"); // Array res = p.currentValue(); // setDensity(res); // just to make really sure, we are at the optimal point // iterative calibration // for(Size i=1; i<k_.size()-1; i++) { // SplineDensityCostFunction2 cost(this,i); // NoConstraint constraint; // Array initial2(1,initial[i-1]); // Problem p(cost,constraint,initial2); // LevenbergMarquardt lm; // //Simplex lm(0.01); // //BFGS lm; // EndCriteria ec(5000,100,1e-35,1e-35,1e-35); // EndCriteria::Type ret = lm.minimize(p,ec); // QL_REQUIRE(ret!=EndCriteria::MaxIterations,"Optimizer returns maxiterations"); // Array res = p.currentValue(); // setDensity(res[0],i); // just to make really sure, we are at the optimal point // } update(); }