Real BlackIborCouponPricer::optionletPrice(Option::Type optionType, Real effStrike) const { Date fixingDate = coupon_->fixingDate(); if (fixingDate <= Settings::instance().evaluationDate()) { // the amount is determined Real a, b; if (optionType==Option::Call) { a = coupon_->indexFixing(); b = effStrike; } else { a = effStrike; b = coupon_->indexFixing(); } return std::max(a - b, 0.0)* accrualPeriod_*discount_; } else { // not yet determined, use Black model QL_REQUIRE(!capletVolatility().empty(), "missing optionlet volatility"); Real stdDev = std::sqrt(capletVolatility()->blackVariance(fixingDate, effStrike)); Real shift = capletVolatility()->displacement(); bool shiftedLn = capletVolatility()->volatilityType() == ShiftedLognormal; Rate fixing = shiftedLn ? blackFormula(optionType, effStrike, adjustedFixing(), stdDev, 1.0, shift) : bachelierBlackFormula(optionType, effStrike, adjustedFixing(), stdDev, 1.0); return fixing * accrualPeriod_ * discount_; } }
Real YoYInflationBachelierCapFloorEngine::optionletImpl(Option::Type type, Rate strike, Rate forward, Real stdDev, Real d) const { return bachelierBlackFormula(type, strike, forward, stdDev, d); }
Real bachelierBlackFormula( const boost::shared_ptr<PlainVanillaPayoff>& payoff, Real forward, Real stdDev, Real discount) { return bachelierBlackFormula(payoff->optionType(), payoff->strike(), forward, stdDev, discount); }
Real SmileSection::optionPrice(Rate strike, Option::Type type, Real discount) const { Real atm = atmLevel(); QL_REQUIRE(atm != Null<Real>(), "smile section must provide atm level to compute option price"); // if lognormal or shifted lognormal, // for strike at -shift, return option price even if outside // minstrike, maxstrike interval if (volatilityType() == ShiftedLognormal) return blackFormula(type,strike,atm, fabs(strike+shift()) < QL_EPSILON ? 0.2 : sqrt(variance(strike)),discount,shift()); else return bachelierBlackFormula(type,strike,atm,sqrt(variance(strike)),discount); }
Real LognormalCmsSpreadPricer::optionletPrice(Option::Type optionType, Real strike) const { // this method is only called for future fixings optionType_ = optionType; phi_ = optionType == Option::Call ? 1.0 : -1.0; Real res = 0.0; if (volType_ == ShiftedLognormal) { // (shifted) lognormal volatility if (strike >= 0.0) { a_ = gearing1_; b_ = gearing2_; s1_ = swapRate1_ + shift1_; s2_ = swapRate2_ + shift2_; m1_ = mu1_; m2_ = mu2_; v1_ = vol1_; v2_ = vol2_; k_ = strike + gearing1_ * shift1_ + gearing2_ * shift2_; } else { a_ = -gearing2_; b_ = -gearing1_; s1_ = swapRate2_ + shift1_; s2_ = swapRate1_ + shift2_; m1_ = mu2_; m2_ = mu1_; v1_ = vol2_; v2_ = vol1_; k_ = -strike - gearing1_ * shift1_ - gearing2_ * shift2_; res += phi_ * (gearing1_ * adjustedRate1_ + gearing2_ * adjustedRate2_ - strike); } res += 1.0 / M_SQRTPI * (*integrator_)(integrand_f(this)); } else { // normal volatility Real forward = gearing1_ * adjustedRate1_ + gearing2_ * adjustedRate2_; Real stddev = std::sqrt(fixingTime_ * (gearing1_ * gearing1_ * vol1_ * vol1_ + gearing2_ * gearing2_ * vol2_ * vol2_ + 2.0 * gearing1_ * gearing2_ * rho_ * vol1_ * vol2_)); res = bachelierBlackFormula(optionType_, strike, forward, stddev, 1.0); } return res * discount_ * coupon_->accrualPeriod(); }
Real value(const Option::Type type, const Real strike, const Real atmForward, const Real stdDev, const Real annuity, const Real) { return bachelierBlackFormula(type, strike, atmForward, stdDev, annuity); }