27#include <boost/lexical_cast.hpp>
36 QL_REQUIRE(
legData_.size() == 2,
"Expected exactly two legs, got " <<
legData_.size());
38 std::set<std::string> legTypes;
40 legTypes.insert(ld.legType());
43 QL_REQUIRE(legTypes.size() == 2 && *legTypes.begin() ==
"Fixed" && *std::next(legTypes.begin(), 1) ==
"Floating",
44 "Expected one 'Floating' and one 'Fixed' type");
49 auto floatAddData = QuantLib::ext::dynamic_pointer_cast<FloatingLegData>(floatLegData.
concreteLegData());
50 auto fixedAddData = QuantLib::ext::dynamic_pointer_cast<FixedLegData>(fixedLegData.
concreteLegData());
52 QL_REQUIRE(floatAddData,
"Internal error: could not cast to float additional data");
53 QL_REQUIRE(fixedAddData,
"Internal error: could not cast to fixed additional data");
55 QL_REQUIRE(fixedLegData.
isPayer() != floatLegData.
isPayer(),
"Expected one payer and one receiver leg");
58 numbers_.emplace_back(
"Number",
"Payer",
"-1");
60 numbers_.emplace_back(
"Number",
"Payer",
"1");
62 QL_REQUIRE(fixedLegData.
notionals().size() == 1,
63 "Expected one notional on fixed leg, got " << fixedLegData.
notionals().size());
64 QL_REQUIRE(floatLegData.
notionals().size() == 1,
65 "Expected one notional on floating leg, got " << floatLegData.
notionals().size());
66 QL_REQUIRE(QuantLib::close_enough(fixedLegData.
notionals().front(), floatLegData.
notionals().front()),
67 "Expected same notional on fixed and floating leg, got " << fixedLegData.
notionals().front() <<
" and "
70 QL_REQUIRE(fixedAddData->rates().size() == 1,
71 "Expected one rate on fixed leg, got " << fixedAddData->rates().size());
72 QL_REQUIRE(floatAddData->spreads().size() <= 1,
73 "Expected at most one spread on floating leg, got " << floatAddData->spreads().size());
74 QL_REQUIRE(floatAddData->gearings().size() <= 1,
75 "Expected at most one gearing on floating leg, got " << floatAddData->gearings().size());
77 numbers_.emplace_back(
"Number",
"Notional", std::to_string(fixedLegData.
notionals().front()));
78 numbers_.emplace_back(
"Number",
"FixedRate", std::to_string(fixedAddData->rates().front()));
79 numbers_.emplace_back(
"Number",
"FloatMargin",
80 floatAddData->spreads().empty() ?
"0.0" : std::to_string(floatAddData->spreads().front()));
81 numbers_.emplace_back(
"Number",
"FloatGearing",
82 floatAddData->gearings().empty() ?
"1.0" : std::to_string(floatAddData->gearings().front()));
85 Size fixingShift = floatAddData->fixingDays() == Null<Size>() ? index->fixingDays() : floatAddData->fixingDays();
86 std::string fixingCalendar = index->fixingCalendar().name();
87 events_.emplace_back(
"FloatFixingSchedule",
"FloatSchedule",
"-" + std::to_string(fixingShift) +
"D", fixingCalendar,
"P");
89 indices_.emplace_back(
"Index",
"FloatIndex", floatAddData->index());
91 std::string floatDayCounter =
93 std::string fixedDayCounter = fixedLegData.
dayCounter().empty() ? floatDayCounter : fixedLegData.
dayCounter();
95 daycounters_.emplace_back(
"Daycounter",
"FixedDayCounter", fixedDayCounter);
96 daycounters_.emplace_back(
"Daycounter",
"FloatDayCounter", floatDayCounter);
102 "Both legs must have the same currency, got '" << fixedLegData.
currency() <<
"' on the fixed leg and '"
103 << floatLegData.
currency() <<
"' on the floating leg.");
104 QL_REQUIRE(fixedLegData.
currency() == index->currency().code(),
105 "Leg currency '" << fixedLegData.
currency() <<
"' must match float index currency '"
106 << index->currency().code() <<
"' of index '" << index->name() <<
"'");
114 if (barrierType == QuantLib::Barrier::DownOut)
115 numbers_.emplace_back(
"Number",
"KnockOutType",
"3");
116 else if (barrierType == QuantLib::Barrier::UpOut)
117 numbers_.emplace_back(
"Number",
"KnockOutType",
"4");
119 QL_FAIL(
"Expected BarrierType 'DownAndOut' or 'UpAndOut', got '" <<
barrierData_.
type());
123 QL_REQUIRE(
barrierData_.
levels().front().value() != Null<Real>(),
"No barrier level specified.");
135 bool isIborBased = QuantLib::ext::dynamic_pointer_cast<QuantLib::OvernightIndex>(index) ==
nullptr;
142 std::string mc_script = std::string(
143 "REQUIRE KnockOutType == 3 OR KnockOutType == 4;\n"
144 "NUMBER Alive[SIZE(FloatFixingSchedule)], aliveInd, lastFixedIndex, lastFloatIndex, d, j, fix;\n"
148 "FOR d IN (1, SIZE(FloatFixingSchedule), 1) DO\n"
150 " FOR j IN (lastFixedIndex + 1, SIZE(FixedSchedule) - 1, 1) DO\n"
151 " IF FixedSchedule[j] < FloatFixingSchedule[d] OR d == SIZE(FloatFixingSchedule) THEN\n"
152 " value = value + LOGPAY( Payer * aliveInd * Notional * FixedRate * dcf( FixedDayCounter, FixedSchedule[j], FixedSchedule[j+1]),\n"
153 " FixedSchedule[j], FixedSchedule[j+1], PayCurrency, 1, FixedLegCoupon );\n"
154 " lastFixedIndex = j;\n"
158 " FOR j IN (lastFloatIndex + 1, SIZE(FloatSchedule) - 1, 1) DO\n"
159 " IF FloatSchedule[j] < FloatFixingSchedule[d] OR d == SIZE(FloatFixingSchedule) THEN\n"
160 " value = value + LOGPAY( (-Payer) * aliveInd * Notional *\n") + std::string(
162 " ( FloatGearing * FloatIndex(FloatFixingSchedule[j]) + FloatMargin)\n"
164 " FWDCOMP(FloatIndex, FloatFixingSchedule[j], FloatSchedule[j], FloatSchedule[j+1], FloatMargin, FloatGearing)\n") + std::string(
166 " * dcf( FloatDayCounter, FloatSchedule[j], FloatSchedule[j+1]),\n"
167 " FloatFixingSchedule[j], FloatSchedule[j+1], PayCurrency, 2, FloatingLegCoupon );\n"
168 " lastFloatIndex = j;\n"
172 " IF d < SIZE(FloatFixingSchedule) THEN\n"
173 " fix = FloatIndex(FloatFixingSchedule[d]);\n"
174 " IF FloatFixingSchedule[d] >= BarrierStartDate AND\n"
175 " {{KnockOutType == 3 AND fix <= KnockOutLevel} OR\n"
176 " {KnockOutType == 4 AND fix >= KnockOutLevel}} THEN\n"
179 " Alive[d] = aliveInd;\n"
187 mc_script,
"value", {{
"currentNotional",
"Notional"}, {
"notionalCurrency",
"PayCurrency"}, {
"Alive",
"Alive"}},
198 QL_REQUIRE(dataNode,
tradeType() +
"Data node not found");
const std::string & type() const
virtual void fromXML(ore::data::XMLNode *node) override
virtual ore::data::XMLNode * toXML(ore::data::XMLDocument &doc) const override
std::vector< ore::data::TradeBarrier > levels() const
const std::string & style() const
std::vector< LegData > legData_
void fromXML(XMLNode *node) override
XMLNode * toXML(XMLDocument &doc) const override
std::string barrierStartDate_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
Serializable object holding leg data.
const string & currency() const
const ScheduleData & schedule() const
const string & dayCounter() const
QuantLib::ext::shared_ptr< LegAdditionalData > concreteLegData() const
const vector< double > & notionals() const
std::vector< ScriptedTradeValueTypeData > daycounters_
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > indices_
std::vector< ScriptedTradeValueTypeData > numbers_
std::map< std::string, ScriptedTradeScriptData > script_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
virtual void fromXML(XMLNode *node) override
virtual XMLNode * toXML(XMLDocument &doc) const override
const string & tradeType() const
Small XML Document wrapper class.
XMLNode * allocNode(const string &nodeName)
util functions that wrap rapidxml
static vector< XMLNode * > getChildrenNodes(XMLNode *node, const string &name)
Returns all the children with a given name.
static string getChildValue(XMLNode *node, const string &name, bool mandatory=false, const string &defaultValue=string())
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)
QuantLib::ext::shared_ptr< IborIndex > parseIborIndex(const string &s, const Handle< YieldTermStructure > &h)
Convert std::string to QuantLib::IborIndex.
Barrier::Type parseBarrierType(const std::string &s)
Convert std::string to QuantLib::BarrierType.
knock out swap wrapper for scripted trade
leg data model and serialization
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
string conversion utilities