@@ -30,7 +30,7 @@ namespace data {
3030
3131 static const std::string mcscript =
3232 " REQUIRE PayoffType == 0 OR PayoffType == 1;\n "
33- " REQUIRE TransatlanticBarrierType >= 0 AND TransatlanticBarrierType <= 4 ;\n "
33+ " REQUIRE SIZE(Underlyings) == SIZE(TransatlanticBarrierType) ;\n "
3434 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierLevels) / SIZE(Underlyings);\n "
3535 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebates);\n "
3636 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebateCurrencies);\n "
@@ -90,10 +90,11 @@ namespace data {
9090 " \n "
9191 " TransatlanticActive = 1;\n "
9292 " FOR k IN (1, SIZE(Underlyings), 1) DO\n "
93- " IF { TransatlanticBarrierType == 1 AND Underlyings[k](ExpiryDate) >= TransatlanticBarrierLevel[k] } OR\n "
94- " { TransatlanticBarrierType == 2 AND Underlyings[k](ExpiryDate) <= TransatlanticBarrierLevel[k] } OR\n "
95- " { TransatlanticBarrierType == 3 AND Underlyings[k](ExpiryDate) < TransatlanticBarrierLevel[k] } OR\n "
96- " { TransatlanticBarrierType == 4 AND Underlyings[k](ExpiryDate) > TransatlanticBarrierLevel[k] } THEN\n "
93+ " REQUIRE TransatlanticBarrierType[k] >= 0 AND TransatlanticBarrierType[k] <= 4;\n "
94+ " IF { TransatlanticBarrierType[k] == 1 AND Underlyings[k](ExpiryDate) >= TransatlanticBarrierLevel[k] } OR\n "
95+ " { TransatlanticBarrierType[k] == 2 AND Underlyings[k](ExpiryDate) <= TransatlanticBarrierLevel[k] } OR\n "
96+ " { TransatlanticBarrierType[k] == 3 AND Underlyings[k](ExpiryDate) < TransatlanticBarrierLevel[k] } OR\n "
97+ " { TransatlanticBarrierType[k] == 4 AND Underlyings[k](ExpiryDate) > TransatlanticBarrierLevel[k] } THEN\n "
9798 " TransatlanticActive = 0;\n "
9899 " END;\n "
99100 " END;\n "
@@ -116,7 +117,7 @@ namespace data {
116117
117118 static const std::string fdscript =
118119 " REQUIRE PayoffType == 0 OR PayoffType == 1;\n "
119- " REQUIRE TransatlanticBarrierType >= 0 AND TransatlanticBarrierType <= 4 ;\n "
120+ " REQUIRE SIZE(Underlyings) == SIZE(TransatlanticBarrierType) ;\n "
120121 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierLevels) / SIZE(Underlyings);\n "
121122 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebates);\n "
122123 " REQUIRE SIZE(BarrierTypes) == SIZE(BarrierRebateCurrencies);\n "
@@ -135,10 +136,11 @@ namespace data {
135136 " \n "
136137 " TransatlanticActive = 1;\n "
137138 " FOR k IN (1, SIZE(Underlyings), 1) DO\n "
138- " IF { TransatlanticBarrierType == 1 AND Underlyings[k](ExpiryDate) >= TransatlanticBarrierLevel[k] } OR\n "
139- " { TransatlanticBarrierType == 2 AND Underlyings[k](ExpiryDate) <= TransatlanticBarrierLevel[k] } OR\n "
140- " { TransatlanticBarrierType == 3 AND Underlyings[k](ExpiryDate) < TransatlanticBarrierLevel[k] } OR\n "
141- " { TransatlanticBarrierType == 4 AND Underlyings[k](ExpiryDate) > TransatlanticBarrierLevel[k] } THEN\n "
139+ " REQUIRE TransatlanticBarrierType[k] >= 0 AND TransatlanticBarrierType[k] <= 4;\n "
140+ " IF { TransatlanticBarrierType[k] == 1 AND Underlyings[k](ExpiryDate) >= TransatlanticBarrierLevel[k] } OR\n "
141+ " { TransatlanticBarrierType[k] == 2 AND Underlyings[k](ExpiryDate) <= TransatlanticBarrierLevel[k] } OR\n "
142+ " { TransatlanticBarrierType[k] == 3 AND Underlyings[k](ExpiryDate) < TransatlanticBarrierLevel[k] } OR\n "
143+ " { TransatlanticBarrierType[k] == 4 AND Underlyings[k](ExpiryDate) > TransatlanticBarrierLevel[k] } THEN\n "
142144 " TransatlanticActive = 0;\n "
143145 " END;\n "
144146 " END;\n "
@@ -297,31 +299,62 @@ void GenericBarrierOption::build(const boost::shared_ptr<EngineFactory>& factory
297299 (quantity_.empty () && strike_.empty () && !amount_.empty ()),
298300 " Need no Quantity, no Strike, Amount for PayoffType = CashOrNothing" );
299301
300- std::string transatlanticBarrierType = " 0" ;
302+ std::vector<std:: string> transatlanticBarrierType (underlyings_. size (), " 0" ) ;
301303 std::vector<std::string> transatlanticBarrierLevel (underlyings_.size (), " 0" );
302304 std::string transatlanticBarrierRebate = " 0.0" ;
303305 std::string transatlanticBarrierRebateCurrency = payCurrency_;
304- if (!transatlanticBarrier_.type ().empty ()) {
305- if (transatlanticBarrier_.type () == " DownAndIn" )
306- transatlanticBarrierType = " 1" ;
307- else if (transatlanticBarrier_.type () == " UpAndIn" )
308- transatlanticBarrierType = " 2" ;
309- else if (transatlanticBarrier_.type () == " DownAndOut" )
310- transatlanticBarrierType = " 3" ;
311- else if (transatlanticBarrier_.type () == " UpAndOut" )
312- transatlanticBarrierType = " 4" ;
313- else {
314- QL_FAIL (" Transatlantic BarrierType (" << transatlanticBarrier_.type ()
315- << " ) must be DownAndIn, UpAndIn, DownAndOut, UpAndOut" );
306+ if (!transatlanticBarrier_[0 ].type ().empty ()) {
307+ transatlanticBarrierType.clear ();
308+ for (auto const & n : transatlanticBarrier_) {
309+ if (n.type () == " DownAndIn" )
310+ transatlanticBarrierType.push_back (" 1" );
311+ else if (n.type () == " UpAndIn" )
312+ transatlanticBarrierType.push_back (" 2" );
313+ else if (n.type () == " DownAndOut" )
314+ transatlanticBarrierType.push_back (" 3" );
315+ else if (n.type () == " UpAndOut" )
316+ transatlanticBarrierType.push_back (" 4" );
317+ else {
318+ QL_FAIL (" Transatlantic BarrierType (" << n.type ()
319+ << " ) must be DownAndIn, UpAndIn, DownAndOut, UpAndOut" );
320+ }
321+ }
322+ QL_REQUIRE (transatlanticBarrierType.size () == 1 || transatlanticBarrierType.size () == underlyings_.size (),
323+ " Transatlantic Barrier must have only 1 Barrier block or 1 block for each underlyings, got "
324+ << transatlanticBarrierType.size ());
325+ if (transatlanticBarrierType.size () == 1 && underlyings_.size () > 1 ) {
326+ transatlanticBarrierType.assign (underlyings_.size (), transatlanticBarrierType[0 ]);
327+ for (Size i = 0 ; i < transatlanticBarrierType.size (); i++) {
328+ std::cout << i << " : " << transatlanticBarrierType[i] << std::endl;
329+ }
330+ }
331+ for (Size i = 0 ; i < transatlanticBarrierType.size (); i++) {
332+ std::cout << i << " : " << transatlanticBarrierType[i] << std::endl;
316333 }
317- QL_REQUIRE (transatlanticBarrier_.levels ().size () == underlyings_.size (),
318- " Transatlantic Barrier must have exactly 1 level for each underlying, got " << transatlanticBarrier_.levels ().size ());
319334 transatlanticBarrierLevel.clear ();
320- for (const auto & l : transatlanticBarrier_.levels ())
321- transatlanticBarrierLevel.push_back (boost::lexical_cast<std::string>(l.value ()));
322- transatlanticBarrierRebate = boost::lexical_cast<std::string>(transatlanticBarrier_.rebate ());
323- if (!transatlanticBarrier_.rebateCurrency ().empty ())
324- transatlanticBarrierRebateCurrency = transatlanticBarrier_.rebateCurrency ();
335+ if (transatlanticBarrier_.size () == 1 ) {
336+ QL_REQUIRE (transatlanticBarrier_[0 ].levels ().size () == underlyings_.size (),
337+ " Transatlantic Barrier must have exactly 1 level for each underlying, got "
338+ << transatlanticBarrier_[0 ].levels ().size ());
339+ for (const auto & l : transatlanticBarrier_[0 ].levels ())
340+ transatlanticBarrierLevel.push_back (boost::lexical_cast<std::string>(l.value ()));
341+ } else {
342+ QL_REQUIRE (transatlanticBarrierType.size () == underlyings_.size (),
343+ " Transatlantic Barrier must have exactly 1 level for each underlying, got "
344+ << transatlanticBarrier_.size ());
345+ for (auto const & n : transatlanticBarrier_) {
346+ QL_REQUIRE (n.levels ().size () == 1 , " Number of level in each barrier block in transatlantic barriers "
347+ " must be exactly 1 if more than 1 barrier blocks are provided, got "
348+ << transatlanticBarrier_.size ());
349+ transatlanticBarrierLevel.push_back (boost::lexical_cast<std::string>(n.levels ()[0 ].value ()));
350+ }
351+ }
352+ if (transatlanticBarrier_.size () > 1 ) {
353+ std::cout << " transatlanticBarrier_[1].rebate() = " << transatlanticBarrier_[1 ].rebate () << std::endl;
354+ }
355+ transatlanticBarrierRebate = boost::lexical_cast<std::string>(transatlanticBarrier_[0 ].rebate ());
356+ if (!transatlanticBarrier_[0 ].rebateCurrency ().empty ())
357+ transatlanticBarrierRebateCurrency = transatlanticBarrier_[0 ].rebateCurrency ();
325358 }
326359 numbers_.emplace_back (" Number" , " TransatlanticBarrierType" , transatlanticBarrierType);
327360 numbers_.emplace_back (" Number" , " TransatlanticBarrierLevel" , transatlanticBarrierLevel);
@@ -553,9 +586,11 @@ void GenericBarrierOption::fromXML(XMLNode* node) {
553586
554587 auto transatlanticBarrierNode = XMLUtils::getChildNode (dataNode, " TransatlanticBarrier" );
555588 if (transatlanticBarrierNode) {
556- auto b = XMLUtils::getChildNode (transatlanticBarrierNode, " BarrierData" );
557- if (b)
558- transatlanticBarrier_.fromXML (b);
589+ auto b = XMLUtils::getChildrenNodes (transatlanticBarrierNode, " BarrierData" );
590+ for (auto const & n : b) {
591+ transatlanticBarrier_.push_back (BarrierData ());
592+ transatlanticBarrier_.back ().fromXML (n);
593+ }
559594 }
560595
561596 payCurrency_ = XMLUtils::getChildValue (dataNode, " PayCurrency" , true );
@@ -597,9 +632,11 @@ XMLNode* GenericBarrierOption::toXML(XMLDocument& doc) {
597632 XMLUtils::addChild (doc, barriers, " KikoType" , kikoType_);
598633 XMLUtils::appendNode (dataNode, barriers);
599634
600- if (!transatlanticBarrier_.type ().empty ()) {
635+ if (!transatlanticBarrier_[ 0 ] .type ().empty ()) {
601636 XMLNode* transatlanticBarrierNode = doc.allocNode (" TransatlanticBarrier" );
602- XMLUtils::appendNode (transatlanticBarrierNode, transatlanticBarrier_.toXML (doc));
637+ for (auto & n : transatlanticBarrier_) {
638+ XMLUtils::appendNode (transatlanticBarrierNode, n.toXML (doc));
639+ }
603640 XMLUtils::appendNode (dataNode, transatlanticBarrierNode);
604641 }
605642
0 commit comments