38 {
40 if (npvDate == Null<Date>()) {
42 }
44 if (settlementDate == Null<Date>()) {
45 settlementDate = npvDate;
46 }
47
48 Real tmpNominal1, tmpNominal2;
49 bool tmpPayCurrency1;
52 <<
ccy1_ <<
"," <<
ccy2_ <<
") in the engine and ("
54 << ") in the instrument");
58 } else {
60 "mismatched currency pairs (" <<
ccy1_ <<
"," <<
ccy2_ <<
") in the engine and ("
62 << ") in the instrument");
66 }
67
69 "Discounting term structure handle is empty.");
70
72 "Term structures should have the same reference date.");
73
75 "FX forward maturity should exceed or equal the "
76 "discount curve reference date.");
77
80 results_.additionalResults[
"fairForwardRate"] = tmpNominal1 / tmpNominal2;
83
84
85 bool includeSettlementDateFlows =
arguments_.includeSettlementDateFlows;
86
87 if (!detail::simple_event(
arguments_.payDate).hasOccurred(settlementDate, includeSettlementDateFlows)) {
92 Real fxfwd = disc1near / disc1far * disc2far / disc2near *
spotFX_->value();
93
94
96 bool settleCcy1 =
ccy1_ == settleCcy;
97
98 Real discNear = settleCcy1 ? disc1near : disc2near;
99 Real discFar = settleCcy1 ? disc1far : disc2far;
100 Real fx1 = settleCcy1 ? 1.0 : fxfwd;
101 Real fx2 = settleCcy1 ? 1 / fxfwd : 1.0;
102
105 "If pay date (" <<
arguments_.payDate <<
") is strictly after fixing date (" <<
arguments_.fixingDate
106 << "), an FX Index must be given for a cash-settled FX Forward.");
112 }
113
114
115 std::vector<CashFlowResults> cashFlowResults;
116 CashFlowResults cf1, cf2;
118 cf1.type = "Notional";
120 cf2.type = "Notional";
125 }
126 cf1.fixingValue = 1.0 / fx1;
127 cf2.fixingValue = 1.0 / fx2;
128 cf1.amount = (tmpPayCurrency1 ? -1.0 : 1.0) * tmpNominal1 / fx1;
129 cf2.amount = (tmpPayCurrency1 ? -1.0 : 1.0) * (-tmpNominal2 / fx2);
130 cf1.currency = settleCcy.code();
131 cf2.currency = settleCcy.code();
132 } else {
133 cf1.amount = (tmpPayCurrency1 ? -1.0 : 1.0) * tmpNominal1;
134 cf2.amount = (tmpPayCurrency1 ? -1.0 : 1.0) * (-tmpNominal2);
135 cf1.currency =
ccy1_.code();
136 cf2.currency =
ccy2_.code();
137 }
139 cf1.legNumber = 0;
140 cf2.legNumber = 1;
141 cashFlowResults.push_back(cf1);
142 cashFlowResults.push_back(cf2);
143 } else {
144 cf1.legNumber = 1;
145 cf2.legNumber = 0;
146 cashFlowResults.push_back(cf2);
147 cashFlowResults.push_back(cf1);
148 }
149 results_.additionalResults[
"cashFlowResults"] = cashFlowResults;
150
151 results_.value = (tmpPayCurrency1 ? -1.0 : 1.0) * discFar / discNear * (tmpNominal1 / fx1 - tmpNominal2 / fx2);
152
154
156 results_.additionalResults[
"fairForwardRate"] = fxfwd;
158 results_.additionalResults[
"discountFactor[1]"] = disc1far;
159 results_.additionalResults[
"discountFactor[2]"] = disc2far;
160 results_.additionalResults[
"legNPV[1]"] = (tmpPayCurrency1 ? -1.0 : 1.0) * discFar / discNear * tmpNominal1 / fx1;
161 results_.additionalResults[
"legNPV[2]"] = (tmpPayCurrency1 ? -1.0 : 1.0) * discFar / discNear * (-tmpNominal2 / fx2);
162
163
165
166 if (tmpNominal1 > tmpNominal2 * fxfwd) {
167 results_.additionalResults[
"currentNotional"] = tmpNominal1;
168 results_.additionalResults[
"notionalCurrency"] =
ccy1_.code();
169 } else {
170 results_.additionalResults[
"currentNotional"] = tmpNominal2;
171 results_.additionalResults[
"notionalCurrency"] =
ccy2_.code();
172 }
173 } else {
174
175 results_.additionalResults[
"currentNotional"] =
178 }
179 }
180
181}
const Instrument::results * results_
Swap::arguments * arguments_