21#include <boost/algorithm/string/join.hpp>
22#include <boost/lexical_cast.hpp>
33#include <ql/cashflows/cpicoupon.hpp>
34#include <ql/cashflows/simplecashflow.hpp>
35#include <ql/instruments/bond.hpp>
36#include <ql/instruments/bonds/zerocouponbond.hpp>
46 return priceQuoteMethod_.empty() ? QuantExt::BondIndex::PriceQuoteMethod::PercentageOfPar
61 QL_REQUIRE(node,
"No BondData Node");
82 while (legNode !=
nullptr) {
139 for (Size i = 0; i <
coupons().size(); ++i) {
151 for (Size i = 0; i <
coupons().size(); ++i) {
156 "bond leg #" << i <<
" isPayer (" << std::boolalpha <<
coupons()[i].
isPayer()
162 for (Size i = 0; i <
coupons().size(); ++i) {
166 bool isIthCouponInflationLinked =
coupons()[i].concreteLegData()->legType() ==
"CPI";
168 "bond leg #" << i <<
" isInflationLinked (" << std::boolalpha << isIthCouponInflationLinked
176 const std::string& startDate,
const std::string& endDate) {
177 DLOG(
"Got BondReferenceDatum for name " <<
securityId_ <<
" overwrite empty elements in trade");
187 const std::string& startDate,
const std::string& endDate) {
188 QL_REQUIRE(!
securityId_.empty(),
"BondData::populateFromBondReferenceData(): no security id given");
190 DLOG(
"could not get BondReferenceDatum for name " <<
securityId_ <<
" leave data in trade unchanged");
194 auto bondRefData = QuantLib::ext::dynamic_pointer_cast<BondReferenceDatum>(
196 QL_REQUIRE(bondRefData,
"could not cast to BondReferenceDatum, this is unexpected");
202 QL_REQUIRE(!
securityId_.empty(),
"BondData invalid: no security id given");
203 std::vector<std::string> missingElements;
205 missingElements.push_back(
"SettlementDays");
207 missingElements.push_back(
"Currency");
208 QL_REQUIRE(missingElements.empty(),
"BondData invalid: missing " + boost::algorithm::join(missingElements,
", ") +
209 " - check if reference data is set up for '"
214 static const std::set<std::string> singleName = {
"ABS",
"Corporate",
"Loans",
"Muni",
"Sovereign"};
215 static const std::set<std::string> index = {
"ABX",
"CMBX",
"MBX",
"PrimeX",
"TRX",
"iBoxx"};
216 if (singleName.find(
subType()) != singleName.end()) {
217 return "Single Name";
218 }
else if (index.find(
subType()) != index.end()) {
221 QL_FAIL(
"BondData::isdaBaseProduct() not defined for subType '"
222 <<
subType() <<
"', expected: "
223 << boost::algorithm::join(singleName,
", ") +
" (map to 'Single Name') " +
224 boost::algorithm::join(index,
", ") +
" (map to 'Index')");
228void Bond::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
229 DLOG(
"Bond::build() called for trade " <<
id());
238 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
239 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(
"Bond");
240 QL_REQUIRE(builder,
"Bond::build(): internal error, builder is null");
248 "no bond settlement days given, if reference data is used, check if securityId '"
251 QuantLib::ext::shared_ptr<QuantLib::Bond> bond;
253 std::string openEndDateStr = builder->modelParameter(
"OpenEndDateReplacement", {},
false,
"");
256 std::vector<Leg> separateLegs;
263 auto configuration = builder->configuration(MarketContext::pricing);
264 auto legBuilder = engineFactory->legBuilder(
bondData_.
coupons()[i].legType());
266 openEndDateReplacement);
267 separateLegs.push_back(leg);
274 QuantLib::ext::shared_ptr<BondEngineBuilder> bondBuilder = QuantLib::ext::dynamic_pointer_cast<BondEngineBuilder>(builder);
275 QL_REQUIRE(bondBuilder,
"No Builder found for Bond: " <<
id());
282 maturity_ = bond->cashflows().back()->date();
289 legs_ = {bond->cashflows()};
293 DLOG(
"Bond::build() finished for trade " <<
id());
297 Trade::fromXML(node);
303 XMLNode* node = Trade::toXML(doc);
308std::map<AssetClass, std::set<std::string>>
310 std::map<AssetClass, std::set<std::string>> result;
319 QL_REQUIRE(
bond,
"need to set the bond before calling inflationFactor()");
323 }
catch (
const std::exception& e) {
324 ALOG(
"Failed to compute the inflation price factor for the bond "
325 <<
securityId <<
", fallback to use factor 1, got " << e.what());
332 const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceData,
333 const std::string& securityId)
const {
334 boost::shared_lock<boost::shared_mutex> lock(mutex_);
335 for (
auto const& b : builders_) {
336 if (referenceData->hasData(b.first, securityId)) {
337 auto tmp = b.second->build(engineFactory, referenceData, securityId);
338 tmp.builderLabel = b.first;
343 QL_FAIL(
"BondFactory: could not build bond '"
345 <<
"': no reference data given or no suitable builder registered. Check if bond is set up in the reference "
346 "data and that there is a builder for the reference data type.");
350 const bool allowOverwrite) {
351 boost::unique_lock<boost::shared_mutex> lock(mutex_);
352 QL_REQUIRE(builders_.insert(std::make_pair(referenceDataType, builder)).second || allowOverwrite,
353 "BondFactory::addBuilder(" << referenceDataType <<
"): builder for key already exists.");
357 const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceData,
358 const std::string& securityId)
const {
360 data.populateFromBondReferenceData(referenceData);
362 bond.
id() =
"VanillaBondBuilder_" + securityId;
363 bond.
build(engineFactory);
365 QL_REQUIRE(bond.
instrument(),
"VanillaBondBuilder: constructed bond is null, this is unexpected");
366 auto qlBond = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(bond.
instrument()->qlInstrument());
369 "VanillaBondBuilder: constructed bond trade does not provide a valid ql instrument, this is unexpected "
370 "(either the instrument wrapper or the ql instrument is null)");
375 if (
data.isInflationLinked()) {
Bond trade data model and serialization.
builder that returns an engine to price a bond instrument
const string & securityId() const
std::vector< LegData > coupons_
std::string isdaBaseProduct() const
return isda sub type "Single Name", "Index" or throw if sub type can not be mapped
bool hasCreditRisk() const
const string & currency() const
const string & subType() const
string volatilityCurveId_
string priceQuoteBaseValue_
Real priceQuoteBaseValue() const
const std::vector< LegData > & coupons() const
void populateFromBondReferenceData(const QuantLib::ext::shared_ptr< BondReferenceDatum > &referenceDatum, const std::string &startDate="", const std::string &endDate="")
populate data from reference datum and check data for completeness
const string & issuerId() const
Inspectors.
const string & referenceCurveId() const
const string & issueDate() const
virtual void fromXML(XMLNode *node) override
XMLSerializable interface.
virtual XMLNode * toXML(XMLDocument &doc) const override
const string & settlementDays() const
const string & calendar() const
void checkData() const
check data for completeness
const string & maturityDate() const
QuantExt::BondIndex::PriceQuoteMethod priceQuoteMethod() const
const string & creditCurveId() const
Real bondNotional() const
void addBuilder(const std::string &referenceDataType, const QuantLib::ext::shared_ptr< BondBuilder > &builder, const bool allowOverwrite=false)
BondBuilder::Result build(const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceData, const std::string &securityId) const
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
Add underlying Bond names.
BondData originalBondData_
virtual void fromXML(XMLNode *node) override
XMLSerializable interface.
virtual XMLNode * toXML(XMLDocument &doc) const override
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Trade interface.
static constexpr const char * TYPE
Serializable object holding generic trade data, reporting dimensions.
Serializable object holding leg data.
virtual void fromXML(XMLNode *node) override
QuantLib::ext::shared_ptr< LegAdditionalData > concreteLegData() const
std::vector< bool > legPayers_
std::vector< string > legCurrencies_
std::vector< QuantLib::Leg > legs_
void setSensitivityTemplate(const EngineBuilder &builder)
string & id()
Set the trade id.
RequiredFixings requiredFixings_
const QuantLib::ext::shared_ptr< InstrumentWrapper > & instrument() const
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
std::map< std::string, boost::any > additionalData_
Vanilla Instrument Wrapper.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
static void checkNode(XMLNode *n, const string &expectedName)
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
static bool getChildValueAsBool(XMLNode *node, const string &name, bool mandatory=false, bool defaultValue=true)
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static string getNodeValue(XMLNode *node)
Get a node's value.
static XMLNode * getNextSibling(XMLNode *node, const string &name="")
Get a node's next sibling node.
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
Logic for calculating required fixing dates on legs.
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
bool tryParseReal(const string &s, QuantLib::Real &result)
Attempt to convert text to Real.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
QuantExt::BondIndex::PriceQuoteMethod parsePriceQuoteMethod(const std::string &s)
Real parseReal(const string &s)
Convert text to Real.
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
Map text representations to QuantLib/QuantExt types.
leg data model and serialization
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
#define ALOG(text)
Logging Macro (Level = Alert)
Real inflationLinkedBondQuoteFactor(const boost::shared_ptr< QuantLib::Bond > &bond)
Real currentNotional(const Leg &leg)
Date getOpenEndDateReplacement(const std::string &replacementPeriodStr, const Calendar &calendar)
void populateFromBondReferenceData(std::string &subType, std::string &issuerId, std::string &settlementDays, std::string &calendar, std::string &issueDate, std::string &priceQuoteMethod, string &priceQuoteBaseValue, std::string &creditCurveId, std::string &creditGroup, std::string &referenceCurveId, std::string &incomeCurveId, std::string &volatilityCurveId, std::vector< LegData > &coupons, const std::string &name, const QuantLib::ext::shared_ptr< BondReferenceDatum > &bondRefData, const std::string &startDate, const std::string &endDate)
Populate bond data from name and ReferenceDataManager.
Leg joinLegs(const std::vector< Leg > &legs)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
std::string creditCurveId
QuantLib::ext::shared_ptr< QuantLib::Bond > bond
QuantExt::BondIndex::PriceQuoteMethod priceQuoteMethod
double inflationFactor() const
double priceQuoteBaseValue
virtual Result build(const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceData, const std::string &securityId) const override
Swap trade data model and serialization.
string conversion utilities