1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*!
4Copyright (C) 2009 Mark Joshi
5
6This file is part of QuantLib, a free-software/open-source library
7for financial quantitative analysts and developers - http://quantlib.org/
8
9QuantLib is free software: you can redistribute it and/or modify it
10under the terms of the QuantLib license. You should have received a
11copy of the license along with this program; if not, please email
12<quantlib-dev@lists.sf.net>. The license is also available online at
13<http://quantlib.org/license.shtml>.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/qldefines.hpp>
21#if !defined(BOOST_ALL_NO_LIB) && defined(BOOST_MSVC)
22# include <ql/auto_link.hpp>
23#endif
24#include <ql/models/marketmodels/marketmodel.hpp>
25#include <ql/models/marketmodels/accountingengine.hpp>
26#include <ql/models/marketmodels/pathwiseaccountingengine.hpp>
27#include <ql/models/marketmodels/products/multiproductcomposite.hpp>
28#include <ql/models/marketmodels/products/multistep/multistepswap.hpp>
29#include <ql/models/marketmodels/products/multistep/callspecifiedmultiproduct.hpp>
30#include <ql/models/marketmodels/products/multistep/exerciseadapter.hpp>
31#include <ql/models/marketmodels/products/multistep/multistepnothing.hpp>
32#include <ql/models/marketmodels/products/multistep/multistepinversefloater.hpp>
33#include <ql/models/marketmodels/products/pathwise/pathwiseproductswap.hpp>
34#include <ql/models/marketmodels/products/pathwise/pathwiseproductinversefloater.hpp>
35#include <ql/models/marketmodels/products/pathwise/pathwiseproductcallspecified.hpp>
36#include <ql/models/marketmodels/models/flatvol.hpp>
37#include <ql/models/marketmodels/callability/swapratetrigger.hpp>
38#include <ql/models/marketmodels/callability/swapbasissystem.hpp>
39#include <ql/models/marketmodels/callability/swapforwardbasissystem.hpp>
40#include <ql/models/marketmodels/callability/nothingexercisevalue.hpp>
41#include <ql/models/marketmodels/callability/collectnodedata.hpp>
42#include <ql/models/marketmodels/callability/lsstrategy.hpp>
43#include <ql/models/marketmodels/callability/upperboundengine.hpp>
44#include <ql/models/marketmodels/correlations/expcorrelations.hpp>
45#include <ql/models/marketmodels/browniangenerators/mtbrowniangenerator.hpp>
46#include <ql/models/marketmodels/browniangenerators/sobolbrowniangenerator.hpp>
47#include <ql/models/marketmodels/evolvers/lognormalfwdratepc.hpp>
48#include <ql/models/marketmodels/evolvers/lognormalfwdrateeuler.hpp>
49#include <ql/models/marketmodels/pathwisegreeks/bumpinstrumentjacobian.hpp>
50#include <ql/models/marketmodels/utilities.hpp>
51#include <ql/methods/montecarlo/genericlsregression.hpp>
52#include <ql/legacy/libormarketmodels/lmlinexpcorrmodel.hpp>
53#include <ql/legacy/libormarketmodels/lmextlinexpvolmodel.hpp>
54#include <ql/time/schedule.hpp>
55#include <ql/time/calendars/nullcalendar.hpp>
56#include <ql/time/daycounters/simpledaycounter.hpp>
57#include <ql/pricingengines/blackformula.hpp>
58#include <ql/pricingengines/blackcalculator.hpp>
59#include <ql/utilities/dataformatters.hpp>
60#include <ql/math/integrals/segmentintegral.hpp>
61#include <ql/math/statistics/convergencestatistics.hpp>
62#include <ql/termstructures/volatility/abcd.hpp>
63#include <ql/termstructures/volatility/abcdcalibration.hpp>
64#include <ql/math/optimization/simplex.hpp>
65#include <ql/quotes/simplequote.hpp>
66#include <sstream>
67#include <iostream>
68#include <ctime>
69
70using namespace QuantLib;
71
72std::vector<std::vector<Matrix>>
73theVegaBumps(bool factorwiseBumping, const ext::shared_ptr<MarketModel>& marketModel, bool doCaps) {
74 Real multiplierCutOff = 50.0;
75 Real projectionTolerance = 1E-4;
76 Size numberRates= marketModel->numberOfRates();
77
78 std::vector<VolatilityBumpInstrumentJacobian::Cap> caps;
79
80 if (doCaps)
81 {
82
83 Rate capStrike = marketModel->initialRates()[0];
84
85 for (Size i=0; i< numberRates-1; i=i+1)
86 {
87 VolatilityBumpInstrumentJacobian::Cap nextCap;
88 nextCap.startIndex_ = i;
89 nextCap.endIndex_ = i+1;
90 nextCap.strike_ = capStrike;
91 caps.push_back(x: nextCap);
92 }
93
94
95 }
96
97
98
99 std::vector<VolatilityBumpInstrumentJacobian::Swaption> swaptions(numberRates);
100
101 for (Size i=0; i < numberRates; ++i)
102 {
103 swaptions[i].startIndex_ = i;
104 swaptions[i].endIndex_ = numberRates;
105
106 }
107
108 VegaBumpCollection possibleBumps(marketModel,
109 factorwiseBumping);
110
111 OrthogonalizedBumpFinder bumpFinder(possibleBumps,
112 swaptions,
113 caps,
114 multiplierCutOff, // if vector length grows by more than this discard
115 projectionTolerance); // if vector projection before scaling less than this discard
116
117 std::vector<std::vector<Matrix>> theBumps;
118
119 bumpFinder.GetVegaBumps(theBumps);
120
121 return theBumps;
122
123}
124
125
126
127int Bermudan()
128{
129
130 Size numberRates =20;
131 Real accrual = 0.5;
132 Real firstTime = 0.5;
133
134
135 std::vector<Real> rateTimes(numberRates+1);
136 for (Size i=0; i < rateTimes.size(); ++i)
137 rateTimes[i] = firstTime + i*accrual;
138
139 std::vector<Real> paymentTimes(numberRates);
140 std::vector<Real> accruals(numberRates,accrual);
141 for (Size i=0; i < paymentTimes.size(); ++i)
142 paymentTimes[i] = firstTime + (i+1)*accrual;
143
144
145
146
147 Real fixedRate = 0.05;
148 std::vector<Real> strikes(numberRates,fixedRate);
149 Real receive = -1.0;
150
151 // 0. a payer swap
152 MultiStepSwap payerSwap(rateTimes, accruals, accruals, paymentTimes,
153 fixedRate, true);
154
155 // 1. the equivalent receiver swap
156 MultiStepSwap receiverSwap(rateTimes, accruals, accruals, paymentTimes,
157 fixedRate, false);
158
159 //exercise schedule, we can exercise on any rate time except the last one
160 std::vector<Rate> exerciseTimes(rateTimes);
161 exerciseTimes.pop_back();
162
163 // naive exercise strategy, exercise above a trigger level
164 std::vector<Rate> swapTriggers(exerciseTimes.size(), fixedRate);
165 SwapRateTrigger naifStrategy(rateTimes, swapTriggers, exerciseTimes);
166
167 // Longstaff-Schwartz exercise strategy
168 std::vector<std::vector<NodeData>> collectedData;
169 std::vector<std::vector<Real>> basisCoefficients;
170
171 // control that does nothing, need it because some control is expected
172 NothingExerciseValue control(rateTimes);
173
174// SwapForwardBasisSystem basisSystem(rateTimes,exerciseTimes);
175 SwapBasisSystem basisSystem(rateTimes,exerciseTimes);
176
177
178
179 // rebate that does nothing, need it because some rebate is expected
180 // when you break a swap nothing happens.
181 NothingExerciseValue nullRebate(rateTimes);
182
183 CallSpecifiedMultiProduct dummyProduct =
184 CallSpecifiedMultiProduct(receiverSwap, naifStrategy,
185 ExerciseAdapter(nullRebate));
186
187 const EvolutionDescription& evolution = dummyProduct.evolution();
188
189
190 // parameters for models
191
192
193 Size seed = 12332; // for Sobol generator
194 Size trainingPaths = 65536;
195 Size paths = 16384;
196 Size vegaPaths = 16384*64;
197
198 std::cout << "training paths, " << trainingPaths << "\n";
199 std::cout << "paths, " << paths << "\n";
200 std::cout << "vega Paths, " << vegaPaths << "\n";
201#ifdef _DEBUG
202 trainingPaths = 512;
203 paths = 1024;
204 vegaPaths = 1024;
205#endif
206
207
208 // set up a calibration, this would typically be done by using a calibrator
209
210
211
212 Real rateLevel =0.05;
213
214
215 Real initialNumeraireValue = 0.95;
216
217 Real volLevel = 0.11;
218 Real beta = 0.2;
219 Real gamma = 1.0;
220 Size numberOfFactors = std::min<Size>(a: 5,b: numberRates);
221
222 Spread displacementLevel =0.02;
223
224 // set up vectors
225 std::vector<Rate> initialRates(numberRates,rateLevel);
226 std::vector<Volatility> volatilities(numberRates, volLevel);
227 std::vector<Spread> displacements(numberRates, displacementLevel);
228
229 ExponentialForwardCorrelation correlations(
230 rateTimes,volLevel, beta,gamma);
231
232
233
234
235 FlatVol calibration(
236 volatilities,
237 ext::make_shared<ExponentialForwardCorrelation>(args&: correlations),
238 evolution,
239 numberOfFactors,
240 initialRates,
241 displacements);
242
243 auto marketModel = ext::make_shared<FlatVol>(args&: calibration);
244
245 // we use a factory since there is data that will only be known later
246 SobolBrownianGeneratorFactory generatorFactory(
247 SobolBrownianGenerator::Diagonal, seed);
248
249 std::vector<Size> numeraires( moneyMarketMeasure(evolution));
250
251 // the evolver will actually evolve the rates
252 LogNormalFwdRatePc evolver(marketModel,
253 generatorFactory,
254 numeraires // numeraires for each step
255 );
256
257 auto evolverPtr = ext::make_shared<LogNormalFwdRatePc>(args&: evolver);
258
259 int t1= clock();
260
261 // gather data before computing exercise strategy
262 collectNodeData(evolver,
263 product&: receiverSwap,
264 dataProvider&: basisSystem,
265 rebate&: nullRebate,
266 control,
267 numberOfPaths: trainingPaths,
268 collectedData);
269
270 int t2 = clock();
271
272
273 // calculate the exercise strategy's coefficients
274 genericLongstaffSchwartzRegression(simulationData&: collectedData,
275 basisCoefficients);
276
277
278 // turn the coefficients into an exercise strategy
279 LongstaffSchwartzExerciseStrategy exerciseStrategy(
280 basisSystem, basisCoefficients,
281 evolution, numeraires,
282 nullRebate, control);
283
284 // bermudan swaption to enter into the payer swap
285 CallSpecifiedMultiProduct bermudanProduct =
286 CallSpecifiedMultiProduct(
287 MultiStepNothing(evolution),
288 exerciseStrategy, payerSwap);
289
290 // callable receiver swap
291 CallSpecifiedMultiProduct callableProduct =
292 CallSpecifiedMultiProduct(
293 receiverSwap, exerciseStrategy,
294 ExerciseAdapter(nullRebate));
295
296 // lower bound: evolve all 4 products togheter
297 MultiProductComposite allProducts;
298 allProducts.add(payerSwap);
299 allProducts.add(receiverSwap);
300 allProducts.add(bermudanProduct);
301 allProducts.add(callableProduct);
302 allProducts.finalize();
303
304 AccountingEngine accounter(evolverPtr,
305 Clone<MarketModelMultiProduct>(allProducts),
306 initialNumeraireValue);
307
308 SequenceStatisticsInc stats;
309
310 accounter.multiplePathValues (stats,numberOfPaths: paths);
311
312 int t3 = clock();
313
314 std::vector<Real> means(stats.mean());
315
316 for (Real mean : means)
317 std::cout << mean << "\n";
318
319 std::cout << " time to build strategy, " << (t2-t1)/static_cast<Real>(CLOCKS_PER_SEC)<< ", seconds.\n";
320 std::cout << " time to price, " << (t3-t2)/static_cast<Real>(CLOCKS_PER_SEC)<< ", seconds.\n";
321
322 // vegas
323
324 // do it twice once with factorwise bumping, once without
325 Size pathsToDoVegas = vegaPaths;
326
327 for (Size i=0; i < 4; ++i)
328 {
329
330 bool allowFactorwiseBumping = i % 2 > 0 ;
331
332 bool doCaps = i / 2 > 0 ;
333
334
335
336
337
338 LogNormalFwdRateEuler evolverEuler(marketModel,
339 generatorFactory,
340 numeraires
341 ) ;
342
343 MarketModelPathwiseSwap receiverPathwiseSwap( rateTimes,
344 accruals,
345 strikes,
346 receive);
347 Clone<MarketModelPathwiseMultiProduct> receiverPathwiseSwapPtr(receiverPathwiseSwap.clone());
348
349 // callable receiver swap
350 CallSpecifiedPathwiseMultiProduct callableProductPathwise(receiverPathwiseSwapPtr,
351 exerciseStrategy);
352
353 Clone<MarketModelPathwiseMultiProduct> callableProductPathwisePtr(callableProductPathwise.clone());
354
355
356 std::vector<std::vector<Matrix>> theBumps(theVegaBumps(factorwiseBumping: allowFactorwiseBumping,
357 marketModel,
358 doCaps));
359
360 PathwiseVegasOuterAccountingEngine
361 accountingEngineVegas(ext::make_shared<LogNormalFwdRateEuler>(args&: evolverEuler),
362 callableProductPathwisePtr,
363 marketModel,
364 theBumps,
365 initialNumeraireValue);
366
367 std::vector<Real> values,errors;
368
369 accountingEngineVegas.multiplePathValues(means&: values,errors,numberOfPaths: pathsToDoVegas);
370
371
372 std::cout << "vega output \n";
373 std::cout << " factorwise bumping " << allowFactorwiseBumping << "\n";
374 std::cout << " doCaps " << doCaps << "\n";
375
376
377
378 Size r=0;
379
380 std::cout << " price estimate, " << values[r++] << "\n";
381
382 for (Size i=0; i < numberRates; ++i, ++r)
383 std::cout << " Delta, " << i << ", " << values[r] << ", " << errors[r] << "\n";
384
385 Real totalVega = 0.0;
386
387 for (; r < values.size(); ++r)
388 {
389 std::cout << " vega, " << r - 1 - numberRates<< ", " << values[r] << " ," << errors[r] << "\n";
390 totalVega += values[r];
391 }
392
393 std::cout << " total Vega, " << totalVega << "\n";
394 }
395
396 // upper bound
397
398 MTBrownianGeneratorFactory uFactory(seed+142);
399
400 auto upperEvolver = ext::make_shared<LogNormalFwdRatePc>(args: ext::make_shared<FlatVol>(args&: calibration),
401 args&: uFactory,
402 args&: numeraires // numeraires for each step
403 );
404
405 std::vector<ext::shared_ptr<MarketModelEvolver>> innerEvolvers;
406
407 std::valarray<bool> isExerciseTime = isInSubset(set: evolution.evolutionTimes(), subset: exerciseStrategy.exerciseTimes());
408
409 for (Size s=0; s < isExerciseTime.size(); ++s)
410 {
411 if (isExerciseTime[s])
412 {
413 MTBrownianGeneratorFactory iFactory(seed+s);
414 auto e = ext::make_shared<LogNormalFwdRatePc>(args: ext::make_shared<FlatVol>(args&: calibration),
415 args&: uFactory,
416 args&: numeraires, // numeraires for each step
417 args&: s);
418
419 innerEvolvers.push_back(x: e);
420 }
421 }
422
423
424
425 UpperBoundEngine uEngine(upperEvolver, // does outer paths
426 innerEvolvers, // for sub-simulations that do continuation values
427 receiverSwap,
428 nullRebate,
429 receiverSwap,
430 nullRebate,
431 exerciseStrategy,
432 initialNumeraireValue);
433
434 Statistics uStats;
435 Size innerPaths = 255;
436 Size outerPaths =256;
437
438 int t4 = clock();
439
440 uEngine.multiplePathValues(stats&: uStats,outerPaths,innerPaths);
441 Real upperBound = uStats.mean();
442 Real upperSE = uStats.errorEstimate();
443
444 int t5=clock();
445
446 std::cout << " Upper - lower is, " << upperBound << ", with standard error " << upperSE << "\n";
447 std::cout << " time to compute upper bound is, " << (t5-t4)/static_cast<Real>(CLOCKS_PER_SEC) << ", seconds.\n";
448
449 return 0;
450}
451
452int InverseFloater(Real rateLevel)
453{
454
455 Size numberRates =20;
456 Real accrual = 0.5;
457 Real firstTime = 0.5;
458
459 Real strike =0.15;
460 Real fixedMultiplier = 2.0;
461 Real floatingSpread =0.0;
462 bool payer = true;
463
464
465 std::vector<Real> rateTimes(numberRates+1);
466 for (Size i=0; i < rateTimes.size(); ++i)
467 rateTimes[i] = firstTime + i*accrual;
468
469 std::vector<Real> paymentTimes(numberRates);
470 std::vector<Real> accruals(numberRates,accrual);
471 std::vector<Real> fixedStrikes(numberRates,strike);
472 std::vector<Real> floatingSpreads(numberRates,floatingSpread);
473 std::vector<Real> fixedMultipliers(numberRates,fixedMultiplier);
474
475 for (Size i=0; i < paymentTimes.size(); ++i)
476 paymentTimes[i] = firstTime + (i+1)*accrual;
477
478 MultiStepInverseFloater inverseFloater(
479 rateTimes,
480 accruals,
481 accruals,
482 fixedStrikes,
483 fixedMultipliers,
484 floatingSpreads,
485 paymentTimes,
486 payer);
487
488
489
490
491 //exercise schedule, we can exercise on any rate time except the last one
492 std::vector<Rate> exerciseTimes(rateTimes);
493 exerciseTimes.pop_back();
494
495 // naive exercise strategy, exercise above a trigger level
496 Real trigger =0.05;
497 std::vector<Rate> swapTriggers(exerciseTimes.size(), trigger);
498 SwapRateTrigger naifStrategy(rateTimes, swapTriggers, exerciseTimes);
499
500 // Longstaff-Schwartz exercise strategy
501 std::vector<std::vector<NodeData>> collectedData;
502 std::vector<std::vector<Real>> basisCoefficients;
503
504 // control that does nothing, need it because some control is expected
505 NothingExerciseValue control(rateTimes);
506
507 SwapForwardBasisSystem basisSystem(rateTimes,exerciseTimes);
508// SwapBasisSystem basisSystem(rateTimes,exerciseTimes);
509
510
511
512 // rebate that does nothing, need it because some rebate is expected
513 // when you break a swap nothing happens.
514 NothingExerciseValue nullRebate(rateTimes);
515
516 CallSpecifiedMultiProduct dummyProduct =
517 CallSpecifiedMultiProduct(inverseFloater, naifStrategy,
518 ExerciseAdapter(nullRebate));
519
520 const EvolutionDescription& evolution = dummyProduct.evolution();
521
522
523 // parameters for models
524
525
526 Size seed = 12332; // for Sobol generator
527 Size trainingPaths = 65536;
528 Size paths = 65536;
529 Size vegaPaths =16384;
530
531#ifdef _DEBUG
532 trainingPaths = 8192;
533 paths = 8192;
534 vegaPaths = 1024;
535#endif
536
537
538 std::cout << " inverse floater \n";
539 std::cout << " fixed strikes : " << strike << "\n";
540 std::cout << " number rates : " << numberRates << "\n";
541
542 std::cout << "training paths, " << trainingPaths << "\n";
543 std::cout << "paths, " << paths << "\n";
544 std::cout << "vega Paths, " << vegaPaths << "\n";
545
546
547 // set up a calibration, this would typically be done by using a calibrator
548
549
550
551 //Real rateLevel =0.08;
552
553 std::cout << " rate level " << rateLevel << "\n";
554
555 Real initialNumeraireValue = 0.95;
556
557 Real volLevel = 0.11;
558 Real beta = 0.2;
559 Real gamma = 1.0;
560 Size numberOfFactors = std::min<Size>(a: 5,b: numberRates);
561
562 Spread displacementLevel =0.02;
563
564 // set up vectors
565 std::vector<Rate> initialRates(numberRates,rateLevel);
566 std::vector<Volatility> volatilities(numberRates, volLevel);
567 std::vector<Spread> displacements(numberRates, displacementLevel);
568
569 ExponentialForwardCorrelation correlations(
570 rateTimes,volLevel, beta,gamma);
571
572
573
574
575 FlatVol calibration(
576 volatilities,
577 ext::make_shared<ExponentialForwardCorrelation>(args&: correlations),
578 evolution,
579 numberOfFactors,
580 initialRates,
581 displacements);
582
583 auto marketModel = ext::make_shared<FlatVol>(args&: calibration);
584
585 // we use a factory since there is data that will only be known later
586 SobolBrownianGeneratorFactory generatorFactory(
587 SobolBrownianGenerator::Diagonal, seed);
588
589 std::vector<Size> numeraires( moneyMarketMeasure(evolution));
590
591 // the evolver will actually evolve the rates
592 LogNormalFwdRatePc evolver(marketModel,
593 generatorFactory,
594 numeraires // numeraires for each step
595 );
596
597 auto evolverPtr = ext::make_shared<LogNormalFwdRatePc>(args&: evolver);
598
599 int t1= clock();
600
601 // gather data before computing exercise strategy
602 collectNodeData(evolver,
603 product&: inverseFloater,
604 dataProvider&: basisSystem,
605 rebate&: nullRebate,
606 control,
607 numberOfPaths: trainingPaths,
608 collectedData);
609
610 int t2 = clock();
611
612
613 // calculate the exercise strategy's coefficients
614 genericLongstaffSchwartzRegression(simulationData&: collectedData,
615 basisCoefficients);
616
617
618 // turn the coefficients into an exercise strategy
619 LongstaffSchwartzExerciseStrategy exerciseStrategy(
620 basisSystem, basisCoefficients,
621 evolution, numeraires,
622 nullRebate, control);
623
624
625 // callable receiver swap
626 CallSpecifiedMultiProduct callableProduct =
627 CallSpecifiedMultiProduct(
628 inverseFloater, exerciseStrategy,
629 ExerciseAdapter(nullRebate));
630
631 MultiProductComposite allProducts;
632 allProducts.add(inverseFloater);
633 allProducts.add(callableProduct);
634 allProducts.finalize();
635
636
637 AccountingEngine accounter(evolverPtr,
638 Clone<MarketModelMultiProduct>(allProducts),
639 initialNumeraireValue);
640
641 SequenceStatisticsInc stats;
642
643 accounter.multiplePathValues (stats,numberOfPaths: paths);
644
645 int t3 = clock();
646
647 std::vector<Real> means(stats.mean());
648
649 for (Real mean : means)
650 std::cout << mean << "\n";
651
652 std::cout << " time to build strategy, " << (t2-t1)/static_cast<Real>(CLOCKS_PER_SEC)<< ", seconds.\n";
653 std::cout << " time to price, " << (t3-t2)/static_cast<Real>(CLOCKS_PER_SEC)<< ", seconds.\n";
654
655 // vegas
656
657 // do it twice once with factorwise bumping, once without
658 Size pathsToDoVegas = vegaPaths;
659
660 for (Size i=0; i < 4; ++i)
661 {
662
663 bool allowFactorwiseBumping = i % 2 > 0 ;
664
665 bool doCaps = i / 2 > 0 ;
666
667
668 LogNormalFwdRateEuler evolverEuler(marketModel,
669 generatorFactory,
670 numeraires
671 ) ;
672
673 MarketModelPathwiseInverseFloater pathwiseInverseFloater(
674 rateTimes,
675 accruals,
676 accruals,
677 fixedStrikes,
678 fixedMultipliers,
679 floatingSpreads,
680 paymentTimes,
681 payer);
682
683 Clone<MarketModelPathwiseMultiProduct> pathwiseInverseFloaterPtr(pathwiseInverseFloater.clone());
684
685 // callable inverse floater
686 CallSpecifiedPathwiseMultiProduct callableProductPathwise(pathwiseInverseFloaterPtr,
687 exerciseStrategy);
688
689 Clone<MarketModelPathwiseMultiProduct> callableProductPathwisePtr(callableProductPathwise.clone());
690
691
692 std::vector<std::vector<Matrix>> theBumps(theVegaBumps(factorwiseBumping: allowFactorwiseBumping,
693 marketModel,
694 doCaps));
695
696 PathwiseVegasOuterAccountingEngine
697 accountingEngineVegas(ext::make_shared<LogNormalFwdRateEuler>(args&: evolverEuler),
698 // pathwiseInverseFloaterPtr,
699 callableProductPathwisePtr,
700 marketModel,
701 theBumps,
702 initialNumeraireValue);
703
704 std::vector<Real> values,errors;
705
706 accountingEngineVegas.multiplePathValues(means&: values,errors,numberOfPaths: pathsToDoVegas);
707
708
709 std::cout << "vega output \n";
710 std::cout << " factorwise bumping " << allowFactorwiseBumping << "\n";
711 std::cout << " doCaps " << doCaps << "\n";
712
713
714
715 Size r=0;
716
717 std::cout << " price estimate, " << values[r++] << "\n";
718
719 for (Size i=0; i < numberRates; ++i, ++r)
720 std::cout << " Delta, " << i << ", " << values[r] << ", " << errors[r] << "\n";
721
722 Real totalVega = 0.0;
723
724 for (; r < values.size(); ++r)
725 {
726 std::cout << " vega, " << r - 1 - numberRates<< ", " << values[r] << " ," << errors[r] << "\n";
727 totalVega += values[r];
728 }
729
730 std::cout << " total Vega, " << totalVega << "\n";
731 }
732
733 // upper bound
734
735 MTBrownianGeneratorFactory uFactory(seed+142);
736
737
738 auto upperEvolver = ext::make_shared<LogNormalFwdRatePc>(args: ext::make_shared<FlatVol>(args&: calibration),
739 args&: uFactory,
740 args&: numeraires // numeraires for each step
741 );
742
743 std::vector<ext::shared_ptr<MarketModelEvolver>> innerEvolvers;
744
745 std::valarray<bool> isExerciseTime = isInSubset(set: evolution.evolutionTimes(), subset: exerciseStrategy.exerciseTimes());
746
747 for (Size s=0; s < isExerciseTime.size(); ++s)
748 {
749 if (isExerciseTime[s])
750 {
751 MTBrownianGeneratorFactory iFactory(seed+s);
752 auto e = ext::make_shared<LogNormalFwdRatePc>(args: ext::make_shared<FlatVol>(args&: calibration),
753 args&: uFactory,
754 args&: numeraires , // numeraires for each step
755 args&: s);
756
757 innerEvolvers.push_back(x: e);
758 }
759 }
760
761
762
763 UpperBoundEngine uEngine(upperEvolver, // does outer paths
764 innerEvolvers, // for sub-simulations that do continuation values
765 inverseFloater,
766 nullRebate,
767 inverseFloater,
768 nullRebate,
769 exerciseStrategy,
770 initialNumeraireValue);
771
772 Statistics uStats;
773 Size innerPaths = 255;
774 Size outerPaths =256;
775
776 int t4 = clock();
777
778 uEngine.multiplePathValues(stats&: uStats,outerPaths,innerPaths);
779 Real upperBound = uStats.mean();
780 Real upperSE = uStats.errorEstimate();
781
782 int t5=clock();
783
784 std::cout << " Upper - lower is, " << upperBound << ", with standard error " << upperSE << "\n";
785 std::cout << " time to compute upper bound is, " << (t5-t4)/static_cast<Real>(CLOCKS_PER_SEC) << ", seconds.\n";
786
787
788 return 0;
789
790}
791
792int main()
793{
794 try {
795 for (Size i=5; i < 10; ++i)
796 InverseFloater(rateLevel: i/100.0);
797
798 return 0;
799 } catch (std::exception& e) {
800 std::cerr << e.what() << std::endl;
801 return 1;
802 } catch (...) {
803 std::cerr << "unknown error" << std::endl;
804 return 1;
805 }
806}
807

source code of quantlib/Examples/MarketModels/MarketModels.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.