28#include <ql/currencies/europe.hpp>
29#include <ql/errors.hpp>
30#include <ql/termstructures/credit/flathazardrate.hpp>
32#include <ql/math/functional.hpp>
33#include <ql/quotes/derivedquote.hpp>
42static DefaultProbKey dummyDefaultProbKey() {
43 Currency currency = QuantLib::EURCurrency();
44 Seniority seniority = NoSeniority;
45 QuantLib::ext::shared_ptr<DefaultType> defaultType(
new DefaultType());
46 vector<QuantLib::ext::shared_ptr<DefaultType>> defaultTypes(1, defaultType);
47 DefaultProbKey key(defaultTypes, currency, seniority);
51static Issuer dummyIssuer(Handle<DefaultProbabilityTermStructure> dts) {
52 Issuer::key_curve_pair curve(dummyDefaultProbKey(), dts);
53 return Issuer(vector<Issuer::key_curve_pair>(1, curve));
56QuantLib::ext::shared_ptr<QuantExt::BondBasket>
BondBasket::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory,
57 const QuantLib::Currency& baseCcy,
58 const string& reinvestmentEndDate) {
59 DLOG(
"BondBasket::build() called");
61 QuantLib::ext::shared_ptr<Pool>
pool(
new Pool());
62 vector<Issuer> issuerPair;
63 set<Currency> currencies_unique;
65 map<string, QuantLib::ext::shared_ptr<QuantLib::Bond>> qlBonds;
66 map<string, double> recoveries;
67 map<string, double> multipliers;
68 map<string, Handle<YieldTermStructure>> yieldTermStructures;
69 map<string, Currency> currencies;
71 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
73 for (
size_t i = 0; i < bonds_.size(); i++) {
74 DLOG(
"BondBasket::build() -- processing issuer number " << i);
76 bonds_[i]->build(engineFactory);
77 string creditId = bonds_[i]->bondData().creditCurveId();
78 string securityId = bonds_[i]->bondData().securityId();
80 Handle<DefaultProbabilityTermStructure> defaultOriginal =
82 Handle<DefaultProbabilityTermStructure> defaultTS;
83 Handle<Quote> recovery;
85 recovery = market->recoveryRate(securityId, Market::defaultConfiguration);
91 Real rr = recovery.empty() ? 0.0 : recovery->value();
92 auto m = [rr](Real x) {
return x / (1.0 - rr); };
93 Handle<Quote> scaledSpread(QuantLib::ext::make_shared<DerivedQuote<
decltype(m)>>(
94 market->securitySpread(securityId, Market::defaultConfiguration), m));
96 defaultTS = Handle<DefaultProbabilityTermStructure>(
97 QuantLib::ext::make_shared<QuantExt::HazardSpreadedDefaultTermStructure>(defaultOriginal, scaledSpread));
99 bonds_[i]->instrument()->qlInstrument()->registerWith(scaledSpread);
100 recoveries[bonds_[i]->id()] = rr;
103 defaultTS = defaultOriginal;
104 recoveries[bonds_[i]->id()] = 0.0;
108 issuerPair.push_back(dummyIssuer(defaultTS));
109 pool->add(bonds_[i]->
id(), issuerPair[i]);
111 requiredFixings_.addData(bonds_[i]->requiredFixings());
113 QuantLib::ext::shared_ptr<QuantLib::Bond> qlBond = QuantLib::ext::dynamic_pointer_cast<QuantLib::Bond>(bonds_[i]->instrument()->qlInstrument());
114 QL_REQUIRE(qlBond,
"ql bond expected " << bonds_[i]->
id());
115 qlBonds[bonds_[i]->id()]= qlBond;
117 multipliers[bonds_[i]->id()] = bonds_[i]->instrument()->multiplier();
118 yieldTermStructures[bonds_[i]->id()] = market->discountCurve(bonds_[i]->bondData().
currency());
124 for (
size_t i = 0; i <
pool->names().
size(); i++) {
125 DLOG(
"name: " <<
pool->names()[i] <<
", included: " <<
pool->has(bonds_[i]->id()));
129 for (
auto it = currencies_unique.begin(); it!=currencies_unique.end(); ++it){
130 if(it->code() != baseCcy.code()){
131 string source = it->code();
132 string target = baseCcy.code();
133 Handle<YieldTermStructure> sorTS = market->discountCurve(source);
134 Handle<YieldTermStructure> tarTS = market->discountCurve(target);
135 Handle<Quote> spot = market->fxSpot(source + target);
136 Calendar cal = NullCalendar();
137 Natural fixingDays = 0;
139 string name = source + target +
"Index";
141 QuantLib::ext::shared_ptr<QuantExt::FxIndex> fxi = QuantLib::ext::make_shared<QuantExt::FxIndex>(
146 DLOG(
"BondBasket::build() -- created FX Index for " << source + target);
150 reinvestment_ = Date().minDate();
151 if(reinvestmentEndDate !=
"")
154 setReinvestmentScalar();
156 QuantLib::ext::shared_ptr<QuantExt::BondBasket> basket(
160 DLOG(
"BondBasket::build() -- completed");
165bool BondBasket::isFeeFlow(
const ext::shared_ptr<QuantLib::CashFlow>& cf,
const std::string&
name) {
171 for(
auto& bond : bonds_){
172 if(bond->id() ==
name){
173 auto oreBondData = QuantLib::ext::make_shared<ore::data::BondData>(bond->bondData());
175 for (
auto legData : oreBondData->coupons()){
176 auto cfData = QuantLib::ext::dynamic_pointer_cast<ore::data::CashflowData>(legData.concreteLegData());
178 auto amounts = cfData->amounts();
179 auto dates = cfData->dates();
180 for(
size_t d = 0; d < dates.size(); d++){
182 if(cf->amount() == amounts[d])
194void BondBasket::setReinvestmentScalar(){
196 Date today = Settings::instance().evaluationDate();
198 for(
auto& bond : bonds_){
200 string name = bond->id();
201 if(bond->maturity() <= reinvestment_)
202 ALOG(
"bond " <<
name <<
" maturity " << io::iso_date(bond->maturity()) <<
" <= " <<
"reinvestment end " << io::iso_date(reinvestment_));
205 const vector<Leg>& legs = bond->legs();
207 ALOG(
"bond " <<
name <<
" has more than one leg, only the first is considered.")
208 const Leg& leg = legs[0];
211 for (
size_t j = 0; j < leg.size(); j++) {
212 QuantLib::ext::shared_ptr<QuantLib::Coupon> ptrCoupon =
213 QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(leg[j]);
215 if(ptrCoupon->date() > reinvestment_){
222 double baseNotional = bond->notional();
223 vector<double>scalars(leg.size(), 1.0);
224 vector<string>
flowType(leg.size(),
"");
225 double currentScalar = 1.0;
227 for (
size_t j = 0; j < leg.size(); j++) {
229 QuantLib::ext::shared_ptr<QuantLib::Coupon> ptrCoupon =
230 QuantLib::ext::dynamic_pointer_cast<QuantLib::Coupon>(leg[j]);
232 if(isFeeFlow(leg[j],
name))
237 if(j <= jmax && ptrCoupon->date() >= today){
238 double periodNotional = ptrCoupon->nominal();
240 if(periodNotional < 1e-10)
241 ALOG(
name <<
" amortises too early: periodNotional " << periodNotional
242 <<
" cpnDate " << io::iso_date(ptrCoupon->date())
243 <<
" (first period after) reinvestment end " << io::iso_date(reinvestment_));
245 if(periodNotional < baseNotional && periodNotional > 1e-10)
246 currentScalar = baseNotional/periodNotional;
249 scalars[j] = currentScalar;
256void BondBasket::clear() {
265 XMLUtils::checkNode(node,
"BondBasketData");
267 for (
XMLNode* child = XMLUtils::getChildNode(node,
"Trade"); child; child = XMLUtils::getNextSibling(child)) {
268 string id = XMLUtils::getAttribute(child,
"id");
269 auto bonddata = QuantLib::ext::make_shared<ore::data::Bond>();
270 bonddata->fromXML(child);
272 bonds_.push_back(bonddata);
278 for (Size i = 0; i < bonds_.size(); i++) {
279 XMLUtils::appendNode(node, bonds_[i]->toXML(doc));
284std::map<AssetClass, std::set<std::string>> BondBasket::underlyingIndices(
const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager)
const {
285 std::map<AssetClass, std::set<std::string>> result;
286 result[AssetClass::BOND] = {};
287 for (
auto b : bonds_)
288 result[AssetClass::BOND].insert(b->bondData().securityId());
credit bond basket data model and serialization
const std::map< std::string, boost::shared_ptr< QuantExt::FxIndex > > fxIndexMap_
const std::map< std::string, std::vector< double > > reinvestmentScalar_
const Currency currency(const std::string &name) const
const boost::shared_ptr< QuantLib::Pool > & pool() const
const std::map< std::string, std::vector< std::string > > flowType_
const std::string flowType(const std::string &name, int idx) const
QuantLib::ext::shared_ptr< QuantExt::BondBasket > build(const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, const QuantLib::Currency &ccy, const std::string &reinvestmentEndDate)
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
#define ALOG(text)
Logging Macro (Level = Alert)
market data related utilties
Size size(const ValueType &v)
QuantLib::Handle< QuantExt::CreditCurve > securitySpecificCreditCurve(const QuantLib::ext::shared_ptr< Market > &market, const std::string &securityId, const std::string &creditCurveId, const std::string &configuration)
Serializable Credit Default Swap.
string conversion utilities