23#include <ql/experimental/coupons/cmsspreadcoupon.hpp>
24#include <ql/experimental/coupons/lognormalcmsspreadpricer.hpp>
25#include <ql/math/integrals/kronrodintegral.hpp>
26#include <ql/pricingengines/blackformula.hpp>
27#include <ql/termstructures/volatility/swaption/swaptionvolcube.hpp>
28#include <ql/optional.hpp>
35 class LognormalCmsSpreadPricer::integrand_f {
36 const LognormalCmsSpreadPricer* pricer;
38 explicit integrand_f(
const LognormalCmsSpreadPricer* pricer)
41 return pricer->integrand(x);
46 const ext::shared_ptr<CmsCouponPricer>& cmsPricer,
49 const Size integrationPoints,
50 const ext::optional<VolatilityType>& volatilityType,
54 couponDiscountCurve_(
std::move(couponDiscountCurve)) {
61 QL_REQUIRE(integrationPoints >= 4,
62 "at least 4 integration points should be used ("
63 << integrationPoints <<
")");
65 ext::make_shared<GaussHermiteIntegration>(integrationPoints);
67 cnd_ = ext::make_shared<CumulativeNormalDistribution>(0.0, 1.0);
69 if (!volatilityType) {
71 "if volatility type is inherited, no shifts should be "
74 volType_ = cmsPricer->swaptionVolatility()->volatilityType();
108 return std::exp(-x * x) * f;
115 Real s = M_SQRT2 * x;
124 ?
Real(std::max(beta, 0.0))
128 return std::exp(-x * x) * f;
135 QL_REQUIRE(
coupon_,
"CMS spread coupon needed");
156 index_->swapIndex1()->exogenousDiscount()
157 ?
index_->swapIndex1()->discountingTermStructure()
158 :
index_->swapIndex1()->forwardingTermStructure();
171 <<
") should be positive while gearing2 ("
174 c1_ = ext::make_shared<CmsCoupon>(
181 c2_ = ext::make_shared<CmsCoupon>(
202 ext::shared_ptr<SwaptionVolatilityStructure> swvol =
204 ext::shared_ptr<SwaptionVolatilityCube> swcub =
205 ext::dynamic_pointer_cast<SwaptionVolatilityCube>(swvol);
214 if (swcub ==
nullptr) {
218 "if only an atm surface is given, the volatility "
219 "type must be inherited");
220 vol1_ = swvol->volatility(
222 vol2_ = swvol->volatility(
226 index_->swapIndex1()->tenor())
229 index_->swapIndex2()->tenor())
283 1.0 / M_SQRTPI * (*integrator_)(integrand_f(
this));
307 const Rate Rs = std::max(
326 const Rate Rs = std::max(
const ext::shared_ptr< SwapSpreadIndex > & swapSpreadIndex() const
base pricer for vanilla CMS spread coupons
Handle< Quote > correlation() const
const Date & referencePeriodEnd() const
end date of the reference period
const Date & accrualStartDate() const
start of the accrual period
virtual Real nominal() const
const Date & accrualEndDate() const
end of the accrual period
Date date() const override
Time accrualPeriod() const
accrual period as fraction of year
const Date & referencePeriodStart() const
start date of the reference period
base floating-rate coupon class
virtual Date fixingDate() const
fixing date
Natural fixingDays() const
fixing days
Real gearing() const
index gearing, i.e. multiplicative coefficient for the index
DayCounter dayCounter() const override
day counter for accrual calculation
const ext::shared_ptr< InterestRateIndex > & index() const
floating index
Spread spread() const
spread paid over the fixing of the underlying index
bool isInArrears() const
whether or not the coupon fixes in arrears
Shared handle to an observable.
Real integrand_normal(Real) const
Real capletPrice(Rate effectiveCap) const override
Rate floorletRate(Rate effectiveFloor) const override
ext::shared_ptr< CmsCoupon > c1_
void initialize(const FloatingRateCoupon &coupon) override
ext::shared_ptr< CmsCoupon > c2_
ext::shared_ptr< GaussianQuadrature > integrator_
Real integrand(Real) const
ext::shared_ptr< CmsCouponPricer > cmsPricer_
LognormalCmsSpreadPricer(const ext::shared_ptr< CmsCouponPricer > &cmsPricer, const Handle< Quote > &correlation, Handle< YieldTermStructure > couponDiscountCurve=Handle< YieldTermStructure >(), Size IntegrationPoints=16, const ext::optional< VolatilityType > &volatilityType=ext::nullopt, Real shift1=Null< Real >(), Real shift2=Null< Real >())
ext::shared_ptr< CumulativeNormalDistribution > cnd_
bool inheritedVolatilityType_
Handle< YieldTermStructure > couponDiscountCurve_
const CmsSpreadCoupon * coupon_
Rate swapletRate() const override
Real floorletPrice(Rate effectiveFloor) const override
ext::shared_ptr< SwapSpreadIndex > index_
Real swapletPrice() const override
Real optionletPrice(Option::Type optionType, Real strike) const
Rate capletRate(Rate effectiveCap) const override
template class providing a null value for a given type.
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
DateProxy & evaluationDate()
the date at which pricing is to be performed.
static Settings & instance()
access to the unique instance
std::size_t Size
size of a container
Real bachelierBlackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount)
bool close_enough(const Quantity &m1, const Quantity &m2, Size n)