Skip to content

Commit f3dea4a

Browse files
committed
QPR-11988 delegate fxkiko to genericoption for amc
1 parent 9a11a41 commit f3dea4a

6 files changed

Lines changed: 117 additions & 11 deletions

File tree

OREData/ored/portfolio/builders/fxbarrieroption.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,62 @@
1515
*/
1616

1717
#include <ored/portfolio/builders/fxbarrieroption.hpp>
18-
18+
#include <ored/portfolio/fxkikobarrieroption.hpp>
19+
#include <ored/portfolio/genericbarrieroption.hpp>
1920
namespace ore {
2021
namespace data {
22+
23+
24+
QuantLib::ext::shared_ptr<ore::data::Trade> FxBarrierOptionScriptedEngineBuilder::build(const Trade* trade, const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory){
25+
auto fxKiKoBarrierOption = dynamic_cast<const ore::data::FxKIKOBarrierOption*>(trade);
26+
27+
QL_REQUIRE(fxKiKoBarrierOption != nullptr,
28+
"FxKIKOBarrierOptionScriptedEngineBuilder: internal error, could not "
29+
"cast to ore::data::FxKIKOBarrierOption. Contact dev.");
30+
std::string indexName =
31+
fxKiKoBarrierOption->fxIndex().empty()
32+
? "GENERIC-" + fxKiKoBarrierOption->boughtCurrency() + "-" + fxKiKoBarrierOption->soldCurrency()
33+
: fxKiKoBarrierOption->fxIndex().substr(3);
34+
QuantLib::ext::shared_ptr<Underlying> underlying = QuantLib::ext::make_shared<FXUnderlying>("FX", indexName, 1.0);
35+
36+
const auto& optionData = fxKiKoBarrierOption->option();
37+
38+
std::string startDate = fxKiKoBarrierOption->startDate();
39+
std::string exerciseDate = optionData.exerciseDates().front();
40+
41+
ScheduleRules rule(startDate, exerciseDate, "1D", fxKiKoBarrierOption->calendar(), "Following", "Following", "Backward");
42+
ScheduleData barrierMonitoringDates(rule);
43+
44+
//! Empty transatlantic barrier
45+
auto transatlanticBarrier = BarrierData();
46+
//! Observation date for schedule monitoring dates only at the end
47+
48+
std::string domesticCurrency = fxKiKoBarrierOption->soldCurrency();
49+
50+
Date expiryDate = parseDate(exerciseDate);
51+
Date paymentDate = expiryDate;
52+
const QuantLib::ext::optional<OptionPaymentData>& opd = optionData.paymentData();
53+
if (opd) {
54+
if (opd->rulesBased()) {
55+
const Calendar& cal = opd->calendar();
56+
QL_REQUIRE(cal != Calendar(), "Need a non-empty calendar for rules based payment date.");
57+
paymentDate = cal.advance(expiryDate, opd->lag(), Days, opd->convention());
58+
} else {
59+
const vector<Date>& dates = opd->dates();
60+
QL_REQUIRE(dates.size() == 1, "Need exactly one payment date for cash settled European option.");
61+
paymentDate = dates[0];
62+
}
63+
QL_REQUIRE(paymentDate >= expiryDate, "Payment date must be greater than or equal to expiry date.");
64+
}
65+
auto qty = fxKiKoBarrierOption->boughtAmount();
66+
auto strike = fxKiKoBarrierOption->strike();
67+
std::vector<BarrierData> barriers = fxKiKoBarrierOption->barriers();
68+
auto barrierOption = QuantLib::ext::make_shared<GenericBarrierOption>(
69+
underlying, optionData, barriers, barrierMonitoringDates, transatlanticBarrier, domesticCurrency,
70+
to_string(paymentDate), to_string(qty), to_string(strike), "", "");
71+
72+
barrierOption->build(engineFactory);
73+
return barrierOption;
74+
}
2175
} // namespace data
2276
} // namespace ore

OREData/ored/portfolio/builders/fxbarrieroption.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#pragma once
2323

2424
#include <boost/make_shared.hpp>
25+
#include <ored/portfolio/enginefactory.hpp>
2526
#include <ored/portfolio/builders/cachingenginebuilder.hpp>
2627
#include <ored/portfolio/enginefactory.hpp>
2728
#include <ored/utilities/parsers.hpp>
@@ -123,5 +124,14 @@ class FxBarrierOptionFDEngineBuilder : public FxBarrierOptionEngineBuilder {
123124
}
124125
};
125126

127+
class FxBarrierOptionScriptedEngineBuilder : public DelegatingEngineBuilder {
128+
public:
129+
FxBarrierOptionScriptedEngineBuilder()
130+
: DelegatingEngineBuilder("ScriptedTrade", "ScriptedTrade", {"FxBarrierOption"}) {}
131+
QuantLib::ext::shared_ptr<ore::data::Trade>
132+
build(const Trade* trade, const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) override;
133+
std::string effectiveTradeType() const override { return "ScriptedTrade"; }
134+
};
135+
126136
} // namespace data
127137
} // namespace oreplus

OREData/ored/portfolio/builders/fxeuropeanbarrieroption.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,20 @@ namespace ore {
2525
namespace data {
2626

2727
QuantLib::ext::shared_ptr<ore::data::Trade>
28-
FxEuropeanBarrierOptionEngineBuilder::build(const Trade* trade,
29-
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
28+
FxEuropeanBarrierOptionScriptedEngineBuilder::build(const Trade* trade,
29+
const QuantLib::ext::shared_ptr<EngineFactory>& engineFactory) {
3030

3131
auto fxEuropeanBarrierOption = dynamic_cast<const ore::data::FxEuropeanBarrierOption*>(trade);
3232

33-
QL_REQUIRE(fxEuropeanBarrierOption != nullptr, "FxEuropeanBarrierOptionEngineBuilder: internal error, could not "
34-
"cast to ore::data::FxEuropeanBarrierOption. Contact dev.");
33+
QL_REQUIRE(fxEuropeanBarrierOption != nullptr,
34+
"FxEuropeanBarrierOptionScriptedEngineBuilder: internal error, could not "
35+
"cast to ore::data::FxEuropeanBarrierOption. Contact dev.");
3536

36-
QuantLib::ext::shared_ptr<Underlying> underlying =
37-
QuantLib::ext::make_shared<FXUnderlying>("FX", fxEuropeanBarrierOption->fxIndex(), 1.0);
37+
std::string indexName =
38+
fxEuropeanBarrierOption->fxIndex().empty()
39+
? "GENERIC-" + fxEuropeanBarrierOption->boughtCurrency() + "-" + fxEuropeanBarrierOption->soldCurrency()
40+
: fxEuropeanBarrierOption->fxIndex().substr(3);
41+
QuantLib::ext::shared_ptr<Underlying> underlying = QuantLib::ext::make_shared<FXUnderlying>("FX", indexName, 1.0);
3842

3943
const auto& optionData = fxEuropeanBarrierOption->option();
4044

OREData/ored/portfolio/builders/fxeuropeanbarrieroption.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
namespace ore {
3131
namespace data {
3232

33-
class FxEuropeanBarrierOptionEngineBuilder : public DelegatingEngineBuilder {
33+
class FxEuropeanBarrierOptionScriptedEngineBuilder : public DelegatingEngineBuilder {
3434
public:
35-
FxEuropeanBarrierOptionEngineBuilder()
35+
FxEuropeanBarrierOptionScriptedEngineBuilder()
3636
: DelegatingEngineBuilder("ScriptedTrade", "ScriptedTrade",
3737
{"FxEuropeanBarrierOption"}) {}
3838
QuantLib::ext::shared_ptr<ore::data::Trade> build(const Trade* trade,

OREData/ored/portfolio/fxkikobarrieroption.cpp

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,33 @@ void FxKIKOBarrierOption::build(const QuantLib::ext::shared_ptr<EngineFactory>&
8585
QL_REQUIRE(!barriers_[0].overrideTriggered() && !barriers_[1].overrideTriggered(),
8686
"FxKIKOBarrierOption::build(): OverrideTriggered not supported by this instrument type.");
8787

88+
QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder("FxOption");
89+
QL_REQUIRE(builder, "No FxOption builder found");
90+
QuantLib::ext::shared_ptr<FxBarrierOptionScriptedEngineBuilder> fxEuropeanBarrierOptionBuilder;
91+
try {
92+
fxEuropeanBarrierOptionBuilder = QuantLib::ext::dynamic_pointer_cast<FxBarrierOptionScriptedEngineBuilder>(
93+
engineFactory->builder(tradeType_));
94+
DLOG("FxEuropeanBarrierOptionScriptedEngineBuilder found for trade " << tradeType_);
95+
} catch (...) {
96+
// no delegating builder found
97+
}
98+
if (fxEuropeanBarrierOptionBuilder) {
99+
// We have a delegating builder for this trade
100+
auto delegatingBuilderTrade_ = fxEuropeanBarrierOptionBuilder->build(this, engineFactory);
101+
instrument_ = delegatingBuilderTrade_->instrument();
102+
maturity_ = delegatingBuilderTrade_->maturity();
103+
npvCurrency_ = delegatingBuilderTrade_->npvCurrency();
104+
additionalData_ = delegatingBuilderTrade_->additionalData();
105+
requiredFixings_ = delegatingBuilderTrade_->requiredFixings();
106+
setSensitivityTemplate(delegatingBuilderTrade_->sensitivityTemplate());
107+
addProductModelEngine(delegatingBuilderTrade_->productModelEngine());
108+
109+
// notional and notional currency are defined in overriden methods!
110+
111+
return;
112+
}
113+
114+
88115
Currency boughtCcy = parseCurrency(boughtCurrency_);
89116
Currency soldCcy = parseCurrency(soldCurrency_);
90117

@@ -208,8 +235,7 @@ void FxKIKOBarrierOption::build(const QuantLib::ext::shared_ptr<EngineFactory>&
208235
}
209236

210237
// All possible instruments require an underlying vanilla option so we set this up
211-
QuantLib::ext::shared_ptr<EngineBuilder> builder = engineFactory->builder("FxOption");
212-
QL_REQUIRE(builder, "No FxOption builder found");
238+
213239
QuantLib::ext::shared_ptr<FxEuropeanOptionEngineBuilder> fxOptBuilder =
214240
QuantLib::ext::dynamic_pointer_cast<FxEuropeanOptionEngineBuilder>(builder);
215241
vanilla->setPricingEngine(fxOptBuilder->engine(boughtCcy, soldCcy, envelope().additionalField("discount_curve", false, std::string()), expiryDate));
@@ -370,5 +396,14 @@ XMLNode* FxKIKOBarrierOption::toXML(XMLDocument& doc) const {
370396
return node;
371397
}
372398

399+
QuantLib::Real FxKIKOBarrierOption::notional() const {
400+
return delegatingBuilderTrade_ != nullptr ? delegatingBuilderTrade_->notional() : Trade::notional();
401+
}
402+
403+
string FxKIKOBarrierOption::notionalCurrency() const {
404+
return delegatingBuilderTrade_ != nullptr ? delegatingBuilderTrade_->notionalCurrency() : Trade::notionalCurrency();
405+
}
406+
407+
373408
} // namespace data
374409
} // namespace oreplus

OREData/ored/portfolio/fxkikobarrieroption.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ class FxKIKOBarrierOption : public FxSingleAssetDerivative {
6464
const string& calendar() const { return calendar_; }
6565
const string& fxIndex() const { return fxIndex_; }
6666
QuantLib::Real strike() const { return soldAmount_ / boughtAmount_; }
67+
QuantLib::Real notional() const override;
68+
string notionalCurrency() const override;
6769
//@}
6870

6971
//! \name Serialisation
@@ -79,6 +81,7 @@ class FxKIKOBarrierOption : public FxSingleAssetDerivative {
7981
string fxIndex_;
8082
QuantLib::Real boughtAmount_;
8183
QuantLib::Real soldAmount_;
84+
QuantLib::ext::shared_ptr<Trade> delegatingBuilderTrade_;
8285
};
8386
} // namespace data
8487
} // namespace oreplus

0 commit comments

Comments
 (0)