Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
fixingdates.hpp
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/*! \file ored/portfolio/fixingdates.hpp
20 \brief Logic for calculating required fixing dates on legs
21*/
22
23#pragma once
24
27
28#include <ql/patterns/visitor.hpp>
29#include <ql/time/date.hpp>
30
31#include <map>
32#include <ostream>
33#include <set>
34#include <string>
35
36namespace QuantLib {
37class CashFlow;
39class IborCoupon;
40class CappedFlooredCoupon;
41class IndexedCashFlow;
42class CPICashFlow;
43class CPICoupon;
44class YoYInflationCoupon;
45class OvernightIndexedCoupon;
46class AverageBMACoupon;
47class CmsSpreadCoupon;
48class DigitalCoupon;
49class StrippedCappedFlooredCoupon;
50} // namespace QuantLib
51
52namespace QuantExt {
53class CappedFlooredAverageBMACoupon;
54class AverageONIndexedCoupon;
55class OvernightIndexedCoupon;
56class BondTRSCashFlow;
57class CappedFlooredAverageONIndexedCoupon;
58class CappedFlooredOvernightIndexedCoupon;
59class EquityCoupon;
60class FloatingRateFXLinkedNotionalCoupon;
61class FXLinkedCashFlow;
62class AverageFXLinkedCashFlow;
63class SubPeriodsCoupon1;
64class IndexedCoupon;
65class IndexWrappedCashFlow;
66class NonStandardYoYInflationCoupon;
67class CmbCoupon;
68class CommodityIndex;
69class CommodityIndexedAverageCashFlow;
70class CommodityIndexedCashFlow;
71class EquityMarginCoupon;
72class TRSCashFlow;
73} // namespace QuantExt
74
75namespace ore {
76namespace data {
77
78class FixingDateGetter;
79
80/*! Class holding the information on the fixings required to price a trade (or a portfolio of trades). */
82public:
84 public:
85 FixingDates() = default;
86
87 FixingDates(const std::set<QuantLib::Date>& dates, const bool mandatory) { addDates(dates, mandatory); }
88
89 FixingDates(const std::map<QuantLib::Date, bool>& dates) : data_(dates){}
90
91 void clear() { data_.clear(); }
92
93 void addDate(const QuantLib::Date& date, const bool mandatory) {
94 auto exits = data_.find(date);
95 if (exits == data_.end() || exits->second == false) {
96 data_[date] = mandatory;
97 }
98 }
99
100 void addDates(const FixingDates& dates) {
101 for (const auto& [d, man] : dates) {
102 addDate(d, man);
103 }
104 }
105
106 void addDates(const FixingDates& dates, bool mandatory) {
107 for (const auto& [d, _] : dates) {
108 addDate(d, mandatory);
109 }
110 }
111
112 void addDates(const std::set<QuantLib::Date>& dates, bool mandatory) {
113 for (const QuantLib::Date& d : dates) {
114 addDate(d, mandatory);
115 }
116 }
117
118 FixingDates filterByDate(const QuantLib::Date& before) const {
119 std::map<QuantLib::Date, bool> results;
120 for (const auto& [d, mandatory] : data_) {
121 if (d < before) {
122 results.insert({d,mandatory});
123 }
124 }
125 return FixingDates(results);
126 }
127
128 //! Iterrator for range-base forloop
129 std::map<QuantLib::Date, bool>::const_iterator begin() const {return data_.begin();}
130 std::map<QuantLib::Date, bool>::const_iterator end() const {return data_.end();}
131
132 size_t size() const { return data_.size(); }
133
134 bool empty() const { return data_.empty(); }
135
136 private:
137 std::map<QuantLib::Date, bool> data_;
138 };
139
140
141 // FixingEntry = indexName, fixingDate, payDate, alwaysAddIfPaysOnSettlement
142 struct FixingEntry {
143 std::string indexName;
144 QuantLib::Date fixingDate;
145 QuantLib::Date payDate;
147 bool mandatory = true;
148 friend bool operator<(const FixingEntry& lhs, const FixingEntry& rhs);
149 };
150
153 QuantLib::Frequency indexFreq;
154 QuantLib::Period availabilityLeg;
155 friend bool operator<(const InflationFixingEntry& lhs, const InflationFixingEntry& rhs);
156 };
157
159 CPI::InterpolationType couponInterpolation;
160 QuantLib::Frequency couponFrequency;
161 friend bool operator<(const ZeroInflationFixingEntry& lhs, const ZeroInflationFixingEntry& rhs);
162 };
163
164 /*! Gives back the dates for which fixings will be required to price the trade assuming a given \p settlementDate.
165 If the \p settlementDate is not provided or is set equal to \c QuantLib::Date(), the settlement date in the
166 implementation is assumed to be the \c Settings::instance().evaluationDate().
167
168 If a cashflow payment is deemed to have already occurred relative to the settlement date, then no fixing is
169 needed. The determination of whether a cashflow has or has not occurred will in general rely on a call to \c
170 CashFlow::hasOccurred which is important in cases where the cash flow payment date falls on the settlement date.
171
172 Another important case is where a cash flow fixing date occurs on the settlement date. In this case, we should
173 always add the fixing date to the set of fixing dates regardless of
174 \c Settings::instance().enforcesTodaysHistoricFixings(). */
175 std::map<std::string, FixingDates>
176 fixingDatesIndices(const QuantLib::Date& settlementDate = QuantLib::Date()) const;
177
178 /*! Adds a single fixing date \p fixingDate for an index given by its ORE index name \p indexName arising from a
179 coupon with payment date \p payDate. If \p alwaysAddIfPaysOnSettlement is true the fixing date will be added
180 if the coupon pays on the settlement date even if the cashflow returns hasOccured(settlementDate) as true. This
181 is conservative and necessary in some cases since some pricing engines in QL (e.g. CapFloor) do not respect
182 hasOccured() and ask for the fixing regardless. If the payDate is not given, it defaults to Date::maxDate()
183 meaning that the added fixing is relevant unconditional on a pay date */
184 void addFixingDate(const QuantLib::Date& fixingDate, const std::string& indexName,
185 const QuantLib::Date& payDate = Date::maxDate(), const bool alwaysAddIfPaysOnSettlement = false,
186 const bool mandatoryFixing = true);
187
188 void addFixingDate(const FixingEntry& fixingEntry);
189
190 /*! adds a vector of fixings dates \p fixingDates and mandatory flags for an index given by is ORE index name \p indexName arising from
191 a coupon with payment date \p payDate */
192 void addFixingDates(const std::vector<std::pair<QuantLib::Date, bool>>& fixingDates, const std::string& indexName,
193 const QuantLib::Date& payDate = Date::maxDate(),
194 const bool alwaysAddIfPaysOnSettlement = false);
195
196 /*! adds a vector of fixings dates \p fixingDates for an index given by is ORE index name \p indexName arising from
197 a coupon with payment date \p payDate */
198 void addFixingDates(const std::vector<QuantLib::Date>& fixingDates, const std::string& indexName,
199 const QuantLib::Date& payDate = Date::maxDate(), const bool alwaysAddIfPaysOnSettlement = false,
200 const bool mandatory = true);
201
202 /*! add a single fixing date \p fixingDate for a coupon based on a zero inflation index given by its ORE index name
203 \p indexName with payment date \p payDate */
204 void addZeroInflationFixingDate(const QuantLib::Date& fixingDate, const std::string& indexName,
205 const bool indexInterpolated, const Frequency indexFrequency,
206 const Period& indexAvailabilityLag,
207 const CPI::InterpolationType coupopnInterpolation, const Frequency couponFrequency,
208 const QuantLib::Date& payDate = Date::maxDate(),
209 const bool alwaysAddIfPaysOnSettlement = false,
210 const bool mandatoryFixing = true);
212
213 /*! add a single fixing date \p fixingDate for a coupon based on a yoy inflation index given by its ORE index name
214 \p indexName with payment date \p payDate */
215 void addYoYInflationFixingDate(const QuantLib::Date& fixingDate, const std::string& indexName,
216 const bool indexInterpolated, const Frequency indexFrequency,
217 const Period& indexAvailabilityLag, const QuantLib::Date& payDate = Date::maxDate(),
218 const bool alwaysAddIfPaysOnSettlement = false,
219 const bool mandatoryFixing = true);
220 void addYoYInflationFixingDate(const InflationFixingEntry& fixingEntry);
221
222 /*! clear all data */
223 void clear();
224
225 /*! add data from another RequiredFixings instance */
226 void addData(const RequiredFixings& requiredFixings);
227
228 /*! Set all pay dates to Date::maxDate(), fixingDatesIndices() will then not filter the required fixings by the
229 given settlement date any more. Needed by total return swaps on bonds for example, where a cashflow in a bond with
230 past payment date can still be relevant for the payment of the current return period. */
231 void unsetPayDates();
232
233
234 /*! Create a copy and set mandatory flag to mandatory for all fixing entries */
236
237 RequiredFixings filteredFixingDates(const QuantLib::Date& settlementDate = QuantLib::Date());
238
239private:
240 // maps an ORE index name to a pair (fixing date, pay date, alwaysAddIfPaysOnSettlment)
241 std::set<FixingEntry> fixingDates_;
242 // same as above, but for zero inflation index based coupons
243 std::set<ZeroInflationFixingEntry> zeroInflationFixingDates_;
244 // same as above, but for yoy inflation index based coupons
245 std::set<InflationFixingEntry> yoyInflationFixingDates_;
246
247 // grant access to stream output operator
248 friend std::ostream& operator<<(std::ostream&, const RequiredFixings&);
249};
250
251
252
253/*! allow output of required fixings data via streams */
254std::ostream& operator<<(std::ostream& out, const RequiredFixings& f);
255
256/*! Helper Class that gets relevant fixing dates from coupons and add them to a RequiredFixings instance.
257
258 Each type of FloatingRateCoupon that we wish to cover should be added here
259 and a \c visit method implemented against it. */
260class FixingDateGetter : public QuantLib::AcyclicVisitor,
261 public QuantLib::Visitor<QuantLib::CashFlow>,
262 public QuantLib::Visitor<QuantLib::FloatingRateCoupon>,
263 public QuantLib::Visitor<QuantLib::IborCoupon>,
264 public QuantLib::Visitor<QuantLib::CappedFlooredCoupon>,
265 public QuantLib::Visitor<QuantLib::IndexedCashFlow>,
266 public QuantLib::Visitor<QuantLib::CPICashFlow>,
267 public QuantLib::Visitor<QuantLib::CPICoupon>,
268 public QuantLib::Visitor<QuantLib::YoYInflationCoupon>,
269 public QuantLib::Visitor<QuantLib::OvernightIndexedCoupon>,
270 public QuantLib::Visitor<QuantExt::OvernightIndexedCoupon>,
271 public QuantLib::Visitor<QuantExt::CappedFlooredOvernightIndexedCoupon>,
272 public QuantLib::Visitor<QuantLib::AverageBMACoupon>,
273 public QuantLib::Visitor<QuantExt::CappedFlooredAverageBMACoupon>,
274 public QuantLib::Visitor<QuantLib::CmsSpreadCoupon>,
275 public QuantLib::Visitor<QuantLib::DigitalCoupon>,
276 public QuantLib::Visitor<QuantLib::StrippedCappedFlooredCoupon>,
277 public QuantLib::Visitor<QuantExt::AverageONIndexedCoupon>,
278 public QuantLib::Visitor<QuantExt::CappedFlooredAverageONIndexedCoupon>,
279 public QuantLib::Visitor<QuantExt::EquityCoupon>,
280 public QuantLib::Visitor<QuantExt::FloatingRateFXLinkedNotionalCoupon>,
281 public QuantLib::Visitor<QuantExt::FXLinkedCashFlow>,
282 public QuantLib::Visitor<QuantExt::AverageFXLinkedCashFlow>,
283 public QuantLib::Visitor<QuantExt::SubPeriodsCoupon1>,
284 public QuantLib::Visitor<QuantExt::IndexedCoupon>,
285 public QuantLib::Visitor<QuantExt::IndexWrappedCashFlow>,
286 public QuantLib::Visitor<QuantExt::NonStandardYoYInflationCoupon>,
287 public QuantLib::Visitor<QuantExt::CmbCoupon>,
288 public QuantLib::Visitor<QuantExt::EquityMarginCoupon>,
289 public QuantLib::Visitor<QuantExt::CommodityCashFlow>,
290 public QuantLib::Visitor<QuantExt::BondTRSCashFlow>,
291 public QuantLib::Visitor<QuantExt::TRSCashFlow> {
292
293public:
294 //! Constructor
295 FixingDateGetter(RequiredFixings& requiredFixings) : requiredFixings_(requiredFixings) {}
296
297 //! \name Visitor interface
298 //@{
299 void visit(QuantLib::CashFlow& c) override;
300 void visit(QuantLib::FloatingRateCoupon& c) override;
301 void visit(QuantLib::IborCoupon& c) override;
302 void visit(QuantLib::CappedFlooredCoupon& c) override;
303 void visit(QuantLib::IndexedCashFlow& c) override;
304 /*! Not added in QuantLib so will never be hit automatically!
305 Managed by passing off from IndexedCashFlow.
306 */
307 void visit(QuantLib::CPICashFlow& c) override;
308 void visit(QuantLib::CPICoupon& c) override;
309 void visit(QuantLib::YoYInflationCoupon& c) override;
311 void visit(QuantLib::OvernightIndexedCoupon& c) override;
312 void visit(QuantExt::OvernightIndexedCoupon& c) override;
314 void visit(QuantLib::AverageBMACoupon& c) override;
316 void visit(QuantLib::CmsSpreadCoupon& c) override;
317 void visit(QuantLib::DigitalCoupon& c) override;
318 void visit(QuantLib::StrippedCappedFlooredCoupon& c) override;
319 void visit(QuantExt::AverageONIndexedCoupon& c) override;
321 void visit(QuantExt::EquityCoupon& c) override;
323 void visit(QuantExt::FXLinkedCashFlow& c) override;
325 void visit(QuantExt::SubPeriodsCoupon1& c) override;
326 void visit(QuantExt::IndexedCoupon& c) override;
327 void visit(QuantExt::IndexWrappedCashFlow& c) override;
328 void visit(QuantExt::CmbCoupon& c) override;
329 void visit(QuantExt::EquityMarginCoupon& c) override;
330 void visit(QuantExt::CommodityCashFlow& c) override;
331 void visit(QuantExt::BondTRSCashFlow& c) override;
332 void visit(QuantExt::TRSCashFlow& c) override;
333 //@}
334
336 void setAdditionalFxIndex(const QuantLib::ext::shared_ptr<QuantExt::FxIndex>& i) { additionalFxIndex_ = i; }
337
338protected:
339 std::string oreIndexName(const std::string& qlIndexName) const;
341
342private:
343 // flag to indicate if coupon start date fixings are always required, even if initial prices provided
345 // We may need fixings for an additional FX Index at every fixing date
346 QuantLib::ext::shared_ptr<QuantExt::FxIndex> additionalFxIndex_;
347};
348
349/*! Populates a RequiredFixings instance based on a given QuantLib::Leg */
350void addToRequiredFixings(const QuantLib::Leg& leg, const QuantLib::ext::shared_ptr<FixingDateGetter>& fixingDateGetter);
351
352/*! Inflation fixings are generally available on a monthly, or coarser, frequency. When a portfolio is asked for its
353 fixings, and it contains inflation fixings, ORE will by convention put the fixing date as the 1st day of the
354 applicable inflation period. Some market data providers by convention supply the inflation fixings with the date
355 as the last date of the applicable inflation period. This function scans the \p fixings map, and moves any
356 inflation fixing dates from the 1st day of the inflation period to the last day of the inflation period. The key
357 in the \p fixings map is the index name and the value is the set of dates for which we require the fixings.
358
359 If inflation indices have been set up via ZeroInflationIndex entries in the Conventions, the \p conventions
360 should be passed here. If not, the default \c nullptr parameter will be sufficient.
361*/
362void amendInflationFixingDates(std::map<std::string, RequiredFixings::FixingDates>& fixings);
363
364/*! Add index and fixing date pairs to \p fixings that will be potentially needed to build a TodaysMarket.
365
366 These additional index and fixing date pairs are found by scanning the \p mktParams and:
367 - for MarketObject::IndexCurve, take the ibor index name and add the dates for each weekday between settlement
368 date minus \p iborLookback period or \p oisLookback period and settlement date. The distinction between
369 Ibor and OIS is made here to cover the fixings necessary for OIS futures. The default value of 4 months
370 covers OIS futures with a contract period of up to 3 months. It would need to be configured differently
371 if OIS futures with a longer contract period are possible.
372 - for MarketObject::ZeroInflationCurve, take the inflation index and add the first of each month between
373 settlement date minus \p inflationLookback period and settlement date
374 - for MarketObject::YoYInflationCurve, take the inflation index and add the first of each month between
375 settlement date minus \p inflationLookback period and settlement date
376 - for MarketObject::CommodityCurve, add \e fixings for future contracts expiring 2 months either side of the
377 settlement date. The fixing dates are added for each weekday going back to the first day of the month that
378 precedes the settlement date by 2 months. The approach here will give rise to some spot commodities being
379 given a future contract name and dates added against them - this should not be a problem as there will be
380 no fixings found for them in any case.
381
382 The original \p fixings map may be empty.
383*/
384void addMarketFixingDates(const QuantLib::Date& asof, std::map<std::string, RequiredFixings::FixingDates>& fixings,
385 const TodaysMarketParameters& mktParams,
386 const QuantLib::Period& iborLookback = 5 * QuantLib::Days,
387 const QuantLib::Period& oisLookback = 4 * QuantLib::Months,
388 const QuantLib::Period& bmaLookback = 2 * QuantLib::Weeks,
389 const QuantLib::Period& inflationLookback = 1 * QuantLib::Years);
390
391} // namespace data
392} // namespace ore
void setRequireFixingStartDates(const bool b)
void visit(QuantLib::CmsSpreadCoupon &c) override
RequiredFixings & requiredFixings_
void visit(QuantLib::CPICoupon &c) override
void visit(QuantLib::CPICashFlow &c) override
std::string oreIndexName(const std::string &qlIndexName) const
void setAdditionalFxIndex(const QuantLib::ext::shared_ptr< QuantExt::FxIndex > &i)
void visit(QuantLib::IborCoupon &c) override
void visit(QuantLib::DigitalCoupon &c) override
void visit(QuantLib::CappedFlooredCoupon &c) override
FixingDateGetter(RequiredFixings &requiredFixings)
Constructor.
void visit(QuantLib::YoYInflationCoupon &c) override
void visit(QuantLib::StrippedCappedFlooredCoupon &c) override
void visit(QuantLib::CashFlow &c) override
void visit(QuantLib::AverageBMACoupon &c) override
void visit(QuantLib::IndexedCashFlow &c) override
void visit(QuantLib::FloatingRateCoupon &c) override
QuantLib::ext::shared_ptr< QuantExt::FxIndex > additionalFxIndex_
std::map< QuantLib::Date, bool >::const_iterator end() const
FixingDates(const std::set< QuantLib::Date > &dates, const bool mandatory)
Definition: fixingdates.hpp:87
std::map< QuantLib::Date, bool > data_
void addDates(const FixingDates &dates)
void addDate(const QuantLib::Date &date, const bool mandatory)
Definition: fixingdates.hpp:93
FixingDates(const std::map< QuantLib::Date, bool > &dates)
Definition: fixingdates.hpp:89
void addDates(const FixingDates &dates, bool mandatory)
std::map< QuantLib::Date, bool >::const_iterator begin() const
Iterrator for range-base forloop.
FixingDates filterByDate(const QuantLib::Date &before) const
void addDates(const std::set< QuantLib::Date > &dates, bool mandatory)
void addFixingDates(const std::vector< std::pair< QuantLib::Date, bool > > &fixingDates, const std::string &indexName, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false)
std::set< ZeroInflationFixingEntry > zeroInflationFixingDates_
std::set< InflationFixingEntry > yoyInflationFixingDates_
void addData(const RequiredFixings &requiredFixings)
std::map< std::string, FixingDates > fixingDatesIndices(const QuantLib::Date &settlementDate=QuantLib::Date()) const
void addZeroInflationFixingDate(const QuantLib::Date &fixingDate, const std::string &indexName, const bool indexInterpolated, const Frequency indexFrequency, const Period &indexAvailabilityLag, const CPI::InterpolationType coupopnInterpolation, const Frequency couponFrequency, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false, const bool mandatoryFixing=true)
RequiredFixings filteredFixingDates(const QuantLib::Date &settlementDate=QuantLib::Date())
friend std::ostream & operator<<(std::ostream &, const RequiredFixings &)
void addFixingDate(const QuantLib::Date &fixingDate, const std::string &indexName, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false, const bool mandatoryFixing=true)
std::set< FixingEntry > fixingDates_
void addYoYInflationFixingDate(const QuantLib::Date &fixingDate, const std::string &indexName, const bool indexInterpolated, const Frequency indexFrequency, const Period &indexAvailabilityLag, const QuantLib::Date &payDate=Date::maxDate(), const bool alwaysAddIfPaysOnSettlement=false, const bool mandatoryFixing=true)
RequiredFixings makeCopyWithMandatoryOverride(bool mandatory)
@ data
Definition: log.hpp:77
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
void amendInflationFixingDates(std::map< std::string, RequiredFixings::FixingDates > &fixings)
void addMarketFixingDates(const Date &asof, map< string, RequiredFixings::FixingDates > &fixings, const TodaysMarketParameters &mktParams, const Period &iborLookback, const Period &oisLookback, const Period &bmaLookback, const Period &inflationLookback)
void addToRequiredFixings(const QuantLib::Leg &leg, const QuantLib::ext::shared_ptr< FixingDateGetter > &fixingDateGetter)
Serializable Credit Default Swap.
Definition: namespaces.docs:23
std::string indexName
QuantLib::Date fixingDate
bool mandatory
QuantLib::Date payDate
bool alwaysAddIfPaysOnSettlement
friend bool operator<(const FixingEntry &lhs, const FixingEntry &rhs)
friend bool operator<(const InflationFixingEntry &lhs, const InflationFixingEntry &rhs)
QuantLib::Period availabilityLeg
bool indexInterpolated
QuantLib::Frequency indexFreq
QuantLib::Frequency couponFrequency
CPI::InterpolationType couponInterpolation
friend bool operator<(const ZeroInflationFixingEntry &lhs, const ZeroInflationFixingEntry &rhs)
A class to hold todays market configuration(s)