19#include <boost/make_shared.hpp>
27#include <ql/cashflows/simplecashflow.hpp>
36 additionalData_[
"isdaAssetClass"] = string(
"Foreign Exchange");
37 additionalData_[
"isdaBaseProduct"] = string(settlement_ ==
"Cash" ?
"NDF" :
"Forward");
38 additionalData_[
"isdaSubProduct"] = string(
"");
39 additionalData_[
"isdaTransaction"] = string(
"");
41 additionalData_[
"soldCurrency"] = soldCurrency_;
42 additionalData_[
"boughtCurrency"] = boughtCurrency_;
43 additionalData_[
"soldAmount"] = soldAmount_;
44 additionalData_[
"boughtAmount"] = boughtAmount_;
46 additionalData_[
"settlement"] = settlement_;
55 if (payCurrency_.empty()) {
61 "Settlement currency must be either " << boughtCcy.code() <<
" or " << soldCcy.code() <<
".");
64 npvCurrency_ =
payCcy.code();
68 if (settlement_ ==
"Physical") {
69 notional_ = soldAmount_;
70 notionalCurrency_ = soldCurrency_;
73 notional_ = soldCcy ==
payCcy ? soldAmount_ : boughtAmount_;
74 notionalCurrency_ =
payCcy.code();
82 Natural conventionalLag = 0;
83 Calendar conventionalCalendar = NullCalendar();
84 BusinessDayConvention conventionalBdc = Unadjusted;
85 if (!
fxIndex_.empty() && settlement_ ==
"Cash") {
86 std::tie(conventionalLag, conventionalCalendar, conventionalBdc) =
91 paymentLag = conventionalLag;
95 Calendar payCalendar = payCalendar_.empty() ? conventionalCalendar :
parseCalendar(payCalendar_);
96 BusinessDayConvention payConvention =
101 QL_REQUIRE(
payDate >=
maturityDate,
"FX Forward settlement date should equal or exceed the maturity date.");
104 additionalData_[
"payDate"] =
payDate;
106 QuantLib::ext::shared_ptr<QuantExt::FxIndex>
fxIndex;
109 if (settlement_ ==
"Cash") {
114 Currency nonPayCcy =
payCcy == boughtCcy ? soldCcy : boughtCcy;
116 engineFactory->configuration(MarketContext::pricing));
126 "FX settlement index must be specified for non-deliverable forward if value date ("
134 additionalData_[
"adjustedValueDate"] =
fixingDate;
137 QL_REQUIRE(tradeActions().empty(),
"TradeActions not supported for FxForward");
139 DLOG(
"Build FxForward with maturity date " << QuantLib::io::iso_date(
maturityDate) <<
" and pay date "
140 << QuantLib::io::iso_date(
payDate));
143 QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
144 QL_REQUIRE(builder,
"No builder found for " << tradeType_);
145 QuantLib::ext::shared_ptr<FxForwardEngineBuilderBase> fxBuilder =
146 QuantLib::ext::dynamic_pointer_cast<FxForwardEngineBuilderBase>(builder);
148 string tmp = fxBuilder->engineParameter(
"includeSettlementDateFlows", {},
false,
"");
149 includeSettlementDateFlows_ = tmp ==
"" ? false :
parseBool(tmp);
151 QuantLib::ext::shared_ptr<QuantLib::Instrument> instrument =
152 QuantLib::ext::make_shared<QuantExt::FxForward>(boughtAmount_, boughtCcy, soldAmount_, soldCcy,
maturityDate,
false,
154 includeSettlementDateFlows_);
158 instrument_->qlInstrument()->setPricingEngine(fxBuilder->engine(boughtCcy, soldCcy));
159 setSensitivityTemplate(*fxBuilder);
162 legs_ = {{QuantLib::ext::make_shared<SimpleCashFlow>(boughtAmount_,
payDate)},
163 {QuantLib::ext::make_shared<SimpleCashFlow>(soldAmount_,
payDate)}};
164 legCurrencies_ = {boughtCurrency_, soldCurrency_};
165 legPayers_ = {
false,
true};
169 if (includeSettlementDateFlows_)
170 return date > maturity_;
172 return date >= maturity_;
175QuantLib::Real FxForward::notional()
const {
178 return instrument_->qlInstrument(
true)->result<Real>(
"currentNotional");
179 }
catch (
const std::exception& e) {
180 if (strcmp(e.what(),
"currentNotional not provided"))
181 ALOG(
"error when retrieving notional: " << e.what());
187std::string FxForward::notionalCurrency()
const {
190 return instrument_->qlInstrument(
true)->result<std::string>(
"notionalCurrency");
191 }
catch (
const std::exception& e) {
192 if (strcmp(e.what(),
"notionalCurrency not provided"))
193 ALOG(
"error when retrieving notional ccy: " << e.what());
196 return notionalCurrency_;
200 Trade::fromXML(node);
201 XMLNode* fxNode = XMLUtils::getChildNode(node,
"FxForwardData");
202 QL_REQUIRE(fxNode,
"No FxForwardData Node");
203 maturityDate_ = XMLUtils::getChildValue(fxNode,
"ValueDate",
true);
204 boughtCurrency_ = XMLUtils::getChildValue(fxNode,
"BoughtCurrency",
true);
205 soldCurrency_ = XMLUtils::getChildValue(fxNode,
"SoldCurrency",
true);
206 boughtAmount_ = XMLUtils::getChildValueAsDouble(fxNode,
"BoughtAmount",
true);
207 soldAmount_ = XMLUtils::getChildValueAsDouble(fxNode,
"SoldAmount",
true);
208 settlement_ = XMLUtils::getChildValue(fxNode,
"Settlement",
false);
209 if (settlement_ ==
"")
210 settlement_ =
"Physical";
212 if (
XMLNode* settlementDataNode = XMLUtils::getChildNode(fxNode,
"SettlementData")) {
213 payCurrency_ = XMLUtils::getChildValue(settlementDataNode,
"Currency",
false);
214 fxIndex_ = XMLUtils::getChildValue(settlementDataNode,
"FXIndex",
false);
215 payDate_ = XMLUtils::getChildValue(settlementDataNode,
"Date",
false);
218 if (
XMLNode* rulesNode = XMLUtils::getChildNode(settlementDataNode,
"Rules")) {
219 payLag_ = XMLUtils::getChildValue(rulesNode,
"PaymentLag",
false);
220 payCalendar_ = XMLUtils::getChildValue(rulesNode,
"PaymentCalendar",
false);
221 payConvention_ = XMLUtils::getChildValue(rulesNode,
"PaymentConvention",
false);
228 XMLNode* node = Trade::toXML(doc);
230 XMLUtils::appendNode(node, fxNode);
232 XMLUtils::addChild(doc, fxNode,
"BoughtCurrency", boughtCurrency_);
233 XMLUtils::addChild(doc, fxNode,
"BoughtAmount", boughtAmount_);
234 XMLUtils::addChild(doc, fxNode,
"SoldCurrency", soldCurrency_);
235 XMLUtils::addChild(doc, fxNode,
"SoldAmount", soldAmount_);
236 XMLUtils::addChild(doc, fxNode,
"Settlement", settlement_);
239 XMLUtils::appendNode(fxNode, settlementDataNode);
241 if (!payCurrency_.empty())
242 XMLUtils::addChild(doc, settlementDataNode,
"Currency", payCurrency_);
244 XMLUtils::addChild(doc, settlementDataNode,
"FXIndex",
fxIndex_);
246 XMLUtils::addChild(doc, settlementDataNode,
"Date",
payDate_);
249 XMLUtils::appendNode(settlementDataNode, rulesNode);
250 if (!payLag_.empty())
251 XMLUtils::addChild(doc, rulesNode,
"PaymentLag", payLag_);
252 if (!payCalendar_.empty())
253 XMLUtils::addChild(doc, rulesNode,
"PaymentCalendar", payCalendar_);
254 if (!payConvention_.empty())
255 XMLUtils::addChild(doc, rulesNode,
"PaymentConvention", payConvention_);
Engine builder for FX Forwards.
bool isExpired() const override
Date maturityDate() const
boost::shared_ptr< QuantExt::FxIndex > fxIndex() const
boost::shared_ptr< FxIndex > fxIndex_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Build QuantLib/QuantExt instrument, link pricing engine.
Vanilla Instrument Wrapper.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
FX Forward data model and serialization.
Calendar parseCalendar(const string &s)
Convert text to QuantLib::Calendar.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
BusinessDayConvention parseBusinessDayConvention(const string &s)
Convert text to QuantLib::BusinessDayConvention.
bool parseBool(const string &s)
Convert text to bool.
PaymentLag parsePaymentLag(const string &s)
Convert text to PaymentLag.
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
QuantLib::Date fixingDate(const QuantLib::Date &d, const QuantLib::Period obsLag, const QuantLib::Frequency freq, bool interpolated)
std::tuple< Natural, Calendar, BusinessDayConvention > getFxIndexConventions(const string &index)
boost::variant< QuantLib::Period, QuantLib::Natural > PaymentLag
QuantLib::ext::shared_ptr< QuantExt::FxIndex > buildFxIndex(const string &fxIndex, const string &domestic, const string &foreign, const QuantLib::ext::shared_ptr< Market > &market, const string &configuration, bool useXbsCurves)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.