Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
cpiblackcapfloorengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016,2021,2022 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/*!
20 \file cpibacheliercapfloorengines.cpp
21 \brief Engines for CPI options
22 \ingroup PricingEngines
23 */
24
25#include <ql/time/daycounters/actualactual.hpp>
26#include <ql/pricingengines/blackformula.hpp>
29
30using namespace QuantLib;
31
32namespace QuantExt {
33
34CPICapFloorEngine::CPICapFloorEngine(const QuantLib::Handle<QuantLib::YieldTermStructure>& discountCurve,
35 const QuantLib::Handle<QuantLib::CPIVolatilitySurface>& surface,
36 const bool ttmFromLastAvailableFixing)
37 : discountCurve_(discountCurve), volatilitySurface_(surface),
38 ttmFromLastAvailableFixing_(ttmFromLastAvailableFixing) {
39 registerWith(discountCurve_);
40 registerWith(volatilitySurface_);
41}
42
43
44void CPICapFloorEngine::setVolatility(const QuantLib::Handle<QuantLib::CPIVolatilitySurface>& surface) {
45 if (!volatilitySurface_.empty())
46 unregisterWith(volatilitySurface_);
47 volatilitySurface_ = surface;
48 registerWith(volatilitySurface_);
49 update();
50}
51
53 Date maturity = arguments_.payDate;
54
55 auto index = arguments_.index;
56 DiscountFactor d = arguments_.nominal * discountCurve_->discount(maturity);
57
58 QL_DEPRECATED_DISABLE_WARNING
59 bool isInterpolated = arguments_.observationInterpolation == CPI::Linear ||
60 (arguments_.observationInterpolation == CPI::AsIndex && index->interpolated());
61 QL_DEPRECATED_ENABLE_WARNING
62
63 Date optionObservationDate = QuantExt::ZeroInflation::fixingDate(arguments_.payDate, arguments_.observationLag,
64 index->frequency(), isInterpolated);
65
66 Date optionBaseDate = QuantExt::ZeroInflation::fixingDate(arguments_.startDate, arguments_.observationLag,
67 index->frequency(), isInterpolated);
68
69 Real optionBaseFixing = arguments_.baseCPI == Null<Real>()
70 ? ZeroInflation::cpiFixing(index, arguments_.startDate,
71 arguments_.observationLag, isInterpolated)
72 : arguments_.baseCPI;
73
74 Real atmCPIFixing = ZeroInflation::cpiFixing(index, maturity,
75 arguments_.observationLag, isInterpolated);
76
77 Time timeToMaturityFromInception =
78 inflationYearFraction(index->frequency(), isInterpolated, index->zeroInflationTermStructure()->dayCounter(),
79 optionBaseDate, optionObservationDate);
80
81 Real atmGrowth = atmCPIFixing / optionBaseFixing;
82 Real strike = std::pow(1.0 + arguments_.strike, timeToMaturityFromInception);
83
84 auto lastKnownFixingDate = ZeroInflation::lastAvailableFixing(*index, volatilitySurface_->referenceDate());
85 auto observationPeriod = inflationPeriod(optionObservationDate, index->frequency());
86 auto requiredFixing = isInterpolated ? observationPeriod.first : observationPeriod.second + 1 * Days;
87
88
89 // if time from base <= 0 the fixing is already known and stdDev is zero, return the intrinsic value
90 Real stdDev = 0.0;
91 Real vol = 0.0;
92 Real strikeZeroRate = 0.0;
93 Real ttmFromSurfaceBaseDate = 0.0;
94 Real surfaceBaseFixing = 0.0;
95 if (requiredFixing > lastKnownFixingDate) {
96 // For reading volatility in the current market volatiltiy structure
97 // baseFixingSwap(T0) * pow(1 + strikeRate(T0), T-T0) = StrikeIndex = baseFixing(t) * pow(1 + strikeRate(t), T-t),
98 // solve for strikeRate(t):
99 surfaceBaseFixing =
101 0 * Days, volatilitySurface_->indexIsInterpolated());
102 ttmFromSurfaceBaseDate =
103 inflationYearFraction(volatilitySurface_->frequency(), volatilitySurface_->indexIsInterpolated(),
104 index->zeroInflationTermStructure()->dayCounter(), volatilitySurface_->baseDate(), optionObservationDate);
105 strikeZeroRate = pow(optionBaseFixing / surfaceBaseFixing * strike, 1.0 / ttmFromSurfaceBaseDate) - 1.0;
106 vol = volatilitySurface_->volatility(optionObservationDate, strikeZeroRate, 0 * Days);
108 auto ttm =
109 inflationYearFraction(volatilitySurface_->frequency(), volatilitySurface_->indexIsInterpolated(),
110 volatilitySurface_->dayCounter(), lastKnownFixingDate, optionObservationDate);
111 stdDev = std::sqrt(ttm * vol * vol);
112 } else {
113 stdDev = std::sqrt(volatilitySurface_->totalVariance(optionObservationDate, strikeZeroRate, 0 * Days));
114 }
115 }
116 results_.value = optionPriceImpl(arguments_.type, strike, atmGrowth, stdDev, d);
117
118 results_.additionalResults["npv"] = results_.value;
119 results_.additionalResults["strike"] = strike;
120 results_.additionalResults["forward"] = atmGrowth;
121 results_.additionalResults["stdDev"] = stdDev;
122 results_.additionalResults["discount"] = d;
123 results_.additionalResults["vol"] = vol;
124 results_.additionalResults["timeToExpiry"] = stdDev * stdDev / (vol * vol);
125 results_.additionalResults["BaseDate_trade"] = optionBaseDate;
126 results_.additionalResults["BaseDate_today"] = volatilitySurface_->baseDate();
127 results_.additionalResults["FixingDate"] = optionObservationDate;
128 results_.additionalResults["PaymentDate"] = maturity;
129 results_.additionalResults["BaseCPI_trade"] = optionBaseFixing;
130 results_.additionalResults["BaseCPI_today"] = surfaceBaseFixing;
131 results_.additionalResults["ForwardCPI"] = atmCPIFixing;
132 results_.additionalResults["strike_asof_trade"] = arguments_.strike;
133 results_.additionalResults["strike_asof_today"] = strikeZeroRate;
134 results_.additionalResults["timeToExpiry_from_trade_baseDate"] = timeToMaturityFromInception;
135 results_.additionalResults["timeToExpiry_from_todays_baseDate"] = ttmFromSurfaceBaseDate;
136
137
138
139
140 // std::cout << "CPIBlackCapFloorEngine ==========" << std::endl
141 // << "startDate = " << QuantLib::io::iso_date(arguments_.startDate) << std::endl
142 // << "maturityDate = " << QuantLib::io::iso_date(maturity) << std::endl
143 // << "effStartDate = " << QuantLib::io::iso_date(effectiveStart) << std::endl
144 // << "effEndDate = " << QuantLib::io::iso_date(effectiveMaturity) << std::endl
145 // << "lagDiff = " << lagDiff << std::endl
146 // << "timeFromStart = " << timeFromStart << std::endl
147 // << "timeFromBase = " << timeFromBase << std::endl
148 // << "baseFixing = " << baseFixing << std::endl
149 // << "baseCPI = " << baseCPI << std::endl
150 // << "K = " << K << std::endl
151 // << "F = " << F << std::endl
152 // << "stdDev = " << stdDev << std::endl
153 // << "value = " << results_.value << std::endl;
154}
155
156
157
158double CPIBlackCapFloorEngine::optionPriceImpl(QuantLib::Option::Type type, double strike, double forward,
159 double stdDev, double discount) const {
160 return blackFormula(type, strike, forward, stdDev, discount);
161}
162} // namespace QuantExt
const Instrument::results * results_
Definition: cdsoption.cpp:81
virtual double optionPriceImpl(QuantLib::Option::Type type, double strike, double forward, double stdDev, double discount) const override
QuantLib::Handle< QuantLib::CPIVolatilitySurface > volatilitySurface_
virtual double optionPriceImpl(QuantLib::Option::Type type, double forward, double strike, double stdDev, double discount) const =0
virtual void calculate() const override
QuantLib::Handle< QuantLib::YieldTermStructure > discountCurve_
void setVolatility(const QuantLib::Handle< QuantLib::CPIVolatilitySurface > &surface)
CPICapFloorEngine(const QuantLib::Handle< QuantLib::YieldTermStructure > &discountCurve, const QuantLib::Handle< QuantLib::CPIVolatilitySurface > &surface, const bool ttmFromLastAvailableFixing=false)
CPI cap/floor engine using the Black pricing formula and interpreting the volatility data as lognorma...
some inflation related utilities.
QuantLib::Date fixingDate(const QuantLib::Date &d, const QuantLib::Period obsLag, const QuantLib::Frequency freq, bool interpolated)
Definition: inflation.cpp:183
QuantLib::Date lastAvailableFixing(const QuantLib::ZeroInflationIndex &index, const QuantLib::Date &asof)
Check if today - availabilityLag is already known, otherwise return the fixingDate of the previous fi...
Definition: inflation.cpp:156
QuantLib::Rate cpiFixing(const QuantLib::ext::shared_ptr< QuantLib::ZeroInflationIndex > &index, const QuantLib::Date &maturity, const QuantLib::Period &obsLag, bool interpolated)
Computes a CPI fixing giving an zeroIndex, with interpolation if needed.
Definition: inflation.cpp:166
CompiledFormula pow(CompiledFormula x, const CompiledFormula &y)
Swap::arguments * arguments_