• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lballabio / QuantLib / 10982265308

22 Sep 2024 03:17PM UTC coverage: 72.665% (-0.01%) from 72.678%
10982265308

push

github

web-flow
Manage interpolation of year-on-year inflation index inside coupons (#2073)

76 of 102 new or added lines in 13 files covered. (74.51%)

3 existing lines in 2 files now uncovered.

55133 of 75873 relevant lines covered (72.66%)

8651333.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.76
/ql/termstructures/inflation/inflationhelpers.cpp
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2

3
/*
4
 Copyright (C) 2007, 2009 Chris Kenyon
5
 Copyright (C) 2007 StatPro Italia srl
6

7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9

10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <http://quantlib.org/license.shtml>.
15

16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
 */
20

21
#include <ql/cashflows/inflationcouponpricer.hpp>
22
#include <ql/indexes/inflationindex.hpp>
23
#include <ql/pricingengines/swap/discountingswapengine.hpp>
24
#include <ql/shared_ptr.hpp>
25
#include <ql/termstructures/inflation/inflationhelpers.hpp>
26
#include <ql/utilities/null_deleter.hpp>
27
#include <utility>
28

29
namespace QuantLib {
30

31
    ZeroCouponInflationSwapHelper::ZeroCouponInflationSwapHelper(
147✔
32
        const Handle<Quote>& quote,
33
        const Period& swapObsLag,
34
        const Date& maturity,
35
        Calendar calendar,
36
        BusinessDayConvention paymentConvention,
37
        DayCounter dayCounter,
38
        ext::shared_ptr<ZeroInflationIndex> zii,
39
        CPI::InterpolationType observationInterpolation,
40
        Handle<YieldTermStructure> nominalTermStructure)
147✔
41
    : BootstrapHelper<ZeroInflationTermStructure>(quote), swapObsLag_(swapObsLag),
147✔
42
      maturity_(maturity), calendar_(std::move(calendar)), paymentConvention_(paymentConvention),
147✔
43
      dayCounter_(std::move(dayCounter)), zii_(std::move(zii)),
147✔
44
      observationInterpolation_(observationInterpolation),
147✔
45
      nominalTermStructure_(std::move(nominalTermStructure)) {
294✔
46

47
        auto fixingPeriod = inflationPeriod(maturity_ - swapObsLag_, zii_->frequency());
147✔
48
        auto interpolationPeriod = inflationPeriod(maturity, zii_->frequency());
147✔
49

50
        if (detail::CPI::isInterpolated(observationInterpolation_) && maturity > interpolationPeriod.first) {
147✔
51
            // if interpolated, we need to cover the end of the interpolation period
NEW
52
            earliestDate_ = fixingPeriod.first;
×
NEW
53
            latestDate_ = fixingPeriod.second + 1;
×
54
        } else {
55
            // if not interpolated, the date of the initial fixing is enough
56
            earliestDate_ = fixingPeriod.first;
147✔
57
            latestDate_ = fixingPeriod.first;
147✔
58
        }
59

60
        // check that the observation lag of the swap
61
        // is compatible with the availability lag of the index AND
62
        // it's interpolation (assuming the start day is spot)
63
        if (detail::CPI::isInterpolated(observationInterpolation_)) {
147✔
64
            Period pShift(zii_->frequency());
×
65
            QL_REQUIRE(swapObsLag_ - pShift >= zii_->availabilityLag(),
×
66
                       "inconsistency between swap observation lag "
67
                           << swapObsLag_ << ", index period " << pShift << " and index availability "
68
                           << zii_->availabilityLag() << ": need (obsLag-index period) >= availLag");
69
        }
70

71
        registerWith(Settings::instance().evaluationDate());
294✔
72
        registerWith(nominalTermStructure_);
147✔
73
    }
147✔
74

75

76
    Real ZeroCouponInflationSwapHelper::impliedQuote() const {
1,031✔
77
        zciis_->deepUpdate();
1,031✔
78
        return zciis_->fairRate();
1,031✔
79
    }
80

81

82
    void ZeroCouponInflationSwapHelper::setTermStructure(ZeroInflationTermStructure* z) {
175✔
83

84
        BootstrapHelper<ZeroInflationTermStructure>::setTermStructure(z);
175✔
85

86
        // set up a new ZCIIS
87
        // but this one does NOT own its inflation term structure
88
        const bool own = false;
89
        Rate K = quote()->value();
175✔
90

91
        // The effect of the new inflation term structure is
92
        // felt via the effect on the inflation index
93
        Handle<ZeroInflationTermStructure> zits(
94
            ext::shared_ptr<ZeroInflationTermStructure>(z, null_deleter()), own);
175✔
95

96
        ext::shared_ptr<ZeroInflationIndex> new_zii = zii_->clone(zits);
175✔
97

98
        Real nominal = 1000000.0; // has to be something but doesn't matter what
175✔
99
        Date start = nominalTermStructure_->referenceDate();
175✔
100
        zciis_ = ext::make_shared<ZeroCouponInflationSwap>(Swap::Payer, nominal, start,
350✔
101
                                                 maturity_, calendar_, paymentConvention_,
175✔
102
                                                 dayCounter_, K, // fixed side & fixed rate
175✔
103
                                                 new_zii, swapObsLag_, observationInterpolation_);
175✔
104
        // Because very simple instrument only takes
105
        // standard discounting swap engine.
106
        zciis_->setPricingEngine(
350✔
107
            ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(nominalTermStructure_)));
350✔
108
    }
175✔
109

110

111
    YearOnYearInflationSwapHelper::YearOnYearInflationSwapHelper(
165✔
112
        const Handle<Quote>& quote,
113
        const Period& swapObsLag,
114
        const Date& maturity,
115
        Calendar calendar,
116
        BusinessDayConvention paymentConvention,
117
        DayCounter dayCounter,
118
        ext::shared_ptr<YoYInflationIndex> yii,
119
        CPI::InterpolationType interpolation,
120
        Handle<YieldTermStructure> nominalTermStructure)
165✔
121
    : BootstrapHelper<YoYInflationTermStructure>(quote), swapObsLag_(swapObsLag),
165✔
122
      maturity_(maturity), calendar_(std::move(calendar)), paymentConvention_(paymentConvention),
165✔
123
      dayCounter_(std::move(dayCounter)), yii_(std::move(yii)), interpolation_(interpolation),
165✔
124
      nominalTermStructure_(std::move(nominalTermStructure)) {
330✔
125

126
        auto fixingPeriod = inflationPeriod(maturity_ - swapObsLag_, yii_->frequency());
165✔
127
        auto interpolationPeriod = inflationPeriod(maturity, yii_->frequency());
165✔
128

129
        if (detail::CPI::isInterpolated(interpolation_, yii_) && maturity > interpolationPeriod.first) {
165✔
130
            // if interpolated, we need to cover the end of the interpolation period
131
            earliestDate_ = fixingPeriod.first;
60✔
132
            latestDate_ = fixingPeriod.second + 1;
60✔
133
        } else {
134
            // if not interpolated, the date of the initial fixing is enough
135
            earliestDate_ = fixingPeriod.first;
105✔
136
            latestDate_ = fixingPeriod.first;
105✔
137
        }
138

139
        // check that the observation lag of the swap
140
        // is compatible with the availability lag of the index AND
141
        // its interpolation (assuming the start day is spot)
142
        if (detail::CPI::isInterpolated(interpolation_, yii_)) {
165✔
143
            Period pShift(yii_->frequency());
60✔
144
            QL_REQUIRE(swapObsLag_ - pShift >= yii_->availabilityLag(),
120✔
145
                       "inconsistency between swap observation lag "
146
                       << swapObsLag_ << ", index period " << pShift << " and index availability "
147
                       << yii_->availabilityLag() << ": need (obsLag-index period) >= availLag");
148
        }
149

150
        registerWith(Settings::instance().evaluationDate());
330✔
151
        registerWith(nominalTermStructure_);
165✔
152
    }
165✔
153

NEW
154
    YearOnYearInflationSwapHelper::YearOnYearInflationSwapHelper(
×
155
        const Handle<Quote>& quote,
156
        const Period& swapObsLag,
157
        const Date& maturity,
158
        Calendar calendar,
159
        BusinessDayConvention paymentConvention,
160
        DayCounter dayCounter,
161
        ext::shared_ptr<YoYInflationIndex> yii,
NEW
162
        Handle<YieldTermStructure> nominalTermStructure)
×
163
    : YearOnYearInflationSwapHelper(quote, swapObsLag, maturity, calendar, paymentConvention,
NEW
164
                                    dayCounter, yii, CPI::AsIndex, nominalTermStructure) {}
×
165

166

167
    Real YearOnYearInflationSwapHelper::impliedQuote() const {
922✔
168
        yyiis_->deepUpdate();
922✔
169
        return yyiis_->fairRate();
922✔
170
    }
171

172

173
    void YearOnYearInflationSwapHelper::setTermStructure(YoYInflationTermStructure* y) {
165✔
174

175
        BootstrapHelper<YoYInflationTermStructure>::setTermStructure(y);
165✔
176

177
        // set up a new YYIIS
178
        // but this one does NOT own its inflation term structure
179
        const bool own = false;
180

181
        // The effect of the new inflation term structure is
182
        // felt via the effect on the inflation index
183
        Handle<YoYInflationTermStructure> yyts(
184
            ext::shared_ptr<YoYInflationTermStructure>(y, null_deleter()), own);
165✔
185

186
        ext::shared_ptr<YoYInflationIndex> new_yii = yii_->clone(yyts);
165✔
187

188
        // always works because tenor is always 1 year so
189
        // no problem with different days-in-month
190
        Date from = Settings::instance().evaluationDate();
165✔
191
        Date to = maturity_;
165✔
192
        Schedule fixedSchedule = MakeSchedule()
165✔
193
                                     .from(from)
165✔
194
                                     .to(to)
165✔
195
                                     .withTenor(1 * Years)
330✔
196
                                     .withConvention(Unadjusted)
165✔
197
                                     .withCalendar(calendar_) // fixed leg gets cal from sched
165✔
198
                                     .backwards();
165✔
199
        const Schedule& yoySchedule = fixedSchedule;
200
        Spread spread = 0.0;
165✔
201
        Rate fixedRate = quote()->value();
165✔
202

203
        Real nominal = 1000000.0; // has to be something but doesn't matter what
165✔
204
        yyiis_ = ext::make_shared<YearOnYearInflationSwap>(
330✔
205
            Swap::Payer, nominal, fixedSchedule, fixedRate, dayCounter_,
330✔
206
            yoySchedule, new_yii, swapObsLag_, interpolation_,
165✔
207
            spread, dayCounter_, calendar_, paymentConvention_);
165✔
208

209
        // The instrument takes a standard discounting swap engine.
210
        // The inflation-related work is done by the coupons.
211

212
        yyiis_->setPricingEngine(
330✔
213
            ext::shared_ptr<PricingEngine>(new DiscountingSwapEngine(nominalTermStructure_)));
330✔
214
    }
330✔
215

216
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc