Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Attributes | List of all members
RepresentativeFxOptionMatcher Class Reference

#include <qle/models/representativefxoption.hpp>

+ Collaboration diagram for RepresentativeFxOptionMatcher:

Public Member Functions

 RepresentativeFxOptionMatcher (const std::vector< Leg > &underlying, const std::vector< bool > &isPayer, const std::vector< std::string > &currencies, const Date &referenceDate, const std::string &forCcy, const std::string &domCcy, const Handle< YieldTermStructure > &forCurve, const Handle< YieldTermStructure > &domCurve, const Handle< Quote > &fxSpot, const bool includeRefDateFlows=false)
 
std::string currency1 () const
 
std::string currency2 () const
 
Real amount1 () const
 
Real amount2 () const
 

Private Attributes

std::string ccy1_
 
std::string ccy2_
 
Real amount1_
 
Real amount2_
 

Detailed Description

Given cashflows in two currencies and a reference date >= today, find amounts in the two currencies to be paid on the reference date such that the NPV and FX Delta of the original cashflows and the original cashflows as seen from the reference date are equal.

The output amounts have a sign, i.e. they are received if positive and paid if negative.

Definition at line 41 of file representativefxoption.hpp.

Constructor & Destructor Documentation

◆ RepresentativeFxOptionMatcher()

RepresentativeFxOptionMatcher ( const std::vector< Leg > &  underlying,
const std::vector< bool > &  isPayer,
const std::vector< std::string > &  currencies,
const Date &  referenceDate,
const std::string &  forCcy,
const std::string &  domCcy,
const Handle< YieldTermStructure > &  forCurve,
const Handle< YieldTermStructure > &  domCurve,
const Handle< Quote > &  fxSpot,
const bool  includeRefDateFlows = false 
)

Definition at line 39 of file representativefxoption.cpp.

43 {
44
45 Date today = Settings::instance().evaluationDate();
46
47 // 1 check inputs
48
49 QL_REQUIRE(referenceDate >= today, "RepresentativeFxOptionMatcher: referenceDate ("
50 << referenceDate << ") must be < today (" << today << ")");
51 QL_REQUIRE(isPayer.size() == underlying.size(), "RepresentativeFxOptionMatcher: isPayer ("
52 << isPayer.size() << ") does not match underlying ("
53 << underlying.size() << ")");
54 QL_REQUIRE(currencies.size() == underlying.size(), "RepresentativeFxOptionMatcher: currencies ("
55 << currencies.size() << ") does not match underlying ("
56 << underlying.size() << ")");
57
58 // 2a make a copy of the input fx spot that we can shift later
59
60 auto fxScenarioValue = QuantLib::ext::make_shared<SimpleQuote>(fxSpot->value());
61 Handle<Quote> fxSpotScen(fxScenarioValue);
62
63 // 2b create the inverse spot, this is convenient when we clone fx linked cashflows below
64
65 auto m = [](Real x) { return 1.0 / x; };
66 Handle<Quote> fxSpotScenInv(QuantLib::ext::make_shared<DerivedQuote<decltype(m)>>(fxSpotScen, m));
67
68 // 3 collect cashflows by their pay currencies and link them to the fx spot copy (if applicable)
69
70 Leg forCfs, domCfs;
71
72 for (Size i = 0; i < underlying.size(); ++i) {
73 // 3a check the pay ccy is one of the two currencies to be matched
74
75 QL_REQUIRE(currencies[i] == forCcy || currencies[i] == domCcy,
76 "RepresentativeFxOptionMatcher: currency at index "
77 << i << " (" << currencies[i] << ") does not match forCcy (" << forCcy << ") or domCcy ("
78 << domCcy << ")");
79
80 for (auto const& c : underlying[i]) {
81
82 // 3b skip cashflows with pay date on or
83
84 if (c->date() < referenceDate || (c->date() == referenceDate && !includeRefDateFlows))
85 continue;
86
87 // 3b check for non-supported coupon types that are linked to fx
88
89 QL_REQUIRE(!QuantLib::ext::dynamic_pointer_cast<IndexedCoupon>(c),
90 "RepresentativeFxOptionMatcher: Indexed Coupons are not supported");
91
92 QuantLib::ext::shared_ptr<CashFlow> res;
93
94 if (auto fxlinked = QuantLib::ext::dynamic_pointer_cast<FXLinked>(c)) {
95
96 // 3c clone fx linked coupons and link them to our scenario fx spot quote
97
98 std::set<std::string> ccys = {fxlinked->fxIndex()->sourceCurrency().code(),
99 fxlinked->fxIndex()->targetCurrency().code()};
100 QL_REQUIRE((ccys == std::set<std::string>{forCcy, domCcy}),
101 "RepresentativeFxOptionMatcher: FXLinked coupon ccys "
102 << fxlinked->fxIndex()->sourceCurrency().code() << ", "
103 << fxlinked->fxIndex()->targetCurrency().code()
104 << " do noth match currencies to be matched (" << forCcy << ", " << domCcy << ")");
105
106 res = QuantLib::ext::dynamic_pointer_cast<CashFlow>(fxlinked->clone(fxlinked->fxIndex()->clone(
107 fxlinked->fxIndex()->sourceCurrency().code() == forCcy ? fxSpotScen : fxSpotScenInv,
108 fxlinked->fxIndex()->sourceCurve(), fxlinked->fxIndex()->targetCurve())));
109 QL_REQUIRE(res, "RepresentativeFxOptionMatcher: internal error, cloned fx linked cashflow could not be "
110 "cast to CashFlow");
111
112 } else {
113
114 // 3d for all other coupons, just push a fixed cashflow with the amount
115
116 res = QuantLib::ext::make_shared<SimpleCashFlow>(c->amount(), c->date());
117 }
118
119 // 3e push the cashflow with the correct sign to the vector holding the flows in the its pay ccy
120
121 res = QuantLib::ext::make_shared<ScaledCashFlow>(isPayer[i] ? -1.0 : 1.0, res);
122
123 if (currencies[i] == forCcy)
124 forCfs.push_back(res);
125 else
126 domCfs.push_back(res);
127 }
128 }
129
130 // 4a determine the NPV of the collected cashflows in dom ccy and as seen from the global evaluation date
131
132 Real npv =
133 CashFlows::npv(forCfs, **forCurve, false) * fxSpotScen->value() + CashFlows::npv(domCfs, **domCurve, false);
134
135 // 4b determine the FX Delta of the collected cashflows as seen from the global evaluation date
136
137 constexpr Real relShift = 0.01;
138
139 Real baseFx = fxScenarioValue->value();
140
141 fxScenarioValue->setValue(baseFx * (1.0 + relShift));
142 Real npv_up =
143 CashFlows::npv(forCfs, **forCurve, false) * fxSpotScen->value() + CashFlows::npv(domCfs, **domCurve, false);
144
145 fxScenarioValue->setValue(baseFx * (1.0 - relShift));
146 Real npv_down =
147 CashFlows::npv(forCfs, **forCurve, false) * fxSpotScen->value() + CashFlows::npv(domCfs, **domCurve, false);
148
149 Real fxDelta = (npv_up - npv_down) / (2.0 * baseFx * relShift);
150
151 // 4c determine the amounts in for and dom ccy matching the fx delta and the npv, as seen from the global evaluation
152 // date, then compound the resulting amounts to the reference date
153
154 amount1_ = fxDelta / forCurve->discount(referenceDate);
155 amount2_ = (npv - fxDelta * baseFx) / domCurve->discount(referenceDate);
156 ccy1_ = forCcy;
157 ccy2_ = domCcy;
158}

Member Function Documentation

◆ currency1()

std::string currency1 ( ) const

Definition at line 51 of file representativefxoption.hpp.

51{ return ccy1_; }

◆ currency2()

std::string currency2 ( ) const

Definition at line 52 of file representativefxoption.hpp.

52{ return ccy2_; }

◆ amount1()

Real amount1 ( ) const

Definition at line 53 of file representativefxoption.hpp.

53{ return amount1_; }

◆ amount2()

Real amount2 ( ) const

Definition at line 54 of file representativefxoption.hpp.

54{ return amount2_; }

Member Data Documentation

◆ ccy1_

std::string ccy1_
private

Definition at line 57 of file representativefxoption.hpp.

◆ ccy2_

std::string ccy2_
private

Definition at line 57 of file representativefxoption.hpp.

◆ amount1_

Real amount1_
private

Definition at line 58 of file representativefxoption.hpp.

◆ amount2_

Real amount2_
private

Definition at line 58 of file representativefxoption.hpp.