25#include <boost/algorithm/string/case_conv.hpp>
34 DLOG(
"Building Composite Trade: " <<
id());
36 QuantLib::ext::shared_ptr<MultiCcyCompositeInstrument> compositeInstrument =
37 QuantLib::ext::make_shared<MultiCcyCompositeInstrument>();
45 for (
const QuantLib::ext::shared_ptr<Trade>& trade :
trades_) {
48 trade->build(engineFactory);
54 Handle<Quote> fx = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.0));
56 fx = engineFactory->market()->fxRate(trade->npvCurrency() +
npvCurrency_);
59 Handle<Quote> fxNotional = Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(1.0));
60 if (trade->notionalCurrency().empty()) {
62 if (trade->notional() != Null<Real>()) {
64 trade,
"Error building composite trade '" +
id() +
"'",
65 "Component trade '" + trade->id() +
"' does not provide notional currency for notional " +
66 std::to_string(trade->notional()) +
". Assuming " +
npvCurrency_ +
".")
70 fxNotional = engineFactory->market()->fxRate(trade->notionalCurrency() +
npvCurrency_);
73 QuantLib::ext::shared_ptr<InstrumentWrapper> instrumentWrapper = trade->instrument();
74 Real effectiveMultiplier = instrumentWrapper->multiplier();
75 if (
auto optionWrapper = QuantLib::ext::dynamic_pointer_cast<ore::data::OptionWrapper>(instrumentWrapper)) {
76 effectiveMultiplier *= optionWrapper->isLong() ? 1.0 : -1.0;
79 compositeInstrument->add(instrumentWrapper->qlInstrument(), effectiveMultiplier, fx);
80 for (Size i = 0; i < instrumentWrapper->additionalInstruments().
size(); ++i) {
81 compositeInstrument->add(instrumentWrapper->additionalInstruments()[i],
82 instrumentWrapper->additionalMultipliers()[i]);
85 bool isDuplicate =
false;
87 if (instrumentWrapper->additionalResults().find(
"cashFlowResults") != trade->instrument()->additionalResults().end())
92 legs_.insert(
legs_.end(), trade->legs().begin(), trade->legs().end());
109 vector<Real> notionals;
110 vector<Handle<Quote>> fxRates;
112 for (
const QuantLib::ext::shared_ptr<Trade>& trade :
trades_)
113 notionals.push_back(trade->notional() != Null<Real>() ? trade->notional() : 0.0);
116 auto notionalConverter = [](
const Real ntnl,
const Handle<Quote>& fx) {
return (ntnl * fx->value()); };
117 std::transform(begin(notionals), end(notionals), begin(
fxRates_), begin(notionals), notionalConverter);
123 "Wrong trade type in composite trade builder.");
128 QL_REQUIRE(compNode,
"Could not find CompositeTradeData node.");
142 QL_REQUIRE(
notionalCalculation_ !=
"Override",
"Notional override value has not been provided.");
155 QL_REQUIRE(tradesNode,
"Required a Portfolio Id or a Components Node.");
160 for (Size i = 0; i < nodes.size(); i++) {
164 WLOG(
"Empty component trade id being overwritten in composite trade " << this->
id() <<
".");
166 id = this->
id() +
"_" + std::to_string(i);
167 DLOG(
"Parsing composite trade " << this->
id() <<
" node " << i <<
" with id: " <<
id);
169 QuantLib::ext::shared_ptr<Trade> trade;
171 trade = TradeFactory::instance().build(
tradeType);
175 componentEnvelope.
fromXML(envNode);
183 trade->setEnvelope(env);
184 trade->fromXML(nodes[i]);
186 DLOG(
"Added Trade " <<
id <<
" (" << trade->id() <<
")"
187 <<
" type:" <<
tradeType <<
" to composite trade " << this->id() <<
".");
188 }
catch (
const std::exception& e) {
191 "Failed to build subtrade with id '" +
id +
"' inside composite trade: ", e.what())
195 LOG(
"Finished Parsing XML doc");
212 XMLNode* subTradeNode = trade->toXML(doc);
220 return std::accumulate(notionals.begin(), notionals.end(), 0.0);
222 return std::accumulate(notionals.begin(), notionals.end(), 0.0) / notionals.size();
226 return notionals.back();
228 return *std::min_element(notionals.begin(), notionals.end());
230 return *std::min_element(notionals.begin(), notionals.end());
234 QL_FAIL(
"Unsupported notional calculation type.");
239 map<string, RequiredFixings::FixingDates> result;
240 for (
const auto& t :
trades_) {
241 auto fixings = t->fixings(settlementDate);
242 for (
const auto& [indexName, fixingDates] :
fixings) {
243 result[indexName].addDates(fixingDates);
249std::map<AssetClass, std::set<std::string>>
252 map<AssetClass, std::set<std::string>> result;
253 for (
const auto& t :
trades_) {
254 auto underlyings = t->underlyingIndices(referenceDataManager);
255 for (
const auto& kv : underlyings) {
256 result[kv.first].insert(kv.second.begin(), kv.second.end());
265 for (
auto const& t :
trades_) {
266 for (
auto const& d : t->additionalData()) {
276 if (!
portfolioId_.empty() && referenceData !=
nullptr &&
278 auto ptfRefData = QuantLib::ext::dynamic_pointer_cast<PortfolioBasketReferenceDatum>(
280 QL_REQUIRE(ptfRefData,
"could not cast to PortfolioBasketReferenceDatum, this is unexpected");
283 DLOG(
"Could not get PortfolioBasketReferenceDatum for Id " <<
portfolioId_ <<
" leave data in trade unchanged");
289 const QuantLib::ext::shared_ptr<PortfolioBasketReferenceDatum>& ptfReferenceDatum) {
291 DLOG(
"populating portfolio basket data from reference data");
292 QL_REQUIRE(ptfReferenceDatum,
"populateFromReferenceData(): empty cbo reference datum given");
294 auto refData = ptfReferenceDatum->getTrades();
296 for (Size i = 0; i < refData.size(); i++) {
299 LOG(
"Finished Parsing XML doc");
vector< Handle< Quote > > fxRatesNotional_
std::map< std::string, RequiredFixings::FixingDates > fixings(const QuantLib::Date &settlementDate) const override
Real calculateNotional(const vector< Real > &tradeNotionals) const
calculates the CompositeTrade notional, when supplied with the notionals of the subtrades
void getTradesFromReferenceData(const QuantLib::ext::shared_ptr< PortfolioBasketReferenceDatum > &ptfReferenceDatum)
vector< Handle< Quote > > fxRates_
QuantLib::Real notional() const override
Return the current notional in npvCurrency. See individual sub-classes for the precise definition.
vector< QuantLib::ext::shared_ptr< Trade > > trades_
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
string notionalCalculation_
void populateFromReferenceData(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager)
Size size() const
returns the number of subtrades in the strategy
std::map< AssetClass, std::set< std::string > > underlyingIndices(const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceDataManager) const override
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
Serializable object holding generic trade data, reporting dimensions.
virtual void fromXML(XMLNode *node) override
void setAdditionalField(const std::string &key, const boost::any &value)
const map< string, boost::any > & fullAdditionalFields() const
void log() const
generate Boost log record to pass to corresponding sinks
static constexpr const char * TYPE
void addData(const RequiredFixings &requiredFixings)
Utility class for Structured Trade errors, contains the Trade ID and Type.
std::vector< bool > legPayers_
string sensitivityTemplate_
std::vector< string > legCurrencies_
std::vector< QuantLib::Leg > legs_
virtual void fromXML(XMLNode *node) override
void setSensitivityTemplate(const EngineBuilder &builder)
virtual XMLNode * toXML(XMLDocument &doc) const override
string & id()
Set the trade id.
RequiredFixings requiredFixings_
const Envelope & envelope() const
QuantLib::ext::shared_ptr< InstrumentWrapper > instrument_
const string & tradeType() 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
static string getAttribute(XMLNode *node, const string &attrName)
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
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 bool getChildValueAsBool(XMLNode *node, const string &name, bool mandatory=false, bool defaultValue=true)
static XMLNode * getChildNode(XMLNode *n, const string &name="")
static XMLNode * addChild(XMLDocument &doc, XMLNode *n, const string &name)
static void appendNode(XMLNode *parent, XMLNode *child)
Composite trades operate as a mini portfolio. Their intended use is for strategies like straddles.
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)
Serializable Credit Default Swap.
Wrapper for option instruments, tracks whether option has been exercised or not.
Structured Trade Error class.
string conversion utilities