32#include <ql/quotes/compositequote.hpp>
33#include <ql/time/daycounters/actualactual.hpp>
42bool hasPseudoCurrencyConfig(
const string& code) {
43 QL_REQUIRE(code.size() == 3,
"Invalid currency code \"" << code <<
"\" for hasPseudoCurrencyConfig()");
44 const PseudoCurrencyMarketParameters& params = GlobalPseudoCurrencyMarketParameters::instance().get();
45 return params.curves.find(code) != params.curves.end();
48bool hasPseudoCurrencyConfigPair(
const string& pair) {
49 QL_REQUIRE(pair.size() == 6,
"Invalid currency pair \"" << pair <<
"\" for isPseudoCurrencyConfigPair()");
50 return hasPseudoCurrencyConfig(pair.substr(0, 3)) || hasPseudoCurrencyConfig(pair.substr(3));
60 auto it = pegp.find(
"PseudoCurrency.TreatAsFX");
61 if (it != pegp.end()) {
62 DLOG(
"Building PseudoCurrencyMarketParameters from PricingEngine GlobalParameters");
66 it = pegp.find(
"PseudoCurrency.BaseCurrency");
67 QL_REQUIRE(it != pegp.end(),
"No BaseCurrency field");
72 for (
const string& pm : CurrencyParser::instance().pseudoCurrencyCodes()) {
73 it = pegp.find(
"PseudoCurrency.Curve." + pm);
75 params.
curves[pm] = it->second;
77 QL_REQUIRE(!params.
curves.empty(),
"At least one PM Curve required");
80 it = pegp.find(
"PseudoCurrency.FXIndexTag");
81 QL_REQUIRE(it != pegp.end(),
"No FXIndexTag field");
85 it = pegp.find(
"PseudoCurrency.DefaultCorrelation");
86 if (it == pegp.end()) {
87 LOG(
"No Default Correlation present");
90 LOG(
"Default Correlation is \"" << it->second <<
"\"");
93 "Invalid DefaultCorrelation value " << it->second);
95 }
catch (std::exception& e) {
96 QL_FAIL(
"Failed to build PseudoCurrencyMarketParameters : " << e.what());
99 DLOG(
"Building default PseudoCurrencyMarketParameters");
108 return os <<
"PseudoCurrencyMarketParameters { "
114 auto it = GlobalPseudoCurrencyMarketParameters::instance().get().curves.find(pm);
115 QL_REQUIRE(it != GlobalPseudoCurrencyMarketParameters::instance().get().curves.end(),
116 "Unable to find a commodity curve for pseudo currency " << pm <<
" in Market");
122 if (hasPseudoCurrencyConfig(ccy)) {
124 QL_REQUIRE(!priceCurve.empty(),
126 TLOG(
"PseudoCurrencyMarket building DerivedPriceQuote for "
127 << ccy <<
"/" << GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency
128 <<
" with curve that has minTime of " << priceCurve->minTime());
129 return Handle<Quote>(QuantLib::ext::make_shared<QuantExt::DerivedPriceQuote>(priceCurve));
131 return fxRateImpl(ccy + GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency, config);
137 if (hasPseudoCurrencyConfig(ccy)) {
140 QL_REQUIRE(!priceCurve.empty(),
142 TLOG(
"PseudoCurrencyMarket building DerivedPriceQuote for "
143 << ccy <<
"/" << GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency
144 <<
" with curve that has minTime of " << priceCurve->minTime());
145 return Handle<Quote>(QuantLib::ext::make_shared<QuantExt::DerivedPriceQuote>(priceCurve));
147 return fxSpotImpl(ccy + GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency, config);
151QuantLib::Handle<QuantExt::FxIndex>
Market::fxIndex(
const string& fxIndex,
const string& configuration)
const {
155 std::string familyName;
161 familyName = ind->familyName();
162 forCcy = ind->sourceCurrency().code();
163 domCcy = ind->targetCurrency().code();
165 familyName =
"GENERIC";
170 if (hasPseudoCurrencyConfigPair(forCcy + domCcy)) {
171 DLOG(
"Market::fxIndex() requested for PM pair " << forCcy << domCcy);
172 string index =
"FX-" + familyName +
"-" + forCcy +
"-" + domCcy;
173 Handle<QuantExt::FxIndex> fxInd;
178 QuantLib::ext::shared_ptr<QuantExt::FxIndex> fxIndexBase =
parseFxIndex(index);
180 string source = fxIndexBase->sourceCurrency().code();
181 string target = fxIndexBase->targetCurrency().code();
184 Handle<Quote> spot =
fxRate(source + target, configuration);
186 Handle<YieldTermStructure> sorTS =
discountCurve(source, configuration);
187 Handle<YieldTermStructure> tarTS =
discountCurve(target, configuration);
190 Natural spotDays = 0;
193 if (source != target) {
198 WLOG(
"Market::fxIndex Cannot find commodity conventions for " <<
fxIndex);
201 fxInd = Handle<QuantExt::FxIndex>(QuantLib::ext::make_shared<QuantExt::FxIndex>(
202 fxIndexBase->familyName(), spotDays, fxIndexBase->sourceCurrency(), fxIndexBase->targetCurrency(),
219 if (hasPseudoCurrencyConfigPair(pair)) {
220 DLOG(
"Market::fxSpot() requested for PM pair " << pair);
231 auto fx = Handle<Quote>(QuantLib::ext::make_shared<CompositeQuote<std::function<Real(Real, Real)>>>(
232 forBaseSpot, domBaseSpot, [](Real a, Real b) {
return b > 0.0 ? a / b : 0.0; }));
233 DLOG(
"Market returning " << fx->value() <<
" for " << pair <<
".");
244 if (hasPseudoCurrencyConfigPair(pair)) {
245 DLOG(
"Market::fxSpot() requested for PM pair " << pair);
256 auto fx = Handle<Quote>(QuantLib::ext::make_shared<CompositeQuote<std::function<Real(Real, Real)>>>(
257 forBaseSpot, domBaseSpot, [](Real a, Real b) {
return b > 0.0 ? a / b : 0.0; }));
258 DLOG(
"Market returning " << fx->value() <<
" for " << pair <<
".");
268 if (hasPseudoCurrencyConfig(ccy)) {
271 return fxVolImpl(ccy + GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency, config);
276 QL_REQUIRE(
handlePseudoCurrencies_,
"Market::getCorrelationIndexName() disabled - this is an internal error.");
277 if (hasPseudoCurrencyConfig(ccy)) {
282 return "FX-" + GlobalPseudoCurrencyMarketParameters::instance().get().fxIndexTag +
"-" + ccy +
"-" +
283 GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency;
287Handle<BlackVolTermStructure>
Market::fxVol(
const string& pair,
const string& config)
const {
291 if (hasPseudoCurrencyConfigPair(pair)) {
292 DLOG(
"Market::fxVol() requested for PM pair " << pair);
295 Handle<BlackVolTermStructure> vol;
297 auto forCode = pair.substr(0, 3);
298 auto domCode = pair.substr(3);
301 if (forCode == GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency ||
302 domCode == GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency) {
305 forCode == GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency ? domCode : forCode;
307 if (domCode == GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency)
310 vol = Handle<BlackVolTermStructure>(
311 QuantLib::ext::make_shared<QuantExt::BlackInvertedVolTermStructure>(comVol));
321 Handle<QuantExt::CorrelationTermStructure> rho;
324 }
catch (std::exception& e) {
326 WLOG(
"No correlation found for " << forIndex <<
"/" << domIndex);
327 if (GlobalPseudoCurrencyMarketParameters::instance().get().defaultCorrelation != Null<Real>()) {
328 WLOG(
"Using default correlation value "
329 << GlobalPseudoCurrencyMarketParameters::instance().get().defaultCorrelation);
330 rho = Handle<QuantExt::CorrelationTermStructure>(QuantLib::ext::make_shared<QuantExt::FlatCorrelation>(
331 asofDate(), GlobalPseudoCurrencyMarketParameters::instance().get().defaultCorrelation,
332 ActualActual(ActualActual::ISDA)));
334 QL_FAIL(
"No Correlation which is needed for PseudoCurrency Volatility :" << e.what());
339 vol = Handle<BlackVolTermStructure>(
340 QuantLib::ext::make_shared<QuantExt::BlackTriangulationATMVolTermStructure>(forBaseVol, domBaseVol, rho));
343 DLOG(
"Market returning vol surface for " << pair <<
".");
355 string baseCcy = GlobalPseudoCurrencyMarketParameters::instance().get().baseCurrency;
357 if (hasPseudoCurrencyConfig(ccy)) {
358 DLOG(
"Market::discount() requested for PM " << ccy);
362 QL_REQUIRE(!priceCurve.empty(),
365 Handle<YieldTermStructure>(QuantLib::ext::make_shared<QuantExt::PriceTermStructureAdapter>(
366 priceCurve.currentLink(), baseDiscount.currentLink(),
fxRate(ccy + baseCcy, config)));
Handle< Quote > fxSpot(const string &ccypair, const string &configuration=Market::defaultConfiguration) const
static const string inCcyConfiguration
InCcy configuration label.
virtual QuantLib::Handle< QuantLib::BlackVolTermStructure > commodityVolatility(const std::string &commodityName, const std::string &configuration=Market::defaultConfiguration) const =0
std::map< std::pair< string, string >, QuantLib::Handle< QuantExt::FxIndex > > fxIndicesCache_
std::map< string, Handle< BlackVolTermStructure > > volCache_
std::map< string, Handle< YieldTermStructure > > discountCurveCache_
Handle< Quote > fxRate(const string &ccypair, const string &configuration=Market::defaultConfiguration) const
bool handlePseudoCurrencies_
virtual QuantLib::Handle< QuantExt::PriceTermStructure > commodityPriceCurve(const std::string &commodityName, const std::string &configuration=Market::defaultConfiguration) const =0
std::map< string, Handle< Quote > > fxRateCache_
Handle< BlackVolTermStructure > fxVol(const string &ccypair, const string &configuration=Market::defaultConfiguration) const
Handle< BlackVolTermStructure > getVolatility(const string &ccy, const string &config) const
virtual Handle< YieldTermStructure > discountCurveImpl(const string &ccy, const string &configuration=Market::defaultConfiguration) const =0
virtual QuantLib::Handle< QuantExt::CorrelationTermStructure > correlationCurve(const std::string &index1, const std::string &index2, const std::string &configuration=Market::defaultConfiguration) const =0
string commodityCurveLookup(const string &pm) const
QuantLib::Handle< QuantExt::FxIndex > fxIndex(const string &fxIndex, const string &configuration=Market::defaultConfiguration) const
static const string defaultConfiguration
Default configuration label.
virtual Date asofDate() const =0
Get the asof Date.
virtual Handle< Quote > fxSpotImpl(const string &ccypair, const string &configuration=Market::defaultConfiguration) const =0
virtual QuantLib::Handle< QuantExt::FxIndex > fxIndexImpl(const string &fxIndex, const string &configuration=Market::defaultConfiguration) const =0
virtual Handle< Quote > fxRateImpl(const string &ccypair, const string &configuration=Market::defaultConfiguration) const =0
Handle< Quote > getFxSpotBaseQuote(const string &ccy, const string &config) const
string getCorrelationIndexName(const string &ccy) const
Handle< Quote > getFxBaseQuote(const string &ccy, const string &config) const
virtual Handle< BlackVolTermStructure > fxVolImpl(const string &ccypair, const string &configuration=Market::defaultConfiguration) const =0
std::map< string, Handle< Quote > > spotCache_
Handle< YieldTermStructure > discountCurve(const string &ccy, const string &configuration=Market::defaultConfiguration) const
currency parser singleton class
QuantLib::ext::shared_ptr< FxIndex > parseFxIndex(const string &s, const Handle< Quote > &fxSpot, const Handle< YieldTermStructure > &sourceYts, const Handle< YieldTermStructure > &targetYts, const bool useConventions)
Convert std::string to QuantExt::FxIndex.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
bool parseBool(const string &s)
Convert text to bool.
Real parseReal(const string &s)
Convert text to Real.
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
#define WLOG(text)
Logging Macro (Level = Warning)
#define TLOG(text)
Logging Macro (Level = Data)
market data related utilties
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
bool isFxIndex(const std::string &indexName)
PseudoCurrencyMarketParameters buildPseudoCurrencyMarketParameters(const std::map< string, string > &pegp)
Function to build parameters from PricingEngine GlobalParametrs.
std::tuple< Natural, Calendar, BusinessDayConvention > getFxIndexConventions(const string &index)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
Struct to store parameters for commodities to be treatred as pseudo currencies.
std::map< string, string > curves