21#include <ql/cashflows/cashflows.hpp>
22#include <ql/cashflows/cashflowvectors.hpp>
23#include <ql/cashflows/coupon.hpp>
24#include <ql/cashflows/iborcoupon.hpp>
25#include <ql/cashflows/simplecashflow.hpp>
26#include <ql/termstructures/yieldtermstructure.hpp>
45 const std::vector<Currency>& currency,
const bool isPhysicallySettled,
46 const bool isResettable)
47 : legs_(legs), payer_(legs.size(), 1.0), currency_(currency), isPhysicallySettled_(isPhysicallySettled),
48 isResettable_(isResettable), legNPV_(legs.size(), 0.0), inCcyLegNPV_(legs.size(), 0.0), legBPS_(legs.size(), 0.0),
49 inCcyLegBPS_(legs.size(), 0.0), startDiscounts_(legs.size(), 0.0), endDiscounts_(legs.size(), 0.0),
50 npvDateDiscount_(0.0) {
51 QL_REQUIRE(payer.size() ==
legs_.size(),
52 "size mismatch between payer (" << payer.size() <<
") and legs (" <<
legs_.size() <<
")");
53 QL_REQUIRE(currency.size() ==
legs_.size(),
54 "size mismatch between currency (" << currency.size() <<
") and legs (" <<
legs_.size() <<
")");
55 for (Size j = 0; j <
legs_.size(); ++j) {
58 for (Leg::iterator i =
legs_[j].begin(); i !=
legs_[j].end(); ++i)
64 for (Size j = 0; j <
legs_.size(); ++j) {
65 Leg::const_iterator i;
66 for (i =
legs_[j].begin(); i !=
legs_[j].end(); ++i)
67 if (!(*i)->hasOccurred())
74 Instrument::setupExpired();
86 QL_REQUIRE(
arguments != 0,
"wrong argument type");
96 Instrument::fetchResults(r);
99 QL_REQUIRE(
results != 0,
"wrong result type");
131 "wrong number of leg start discounts returned");
152 QL_REQUIRE(!
legs_.empty(),
"no legs given");
153 Date d = CashFlows::startDate(
legs_[0]);
154 for (Size j = 1; j <
legs_.size(); ++j)
155 d = std::min(d, CashFlows::startDate(
legs_[j]));
160 QL_REQUIRE(!
legs_.empty(),
"no legs given");
161 Date d = CashFlows::maturityDate(
legs_[0]);
162 for (Size j = 1; j <
legs_.size(); ++j)
163 d = std::max(d, CashFlows::maturityDate(
legs_[j]));
168 QL_REQUIRE(
legs.size() ==
payer.size(),
"number of legs and multipliers differ");
169 QL_REQUIRE(
currency.size() ==
legs.size(),
"number of legs and currencies differ");
173 Instrument::results::reset();
185 for (
auto& k :
leg) {
186 if (
auto lazy = ext::dynamic_pointer_cast<LazyObject>(k))
195 for (
auto& k :
leg) {
196 if (
auto lazy = ext::dynamic_pointer_cast<LazyObject>(k))
197 lazy->alwaysForwardNotifications();
200 LazyObject::alwaysForwardNotifications();
208 const Schedule& fixedSchedule, Rate fixedRate,
209 const DayCounter& fixedDayCount, Currency floatCcy,
210 Real floatNominal,
const Schedule& floatSchedule,
211 const QuantLib::ext::shared_ptr<IborIndex>& iborIndex, Rate floatSpread,
212 boost::optional<BusinessDayConvention> paymentConvention,
213 const bool isPhysicallySettled,
const bool isResettable)
219 BusinessDayConvention convention;
220 if (paymentConvention)
221 convention = *paymentConvention;
223 convention = floatSchedule.businessDayConvention();
227 payer_[0] = (payFixed ? -1 : +1);
228 legs_[0] = FixedRateLeg(fixedSchedule)
229 .withNotionals(fixedNominal)
230 .withCouponRates(fixedRate, fixedDayCount)
231 .withPaymentAdjustment(convention);
236 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
237 new SimpleCashFlow(-fixedNominal, fixedSchedule.calendar().adjust(fixedSchedule.dates().front(), convention))));
238 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
239 new SimpleCashFlow(fixedNominal, fixedSchedule.calendar().adjust(fixedSchedule.dates().back(), convention))));
243 payer_[2] = (payFixed ? +1 : -1);
244 legs_[2] = IborLeg(floatSchedule, iborIndex)
245 .withNotionals(floatNominal)
246 .withPaymentDayCounter(iborIndex->dayCounter())
247 .withPaymentAdjustment(convention)
248 .withSpreads(floatSpread);
249 for (Leg::const_iterator i =
legs_[2].begin(); i <
legs_[2].end(); ++i)
255 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
256 new SimpleCashFlow(-floatNominal, floatSchedule.calendar().adjust(floatSchedule.dates().front(), convention))));
257 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
258 new SimpleCashFlow(floatNominal, floatSchedule.calendar().adjust(floatSchedule.dates().back(), convention))));
263 const Schedule& fixedSchedule, std::vector<Rate> fixedRates,
264 const DayCounter& fixedDayCount, Currency floatCcy,
265 std::vector<Real> floatNominals,
const Schedule& floatSchedule,
266 const QuantLib::ext::shared_ptr<IborIndex>& iborIndex, std::vector<Rate> floatSpreads,
267 boost::optional<BusinessDayConvention> paymentConvention,
268 const bool isPhysicallySettled,
const bool isResettable)
274 BusinessDayConvention convention;
275 if (paymentConvention)
276 convention = *paymentConvention;
278 convention = floatSchedule.businessDayConvention();
282 payer_[0] = (payFixed ? -1 : +1);
283 legs_[0] = FixedRateLeg(fixedSchedule)
284 .withNotionals(fixedNominals)
285 .withCouponRates(fixedRates, fixedDayCount)
286 .withPaymentAdjustment(convention);
292 QuantLib::ext::shared_ptr<CashFlow>(
new SimpleCashFlow(-fixedNominals[0], fixedSchedule.dates().front())));
293 QL_REQUIRE(fixedNominals.size() < fixedSchedule.size(),
"too many fixed nominals provided");
294 for (Size i = 1; i < fixedNominals.size(); i++) {
295 Real flow = fixedNominals[i - 1] - fixedNominals[i];
296 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
297 new SimpleCashFlow(flow, fixedSchedule.calendar().adjust(fixedSchedule[i], convention))));
299 if (fixedNominals.back() > 0)
300 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
new SimpleCashFlow(
301 fixedNominals.back(), fixedSchedule.calendar().adjust(fixedSchedule.dates().back(), convention))));
305 payer_[2] = (payFixed ? +1 : -1);
306 legs_[2] = IborLeg(floatSchedule, iborIndex)
307 .withNotionals(floatNominals)
308 .withPaymentDayCounter(iborIndex->dayCounter())
309 .withPaymentAdjustment(convention)
310 .withSpreads(floatSpreads);
311 for (Leg::const_iterator i =
legs_[2].begin(); i <
legs_[2].end(); ++i)
318 QuantLib::ext::shared_ptr<CashFlow>(
new SimpleCashFlow(-floatNominals[0], floatSchedule.dates().front())));
319 QL_REQUIRE(floatNominals.size() < floatSchedule.size(),
"too many float nominals provided");
320 for (Size i = 1; i < floatNominals.size(); i++) {
321 Real flow = floatNominals[i - 1] - floatNominals[i];
322 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
323 new SimpleCashFlow(flow, floatSchedule.calendar().adjust(floatSchedule[i], convention))));
325 if (floatNominals.back() > 0)
326 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
new SimpleCashFlow(
327 floatNominals.back(), floatSchedule.calendar().adjust(floatSchedule.dates().back(), convention))));
332 std::vector<Rate> rates1,
const DayCounter& dayCount1, Currency ccy2,
333 std::vector<Real> nominals2,
const Schedule& schedule2, std::vector<Rate> rates2,
334 const DayCounter& dayCount2,
335 boost::optional<BusinessDayConvention> paymentConvention,
336 const bool isPhysicallySettled,
const bool isResettable)
342 BusinessDayConvention convention;
343 if (paymentConvention)
344 convention = *paymentConvention;
346 convention = schedule1.businessDayConvention();
350 payer_[0] = (pay1 ? -1 : +1);
351 legs_[0] = FixedRateLeg(schedule1)
352 .withNotionals(nominals1)
353 .withCouponRates(rates1, dayCount1)
354 .withPaymentAdjustment(convention);
359 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
360 new SimpleCashFlow(-nominals1[0], schedule1.calendar().adjust(schedule1.dates().front(), convention))));
361 QL_REQUIRE(nominals1.size() < schedule1.size(),
"too many fixed nominals provided, leg 1");
362 for (Size i = 1; i < nominals1.size(); i++) {
363 Real flow = nominals1[i - 1] - nominals1[i];
364 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
365 new SimpleCashFlow(flow, schedule1.calendar().adjust(schedule1[i], convention))));
367 if (nominals1.back() > 0)
368 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
369 new SimpleCashFlow(nominals1.back(), schedule1.calendar().adjust(schedule1.dates().back(), convention))));
373 payer_[2] = (pay1 ? +1 : -1);
374 legs_[2] = FixedRateLeg(schedule2)
375 .withNotionals(nominals2)
376 .withCouponRates(rates2, dayCount2)
377 .withPaymentAdjustment(convention);
382 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
383 new SimpleCashFlow(-nominals2[0], schedule2.calendar().adjust(schedule2.dates().front(), convention))));
384 QL_REQUIRE(nominals2.size() < schedule2.size(),
"too many fixed nominals provided, leg 2");
385 for (Size i = 1; i < nominals2.size(); i++) {
386 Real flow = nominals2[i - 1] - nominals2[i];
387 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
388 new SimpleCashFlow(flow, schedule2.calendar().adjust(schedule2[i], convention))));
390 if (nominals2.back() > 0)
391 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
392 new SimpleCashFlow(nominals2.back(), schedule2.calendar().adjust(schedule2.dates().back(), convention))));
397 const QuantLib::ext::shared_ptr<IborIndex>& iborIndex1, std::vector<Rate> spreads1,
398 Currency ccy2, std::vector<Real> nominals2,
const Schedule& schedule2,
399 const QuantLib::ext::shared_ptr<IborIndex>& iborIndex2, std::vector<Rate> spreads2,
400 boost::optional<BusinessDayConvention> paymentConvention,
401 const bool isPhysicallySettled,
const bool isResettable)
407 BusinessDayConvention convention;
408 if (paymentConvention)
409 convention = *paymentConvention;
411 convention = schedule1.businessDayConvention();
415 payer_[0] = (pay1 ? -1 : +1);
416 legs_[0] = IborLeg(schedule1, iborIndex1)
417 .withNotionals(nominals1)
418 .withPaymentDayCounter(iborIndex1->dayCounter())
419 .withPaymentAdjustment(convention)
420 .withSpreads(spreads1);
421 for (Leg::const_iterator i =
legs_[0].begin(); i <
legs_[0].end(); ++i)
427 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
428 new SimpleCashFlow(-nominals1[0], schedule1.calendar().adjust(schedule1.dates().front(), convention))));
429 QL_REQUIRE(nominals1.size() < schedule1.size(),
"too many float nominals provided");
430 for (Size i = 1; i < nominals1.size(); i++) {
431 Real flow = nominals1[i - 1] - nominals1[i];
432 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
433 new SimpleCashFlow(flow, schedule1.calendar().adjust(schedule1[i], convention))));
435 if (nominals1.back() > 0)
436 legs_[1].push_back(QuantLib::ext::shared_ptr<CashFlow>(
437 new SimpleCashFlow(nominals1.back(), schedule1.calendar().adjust(schedule1.dates().back(), convention))));
441 payer_[2] = (pay1 ? +1 : -1);
442 legs_[2] = IborLeg(schedule2, iborIndex2)
443 .withNotionals(nominals2)
444 .withPaymentDayCounter(iborIndex2->dayCounter())
445 .withPaymentAdjustment(convention)
446 .withSpreads(spreads2);
447 for (Leg::const_iterator i =
legs_[2].begin(); i <
legs_[2].end(); ++i)
453 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
454 new SimpleCashFlow(-nominals2[0], schedule2.calendar().adjust(schedule2.dates().front(), convention))));
455 QL_REQUIRE(nominals2.size() < schedule2.size(),
"too many float nominals provided");
456 for (Size i = 1; i < nominals2.size(); i++) {
457 Real flow = nominals2[i - 1] - nominals2[i];
458 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
459 new SimpleCashFlow(flow, schedule2.calendar().adjust(schedule2[i], convention))));
461 if (nominals2.back() > 0)
462 legs_[3].push_back(QuantLib::ext::shared_ptr<CashFlow>(
463 new SimpleCashFlow(nominals2.back(), schedule2.calendar().adjust(schedule2.dates().back(), convention))));
CrossCurrencySwap(bool payFixed, Currency fixedCcy, std::vector< Real > fixedNominals, const Schedule &fixedSchedule, std::vector< Rate > fixedRates, const DayCounter &fixedDayCount, Currency floatCcy, std::vector< Real > floatNominals, const Schedule &floatSchedule, const QuantLib::ext::shared_ptr< IborIndex > &iborIndex, std::vector< Rate > floatSpreads, boost::optional< BusinessDayConvention > paymentConvention=boost::none, const bool isPhysicallySettled=true, const bool isResettable=false)
std::vector< Currency > currency
void validate() const override
std::vector< Real > payer
std::vector< Real > legBPS
DiscountFactor npvDateDiscount
std::vector< DiscountFactor > endDiscounts
std::vector< DiscountFactor > startDiscounts
std::vector< Real > legNPV
std::vector< Real > inCcyLegNPV
std::vector< Real > inCcyLegBPS
Currency Interest Rate Swap
DiscountFactor endDiscounts(Size j) const
DiscountFactor npvDateDiscount_
std::vector< Real > inCcyLegNPV_
std::vector< Currency > currency_
void setupArguments(PricingEngine::arguments *) const override
CurrencySwap(const std::vector< Leg > &legs, const std::vector< bool > &payer, const std::vector< Currency > ¤cy, const bool isPhysicallySettled=true, const bool isResettable=false)
bool isExpired() const override
Real inCcyLegNPV(Size j) const
Real legBPS(Size j) const
void deepUpdate() override
std::vector< Real > inCcyLegBPS_
std::vector< Real > legNPV_
const Leg & leg(Size j) const
DiscountFactor npvDateDiscount() const
std::vector< Real > legBPS_
bool isPhysicallySettled_
Date maturityDate() const
std::vector< DiscountFactor > startDiscounts_
Real legNPV(Size j) const
Real inCcyLegBPS(Size j) const
void setupExpired() const override
DiscountFactor startDiscounts(Size j) const
void fetchResults(const PricingEngine::results *) const override
std::vector< DiscountFactor > endDiscounts_
void alwaysForwardNotifications() override
std::vector< Real > payer_
VanillaCrossCurrencySwap(bool payFixed, Currency fixedCcy, Real fixedNominal, const Schedule &fixedSchedule, Rate fixedRate, const DayCounter &fixedDayCount, Currency floatCcy, Real floatNominal, const Schedule &floatSchedule, const QuantLib::ext::shared_ptr< IborIndex > &iborIndex, Rate floatSpread, boost::optional< BusinessDayConvention > paymentConvention=boost::none, const bool isPhysicallySettled=true, const bool isResettable=false)
Interest rate swap with extended interface.