Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
jyimpliedyoyinflationtermstructure.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 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/termstructures/inflation/inflationhelpers.hpp>
20#include <ql/termstructures/inflation/piecewiseyoyinflationcurve.hpp>
21#include <ql/termstructures/yield/discountcurve.hpp>
22#include <ql/time/schedule.hpp>
28
29using QuantLib::Date;
30using QuantLib::InterpolatedDiscountCurve;
31using QuantLib::Linear;
32using QuantLib::MakeSchedule;
33using QuantLib::PiecewiseYoYInflationCurve;
34using QuantLib::Real;
35using QuantLib::Schedule;
36using QuantLib::Size;
37using QuantLib::Time;
38using QuantLib::YearOnYearInflationSwapHelper;
39using std::exp;
40using std::map;
41using std::vector;
42
43namespace QuantExt {
44
45JyImpliedYoYInflationTermStructure::JyImpliedYoYInflationTermStructure(const QuantLib::ext::shared_ptr<CrossAssetModel>& model,
46 Size index, bool indexIsInterpolated)
47 : YoYInflationModelTermStructure(model, index, indexIsInterpolated) {}
48
49map<Date, Real> JyImpliedYoYInflationTermStructure::yoyRates(const vector<Date>& dts, const Period& obsLag) const {
50
51 // First step is to calculate the YoY swap rate for each maturity date in dts and store in yyiisRates.
52 map<Date, Real> yoySwaplets;
53 map<Date, Real> discounts;
54 map<Date, Real> yyiisRates;
55 auto irIdx = model_->ccyIndex(model_->infjy(index_)->currency());
56
57 // Will need a YoY index below in the helpers.
58 QuantLib::ext::shared_ptr<YoYInflationIndex> index =
59 QuantLib::ext::make_shared<YoYInflationIndexWrapper>(model_->infjy(index_)->inflationIndex(), indexIsInterpolated());
60
61 for (const auto& maturity : dts) {
62
63 // Schedule for the YoY swap with maturity date equal to `maturity`
64 Schedule schedule = MakeSchedule()
65 .from(referenceDate_)
66 .to(maturity)
67 .withTenor(1 * Years)
68 .withConvention(Unadjusted)
69 .withCalendar(calendar())
70 .backwards();
71
72 // Store the value of the model implied YoY leg and the value of the fixed leg annuity.
73 Real yoyLegValue = 0.0;
74 Real fixedLegAnnuity = 0.0;
75
76 for (Size i = 1; i < schedule.dates().size(); ++i) {
77
78 // Start and end of the current YoY swaplet period.
79 const auto& start = schedule.dates()[i - 1];
80 const auto& end = schedule.dates()[i];
81
82 // If we have already calculated the YoY swaplet price for this period, use it.
83 // We should always have a discount factor in this case also.
84 auto it = yoySwaplets.find(end);
85 if (it != yoySwaplets.end()) {
86 yoyLegValue += it->second;
87 fixedLegAnnuity += discounts.at(end);
88 continue;
89 }
90
91 // Need to calculate the YoY swaplet value over the period [start, end]
92 Real swaplet;
93 auto T = relativeTime_ + dayCounter().yearFraction(referenceDate_, end);
94 auto discount = model_->discountBond(irIdx, relativeTime_, T, state_[2]);
95 if (i == 1) {
96 // The first YoY swaplet is a zero coupon swaplet because I_{start} is known.
97 auto growth =
99 swaplet = discount * (growth - 1.0);
100 } else {
101 auto S = relativeTime_ + dayCounter().yearFraction(referenceDate_, start);
102 swaplet = yoySwaplet(S, T);
103 }
104
105 // Cache the swaplet value and the discount factor related to this swaplet end date.
106 yoySwaplets[end] = swaplet;
107 discounts[end] = discount;
108
109 // Update the YoY leg value and the fixed leg annuity
110 yoyLegValue += swaplet;
111 fixedLegAnnuity += discount;
112 }
113
114 // The model implied YoY inflation swap rate
115 yyiisRates[maturity] = yoyLegValue / fixedLegAnnuity;
116 }
117
118 QL_REQUIRE(!yyiisRates.empty(), "JyImpliedYoYInflationTermStructure: yoyRates did not create any YoY swap rates.");
119
120 // Will need a discount term structure in the bootstrap below so create it here from the discounts map.
121 vector<Date> dfDates;
122 vector<Real> dfValues;
123
124 if (discounts.count(referenceDate_) == 0) {
125 dfDates.push_back(referenceDate_);
126 dfValues.push_back(1.0);
127 }
128
129 for (const auto& kv : discounts) {
130 dfDates.push_back(kv.first);
131 dfValues.push_back(kv.second);
132 }
133
134 auto irTs = model_->irlgm1f(irIdx)->termStructure();
135 Handle<YieldTermStructure> yts(
136 QuantLib::ext::make_shared<InterpolatedDiscountCurve<LogLinear>>(dfDates, dfValues, irTs->dayCounter(), LogLinear()));
137
138 // Create the YoY swap helpers from the YoY swap rates calculated above.
139 // Using the curve's day counter as the helper's day counter for now.
140 using YoYHelper = BootstrapHelper<YoYInflationTermStructure>;
141 vector<QuantLib::ext::shared_ptr<YoYHelper>> helpers;
142 for (const auto& kv : yyiisRates) {
143 Handle<Quote> yyiisQuote(QuantLib::ext::make_shared<SimpleQuote>(kv.second));
144 helpers.push_back(QuantLib::ext::make_shared<YearOnYearInflationSwapHelper>(
145 yyiisQuote, observationLag(), kv.first, calendar(), Unadjusted, dayCounter(), index, yts));
146 }
147
148 // Create a YoY curve from the helpers
149 // Use Linear here in line with what is in scenariosimmarket and todaysmarket but should probably be more generic.
150 auto lag = obsLag == -1 * Days ? observationLag() : obsLag;
151 auto baseRate = helpers.front()->quote()->value();
152 auto yoyCurve = QuantLib::ext::make_shared<PiecewiseYoYInflationCurve<Linear>>(
153 referenceDate_, calendar(), dayCounter(), lag, frequency(), indexIsInterpolated(), baseRate, helpers, 1e-12);
154
155 // Read the necessary YoY rates from the bootstrapped YoY inflation curve
156 map<Date, Real> result;
157 for (const auto& maturity : dts) {
158 result[maturity] = yoyCurve->yoyRate(maturity);
159 }
160
161 return result;
162}
163
165
166 // The JY implied swap rate at time t for the period from S to T is:
167 // N \tau(S, T) \left\{ P_n(t,S) \frac{P_r(t,T)}{P_r(t,S)} e^{C(t,S,T)} - P_n(t,T) \right\}
168 // where N is the nominal, \tau(S, T) is the daycount which we assume equals 1 here.
169 // e^{C(t,S,T)} is the correction term which we deal with below.
170
171 // Get P_n(t,S) and P_n(t,T).
172 auto irIdx = model_->ccyIndex(model_->infjy(index_)->currency());
173 auto irTs = model_->irlgm1f(irIdx)->termStructure();
174 auto p_n_t_S = model_->discountBond(irIdx, relativeTime_, S, state_[2]);
175 auto p_n_t_T = model_->discountBond(irIdx, relativeTime_, T, state_[2]);
176
177 // Get the rrRatio := P_r(t,T)}{P_r(t,S)}.
178 auto rrParam = model_->infjy(index_)->realRate();
179 auto H_r_S = rrParam->H(S);
180 auto H_r_T = rrParam->H(T);
181 auto zeta_r_t = rrParam->zeta(relativeTime_);
182 auto rrRatio = exp(-(H_r_T - H_r_S) * state_[0] - 0.5 * (H_r_T * H_r_T - H_r_S * H_r_S) * zeta_r_t);
183
184 const auto& zts = model_->infjy(index_)->realRate()->termStructure();
185 rrRatio *= (irTs->discount(T) * inflationGrowth(zts, T, indexIsInterpolated_)) /
186 (irTs->discount(S) * inflationGrowth(zts, S, indexIsInterpolated_));
187
188 // Calculate the correction term C(t,S,T)
199
200 auto H_n_S = model_->irlgm1f(irIdx)->H(S);
201 auto zeta_r_S = rrParam->zeta(S);
202
203 auto c = H_r_S * (zeta_r_S - zeta_r_t);
204 c -= H_n_S * integral(*model_, P(rzy(irIdx, index_, 0), az(irIdx), ay(index_)), relativeTime_, S);
205 c += integral(*model_,
206 LC(0.0, -1.0, P(ay(index_), ay(index_), Hy(index_)), 1.0,
207 P(rzy(irIdx, index_, 0), az(irIdx), ay(index_), Hz(irIdx)), -1.0,
208 P(ryy(index_, index_, 0, 1), ay(index_), sy(index_))),
209 relativeTime_, S);
210 c *= (H_r_S - H_r_T);
211
212 return p_n_t_S * rrRatio * exp(c) - p_n_t_T;
213}
214
216 // For JY YoY, expect the state to be three variables i.e. z_I and c_I and z_{ir}.
217 QL_REQUIRE(state_.size() == 3, "JyImpliedYoYInflationTermStructure: expected state to have "
218 << "three elements but got " << state_.size());
219}
220
221} // namespace QuantExt
InterpolatedDiscountCurve based on loglinear interpolation of DiscountFactors.
QuantLib::Real yoySwaplet(QuantLib::Time S, QuantLib::Time T) const
Year on year swaplet price for the period from S to T.
std::map< QuantLib::Date, QuantLib::Real > yoyRates(const std::vector< QuantLib::Date > &dates, const QuantLib::Period &obsLag=-1 *QuantLib::Days) const override
JyImpliedYoYInflationTermStructure(const QuantLib::ext::shared_ptr< CrossAssetModel > &model, QuantLib::Size index, bool indexIsInterpolated)
QuantLib::ext::shared_ptr< CrossAssetModel > model_
analytics for the cross asset model
const LC1_< E1 > LC(QuantLib::Real c, QuantLib::Real c1, const E1 &e1)
Real integral(const CrossAssetModel &model, const E &e, const Real a, const Real b)
const P2_< E1, E2 > P(const E1 &e1, const E2 &e2)
some inflation related utilities.
wrapper classes for inflation yoy and interpolation
year on year inflation term structure implied by a Jarrow Yildrim (JY) model
zero inflation term structure implied by a Jarrow Yildrim (JY) model
CompiledFormula exp(CompiledFormula x)
Real inflationGrowth(const QuantLib::ext::shared_ptr< CrossAssetModel > &model, Size index, Time S, Time T, Real irState, Real rrState, bool indexIsInterpolated)
INF H component. May relate to real rate portion of JY model or z component of DK model.
INF alpha component. May relate to real rate portion of JY model or z component of DK model.
JY INF index sigma component.