Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Added base CrossCcySwap, CrossCcySwapEngine and related tests
  • Loading branch information
paolodelia99 committed Jun 13, 2025
commit af4d04446a3313501132ad696639b57bb71a7fc3
4 changes: 4 additions & 0 deletions QuantLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -912,6 +912,7 @@
<ClInclude Include="ql\instruments\cpicapfloor.hpp" />
<ClInclude Include="ql\instruments\cpiswap.hpp" />
<ClInclude Include="ql\instruments\creditdefaultswap.hpp" />
<ClInclude Include="ql\instruments\crossccyswap.hpp" />
<ClInclude Include="ql\instruments\dividendbarrieroption.hpp" />
<ClInclude Include="ql\instruments\dividendschedule.hpp" />
<ClInclude Include="ql\instruments\dividendvanillaoption.hpp" />
Expand Down Expand Up @@ -1580,6 +1581,7 @@
<ClInclude Include="ql\pricingengines\quanto\all.hpp" />
<ClInclude Include="ql\pricingengines\quanto\quantoengine.hpp" />
<ClInclude Include="ql\pricingengines\swap\all.hpp" />
<ClInclude Include="ql\pricingengines\swap\crossccyswapengine.hpp" />
<ClInclude Include="ql\pricingengines\swap\cvaswapengine.hpp" />
<ClInclude Include="ql\pricingengines\swap\discountingswapengine.hpp" />
<ClInclude Include="ql\pricingengines\swap\discretizedswap.hpp" />
Expand Down Expand Up @@ -2187,6 +2189,7 @@
<ClCompile Include="ql\instruments\cpicapfloor.cpp" />
<ClCompile Include="ql\instruments\cpiswap.cpp" />
<ClCompile Include="ql\instruments\creditdefaultswap.cpp" />
<ClCompile Include="ql\instruments\crossccyswap.cpp" />
<ClCompile Include="ql\instruments\doublebarrieroption.cpp" />
<ClCompile Include="ql\instruments\doublebarriertype.cpp" />
<ClCompile Include="ql\instruments\equitytotalreturnswap.cpp" />
Expand Down Expand Up @@ -2635,6 +2638,7 @@
<ClCompile Include="ql\pricingengines\lookback\analyticcontinuouspartialfixedlookback.cpp" />
<ClCompile Include="ql\pricingengines\lookback\analyticcontinuouspartialfloatinglookback.cpp" />
<ClCompile Include="ql\pricingengines\lookback\mclookbackengine.cpp" />
<ClInclude Include="ql\pricingengines\swap\crossccyswapengine.cpp" />
<ClCompile Include="ql\pricingengines\swap\cvaswapengine.cpp" />
<ClCompile Include="ql\pricingengines\swap\discountingswapengine.cpp" />
<ClCompile Include="ql\pricingengines\swap\discretizedswap.cpp" />
Expand Down
12 changes: 12 additions & 0 deletions QuantLib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,9 @@
<ClInclude Include="ql\instruments\creditdefaultswap.hpp">
<Filter>instruments</Filter>
</ClInclude>
<ClInclude Include="ql\instruments\crossccyswap.hpp">
<Filter>instruments</Filter>
</ClInclude>
<ClInclude Include="ql\instruments\dividendschedule.hpp">
<Filter>instruments</Filter>
</ClInclude>
Expand Down Expand Up @@ -2700,6 +2703,9 @@
<ClInclude Include="ql\pricingengines\swap\all.hpp">
<Filter>pricingengines\swap</Filter>
</ClInclude>
<ClInclude Include="ql\pricingengines\swap\crossccyswapengine.hpp">
<Filter>pricingengines\swap</Filter>
</ClInclude>
<ClInclude Include="ql\pricingengines\swap\cvaswapengine.hpp">
<Filter>pricingengines\swap</Filter>
</ClInclude>
Expand Down Expand Up @@ -4745,6 +4751,9 @@
<ClCompile Include="ql\instruments\creditdefaultswap.cpp">
<Filter>instruments</Filter>
</ClCompile>
<ClCompile Include="ql\instruments\crossccyswap.cpp">
<Filter>instruments</Filter>
</ClCompile>
<ClCompile Include="ql\instruments\europeanoption.cpp">
<Filter>instruments</Filter>
</ClCompile>
Expand Down Expand Up @@ -5975,6 +5984,9 @@
<ClCompile Include="ql\pricingengines\bond\discretizedconvertible.cpp">
<Filter>pricingengines\bond</Filter>
</ClCompile>
<ClCompile Include="ql\pricingengines\swap\crossccyswapengine.cpp">
<Filter>pricingengines\swap</Filter>
</ClCompile>
<ClCompile Include="ql\pricingengines\swap\cvaswapengine.cpp">
<Filter>pricingengines\swap</Filter>
</ClCompile>
Expand Down
4 changes: 4 additions & 0 deletions ql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ set(QL_SOURCES
instruments/cpicapfloor.cpp
instruments/cpiswap.cpp
instruments/creditdefaultswap.cpp
instruments/crossccyswap.cpp
instruments/doublebarrieroption.cpp
instruments/doublebarriertype.cpp
instruments/equitytotalreturnswap.cpp
Expand Down Expand Up @@ -723,6 +724,7 @@ set(QL_SOURCES
pricingengines/lookback/analyticcontinuouspartialfixedlookback.cpp
pricingengines/lookback/analyticcontinuouspartialfloatinglookback.cpp
pricingengines/lookback/mclookbackengine.cpp
pricingengines/swap/crossccyswapengine.cpp
pricingengines/swap/cvaswapengine.cpp
pricingengines/swap/discountingswapengine.cpp
pricingengines/swap/discretizedswap.cpp
Expand Down Expand Up @@ -1336,6 +1338,7 @@ set(QL_HEADERS
instruments/cpicapfloor.hpp
instruments/cpiswap.hpp
instruments/creditdefaultswap.hpp
instruments/crossccyswap.hpp
instruments/dividendbarrieroption.hpp
instruments/dividendschedule.hpp
instruments/dividendvanillaoption.hpp
Expand Down Expand Up @@ -1955,6 +1958,7 @@ set(QL_HEADERS
pricingengines/mclongstaffschwartzengine.hpp
pricingengines/mcsimulation.hpp
pricingengines/quanto/quantoengine.hpp
pricingengines/swap/crossccyswapengine.hpp
pricingengines/swap/cvaswapengine.hpp
pricingengines/swap/discountingswapengine.hpp
pricingengines/swap/discretizedswap.hpp
Expand Down
2 changes: 2 additions & 0 deletions ql/instruments/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ this_include_HEADERS = \
cpicapfloor.hpp \
cpiswap.hpp \
creditdefaultswap.hpp \
crossccyswap.hpp \
dividendbarrieroption.hpp \
dividendschedule.hpp \
dividendvanillaoption.hpp \
Expand Down Expand Up @@ -100,6 +101,7 @@ cpp_files = \
cpicapfloor.cpp \
cpiswap.cpp \
creditdefaultswap.cpp \
crossccyswap.cpp \
doublebarrieroption.cpp \
doublebarriertype.cpp \
equitytotalreturnswap.cpp \
Expand Down
107 changes: 107 additions & 0 deletions ql/instruments/crossccyswap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
Copyright (C) 2016 Quaternion Risk Management Ltd
All rights reserved.

This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/

QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<[email protected]>. The license is also available online at
<http://quantlib.org/license.shtml>.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/

#include <ql/instruments/crossccyswap.hpp>

namespace QuantLib {

CrossCcySwap::CrossCcySwap(const Leg& firstLeg, const Currency& firstLegCcy, const Leg& secondLeg,
const Currency& secondLegCcy)
: Swap(firstLeg, secondLeg), inCcyLegNPV_(2, 0.0), inCcyLegBPS_(2, 0.0), npvDateDiscounts_(2, 0.0) {
currencies_.resize(2);
currencies_[0] = firstLegCcy;
currencies_[1] = secondLegCcy;
}

CrossCcySwap::CrossCcySwap(const std::vector<Leg>& legs, const std::vector<bool>& payer,
const std::vector<Currency>& currencies)
: Swap(legs, payer), currencies_(currencies), inCcyLegNPV_(legs.size(), 0.0), inCcyLegBPS_(legs.size(), 0.0), npvDateDiscounts_(legs.size(), 0.0) {
QL_REQUIRE(payer.size() == currencies_.size(), "Size mismatch "
"between payer ("
<< payer.size() << ") and currencies (" << currencies_.size()
<< ")");
}

CrossCcySwap::CrossCcySwap(Size legs)
: Swap(legs), currencies_(legs), inCcyLegNPV_(legs, 0.0), inCcyLegBPS_(legs, 0.0), npvDateDiscounts_(legs, 0.0) {}

void CrossCcySwap::setupArguments(PricingEngine::arguments* args) const {

Swap::setupArguments(args);

CrossCcySwap::arguments* arguments = dynamic_cast<CrossCcySwap::arguments*>(args);
QL_REQUIRE(arguments, "The arguments are not of type "
"cross currency swap");

arguments->currencies = currencies_;
}

void CrossCcySwap::fetchResults(const PricingEngine::results* r) const {

Swap::fetchResults(r);

const CrossCcySwap::results* results = dynamic_cast<const CrossCcySwap::results*>(r);
QL_REQUIRE(results, "The results are not of type "
"cross currency swap");

if (!results->inCcyLegNPV.empty()) {
QL_REQUIRE(results->inCcyLegNPV.size() == inCcyLegNPV_.size(),
"Wrong number of in currency leg NPVs returned by engine");
inCcyLegNPV_ = results->inCcyLegNPV;
} else {
std::fill(inCcyLegNPV_.begin(), inCcyLegNPV_.end(), Null<Real>());
}

if (!results->inCcyLegBPS.empty()) {
QL_REQUIRE(results->inCcyLegBPS.size() == inCcyLegBPS_.size(),
"Wrong number of in currency leg BPSs returned by engine");
inCcyLegBPS_ = results->inCcyLegBPS;
} else {
std::fill(inCcyLegBPS_.begin(), inCcyLegBPS_.end(), Null<Real>());
}

if (!results->npvDateDiscounts.empty()) {
QL_REQUIRE(results->npvDateDiscounts.size() == npvDateDiscounts_.size(),
"Wrong number of npv date discounts returned by engine");
npvDateDiscounts_ = results->npvDateDiscounts;
} else {
std::fill(npvDateDiscounts_.begin(), npvDateDiscounts_.end(), Null<DiscountFactor>());
}
}

void CrossCcySwap::setupExpired() const {
Swap::setupExpired();
std::fill(inCcyLegBPS_.begin(), inCcyLegBPS_.end(), 0.0);
std::fill(inCcyLegNPV_.begin(), inCcyLegNPV_.end(), 0.0);
std::fill(npvDateDiscounts_.begin(), npvDateDiscounts_.end(), 0.0);
}

void CrossCcySwap::arguments::validate() const {
Swap::arguments::validate();
QL_REQUIRE(legs.size() == currencies.size(), "Number of legs is not equal to number of currencies");
}

void CrossCcySwap::results::reset() {
Swap::results::reset();
inCcyLegNPV.clear();
inCcyLegBPS.clear();
npvDateDiscounts.clear();
}
} // namespace QuantLib
147 changes: 147 additions & 0 deletions ql/instruments/crossccyswap.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
Copyright (C) 2016 Quaternion Risk Management Ltd
All rights reserved.

This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/

QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<[email protected]>. The license is also available online at
<http://quantlib.org/license.shtml>.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/

/*! \file crossccyswap.hpp
\brief Swap instrument with legs involving two currencies

\ingroup instruments
*/

#ifndef quantlib_cross_ccy_swap_hpp
#define quantlib_cross_ccy_swap_hpp

#include <ql/currency.hpp>
#include <ql/instruments/swap.hpp>

namespace QuantLib {

//! Cross currency swap
/*! The first leg holds the pay currency cashflows and second leg holds
the receive currency cashflows.

\ingroup instruments
*/
class CrossCcySwap : public QuantLib::Swap {
public:
class arguments;
class results;
class engine;
//! \name Constructors
//@{
//! Constructs a cross-currency swap with two legs and their respective currencies
/*!
First leg is paid and the second is received.

\param firstLeg The sequence of cash flows for the first leg of the swap.
\param firstLegCcy The currency in which the first leg's cash flows are denominated.
\param secondLeg The sequence of cash flows for the second leg of the swap.
\param secondLegCcy The currency in which the second leg's cash flows are denominated.

\note The notional amounts, payment schedules, and other details of each leg must be
set up in the provided Leg objects before constructing the swap.
*/
CrossCcySwap(const Leg& firstLeg, const Currency& firstLegCcy, const Leg& secondLeg, const Currency& secondLegCcy);
//! Constructs a cross-currency swap with multiple legs and their respective currencies
/*!
Initializes a cross-currency swap with an arbitrary number of legs, each specified
by a sequence of cash flows (Leg) and associated with its own currency. The payer vector
determines the direction of each leg (payer or receiver).

\param legs A vector of cash flow sequences, one for each leg of the swap.
\param payer A vector of booleans indicating the direction of each leg:
\c true for payer, \c false for receiver.
\param currencies A vector of currencies, one for each leg, specifying the currency
in which the corresponding leg's cash flows are denominated.

\note The sizes of the \p legs, \p payer, and \p currencies vectors must all be equal.
\warning The notional amounts, payment schedules, and other details of each leg must be
set up in the provided Leg objects before constructing the swap.
*/
CrossCcySwap(const std::vector<Leg>& legs, const std::vector<bool>& payer, const std::vector<Currency>& currencies);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want an arbitrary number of legs here and the complexity that follows? @pcaspers, did you ever have a use for this in the past?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I know of, but we might break our processing if we restrict the class to 2 legs now. What kind of increased complexity do you have in mind?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just that you have to loop over the legs, no big deal. Ok to have a vector.

//@}
//! \name Instrument interface
//@{
void setupArguments(PricingEngine::arguments* args) const override;
void fetchResults(const PricingEngine::results*) const override;
//@}
//! \name Additional interface
//@{
const Currency& legCurrency(Size j) const {
QL_REQUIRE(j < legs_.size(), "leg# " << j << " doesn't exist!");
return currencies_[j];
}
Real inCcyLegBPS(Size j) const {
QL_REQUIRE(j < legs_.size(), "leg# " << j << " doesn't exist!");
calculate();
return inCcyLegBPS_[j];
}
Real inCcyLegNPV(Size j) const {
QL_REQUIRE(j < legs_.size(), "leg #" << j << " doesn't exist!");
calculate();
return inCcyLegNPV_[j];
}
DiscountFactor npvDateDiscounts(Size j) const {
QL_REQUIRE(j < legs_.size(), "leg #" << j << " doesn't exist!");
calculate();
return npvDateDiscounts_[j];
}
//@}
protected:
//! \name Constructors
//@{
/*! This constructor can be used by derived classes that will
build their legs themselves.
*/
CrossCcySwap(Size legs);
//@}
//! \name Instrument interface
//@{
void setupExpired() const override;
//@}

std::vector<Currency> currencies_;

private:
mutable std::vector<Real> inCcyLegNPV_;
mutable std::vector<Real> inCcyLegBPS_;
mutable std::vector<DiscountFactor> npvDateDiscounts_;
};

//! \ingroup instruments
class CrossCcySwap::arguments : public Swap::arguments {
public:
std::vector<Currency> currencies;
void validate() const override;
};

//! \ingroup instruments
class CrossCcySwap::results : public Swap::results {
public:
std::vector<Real> inCcyLegNPV;
std::vector<Real> inCcyLegBPS;
std::vector<DiscountFactor> npvDateDiscounts;
void reset() override;
};

//! \ingroup instruments
class CrossCcySwap::engine : public GenericEngine<CrossCcySwap::arguments, CrossCcySwap::results> {};
} // namespace QuantLib

#endif
2 changes: 2 additions & 0 deletions ql/pricingengines/swap/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ AM_CPPFLAGS = -I${top_builddir} -I${top_srcdir}
this_includedir=${includedir}/${subdir}
this_include_HEADERS = \
all.hpp \
crossccyswapengine.hpp \
cvaswapengine.hpp \
discountingswapengine.hpp \
discretizedswap.hpp \
treeswapengine.hpp

cpp_files = \
crossccyswapengine.cpp \
cvaswapengine.cpp \
discountingswapengine.cpp \
discretizedswap.cpp \
Expand Down
Loading