Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cmscaphelper.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <ql/experimental/coupons/cmsspreadcoupon.hpp>
20#include <ql/experimental/coupons/strippedcapflooredcoupon.hpp>
21#include <ql/experimental/coupons/swapspreadindex.hpp>
22#include <ql/instruments/vanillaswap.hpp>
23#include <ql/math/solvers1d/brent.hpp>
24#include <ql/pricingengines/swap/discountingswapengine.hpp>
25#include <ql/time/daycounters/actual360.hpp>
27
28namespace QuantExt {
29
30QuantLib::Real CmsCapHelper::modelValue() const {
31 calculate();
32 return cap_->NPV();
33}
34
36
37 Date startDate;
38 Date endDate;
39
40 // Compute ATM swap rates
41 Real spread, rate1, rate2;
42
43 std::vector<Real> nominals(1, 1.0);
44
45 {
46 QuantLib::ext::shared_ptr<PricingEngine> swapEngine(
47 new DiscountingSwapEngine(index1_->discountingTermStructure(), false));
48
49 Calendar calendar = index1_->fixingCalendar();
50
51 QuantLib::ext::shared_ptr<IborIndex> index = index1_->iborIndex();
52
53 // FIXME, reduce length by forward start
54 startDate = calendar.advance(calendar.advance(asof_, spotDays_), forwardStart_);
55 endDate = calendar.advance(startDate, length_ - forwardStart_, index->businessDayConvention());
56
57 Schedule cmsSchedule(startDate, endDate, cmsTenor_, calendar, index->businessDayConvention(),
58 index->businessDayConvention(), DateGeneration::Forward, false);
59
60 Leg cmsLeg = CmsLeg(cmsSchedule, index1_)
61 .withNotionals(nominals)
62 .withPaymentAdjustment(index1_->iborIndex()->businessDayConvention())
63 .withPaymentDayCounter(index1_->iborIndex()->dayCounter())
64 .withFixingDays(fixingDays_);
65 QuantLib::setCouponPricer(cmsLeg, cmsPricer_);
66
67 std::vector<Leg> cmsLegs;
68 std::vector<bool> cmsPayers;
69 cmsLegs.push_back(cmsLeg);
70 cmsPayers.push_back(true);
71 QuantLib::ext::shared_ptr<QuantLib::Swap> s = QuantLib::ext::make_shared<QuantLib::Swap>(cmsLegs, cmsPayers);
72 s->setPricingEngine(swapEngine);
73
74 rate1 = s->NPV() / (s->legBPS(0) / 1.0e-4);
75 }
76
77 QuantLib::ext::shared_ptr<PricingEngine> swapEngine(new DiscountingSwapEngine(index2_->discountingTermStructure(), false));
78
79 Calendar calendar = index2_->fixingCalendar();
80
81 QuantLib::ext::shared_ptr<IborIndex> index = index2_->iborIndex();
82 // FIXME, reduce length by forward start
83 startDate = calendar.advance(calendar.advance(asof_, spotDays_), forwardStart_);
84 endDate = calendar.advance(startDate, length_ - forwardStart_, index->businessDayConvention());
85
86 Schedule cmsSchedule(startDate, endDate, cmsTenor_, calendar, index->businessDayConvention(),
87 index->businessDayConvention(), DateGeneration::Forward, false);
88
89 Leg cmsLeg = CmsLeg(cmsSchedule, index2_)
90 .withNotionals(nominals)
91 .withPaymentAdjustment(index2_->iborIndex()->businessDayConvention())
92 .withPaymentDayCounter(index2_->iborIndex()->dayCounter())
93 .withFixingDays(fixingDays_);
94 QuantLib::setCouponPricer(cmsLeg, cmsPricer_);
95
96 std::vector<Leg> cmsLegs;
97 std::vector<bool> cmsPayers;
98 cmsLegs.push_back(cmsLeg);
99 cmsPayers.push_back(true);
100 QuantLib::ext::shared_ptr<QuantLib::Swap> s = QuantLib::ext::make_shared<QuantLib::Swap>(cmsLegs, cmsPayers);
101 s->setPricingEngine(swapEngine);
102
103 rate2 = s->NPV() / (s->legBPS(0) / 1.0e-4);
104
105 spread = rate1 - rate2;
106
107 // Construct CMS Spread CapFloor
108
109 std::vector<Leg> legs;
110 std::vector<bool> legPayers;
111
112 QuantLib::ext::shared_ptr<QuantLib::SwapSpreadIndex> spreadIndex = QuantLib::ext::make_shared<QuantLib::SwapSpreadIndex>(
113 "CMSSpread_" + index1_->familyName() + "_" + index2_->familyName(), index1_, index2_);
114
115 startDate = calendar_.advance(calendar_.advance(asof_, spotDays_), forwardStart_);
116 endDate = calendar_.advance(startDate, length_ - forwardStart_, convention_);
117
118 Schedule cmsSpreadSchedule(startDate, endDate, cmsTenor_, calendar_, convention_, convention_,
119 DateGeneration::Forward, false);
120 Leg cmsLeg1 = CmsSpreadLeg(cmsSpreadSchedule, spreadIndex)
121 .withNotionals(nominals)
122 .withSpreads(std::vector<Rate>(1, 0))
123 .withPaymentAdjustment(convention_)
124 .withPaymentDayCounter(dayCounter_)
125 .withFixingDays(fixingDays_)
126 .inArrears(true)
127 .withCaps(std::vector<Rate>(1, spread));
128
129 QuantLib::setCouponPricer(cmsLeg1, pricer_);
130
131 Leg cmsLeg1b = StrippedCappedFlooredCouponLeg(cmsLeg1);
132
133 legs.push_back(cmsLeg1b);
134 legPayers.push_back(false);
135
136 cap_ = QuantLib::ext::make_shared<QuantLib::Swap>(legs, legPayers);
137 QuantLib::ext::shared_ptr<PricingEngine> swapEngine2(new DiscountingSwapEngine(discountCurve_, false));
138 cap_->setPricingEngine(swapEngine2);
139}
140
141} // namespace QuantExt
QuantLib::Real modelValue() const
returns the price of the instrument according to the model
void performCalculations() const override
Handle< YieldTermStructure > discountCurve_
QuantLib::ext::shared_ptr< FloatingRateCouponPricer > pricer_
BusinessDayConvention convention_
QuantLib::ext::shared_ptr< QuantLib::CmsCouponPricer > cmsPricer_
QuantLib::ext::shared_ptr< QuantLib::Swap > cap_
QuantLib::ext::shared_ptr< SwapIndex > index1_
QuantLib::ext::shared_ptr< SwapIndex > index2_
Cms Option helper class.