27#include <ql/cashflows/simplecashflow.hpp>
29#include <ql/time/calendars/target.hpp>
35#include <ql/instruments/swap.hpp>
36#include <ql/time/daycounters/actualactual.hpp>
45void Swap::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
46 DLOG(
"Swap::build() called for trade " <<
id());
50 QL_REQUIRE(
legData_.size() >= 1,
"Swap must have at least 1 leg");
51 const QuantLib::ext::shared_ptr<Market> market = engineFactory->market();
55 string ccy_str = currency.code();
59 std::vector<QuantLib::Currency> currencies(numLegs);
60 std::vector<QuantLib::Currency> currenciesForMcSimulation;
61 legs_.resize(numLegs);
66 for (Size i = 0; i < numLegs; ++i) {
69 if (
legData_[i].legType() ==
"Equity")
74 if (currencies[i] != currency)
83 auto addUnique = [](vector<Currency>& currencies, Currency ccy) {
84 if (std::find(currencies.begin(), currencies.end(), ccy) ==
86 currencies.push_back(ccy);
90 for (Size i = 0; i < numLegs; ++i) {
91 addUnique(currenciesForMcSimulation, currencies[i]);
92 vector<Indexing> indexings =
legData_[i].indexing();
93 if (!indexings.empty() && indexings.front().hasData()) {
94 Indexing indexing = indexings.front();
95 if (boost::starts_with(indexing.
index(),
"FX-")) {
97 addUnique(currenciesForMcSimulation, index->targetCurrency());
98 addUnique(currenciesForMcSimulation, index->sourceCurrency());
103 static std::set<std::string> eligibleForXbs = {
"Fixed",
"Floating"};
104 bool useXbsCurves =
true;
105 for(Size i=0;i<numLegs;++i) {
106 useXbsCurves = useXbsCurves && (eligibleForXbs.find(
legData_[i].legType()) != eligibleForXbs.end());
121 ALOG(
"no suitable leg found to set notional, set to null and notionalCurrency to empty string");
132 Date today = Settings::instance().evaluationDate();
133 auto d = std::upper_bound(schedule.dates().begin(), schedule.dates().end(), today);
137 if (d == schedule.dates().begin())
139 else if (d == schedule.dates().end())
155 QuantLib::ext::shared_ptr<EngineBuilder> builder =
156 isXCCY_ ? engineFactory->builder(
"CrossCurrencySwap") : engineFactory->builder(
"Swap");
157 auto configuration = builder->configuration(MarketContext::pricing);
159 for (Size i = 0; i < numLegs; ++i) {
161 auto legBuilder = engineFactory->legBuilder(
legData_[i].legType());
164 DLOG(
"Swap::build(): currency[" << i <<
"] = " << currencies[i]);
170 legs_.push_back(leg);
172 currencies.push_back(currencies[i]);
177 QuantLib::ext::shared_ptr<QuantExt::CurrencySwap> swap(
179 QuantLib::ext::shared_ptr<CrossCurrencySwapEngineBuilderBase> swapBuilder =
180 QuantLib::ext::dynamic_pointer_cast<CrossCurrencySwapEngineBuilderBase>(builder);
181 QL_REQUIRE(swapBuilder,
"No Builder found for CrossCurrencySwap " <<
id());
182 swap->setPricingEngine(swapBuilder->engine(currenciesForMcSimulation, npvCcy));
188 QuantLib::ext::shared_ptr<SwapEngineBuilderBase> swapBuilder =
189 QuantLib::ext::dynamic_pointer_cast<SwapEngineBuilderBase>(builder);
190 QL_REQUIRE(swapBuilder,
"No Builder found for Swap " <<
id());
191 swap->setPricingEngine(swapBuilder->engine(npvCcy,
envelope().additionalField(
"discount_curve",
false),
192 envelope().additionalField(
"security_spread",
false)));
197 DLOG(
"Set instrument wrapper");
201 for (Size i = 0; i < currencies.size(); i++)
206 Date startDate = Date::maxDate();
207 for (
auto const& l :
legs_) {
210 startDate = std::min(startDate, l.front()->date());
211 QuantLib::ext::shared_ptr<Coupon> coupon = QuantLib::ext::dynamic_pointer_cast<Coupon>(l.front());
213 startDate = std::min(startDate, coupon->accrualStartDate());
231 QuantLib::ext::shared_ptr<QuantLib::Swap> swap = QuantLib::ext::dynamic_pointer_cast<QuantLib::Swap>(
instrument_->qlInstrument());
232 QuantLib::ext::shared_ptr<QuantExt::CurrencySwap> cswap = QuantLib::ext::dynamic_pointer_cast<QuantExt::CurrencySwap>(
instrument_->qlInstrument());
233 std::map<std::string, Real> legNpv;
234 for (Size i = 0; i < numLegs; ++i) {
243 ALOG(
"single currency swap underlying instrument not set, skip leg npv reporting");
249 Real legNpvInCcy = 0;
250 for (Size j = 0; j < cswap->legs().
size(); ++j) {
251 if (cswap->legCurrency(j).code() ==
legData_[i].currency()) {
252 legNpv += cswap->legNPV(j);
253 legNpvInCcy += cswap->inCcyLegNPV(j);
260 ALOG(
"cross currency swap underlying instrument not set, skip leg npv reporting");
270 return instrument_->qlInstrument(
true)->result<Real>(
"currentNotional");
271 }
catch (
const std::exception& e) {
272 WLOG(
"swap engine does not provide current notional: " << e.what() <<
", using fallback");
276 if (fabs(n) > QL_EPSILON) {
281 WLOG(
"swap does not provide coupon notionals, using face value");
289 return instrument_->qlInstrument(
true)->result<std::string>(
"notionalCurrency");
290 }
catch (
const std::exception& e) {
291 if (strcmp(e.what(),
"notionalCurrency not provided"))
292 WLOG(
"swap engine does not provide notional ccy: " << e.what() <<
", using fallback");
297map<AssetClass, set<string>>
300 map<AssetClass, set<string>> result;
302 for (
auto ind : ld.indices()) {
304 if (ind.substr(0, 5) !=
"COMM-" && ind.substr(0, 3) !=
"EQ-")
307 QuantLib::ext::shared_ptr<Index> index =
parseIndex(ind);
309 if (
auto ei = QuantLib::ext::dynamic_pointer_cast<EquityIndex2>(index)) {
310 result[AssetClass::EQ].insert(ei->name());
311 }
else if (
auto ci = QuantLib::ext::dynamic_pointer_cast<QuantExt::CommodityIndex>(index)) {
312 result[AssetClass::COM].insert(ci->name());
317 if (
auto s =
envelope().additionalField(
"security_spread",
false); !s.empty())
318 result[AssetClass::BOND] = {s};
327 for (Size i = 0; i < legData.size(); ++i) {
328 std::string type = legData[i].legType();
329 if (type ==
"Fixed" ||
330 type ==
"ZeroCouponFixed" ||
332 type ==
"CommodityFixed")
334 else if (type ==
"Floating" ||
338 type ==
"DigitalCMS" ||
339 type ==
"CMSSpread" ||
340 type ==
"DigitalCMSSpread" ||
343 type ==
"DurationAdjustedCMS"||
344 type ==
"FormulaBased"||
345 type ==
"CommodityFloating"||
346 type ==
"EquityMargin")
349 ALOG(
"leg type " << type <<
" not mapped for trade " << tradeId);
354 return string(
"Basis");
355 else if (nFloating >= 1)
356 return string(
"Fixed Float");
358 return string(
"Fixed Fixed");
362 Trade::fromXML(node);
366 if (swapNode ==
nullptr) {
367 swapNode = XMLUtils::getChildNode(node,
"SwapData");
369 QL_REQUIRE(swapNode,
"Swap::fromXML(): expected '" <<
tradeType() <<
"Data'"
370 << (
tradeType() ==
"Swap" ?
"" :
" or 'SwapData'"));
372 settlement_ = XMLUtils::getChildValue(swapNode,
"Settlement",
false);
376 vector<XMLNode*> nodes = XMLUtils::getChildrenNodes(swapNode,
"LegData");
377 for (Size i = 0; i < nodes.size(); i++) {
379 ld->fromXML(nodes[i]);
380 legData_.push_back(*QuantLib::ext::static_pointer_cast<LegData>(ld));
384QuantLib::ext::shared_ptr<LegData>
Swap::createLegData()
const {
return QuantLib::ext::make_shared<LegData>(); }
387 XMLNode* node = Trade::toXML(doc);
389 XMLUtils::appendNode(node, swapNode);
392 XMLUtils::addChild(doc, swapNode,
"Settlement",
settlement_);
393 for (Size i = 0; i <
legData_.size(); i++)
Engine builder for Swaps.
Serializable object holding indexing data.
const string & index() const
Serializable object holding leg data.
const vector< double > & notionals() const
std::string notionalCurrency() const override
virtual QuantLib::ext::shared_ptr< LegData > createLegData() const
vector< LegData > legData_
QuantLib::Real notional() const override
Return the current notional in npvCurrency. See individual sub-classes for the precise definition.
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
Size notionalTakenFromLeg_
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager=nullptr) const override
Add underlying index names.
virtual void setIsdaTaxonomyFields()
virtual void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Build QuantLib/QuantExt instrument, link pricing engine.
const std::map< std::string, boost::any > & additionalData() const override
returns all additional data returned by the trade once built
std::vector< bool > legPayers_
std::vector< string > legCurrencies_
std::vector< QuantLib::Leg > legs_
void setSensitivityTemplate(const EngineBuilder &builder)
RequiredFixings requiredFixings_
const Envelope & envelope() const
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
const string & tradeType() const
void setLegBasedAdditionalData(const Size legNo, Size resultLegId=Null< Size >()) const
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
Logic for calculating required fixing dates on legs.
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 parseCurrencyWithMinors(const string &s)
Convert text to QuantLib::Currency.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
QuantLib::ext::shared_ptr< Index > parseIndex(const string &s)
Convert std::string to QuantLib::Index.
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)
#define WLOG(text)
Logging Macro (Level = Warning)
vector< T > buildScheduledVectorNormalised(const vector< T > &values, const vector< string > &dates, const Schedule &schedule, const T &defaultValue, const bool checkAllValuesAppearInResult=false)
Real currentNotional(const Leg &leg)
void applyIndexing(Leg &leg, const LegData &data, const QuantLib::ext::shared_ptr< EngineFactory > &engineFactory, RequiredFixings &requiredFixings, const QuantLib::Date &openEndDateReplacement, const bool useXbsCurves)
std::string isdaSubProductSwap(const std::string &tradeId, const vector< LegData > &legData)
Size size(const ValueType &v)
Leg buildNotionalLeg(const LegData &data, const Leg &leg, RequiredFixings &requiredFixings, const QuantLib::ext::shared_ptr< Market > &market, const std::string &configuration)
std::string to_string(const LocationInfo &l)
Schedule makeSchedule(const ScheduleDates &data)
Serializable Credit Default Swap.
Swap trade data model and serialization.
string conversion utilities