29 {
30
31 auto builder = QuantLib::ext::dynamic_pointer_cast<ScriptedTradeEngineBuilder>(factory->builder("ScriptedTrade"));
32
33
34
37
38
39
40
41
43
44
47
54 };
55
56
58 string defaultName;
59 ScriptedTradeEventData ed;
60
63 "FixedAccrualSchedule must be specified for accruing fixed coupons.");
64 }
65
66
69 ed = s.second.first;
70 defaultName = s.second.second;
71 if (defaultName.empty()) {
72 QL_REQUIRE(ed.hasData(),
"Could not find mandatory node " <<
name <<
".");
73 }
74 }
75
76
79 ed = s.second.first;
80 defaultName = s.second.second;
81 if (!defaultName.empty() && !ed.hasData()) {
82 auto defaultEventData =
schedules_.find(defaultName);
83 QL_REQUIRE(defaultEventData !=
schedules_.end(),
"Could not find node " << defaultName);
84
86 ScriptedTradeEventData newEventData;
87
89 newEventData = ScriptedTradeEventData(
name, n.schedule());
91 newEventData = ScriptedTradeEventData(
name, n.baseSchedule(), n.shift(), n.calendar(), n.convention());
92 }
94 }
95 }
96
97
99 ed = s.second.first;
102 }
103 }
104
105
107 ed = s.second.first;
110 }
111 }
112
113
116 QL_REQUIRE(u->type() == type, "All of Underlyings must be from the same asset class.");
117 }
119 auto ois = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(floatingIndex);
120
121 if (ois) {
122 DLOG(
"building WorstOfBasketSwap scripted trade wrapper using (internal) script \'Overnight\'")
123 } else {
124 DLOG(
"building WorstOfBasketSwap scripted trade wrapper using (internal) script \'Standard\'");
125 }
126
129 "KnockInDeterminationSchedule must be specified for a Bermudan knock-in.");
130 }
131
134 "FixedAccrualSchedule must be specified for accruing fixed coupons.");
135 }
136
138 QuantLib::Date newKnockInPayDate =
makeSchedule(
schedules_[
"FloatingPayDates"].first.schedule()).dates().back();
140 }
143 QuantLib::Date newInitialFixedPayDate =
makeSchedule(
schedules_[
"FloatingPayDates"].first.schedule()).dates().front();
145 }
147
148
163 if (ois)
166 if (ois)
168 "FloatingLookback (" <<
floatingLookback_ <<
") should be given with units days.");
170
171
178
179
180
181
182
183
184
185
186
187
188
190
191
193
194
195 if (type == "InterestRate") {
197 } else {
199 }
200
202
203
204
205
206 const std::string fixingScriptStandard =
207 " fixing = FloatingIndex(FloatingFixingSchedule[d-1]) + FloatingSpread;\n";
208 const std::string fixingScriptOvernight =
209 std::string(
" fixing = FWD") + (
isAveraged_ ?
"AVG" :
"COMP") + std::string(
"(FloatingIndex, FloatingPeriodSchedule[d-1], FloatingPeriodSchedule[d-1], FloatingPeriodSchedule[d], FloatingSpread, 1, FloatingLookback, FloatingRateCutoff, 0, IncludeSpread);\n");
210
211 const std::string floatingFixingScript = ois ? fixingScriptOvernight : fixingScriptStandard;
212
213
214
216
217 {"",
218 ScriptedTradeScriptData(
219 "NUMBER alive, couponAccumulation, fixing, n, indexInitial;\n"
220 "NUMBER allAssetsTriggered, indexFinal, performance, worstPerformance, d, payoff, u, knockedIn;\n"
221 "NUMBER floatingAccrualFraction, fixedAccrualFraction;\n"
222 "NUMBER lastIdx, accrualPeriodIdx, accrualFractions[SIZE(FixedTriggerLevels)], totalDays;\n"
223 "NUMBER ad, cd, dd, ed, fd;\n"
224 "\n"
225 "Option = Option + LOGPAY(LongShort * Quantity * InitialFixedRate, InitialFixedPayDate,\n"
226 " InitialFixedPayDate, Currency, 0, InitialFixedAmount);\n"
227 "\n"
228 "n = SIZE(FloatingPeriodSchedule);\n"
229 "REQUIRE n - SIZE(FloatingPayDates) <= 1;\n"
230 "REQUIRE n - SIZE(FloatingFixingSchedule) <= 1;\n"
231 "REQUIRE n - SIZE(FixedDeterminationSchedule) <= 1;\n"
232 "REQUIRE n - SIZE(KnockInDeterminationSchedule) <= 1;\n"
233 "REQUIRE n - SIZE(KnockOutDeterminationSchedule) <= 1;\n"
234 "REQUIRE n - SIZE(FixedPayDates) <= 1;\n"
235 "\n"
236 "IF SIZE(FloatingPayDates) == n THEN ad = 0; ELSE ad = -1; END;\n"
237 "IF SIZE(FixedDeterminationSchedule) == n THEN cd = 0; ELSE cd = -1; END;\n"
238 "IF SIZE(KnockInDeterminationSchedule) == n THEN dd = 0; ELSE dd = -1; END;\n"
239 "IF SIZE(KnockOutDeterminationSchedule) == n THEN ed = 0; ELSE ed = -1; END;\n"
240 "IF SIZE(FixedPayDates) == n THEN fd = 0; ELSE fd = -1; END;\n"
241 "\n"
242 "couponAccumulation = 1;\n"
243 "alive = 1;\n"
244 "IF BermudanKnockIn == 1 THEN\n"
245 " FOR d IN (1, SIZE(KnockInDeterminationSchedule), 1) DO\n"
246 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
247 " IF Underlyings[u](KnockInDeterminationSchedule[d+dd]) < KnockInLevel * InitialPrices[u] THEN\n"
248 " knockedIn = 1;\n"
249 " END;\n"
250 " END;\n"
251 " END;\n"
252 "END;\n"
253 "\n"
254 "IF AccruingFixedCoupons == 1 THEN\n"
255 " lastIdx = 1;\n"
256 " FOR d IN (1, SIZE(FixedAccrualSchedule), 1) DO \n"
257 " accrualPeriodIdx = DATEINDEX(FixedAccrualSchedule[d], FixedDeterminationSchedule, GEQ) - 1;\n"
258 " IF accrualPeriodIdx > 0 AND accrualPeriodIdx < SIZE(FixedDeterminationSchedule) THEN\n"
259 " IF lastIdx != accrualPeriodIdx THEN\n"
260 " accrualFractions[lastIdx] = accrualFractions[lastIdx] / totalDays;\n"
261 " lastIdx = accrualPeriodIdx;\n"
262 " totalDays = 1;\n"
263 " END;\n"
264 "\n"
265 " allAssetsTriggered = 1;"
266 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
267 " IF Underlyings[u](FixedAccrualSchedule[d]) < FixedTriggerLevels[accrualPeriodIdx] * InitialPrices[u] THEN\n"
268 " allAssetsTriggered = 0;\n"
269 " END;\n"
270 " END;\n"
271 " accrualFractions[accrualPeriodIdx] = accrualFractions[accrualPeriodIdx] + allAssetsTriggered;\n"
272 " totalDays = totalDays + 1;\n"
273 " IF d == SIZE(FixedAccrualSchedule) THEN\n"
274 " accrualFractions[SIZE(FixedTriggerLevels)] = accrualFractions[SIZE(FixedTriggerLevels)] / totalDays;\n"
275 " END;\n"
276 " END;\n"
277 " END;\n"
278 "END;\n"
279 "\n"
280 "FOR d IN (2, n, 1) DO\n"
281 + floatingFixingScript +
282 " floatingAccrualFraction = dcf(FloatingDayCountFraction, FloatingPeriodSchedule[d-1], FloatingPeriodSchedule[d]);\n"
283 " Option = Option + LOGPAY(-1 * LongShort * Quantity * alive * fixing * floatingAccrualFraction,\n"
284 " FloatingFixingSchedule[d-1], FloatingPayDates[d+ad], Currency, 1, FloatingLeg);\n"
285 "\n"
286 " allAssetsTriggered = 1;\n"
287 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
288 " IF Underlyings[u](FixedDeterminationSchedule[d+cd]) < FixedTriggerLevels[d-1] * InitialPrices[u] THEN\n"
289 " allAssetsTriggered = 0;\n"
290 " END;\n"
291 " END;\n"
292 " IF AccruingFixedCoupons == 1 THEN\n"
293 " fixedAccrualFraction = allAssetsTriggered * accrualFractions[d-1] + (1-allAssetsTriggered) * fixedAccrualFraction;\n"
294 " ELSE\n"
295 " fixedAccrualFraction = allAssetsTriggered + (1-allAssetsTriggered) * fixedAccrualFraction;\n"
296 " END;\n"
297 " Option = Option + LOGPAY(allAssetsTriggered * LongShort * Quantity * alive * FixedRate * couponAccumulation * fixedAccrualFraction,\n"
298 " FixedDeterminationSchedule[d+cd], FixedPayDates[d+fd], Currency, 2, FixedCouponLeg);\n"
299 " couponAccumulation = allAssetsTriggered + (1-allAssetsTriggered) * couponAccumulation;\n"
300 " IF AccumulatingFixedCoupons == 1 THEN\n"
301 " couponAccumulation = couponAccumulation + (1 - allAssetsTriggered);\n"
302 " END;\n"
303 "\n"
304 " IF d == n THEN\n"
305 " worstPerformance = 999999.9;\n"
306 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
307 " indexInitial = InitialPrices[u];\n"
308 " indexFinal = Underlyings[u](FloatingPeriodSchedule[n]);\n"
309 " performance = indexFinal / indexInitial;\n"
310 "\n"
311 " IF performance < worstPerformance THEN\n"
312 " worstPerformance = performance;\n"
313 " END;\n"
314 " END;\n"
315 "\n"
316 " IF worstPerformance < KnockInLevel THEN\n"
317 " knockedIn = 1;\n"
318 " END;\n"
319 "\n"
320 " IF worstPerformance < Strike THEN\n"
321 " payoff = worstPerformance - Strike;\n"
322 " Option = Option + LOGPAY(LongShort * Quantity * alive * payoff * knockedIn, FloatingPeriodSchedule[n],\n"
323 " KnockInPayDate, Currency, 3, EquityAmountPayoff);\n"
324 " END;\n"
325 " END;\n"
326 "\n"
327 " IF d != n THEN\n"
328 " allAssetsTriggered = 1;\n"
329 " FOR u IN (1, SIZE(Underlyings), 1) DO\n"
330 " IF Underlyings[u](KnockOutDeterminationSchedule[d+ed]) < KnockOutLevels[d-1] * InitialPrices[u] THEN\n"
331 " allAssetsTriggered = 0;\n"
332 " END;\n"
333 " END;\n"
334 " alive = alive * (1 - allAssetsTriggered);\n"
335 " END;\n"
336 "END;\n",
337
338 "Option",
339 {{"currentNotional", "Quantity"},
340 {"notionalCurrency", "Currency"}},
341 {})}};
342
343
344
345
347}
std::vector< ScriptedTradeValueTypeData > daycounters_
std::vector< ScriptedTradeEventData > events_
std::vector< ScriptedTradeValueTypeData > currencies_
std::vector< ScriptedTradeValueTypeData > numbers_
std::map< std::string, ScriptedTradeScriptData > script_
void build(const QuantLib::ext::shared_ptr< EngineFactory > &) override
map< string, pair< ScriptedTradeEventData, string > > schedules_
Position::Type parsePositionType(const std::string &s)
Convert text to QuantLib::Position::Type.
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
std::string to_string(const LocationInfo &l)
Schedule makeSchedule(const ScheduleDates &data)