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); } }
Real SmileSection::digitalOptionPrice(Rate strike, Option::Type type, Real discount, Real gap) const { Real m = volatilityType() == ShiftedLognormal ? -shift() : -QL_MAX_REAL; Real kl = std::max(strike-gap/2.0,m); Real kr = kl+gap; return (type==Option::Call ? 1.0 : -1.0) * (optionPrice(kl,type,discount)-optionPrice(kr,type,discount)) / gap; }
Disposable<Array> SplineDensitySmileSection::setDensity(const Array& d) { Array errors(c_.size()-2); std::cout << "***************************" << std::endl; Real signChanges = 0.0; for(Size i=1;i<d_.size()-1;i++) { d_[i] = d[i-1]*d[i-1]; std::cout << "knot " << i << " dens " << d_[i] << std::endl; if( (d_[i]-d_[i-1]) * (d_[i+1]-d_[i]) < 0.0) signChanges+=1.0; } if(signChanges > 0.0) signChanges -= 1.0; density_->update(); update(); Real penalty = 1.0 + /*((std::exp(10.0* (f_ - expectation_) * (f_ - expectation_)) - 1.0) +*/ (std::exp((1.0 - adjustment_) * (1.0 - adjustment_)) - 1.0); //(std::exp(signChanges)-1.0); for (Size i = 1; i < c_.size() - 1; i++) { errors[i-1] = (c_[i] - optionPrice(k_[i])) * penalty; std::cout << "strike " << k_[i] << " market " << c_[i] << " spline " << c_[i] - errors[i-1] << std::endl; } std::cout << "penatly = " << penalty << std::endl; return errors; }
Real BdkSmileSection::volatilityImpl(Rate strike) const { Real vol = 0.0; try { vol = blackFormulaImpliedStdDev(Option::Call, strike, f_, optionPrice(strike)) / sqrt(source_->exerciseTime()); } catch (QuantLib::Error) { } return vol; }
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 SplineDensitySmileSection::setDensity(const Real d, const Size i) { d_[i] = d*d; density_->update(); update(); Real p = optionPrice(k_[i]); std::cout << std::setprecision(16) << "strike " << k_[i] << " dens " << d << " market " << c_[i] << " spline " << p << " error " << (p-c_[i]) << std::endl; return p-c_[i]; }
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; }
Real SplineDensitySmileSection::optionPrice(Rate strike, Option::Type type, Real discount) const { if(type == Option::Put) return discount*(optionPrice(strike, Option::Call, 1.0) - f_ + strike); //strike += expectation_-f_; if(strike <= lowerBound_) return f_-strike; if(strike >= upperBound_) return 0.0; Real price = f_- lowerBound_;// + expectation_-f_; // const std::vector<Real> &pa_ = density_->cCoefficients(); // just for our convenience // const std::vector<Real> &pb_ = density_->bCoefficients(); // const std::vector<Real> &pc_ = density_->aCoefficients(); const std::vector<Real> &pd_ = d_; for(Size j=0; j<=index(strike); j++) { Real mu = std::min(k_[j+1],strike); Real dk = mu - k_[j]; Real dk2 = dk*dk; // price += (dk * (adjustment_*lambda_[j] - 1.0) + adjustment_*( // 1.0 / 20.0 * pa_[j] * dk2*dk2*dk + // 1.0 / 12.0 * pb_[j] * dk2*dk2 + // 1.0 / 6.0 * pc_[j] * dk2*dk + // 1.0 / 2.0 * pd_[j] * dk2)); // linear interpolation Real pa=0.0,pb=0.0; Real pc=(d_[j+1]-d_[j])/(k_[j+1]-k_[j]); price += (dk * (adjustment_*lambda_[j] - 1.0) + adjustment_*( 1.0 / 20.0 * pa * dk2*dk2*dk + 1.0 / 12.0 * pb * dk2*dk2 + 1.0 / 6.0 * pc * dk2*dk + 1.0 / 2.0 * pd_[j] * dk2)); } return price; }
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; }