30using namespace std::placeholders;
36void CBO::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
37 DLOG(
"CBO::build() called for trade " <<
id());
41 additionalData_[
"isdaAssetClass"] = string(
"Credit");
42 additionalData_[
"isdaBaseProduct"] = string(
"");
43 additionalData_[
"isdaSubProduct"] = string(
"");
44 additionalData_[
"isdaTransaction"] = string(
"");
46 requiredFixings_.clear();
48 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
49 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(
"CBO");
51 populateFromCboReferenceData(engineFactory->referenceData());
56 bondbasket_ = bondbasketdata_.build(engineFactory,
parseCurrency(
ccy_), reinvestmentEndDate_);
57 requiredFixings_.addData(bondbasketdata_.requiredFixings());
59 vector<QuantExt::Tranche> tranches;
60 size_t investCount = 0;
63 for(
size_t i = 0; i < trancheData_.size(); i++){
67 tranche.
name = trancheData_[i]->name();;
68 tranche.
faceAmount = trancheData_[i]->faceAmount();
69 tranche.
icRatio = trancheData_[i]->icRatio();
70 tranche.
ocRatio = trancheData_[i]->ocRatio();
73 legdata.
notionals() = {trancheData_[i]->faceAmount()};
79 auto legBuilder = engineFactory->legBuilder(trancheData_[i]->concreteLegData()->legType());
81 auto configuration = builder->configuration(MarketContext::pricing);
82 Leg leg = legBuilder->buildLeg(legdata, engineFactory, requiredFixingsLeg, configuration);
85 requiredFixings_.addData(requiredFixingsLeg);
86 tranches.push_back(tranche);
91 multiplier_ = investedNotional_ / tranche.
faceAmount;
93 ALOG(
"Ratio bigger than 1 : investment=" << investedNotional_ <<
" vs. faceAmount=" << tranche.
faceAmount);
98 QL_REQUIRE(investCount == 1,
"Could not assign CBOInvestment TrancheName " <<
investedTrancheName_ <<
" to Names of CBOTranches.");
101 Date longestBondDate = Settings::instance().evaluationDate();
102 for (
const auto& bond : bondbasket_->bonds()) {
103 Date bondMat = bond.second->maturityDate();
104 if (bondMat > longestBondDate)
105 longestBondDate = bondMat;
107 QL_REQUIRE(schedule.endDate() > longestBondDate,
" Tranche Maturity should be after Bond Maturity: Bond "
108 << longestBondDate <<
" vs. Tranche " << schedule.endDate());
111 QuantLib::ext::shared_ptr<QuantExt::CBO> cbo =
116 QuantLib::ext::shared_ptr<CboMCEngineBuilder> cboBuilder = QuantLib::ext::dynamic_pointer_cast<CboMCEngineBuilder>(builder);
117 QL_REQUIRE(cboBuilder,
"No Builder found for CBO: " <<
id());
118 cbo->setPricingEngine(cboBuilder->engine(bondbasket_->pool()));
119 setSensitivityTemplate(*cboBuilder);
122 maturity_ = schedule.endDate();
124 notional_ = investedNotional_;
125 legs_ = vector<QuantLib::Leg>(1, tranches[idx].leg);
126 legCurrencies_ = vector<string>(1,
ccy_);
127 legPayers_ = vector<bool>(1,
false);
130 for (
const auto& bond : bondBasketData().bonds()) {
132 bond->bondData().creditCurveId()));
133 cbo->registerWith(bond->instrument()->qlInstrument());
136 Leg bondleg = bond->legs().front();
137 for (
auto const& c : bondleg)
138 cbo->registerWith(c);
141 std::map<string, QuantLib::ext::shared_ptr<QuantExt::FxIndex>> fxIndexMap = bondbasket_->fxIndexMap();
142 std::map<string, QuantLib::ext::shared_ptr<QuantExt::FxIndex>>::iterator it;
143 for (it = fxIndexMap.begin(); it != fxIndexMap.end(); ++it)
144 cbo->registerWith(it->second);
149 QL_REQUIRE(!structureId_.empty(),
"CBO::populateFromCboReferenceDat(): no structure id given");
151 DLOG(
"Could not get CboReferenceDatum for Id " << structureId_ <<
" leave data in trade unchanged");
153 auto cboRefData = QuantLib::ext::dynamic_pointer_cast<CboReferenceDatum>(
155 QL_REQUIRE(cboRefData,
"could not cast to CboReferenceDatum, this is unexpected");
156 populateFromCboReferenceData(cboRefData);
164 QL_REQUIRE(cboData,
"expected node CBOData");
168 QL_REQUIRE(cboInvestment,
"expected node CBOInvestment");
190 scheduleData_.fromXML(scheduleData);
192 bondbasketdata_.clear();
195 bondbasketdata_.fromXML(bondbasketNode);
197 trancheData_.clear();
201 auto data = QuantLib::ext::make_shared<ore::data::TrancheData>();
202 data->fromXML(child);
203 trancheData_.push_back(
data);
238 for(
size_t i = 0; i < trancheData_.size(); i++)
245std::map<AssetClass, std::set<std::string>>
247 return bondbasketdata_.underlyingIndices(referenceDataManager);
251 const std::string& parentId,
const QuantLib::ext::shared_ptr<Trade>& underlying,
const std::vector<Date>& valuationDates,
252 const std::vector<Date>& paymentDates,
const std::string& fundingCurrency,
253 const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory, QuantLib::ext::shared_ptr<QuantLib::Index>& underlyingIndex,
254 Real& underlyingMultiplier, std::map<std::string, double>& indexQuantities,
255 std::map<std::string, QuantLib::ext::shared_ptr<QuantExt::FxIndex>>& fxIndices, Real& initialPrice,
256 std::string& assetCurrency, std::string& creditRiskCurrency,
257 std::map<std::string, SimmCreditQualifierMapping>& creditQualifierMapping, Date&
maturity,
258 const std::function<QuantLib::ext::shared_ptr<QuantExt::FxIndex>(
259 const QuantLib::ext::shared_ptr<Market> market,
const std::string& configuration,
const std::string& domestic,
260 const std::string& foreign, std::map<std::string, QuantLib::ext::shared_ptr<QuantExt::FxIndex>>& fxIndices)>&
262 const std::string& underlyingDerivativeId,
RequiredFixings& fixings, std::vector<Leg>& returnLegs)
const {
263 auto t = QuantLib::ext::dynamic_pointer_cast<ore::data::CBO>(underlying);
264 QL_REQUIRE(t,
"could not cast to ore::data::CBO, this is unexpected");
265 string indexName =
"GENERIC-" + t->investedTrancheName();
266 IndexNameTranslator::instance().add(indexName, indexName);
267 indexQuantities[indexName] = t->underlyingMultiplier();
268 underlyingIndex = QuantLib::ext::make_shared<QuantExt::GenericIndex>(indexName);
269 underlyingMultiplier = t->underlyingMultiplier();
270 assetCurrency = t->npvCurrency();
271 creditRiskCurrency = t->npvCurrency();
273 auto fxIndex = getFxIndex(engineFactory->market(), engineFactory->configuration(MarketContext::pricing),
274 assetCurrency, fundingCurrency, fxIndices);
275 returnLegs.push_back(
QuantExt::TRSLeg(valuationDates, paymentDates, underlyingMultiplier, underlyingIndex, fxIndex)
276 .withInitialPrice(initialPrice));
279 auto bonds = t->bondBasketData().bonds();
280 for (Size i = 0; i < bonds.size(); ++i) {
282 bonds[i]->bondData().creditCurveId())] =
284 creditQualifierMapping[bonds[i]->bondData().creditCurveId()] =
292 QL_REQUIRE(node,
"CboReferenceDatum::CboStructure::fromXML(): no node given");
304 QL_REQUIRE(scheduleNode,
"No CBOTranches Node");
305 scheduleData.fromXML(scheduleNode);
307 bondbasketdata.clear();
309 QL_REQUIRE(bondbasketNode,
"No BondBasketData Node");
310 bondbasketdata.fromXML(bondbasketNode);
314 QL_REQUIRE(tranchesNode,
"No CBOTranches Node");
316 auto data = QuantLib::ext::make_shared<ore::data::TrancheData>();
317 data->fromXML(child);
318 trancheData.push_back(
data);
341 for(
size_t i = 0; i < trancheData.size(); i++)
357 XMLNode* dataNode = cboStructure_.toXML(doc);
367 DLOG(
"populating data cbo from reference data");
368 QL_REQUIRE(cboReferenceDatum,
"populateFromCboReferenceData(): empty cbo reference datum given");
371 seniorFee_ = cboReferenceDatum->cbostructure().seniorFee;
381 equityKicker_ = cboReferenceDatum->cbostructure().equityKicker;
391 ccy_ = cboReferenceDatum->cbostructure().ccy;
392 TLOG(
"overwrite currency with '" <<
ccy_ <<
"'");
395 if (reinvestmentEndDate_.empty()) {
396 reinvestmentEndDate_ = cboReferenceDatum->cbostructure().reinvestmentEndDate;
397 TLOG(
"overwrite ReinvestmentEndDate with '" << reinvestmentEndDate_ <<
"'");
400 if (daycounter_.empty()) {
401 daycounter_ = cboReferenceDatum->cbostructure().daycounter;
402 TLOG(
"overwrite DayCounter with '" << daycounter_ <<
"'");
405 if (paymentConvention_.empty()) {
406 paymentConvention_ = cboReferenceDatum->cbostructure().paymentConvention;
407 TLOG(
"overwrite PaymentConvention with '" << paymentConvention_ <<
"'");
410 if (!scheduleData_.hasData()) {
411 scheduleData_ = cboReferenceDatum->cbostructure().scheduleData;
412 TLOG(
"overwrite ScheduleData");
415 if (bondbasketdata_.empty()) {
416 bondbasketdata_ = cboReferenceDatum->cbostructure().bondbasketdata;
417 TLOG(
"overwrite BondBasketData");
420 if (trancheData_.empty()) {
421 trancheData_ = cboReferenceDatum->cbostructure().trancheData;
422 TLOG(
"overwrite TrancheData");
433 std::string missing =
"";
436 missing.append(
"SeniorFee ");
439 missing.append(
"SubordinatedFee ");
442 missing.append(
"EquityKicker ");
445 missing.append(
"FeeDayCounter ");
448 missing.append(
"Currency ");
450 if (daycounter_.empty())
451 missing.append(
"DayCounter ");
453 if (paymentConvention_.empty())
454 missing.append(
"PaymentConvention ");
456 if (!scheduleData_.hasData())
457 missing.append(
"ScheduleData ");
459 if (bondbasketdata_.empty())
460 missing.append(
"BondBasketData ");
462 if (trancheData_.empty())
463 missing.append(
"TrancheData ");
466 QL_FAIL(
"CBO " << structureId_ <<
" expects " + missing +
"elements");
collateralized bond obligation data model
std::string investedTrancheName_
DayCounter feeDayCounter_
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
Add underlying Bond names.
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
void populateFromCboReferenceData(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager)
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
static constexpr const char * TYPE
Serializable object holding leg data.
const string & paymentConvention() const
const ScheduleData & schedule() const
const string & dayCounter() const
QuantLib::ext::shared_ptr< LegAdditionalData > concreteLegData() const
const vector< double > & notionals() const
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override
Serializable schedule data.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Vanilla Instrument Wrapper.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
static Real getChildValueAsDouble(XMLNode *node, const string &name, bool mandatory=false, double defaultValue=0.0)
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static XMLNode * getNextSibling(XMLNode *node, const string &name="")
Get a node's next sibling node.
static void setNodeName(XMLDocument &doc, XMLNode *node, const string &name)
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Real parseReal(const string &s)
Convert text to Real.
DayCounter parseDayCounter(const string &s)
Convert text to QuantLib::DayCounter.
translates between QuantLib::Index::name() and ORE names
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
#define ALOG(text)
Logging Macro (Level = Alert)
#define TLOG(text)
Logging Macro (Level = Data)
market data related utilties
QuantLib::Handle< QuantExt::CreditCurve > securitySpecificCreditCurve(const QuantLib::ext::shared_ptr< Market > &market, const std::string &securityId, const std::string &creditCurveId, const std::string &configuration)
std::string securitySpecificCreditCurveName(const std::string &securityId, const std::string &creditCurveId)
Schedule makeSchedule(const ScheduleDates &data)
Serializable Credit Default Swap.
void build(const std::string &parentId, const QuantLib::ext::shared_ptr< Trade > &underlying, const std::vector< Date > &valuationDates, const std::vector< Date > &paymentDates, const std::string &fundingCurrency, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, QuantLib::ext::shared_ptr< QuantLib::Index > &underlyingIndex, Real &underlyingMultiplier, std::map< std::string, double > &indexQuantities, std::map< std::string, QuantLib::ext::shared_ptr< QuantExt::FxIndex > > &fxIndices, Real &initialPrice, std::string &assetCurrency, std::string &creditRiskCurrency, std::map< std::string, SimmCreditQualifierMapping > &creditQualifierMapping, Date &maturity, const std::function< QuantLib::ext::shared_ptr< QuantExt::FxIndex >(const QuantLib::ext::shared_ptr< Market > market, const std::string &configuration, const std::string &domestic, const std::string &foreign, std::map< std::string, QuantLib::ext::shared_ptr< QuantExt::FxIndex > > &fxIndices)> &getFxIndex, const std::string &underlyingDerivativeId, RequiredFixings &fixings, std::vector< Leg > &returnLegs) const override
void fromXML(XMLNode *node) override
XMLNode * toXML(ore::data::XMLDocument &doc) const override