Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
List of all members
CorrelationCurve Class Reference

Wrapper class for building correlation structures. More...

#include <ored/marketdata/correlationcurve.hpp>

+ Collaboration diagram for CorrelationCurve:

Public Member Functions

Constructors
 CorrelationCurve ()
 Default constructor. More...
 
 CorrelationCurve (Date asof, CorrelationCurveSpec spec, const Loader &loader, const CurveConfigurations &curveConfigs, map< string, QuantLib::ext::shared_ptr< SwapIndex > > &swapIndices, map< string, QuantLib::ext::shared_ptr< YieldCurve > > &yieldCurves, map< string, QuantLib::ext::shared_ptr< GenericYieldVolCurve > > &swaptionVolCurves)
 Detailed constructor. More...
 

Inspectors

CorrelationCurveSpec spec_
 
QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructurecorr_
 
class CalibrationFunction
 
const CorrelationCurveSpecspec () const
 
const QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructure > & corrTermStructure ()
 
void calibrateCMSSpreadCorrelations (const QuantLib::ext::shared_ptr< CorrelationCurveConfig > &config, Date asof, const vector< Handle< Quote > > &prices, vector< Handle< Quote > > &quotes, QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructure > &curve, map< string, QuantLib::ext::shared_ptr< SwapIndex > > &swapIndices, map< string, QuantLib::ext::shared_ptr< YieldCurve > > &yieldCurves, map< string, QuantLib::ext::shared_ptr< GenericYieldVolCurve > > &swaptionVolCurves)
 

Detailed Description

Wrapper class for building correlation structures.

Definition at line 45 of file correlationcurve.hpp.

Constructor & Destructor Documentation

◆ CorrelationCurve() [1/2]

Default constructor.

Definition at line 50 of file correlationcurve.hpp.

50{}

◆ CorrelationCurve() [2/2]

CorrelationCurve ( Date  asof,
CorrelationCurveSpec  spec,
const Loader loader,
const CurveConfigurations curveConfigs,
map< string, QuantLib::ext::shared_ptr< SwapIndex > > &  swapIndices,
map< string, QuantLib::ext::shared_ptr< YieldCurve > > &  yieldCurves,
map< string, QuantLib::ext::shared_ptr< GenericYieldVolCurve > > &  swaptionVolCurves 
)

Detailed constructor.

Definition at line 193 of file correlationcurve.cpp.

197 {
198
199 try {
200
201 const QuantLib::ext::shared_ptr<CorrelationCurveConfig>& config =
202 curveConfigs.correlationCurveConfig(spec.curveConfigID());
203
204 // build default correlation termstructure
205 QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure> corr;
206
207 if (config->quoteType() == MarketDatum::QuoteType::NONE) {
208
209 corr = QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure>(
210 new QuantExt::FlatCorrelation(0, config->calendar(), 0.0, config->dayCounter()));
211
212 } else {
213 QL_REQUIRE(config->dimension() == CorrelationCurveConfig::Dimension::ATM ||
214 config->dimension() == CorrelationCurveConfig::Dimension::Constant,
215 "Unsupported correlation curve building dimension");
216
217 // Check if we are using a regular expression to select the quotes for the curve. If we are, the quotes should
218 // contain exactly one element.
219 auto wildcard = getUniqueWildcard(config->quotes());
220
221 // vector with times, quotes pairs
222 vector<pair<Real, Handle<Quote>>> quotePairs;
223 // Different approaches depending on whether we are using a regex or searching for a list of explicit quotes.
224 if (wildcard) {
225 QL_REQUIRE(config->dimension() == CorrelationCurveConfig::Dimension::ATM,
226 "CorrelationCurve: Wildcards only supported for curve dimension ATM");
227 LOG("Have single quote with pattern " << wildcard->pattern());
228
229 // Loop over quotes and process commodity option quotes matching pattern on asof
230 for (const auto& md : loader.get(*wildcard, asof)) {
231
232 QL_REQUIRE(md->asofDate() == asof, "MarketDatum asofDate '" << md->asofDate() << "' <> asof '" << asof << "'");
233
234 auto q = QuantLib::ext::dynamic_pointer_cast<CorrelationQuote>(md);
235 if (q && q->quoteType() == config->quoteType()) {
236
237 TLOG("The quote " << q->name() << " matched the pattern");
238
239 Date expiryDate = getDateFromDateOrPeriod(q->expiry(), asof, config->calendar(), config->businessDayConvention());
240 if (expiryDate > asof) {
241 // add a <time, quote> pair
242 quotePairs.push_back(make_pair(config->dayCounter().yearFraction(asof, expiryDate), q->quote()));
243 TLOG("Added quote " << q->name() << ": (" << io::iso_date(expiryDate) << "," << fixed
244 << setprecision(9) << q->quote()->value() << ")");
245 }
246 }
247 }
248
249 if (quotePairs.size() == 0) {
250 Real corr = config->index1() == config->index2() ? 1.0 : 0.0;
251 WLOG("CorrelationCurve: No quotes found for correlation curve: "
252 << config->curveID() << ", continuing with correlation " << corr << ".");
253 corr_ = QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure>(
254 new QuantExt::FlatCorrelation(0, config->calendar(), corr, config->dayCounter()));
255 return;
256 }
257
258 } else {
259 vector<Period> optionTenors = parseVectorOfValues<Period>(config->optionTenors(), &parsePeriod);
260 quotePairs.resize(optionTenors.size());
261 bool failed = false;
262
263 // search market data loader for quotes, logging missing ones
264 for (auto& q : config->quotes()) {
265 if (loader.has(q, asof)) {
266 QuantLib::ext::shared_ptr<CorrelationQuote> c =
267 QuantLib::ext::dynamic_pointer_cast<CorrelationQuote>(loader.get(q, asof));
268
269 Size i = std::find(optionTenors.begin(), optionTenors.end(), parsePeriod(c->expiry())) -
270 optionTenors.begin();
271 QL_REQUIRE(i < optionTenors.size(), "CorrelationCurve: correlation tenor not found for " << q);
272
273 Real time;
274 // add the expiry time - don't need for Constant curves
275 if (config->dimension() != CorrelationCurveConfig::Dimension::Constant) {
276 Date d = config->calendar().advance(asof, optionTenors[i], config->businessDayConvention());
277 time = config->dayCounter().yearFraction(asof, d);
278 }
279 quotePairs[i] = make_pair(time, c->quote());
280
281 TLOG("CorrelationCurve: Added quote " << c->name() << ", tenor " << optionTenors[i] << ", with value "
282 << fixed << setprecision(9) << c->quote()->value() );
283 } else {
284 DLOGGERSTREAM("could not find correlation quote " << q);
285 failed = true;
286 }
287 }
288 // fail if any quotes missing
289 if (failed) {
290 QL_FAIL("could not build correlation curve");
291 }
292 }
293 vector<Handle<Quote>> corrs;
294
295 // sort the quotes
296 std::sort(quotePairs.begin(), quotePairs.end());
297 vector<Real> times;
298 vector<Handle<Quote>> quotes;
299 for (Size i = 0; i < quotePairs.size(); i++) {
300 if (config->quoteType() == MarketDatum::QuoteType::RATE) {
301 corrs.push_back(quotePairs[i].second);
302 } else {
303 Handle<Quote> q(QuantLib::ext::make_shared<SimpleQuote>(0));
304 corrs.push_back(q);
305 }
306 quotes.push_back(quotePairs[i].second);
307 times.push_back(quotePairs[i].first);
308 }
309
310 // build correlation termstructure
311 bool flat = (config->dimension() == CorrelationCurveConfig::Dimension::Constant || quotes.size() == 1);
312 LOG("building " << (flat ? "flat" : "interpolated curve") << " correlation termstructure");
313
314 if (flat) {
315 corr = QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure>(
316 new QuantExt::FlatCorrelation(0, config->calendar(), corrs[0], config->dayCounter()));
317
318 corr->enableExtrapolation(config->extrapolate());
319 } else {
320
321 corr = QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure>(
322 new QuantExt::InterpolatedCorrelationCurve<Linear>(times, corrs, config->dayCounter(),
323 config->calendar()));
324 }
325
326 if (config->quoteType() == MarketDatum::QuoteType::PRICE) {
327
328 if (config->correlationType() == CorrelationCurveConfig::CorrelationType::CMSSpread) {
329 calibrateCMSSpreadCorrelations(config, asof, quotes, corrs, corr, swapIndices,
330 yieldCurves, swaptionVolCurves);
331 } else {
332 QL_FAIL("price calibration only supported for CMSSpread correlations");
333 }
334 }
335
336 LOG("Returning correlation surface for config " << spec);
337 }
338 corr_ = corr;
339 } catch (std::exception& e) {
340 QL_FAIL("correlation curve building failed for curve " << spec.curveConfigID() << " on date "
341 << io::iso_date(asof) << ": " << e.what());
342 } catch (...) {
343 QL_FAIL("correlation curve building failed: unknown error");
344 }
345}
const CorrelationCurveSpec & spec() const
QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructure > corr_
void calibrateCMSSpreadCorrelations(const QuantLib::ext::shared_ptr< CorrelationCurveConfig > &config, Date asof, const vector< Handle< Quote > > &prices, vector< Handle< Quote > > &quotes, QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructure > &curve, map< string, QuantLib::ext::shared_ptr< SwapIndex > > &swapIndices, map< string, QuantLib::ext::shared_ptr< YieldCurve > > &yieldCurves, map< string, QuantLib::ext::shared_ptr< GenericYieldVolCurve > > &swaptionVolCurves)
const std::string & curveConfigID() const
Definition: curvespec.hpp:83
Date getDateFromDateOrPeriod(const string &token, Date asof, QuantLib::Calendar cal, QuantLib::BusinessDayConvention bdc)
Get a date from a date string or period.
Period parsePeriod(const string &s)
Convert text to QuantLib::Period.
Definition: parsers.cpp:171
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
#define DLOGGERSTREAM(text)
Definition: log.hpp:632
boost::optional< Wildcard > getUniqueWildcard(const C &c)
checks if at most one element in C has a wild card and returns it in this case
Definition: wildcard.hpp:65
vector< string > curveConfigs
+ Here is the call graph for this function:

Member Function Documentation

◆ spec()

const CorrelationCurveSpec & spec ( ) const

Definition at line 60 of file correlationcurve.hpp.

60{ return spec_; }
CorrelationCurveSpec spec_
+ Here is the caller graph for this function:

◆ corrTermStructure()

const QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructure > & corrTermStructure ( )

Definition at line 62 of file correlationcurve.hpp.

62{ return corr_; }

◆ calibrateCMSSpreadCorrelations()

void calibrateCMSSpreadCorrelations ( const QuantLib::ext::shared_ptr< CorrelationCurveConfig > &  config,
Date  asof,
const vector< Handle< Quote > > &  prices,
vector< Handle< Quote > > &  quotes,
QuantLib::ext::shared_ptr< QuantExt::CorrelationTermStructure > &  curve,
map< string, QuantLib::ext::shared_ptr< SwapIndex > > &  swapIndices,
map< string, QuantLib::ext::shared_ptr< YieldCurve > > &  yieldCurves,
map< string, QuantLib::ext::shared_ptr< GenericYieldVolCurve > > &  swaptionVolCurves 
)
private

Definition at line 93 of file correlationcurve.cpp.

97 {
98
99 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
100
101 // build cms pricingengine
102 string ccy = config->currency();
103 string swaptionVol = "SwaptionVolatility/" + ccy + "/" + config->swaptionVolatility();
104 auto it = swaptionVolCurves.find(swaptionVol);
105
106 if (it == swaptionVolCurves.end())
107 QL_FAIL("The swaption vol curve not found " << swaptionVol);
108 Handle<SwaptionVolatilityStructure> vol(it->second->volTermStructure());
109
110 string dc = "Yield/" + ccy + "/" + config->discountCurve();
111 Handle<YieldTermStructure> yts;
112 auto it2 = yieldCurves.find(dc);
113 if (it2 != yieldCurves.end()) {
114 yts = it2->second->handle();
115 } else {
116 QL_FAIL("The discount curve not found, " << dc);
117 }
118
119 Real lower = (vol->volatilityType() == ShiftedLognormal) ? 0.0001 : -2;
120 Real upper = (vol->volatilityType() == ShiftedLognormal) ? 2.0000 : 2;
121
122 LinearTsrPricer::Settings settings;
123 settings.withRateBound(lower, upper);
124
125 Real rev = 0;
126 Handle<Quote> revQuote(QuantLib::ext::shared_ptr<Quote>(new SimpleQuote(rev)));
127
128 QuantLib::ext::shared_ptr<QuantLib::CmsCouponPricer> cmsPricer =
129 QuantLib::ext::make_shared<LinearTsrPricer>(vol, revQuote, yts, settings);
130
131 // build cms spread pricer
132 Handle<QuantExt::CorrelationTermStructure> ch(curve);
133 QuantLib::ext::shared_ptr<FloatingRateCouponPricer> pricer =
134 QuantLib::ext::make_shared<QuantExt::LognormalCmsSpreadPricer>(cmsPricer, ch, yts, 16);
135
136 // build instruments
137 auto it3 = swapIndices.find(config->index1());
138 if (it3 == swapIndices.end())
139 QL_FAIL("The swap index not found " << config->index1());
140
141 QuantLib::ext::shared_ptr<SwapIndex> index1 = it3->second;
142
143 auto it4 = swapIndices.find(config->index2());
144 if (it4 == swapIndices.end())
145 QL_FAIL("The swap index not found " << config->index2());
146
147 QuantLib::ext::shared_ptr<SwapIndex> index2 = it4->second;
148
149 vector<QuantLib::ext::shared_ptr<QuantExt::CmsCapHelper>> instruments;
150
151 QuantLib::ext::shared_ptr<Convention> tmp = conventions->get(config->conventions());
152 QL_REQUIRE(tmp, "no conventions found with id " << config->conventions());
153
154 QuantLib::ext::shared_ptr<CmsSpreadOptionConvention> conv = QuantLib::ext::dynamic_pointer_cast<CmsSpreadOptionConvention>(tmp);
155 QL_REQUIRE(conv != NULL, "CMS Correlation curves require CMSSpreadOption convention ");
156 Period forwardStart = conv->forwardStart();
157 Period spotDays = conv->spotDays();
158 Period cmsTenor = conv->swapTenor();
159 Natural fixingDays = conv->fixingDays();
160 Calendar calendar = conv->calendar();
161 DayCounter dcount = conv->dayCounter();
162 BusinessDayConvention bdc = conv->rollConvention();
163 vector<Period> optionTenors = parseVectorOfValues<Period>(config->optionTenors(), &parsePeriod);
164
165 for (Size i = 0; i < prices.size(); i++) {
166 QuantLib::ext::shared_ptr<QuantExt::CmsCapHelper> inst = QuantLib::ext::make_shared<QuantExt::CmsCapHelper>(
167 asof, index1, index2, yts, prices[i], correlations[i], optionTenors[i], forwardStart, spotDays, cmsTenor,
168 fixingDays, calendar, dcount, bdc, pricer, cmsPricer);
169 instruments.push_back(inst);
170 }
171
172 // set up problem
173 EndCriteria endCriteria(1000, 500, 1E-8, 1E-8, 1E-8);
174 BoundaryConstraint constraint(-1, 1);
175 vector<Real> weights(prices.size(), 1);
176
177 Array prms(prices.size(), 0);
178 vector<bool> all(prms.size(), false);
179 Projection proj(prms, all);
180 ProjectedConstraint pc(constraint, proj);
181
182 QuantLib::ext::shared_ptr<OptimizationMethod> method = QuantLib::ext::make_shared<LevenbergMarquardt>(1E-8, 1E-8, 1E-8);
183
184 CalibrationFunction c(correlations, instruments, weights, proj);
185
186 Problem prob(c, pc, proj.project(prms));
187
188 method->minimize(prob, endCriteria);
189
190 Array result(prob.currentValue());
191}
Calendar calendar
Definition: utilities.cpp:441
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Friends And Related Function Documentation

◆ CalibrationFunction

friend class CalibrationFunction
friend

Definition at line 76 of file correlationcurve.hpp.

Member Data Documentation

◆ spec_

CorrelationCurveSpec spec_
private

Definition at line 71 of file correlationcurve.hpp.

◆ corr_

QuantLib::ext::shared_ptr<QuantExt::CorrelationTermStructure> corr_
private

Definition at line 72 of file correlationcurve.hpp.