Skip to content

Commit 25fcb20

Browse files
pcaspersjenkins
authored andcommitted
QPR-12372 include settlement date flows in FX Forwards
1 parent b3c259b commit 25fcb20

19 files changed

Lines changed: 266 additions & 242 deletions

File tree

Docs/UserGuide/parameterisation/pricingengines.tex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4410,6 +4410,7 @@ \subsubsection{Product Type: FxForward}
44104410
<Engine>DiscountingFxForwardEngine</Engine>
44114411
<EngineParameters>
44124412
<Parameter name="SensitivityTemplate">FX_Analytical</Parameter>
4413+
<Parameter name="IncludeSettlementDateFlows">true</Parameter>
44134414
</EngineParameters>
44144415
</Product>
44154416
\end{minted}
@@ -4420,6 +4421,10 @@ \subsubsection{Product Type: FxForward}
44204421
CrossAssetModel/AMC builds a McCamFxForwardEngine for use in AMC simulations. We refer to the AMC module documentation
44214422
for further details.
44224423

4424+
Parameter IncludeSettlementDateFlows is set to false by default, i.e. cash flows on the maturity date of the trade are
4425+
not taken into account when pricing as of maturity date so that the trade has zero value on maturity. In case of true
4426+
we do take the final flows into account while the trade is ``maturing''.
4427+
44234428
%--------------------------------------------------------
44244429
\subsubsection{Product Type: FxOption}
44254430
%--------------------------------------------------------

Examples/Example_7/ExpectedOutput/curves.csv

Lines changed: 145 additions & 145 deletions
Large diffs are not rendered by default.
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1-
#TradeId,Type,CashflowNo,LegNo,PayDate,FlowType,Amount,Currency,Coupon,Accrual,AccrualStartDate,AccrualEndDate,AccruedAmount,fixingDate,fixingValue,Notional,DiscountFactor,PresentValue,FXRate(Local-Base),PresentValue(Base),BaseCurrency,FloorStrike,CapStrike,FloorVolatility,CapVolatility
2-
FXFWD_EURUSD_10Y,FxForward,1,0,2026-03-01,Notional,1000000.0000,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9599864296,959986.4295885050,1.0000000000,959986.4295885050,EUR,#N/A,#N/A,#N/A,#N/A
3-
FXFWD_EURUSD_10Y,FxForward,1,1,2026-03-01,Notional,-1100000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.8035576701,-883913.4370770195,0.8831293157,-780609.8688614958,EUR,#N/A,#N/A,#N/A,#N/A
1+
#TradeId,Type,CashflowNo,LegNo,PayDate,FlowType,Amount,Currency,Coupon,Accrual,AccrualStartDate,AccrualEndDate,AccruedAmount,fixingDate,fixingValue,Notional,DiscountFactor,PresentValue,FXRate(Local-Base),PresentValue(Base),BaseCurrency,FloorStrike,CapStrike,FloorVolatility,CapVolatility,EffectiveFloorVolatility,EffectiveCapVolatility
2+
FXFWD_EURUSD_10Y,FxForward,1,0,2026-03-01,Notional,1000000.0000,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.9599864296,959986.4295885050,1.0000000000,959986.4295885050,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
3+
FXFWD_EURUSD_10Y,FxForward,1,1,2026-03-01,Notional,-1100000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,0.8035576701,-883913.4370770195,0.8831293157,-780609.8688614958,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
4+
FXFWD_MATURING,FxForward,1,0,2016-02-05,Notional,1000000.0000,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,1.0000000000,1000000.0000000000,1.0000000000,1000000.0000000000,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A
5+
FXFWD_MATURING,FxForward,1,1,2016-02-05,Notional,-1100000.0000,USD,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A,1.0000000000,-1100000.0000000000,0.8831293157,-971442.2473168324,EUR,#N/A,#N/A,#N/A,#N/A,#N/A,#N/A

Examples/Example_7/ExpectedOutput/log_progress.json

Lines changed: 0 additions & 61 deletions
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#TradeId,TradeType,Maturity,MaturityTime,NPV,NpvCurrency,NPV(Base),BaseCurrency,Notional,NotionalCurrency,Notional(Base),NettingSet,CounterParty
22
FXFWD_EURUSD_10Y,FxForward,2026-03-01,10.066015,203114.716644,USD,179376.560727,EUR,1000000.00,EUR,1000000.00,CPTY_A,CPTY_A
3+
FXFWD_MATURING,FxForward,2016-02-05,0.000000,32337.000000,USD,28557.752683,EUR,1000000.00,EUR,1000000.00,CPTY_A,CPTY_A
34
FX_CALL_OPTION_EURUSD_10Y,FxOption,2026-03-01,10.066015,288852.452705,USD,255094.068908,EUR,1100000.00,USD,971442.25,CPTY_A,CPTY_A
45
FX_PUT_OPTION_EURUSD_10Y,FxOption,2026-03-01,10.066015,85737.736061,USD,75717.508181,EUR,1100000.00,USD,971442.25,CPTY_A,CPTY_A

Examples/Example_7/Input/ore.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<Parameter name="curveConfigFile">../../Input/curveconfig.xml</Parameter>
1212
<Parameter name="conventionsFile">../../Input/conventions.xml</Parameter>
1313
<Parameter name="marketConfigFile">../../Input/todaysmarket.xml</Parameter>
14-
<Parameter name="pricingEnginesFile">../../Input/pricingengine.xml</Parameter>
14+
<Parameter name="pricingEnginesFile">pricingengine.xml</Parameter>
1515
<Parameter name="portfolioFile">portfolio.xml</Parameter>
1616
<Parameter name="observationModel">Disable</Parameter>
1717
</Setup>

Examples/Example_7/Input/portfolio.xml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,19 @@
6363
<SoldAmount>1100000</SoldAmount>
6464
</FxOptionData>
6565
</Trade>
66+
<Trade id="FXFWD_MATURING">
67+
<TradeType>FxForward</TradeType>
68+
<Envelope>
69+
<CounterParty>CPTY_A</CounterParty>
70+
<NettingSetId>CPTY_A</NettingSetId>
71+
<AdditionalFields/>
72+
</Envelope>
73+
<FxForwardData>
74+
<ValueDate>2016-02-05</ValueDate>
75+
<BoughtCurrency>EUR</BoughtCurrency>
76+
<BoughtAmount>1000000</BoughtAmount>
77+
<SoldCurrency>USD</SoldCurrency>
78+
<SoldAmount>1100000</SoldAmount>
79+
</FxForwardData>
80+
</Trade>
6681
</Portfolio>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0"?>
2+
<PricingEngines>
3+
<Product type="FxForward">
4+
<Model>DiscountedCashflows</Model>
5+
<ModelParameters/>
6+
<Engine>DiscountingFxForwardEngine</Engine>
7+
<EngineParameters>
8+
<Parameter name="includeSettlementDateFlows">true</Parameter>
9+
</EngineParameters>
10+
</Product>
11+
<Product type="FxOption">
12+
<Model>GarmanKohlhagen</Model>
13+
<ModelParameters/>
14+
<Engine>AnalyticEuropeanEngine</Engine>
15+
<EngineParameters/>
16+
</Product>
17+
</PricingEngines>

OREData/ored/portfolio/builders/fxforward.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,13 @@ class FxForwardEngineBuilder : public FxForwardEngineBuilderBase {
5858
protected:
5959
virtual boost::shared_ptr<PricingEngine> engineImpl(const Currency& forCcy, const Currency& domCcy) override {
6060
string pair = keyImpl(forCcy, domCcy);
61+
string tmp = engineParameter("includeSettlementDateFlows", {}, false, "");
62+
bool includeSettlementDateFlows = tmp == "" ? false : parseBool(tmp);
6163
return boost::make_shared<QuantExt::DiscountingFxForwardEngine>(
6264
domCcy, market_->discountCurve(domCcy.code(), configuration(MarketContext::pricing)), forCcy,
6365
market_->discountCurve(forCcy.code(), configuration(MarketContext::pricing)),
64-
market_->fxRate(pair, configuration(MarketContext::pricing)));
66+
market_->fxRate(pair, configuration(MarketContext::pricing)),
67+
includeSettlementDateFlows);
6568
}
6669
};
6770

OREData/ored/portfolio/fxforward.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,11 +110,25 @@ void FxForward::build(const boost::shared_ptr<EngineFactory>& engineFactory) {
110110
DLOG("Build FxForward with maturity date " << QuantLib::io::iso_date(maturityDate) << " and pay date "
111111
<< QuantLib::io::iso_date(payDate));
112112

113+
// get pricing engine builder
114+
boost::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
115+
QL_REQUIRE(builder, "No builder found for " << tradeType_);
116+
boost::shared_ptr<FxForwardEngineBuilderBase> fxBuilder =
117+
boost::dynamic_pointer_cast<FxForwardEngineBuilderBase>(builder);
118+
119+
string tmp = fxBuilder->engineParameter("includeSettlementDateFlows", {}, false, "");
120+
includeSettlementDateFlows_ = tmp == "" ? false : parseBool(tmp);
121+
113122
boost::shared_ptr<QuantLib::Instrument> instrument =
114123
boost::make_shared<QuantExt::FxForward>(boughtAmount_, boughtCcy, soldAmount_, soldCcy, maturityDate, false,
115-
settlement_ == "Physical", payDate, payCcy, fixingDate, fxIndex);
124+
settlement_ == "Physical", payDate, payCcy, fixingDate, fxIndex,
125+
includeSettlementDateFlows_);
116126
instrument_.reset(new VanillaInstrument(instrument));
117127

128+
// set pricing engine
129+
instrument_->qlInstrument()->setPricingEngine(fxBuilder->engine(boughtCcy, soldCcy));
130+
setSensitivityTemplate(*fxBuilder);
131+
118132
npvCurrency_ = payCcy.code();
119133
notional_ = Null<Real>(); // soldAmount_;
120134
notionalCurrency_ = ""; // soldCurrency_;
@@ -126,15 +140,6 @@ void FxForward::build(const boost::shared_ptr<EngineFactory>& engineFactory) {
126140
legCurrencies_ = {boughtCurrency_, soldCurrency_};
127141
legPayers_ = {false, true};
128142

129-
// set Pricing engine
130-
boost::shared_ptr<EngineBuilder> builder = engineFactory->builder(tradeType_);
131-
QL_REQUIRE(builder, "No builder found for " << tradeType_);
132-
boost::shared_ptr<FxForwardEngineBuilderBase> fxBuilder =
133-
boost::dynamic_pointer_cast<FxForwardEngineBuilderBase>(builder);
134-
135-
instrument_->qlInstrument()->setPricingEngine(fxBuilder->engine(boughtCcy, soldCcy));
136-
setSensitivityTemplate(*fxBuilder);
137-
138143
additionalData_["soldCurrency"] = soldCurrency_;
139144
additionalData_["boughtCurrency"] = boughtCurrency_;
140145
additionalData_["soldAmount"] = soldAmount_;
@@ -150,6 +155,13 @@ void FxForward::build(const boost::shared_ptr<EngineFactory>& engineFactory) {
150155
additionalData_["settlement"] = settlement_;
151156
}
152157

158+
bool FxForward::isExpired(const Date& date) {
159+
if (includeSettlementDateFlows_)
160+
return date > maturity_;
161+
else
162+
return date >= maturity_;
163+
}
164+
153165
QuantLib::Real FxForward::notional() const {
154166
// try to get the notional from the additional results of the instrument
155167
try {

0 commit comments

Comments
 (0)