26#include <ql/instruments/compositeinstrument.hpp>
38 const Envelope& envelope,
const OptionData& optionData, Real strike, Real digitalCashPayoff,
const string& currency,
40 const string& paymentCalendar,
const string& paymentLag,
const string& paymentConvention,
41 const string& pricingCalendar,
const string& paymentDate, Real gearing, Spread spread,
43 QuantLib::Natural futureMonthOffset, QuantLib::Natural deliveryRollDays,
bool includePeriodEnd,
44 const BarrierData& barrierData,
const std::string& fxIndex)
45 : Trade(
"CommodityDigitalAveragePriceOption", envelope), optionData_(optionData), barrierData_(barrierData),
46 strike_(strike), digitalCashPayoff_(digitalCashPayoff), currency_(currency), name_(
name),
47 priceType_(priceType),
48 startDate_(startDate), endDate_(endDate), paymentCalendar_(paymentCalendar), paymentLag_(paymentLag),
49 paymentConvention_(paymentConvention), pricingCalendar_(pricingCalendar), paymentDate_(paymentDate),
50 gearing_(gearing),
spread_(spread), commodityQuantityFrequency_(commodityQuantityFrequency),
51 commodityPayRelativeTo_(commodityPayRelativeTo), futureMonthOffset_(futureMonthOffset),
52 deliveryRollDays_(deliveryRollDays), includePeriodEnd_(includePeriodEnd), fxIndex_(fxIndex) {}
54void CommodityDigitalAveragePriceOption::build(
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
58 DLOG(
"CommodityDigitalAveragePriceOption::build() called for trade " <<
id());
61 additionalData_[
"isdaAssetClass"] = std::string(
"Commodity");
62 additionalData_[
"isdaBaseProduct"] = std::string(
"Option");
63 additionalData_[
"isdaSubProduct"] = std::string(
"Price Return Basic Performance");
65 additionalData_[
"isdaTransaction"] = std::string(
"");
67 QL_REQUIRE(optionData_.exerciseDates().size() == 1,
"Invalid number of excercise dates");
68 Date exDate =
parseDate(optionData_.exerciseDates().front());
71 Real strikeSpread = strike_ * 0.01;
72 Real strike1 = strike_ - strikeSpread / 2;
73 Real strike2 = strike_ + strikeSpread / 2;
75 envelope(), optionData_, 1.0, strike1, currency_, name_, priceType_, startDate_, endDate_, paymentCalendar_,
76 paymentLag_, paymentConvention_, pricingCalendar_, paymentDate_, gearing_,
spread_, commodityQuantityFrequency_,
77 commodityPayRelativeTo_, futureMonthOffset_, deliveryRollDays_, includePeriodEnd_, barrierData_, fxIndex_);
80 startDate_, endDate_, paymentCalendar_,
81 paymentLag_, paymentConvention_, pricingCalendar_, paymentDate_, gearing_,
spread_, commodityQuantityFrequency_,
82 commodityPayRelativeTo_, futureMonthOffset_, deliveryRollDays_, includePeriodEnd_, barrierData_, fxIndex_);
84 opt1.build(engineFactory);
85 opt2.build(engineFactory);
87 setSensitivityTemplate(opt1.sensitivityTemplate());
89 QuantLib::ext::shared_ptr<Instrument> inst1 = opt1.instrument()->qlInstrument();
90 QuantLib::ext::shared_ptr<Instrument> inst2 = opt2.instrument()->qlInstrument();
92 QuantLib::ext::shared_ptr<CompositeInstrument> composite = QuantLib::ext::make_shared<CompositeInstrument>();
94 if (optionData_.callPut() ==
"Call") {
95 composite->add(inst1);
96 composite->subtract(inst2);
97 }
else if (optionData_.callPut() ==
"Put") {
98 composite->add(inst2);
99 composite->subtract(inst1);
101 QL_FAIL(
"OptionType Call or Put required in CommodityDigitalOption " <<
id());
105 Real bsIndicator = (positionType == QuantLib::Position::Long ? 1.0 : -1.0);
106 Real multiplier = digitalCashPayoff_ * bsIndicator / strikeSpread;
107 std::vector<QuantLib::ext::shared_ptr<Instrument>> additionalInstruments;
108 std::vector<Real> additionalMultipliers;
110 string configuration = Market::defaultConfiguration;
114 std::max(exDate, addPremiums(additionalInstruments, additionalMultipliers, multiplier,
115 optionData_.premiumData(), -bsIndicator, ccy, engineFactory, configuration));
117 instrument_ = QuantLib::ext::shared_ptr<InstrumentWrapper>(
118 new VanillaInstrument(composite, multiplier, additionalInstruments, additionalMultipliers));
120 npvCurrency_ = currency_;
121 notional_ = digitalCashPayoff_;
122 notionalCurrency_ = currency_;
125 if (exDate > Settings::instance().evaluationDate()) {
126 DLOG(
"Implied vol for " << tradeType_ <<
" on " << name_ <<
" with expiry " << exDate <<
" and strike "
128 << engineFactory->market()->commodityVolatility(name_)->blackVol(exDate, strike_));
131 additionalData_[
"payoff"] = digitalCashPayoff_;
132 additionalData_[
"strike"] = strike_;
133 additionalData_[
"optionType"] = optionData_.callPut();
134 additionalData_[
"strikeCurrency"] = currency_;
137std::map<AssetClass, std::set<std::string>> CommodityDigitalAveragePriceOption::underlyingIndices(
138 const QuantLib::ext::shared_ptr<ReferenceDataManager>& referenceDataManager)
const {
139 return {{AssetClass::COM, std::set<std::string>({name_})}};
142void CommodityDigitalAveragePriceOption::fromXML(
XMLNode* node) {
144 Trade::fromXML(node);
146 XMLNode* apoNode = XMLUtils::getChildNode(node,
"CommodityDigitalAveragePriceOptionData");
147 QL_REQUIRE(apoNode,
"No CommodityDigitalAveragePriceOptionData Node");
149 optionData_.fromXML(XMLUtils::getChildNode(apoNode,
"OptionData"));
150 if(
auto b = XMLUtils::getChildNode(apoNode,
"BarrierData")) {
151 barrierData_.fromXML(b);
153 name_ = XMLUtils::getChildValue(apoNode,
"Name",
true);
154 currency_ = XMLUtils::getChildValue(apoNode,
"Currency",
true);
155 strike_ = XMLUtils::getChildValueAsDouble(apoNode,
"Strike",
true);
156 digitalCashPayoff_ = XMLUtils::getChildValueAsDouble(apoNode,
"DigitalCashPayoff",
true);
158 startDate_ = XMLUtils::getChildValue(apoNode,
"StartDate",
true);
159 endDate_ = XMLUtils::getChildValue(apoNode,
"EndDate",
true);
160 paymentCalendar_ = XMLUtils::getChildValue(apoNode,
"PaymentCalendar",
true);
161 paymentLag_ = XMLUtils::getChildValue(apoNode,
"PaymentLag",
true);
162 paymentConvention_ = XMLUtils::getChildValue(apoNode,
"PaymentConvention",
true);
163 pricingCalendar_ = XMLUtils::getChildValue(apoNode,
"PricingCalendar",
true);
165 paymentDate_ = XMLUtils::getChildValue(apoNode,
"PaymentDate",
false);
168 if (
XMLNode* n = XMLUtils::getChildNode(apoNode,
"Gearing")) {
169 gearing_ =
parseReal(XMLUtils::getNodeValue(n));
172 spread_ = XMLUtils::getChildValueAsDouble(apoNode,
"Spread",
false);
174 commodityQuantityFrequency_ = CommodityQuantityFrequency::PerCalculationPeriod;
175 if (
XMLNode* n = XMLUtils::getChildNode(apoNode,
"CommodityQuantityFrequency")) {
179 commodityPayRelativeTo_ = CommodityPayRelativeTo::CalculationPeriodEndDate;
180 if (
XMLNode* n = XMLUtils::getChildNode(apoNode,
"CommodityPayRelativeTo")) {
184 futureMonthOffset_ = XMLUtils::getChildValueAsInt(apoNode,
"FutureMonthOffset",
false);
185 deliveryRollDays_ = XMLUtils::getChildValueAsInt(apoNode,
"DeliveryRollDays",
false);
187 includePeriodEnd_ =
true;
188 if (
XMLNode* n = XMLUtils::getChildNode(apoNode,
"IncludePeriodEnd")) {
189 includePeriodEnd_ =
parseBool(XMLUtils::getNodeValue(n));
192 if (
XMLNode* n = XMLUtils::getChildNode(apoNode,
"FXIndex")){
193 fxIndex_ = XMLUtils::getNodeValue(n);
199 XMLNode* node = Trade::toXML(doc);
202 XMLUtils::appendNode(node, apoNode);
204 XMLUtils::appendNode(apoNode, optionData_.toXML(doc));
205 if (barrierData_.initialized())
206 XMLUtils::appendNode(apoNode, barrierData_.toXML(doc));
207 XMLUtils::addChild(doc, apoNode,
"Name", name_);
208 XMLUtils::addChild(doc, apoNode,
"Currency", currency_);
209 XMLUtils::addChild(doc, apoNode,
"Strike", strike_);
210 XMLUtils::addChild(doc, apoNode,
"DigitalCashPayoff", digitalCashPayoff_);
211 XMLUtils::addChild(doc, apoNode,
"PriceType",
to_string(priceType_));
212 XMLUtils::addChild(doc, apoNode,
"StartDate", startDate_);
213 XMLUtils::addChild(doc, apoNode,
"EndDate", endDate_);
214 XMLUtils::addChild(doc, apoNode,
"PaymentCalendar", paymentCalendar_);
215 XMLUtils::addChild(doc, apoNode,
"PaymentLag", paymentLag_);
216 XMLUtils::addChild(doc, apoNode,
"PaymentConvention", paymentConvention_);
217 XMLUtils::addChild(doc, apoNode,
"PricingCalendar", pricingCalendar_);
218 XMLUtils::addChild(doc, apoNode,
"PaymentDate", paymentDate_);
219 XMLUtils::addChild(doc, apoNode,
"Gearing", gearing_);
220 XMLUtils::addChild(doc, apoNode,
"Spread",
spread_);
221 XMLUtils::addChild(doc, apoNode,
"CommodityQuantityFrequency",
to_string(commodityQuantityFrequency_));
222 XMLUtils::addChild(doc, apoNode,
"CommodityPayRelativeTo",
to_string(commodityPayRelativeTo_));
223 XMLUtils::addChild(doc, apoNode,
"FutureMonthOffset",
static_cast<int>(futureMonthOffset_));
224 XMLUtils::addChild(doc, apoNode,
"DeliveryRollDays",
static_cast<int>(deliveryRollDays_));
225 XMLUtils::addChild(doc, apoNode,
"IncludePeriodEnd", includePeriodEnd_);
226 if(!fxIndex_.empty()){
227 XMLUtils::addChild(doc, apoNode,
"FXIndex", fxIndex_);
CommodityDigitalAveragePriceOption()
Vanilla Instrument Wrapper.
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
Commodity Average Price Option data model and serialization.
Currency parseCurrencyWithMinors(const string &s)
Convert text to QuantLib::Currency.
Date parseDate(const string &s)
Convert std::string to QuantLib::Date.
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
bool parseBool(const string &s)
Convert text to bool.
Real parseReal(const string &s)
Convert text to Real.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
CommodityQuantityFrequency
CommodityPriceType parseCommodityPriceType(const string &s)
CommodityPayRelativeTo parseCommodityPayRelativeTo(const string &s)
void reset(const ASTNodePtr root)
std::string to_string(const LocationInfo &l)
CommodityQuantityFrequency parseCommodityQuantityFrequency(const string &s)
Convert text to QuantExt::CommodityQuantityFrequency.
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
string conversion utilities