Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
randomvariable.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
21
22#include <ql/experimental/math/moorepenroseinverse.hpp>
23#include <ql/math/comparison.hpp>
24#include <ql/math/generallinearleastsquares.hpp>
25#include <ql/math/matrixutilities/qrdecomposition.hpp>
26#include <ql/math/matrixutilities/symmetricschurdecomposition.hpp>
27
28#include <boost/math/distributions/normal.hpp>
29
30#include <boost/accumulators/accumulators.hpp>
31#include <boost/accumulators/statistics/covariance.hpp>
32#include <boost/accumulators/statistics/mean.hpp>
33#include <boost/accumulators/statistics/stats.hpp>
34#include <boost/accumulators/statistics/variance.hpp>
35#include <boost/accumulators/statistics/variates/covariate.hpp>
36
37#include <iostream>
38#include <map>
39
40// if defined, RandomVariableStats are updated (this might impact perfomance!), default is undefined
41//#define ENABLE_RANDOMVARIABLE_STATS
42
43namespace QuantExt {
44
45namespace {
46
47#ifdef ENABLE_RANDOMVARIABLE_STATS
48
49inline void resumeDataStats() {
50 if (RandomVariableStats::instance().enabled)
51 RandomVariableStats::instance().data_timer.resume();
52}
53
54inline void stopDataStats(const std::size_t n) {
55 if (RandomVariableStats::instance().enabled) {
56 RandomVariableStats::instance().data_timer.stop();
57 RandomVariableStats::instance().data_ops += n;
58 }
59}
60
61inline void resumeCalcStats() {
62 if (RandomVariableStats::instance().enabled)
63 RandomVariableStats::instance().calc_timer.resume();
64}
65
66inline void stopCalcStats(const std::size_t n) {
67 if (RandomVariableStats::instance().enabled) {
68 RandomVariableStats::instance().calc_timer.stop();
69 RandomVariableStats::instance().calc_ops += n;
70 }
71}
72
73#else
74
75inline void resumeDataStats() {}
76inline void stopDataStats(const std::size_t n) {}
77inline void resumeCalcStats() {}
78inline void stopCalcStats(const std::size_t n) {}
79
80#endif
81
82double getDelta(const RandomVariable& x, const Real eps) {
83 Real sum = 0.0;
84 for (Size i = 0; i < x.size(); ++i) {
85 sum += x[i] * x[i];
86 }
87 return std::sqrt(sum / static_cast<Real>(x.size())) * eps / 2.0;
88}
89
90} // namespace
91
93
94Filter::Filter() : n_(0), constantData_(false), data_(nullptr), deterministic_(false) {}
95
97 n_ = r.n_;
99 if (r.data_) {
100 resumeDataStats();
101 data_ = new bool[n_];
102 // std::memcpy(data_, r.data_, n_ * sizeof(bool));
103 std::copy(r.data_, r.data_ + n_, data_);
104 stopDataStats(n_);
105 } else {
106 data_ = nullptr;
107 }
109}
110
112 n_ = r.n_;
113 constantData_ = r.constantData_;
114 data_ = r.data_;
115 r.data_ = nullptr;
116 deterministic_ = r.deterministic_;
117}
118
120 if (r.deterministic_) {
121 deterministic_ = true;
122 if (data_) {
123 delete[] data_;
124 data_ = nullptr;
125 }
126 } else {
127 deterministic_ = false;
128 if (r.n_ != 0) {
129 resumeDataStats();
130 if (n_ != r.n_) {
131 if (data_)
132 delete[] data_;
133 data_ = new bool[r.n_];
134 }
135 // std::memcpy(data_, r.data_, r.n_ * sizeof(bool));
136 std::copy(r.data_, r.data_ + r.n_, data_);
137 stopDataStats(r.n_);
138 } else {
139 if (data_) {
140 delete[] data_;
141 data_ = nullptr;
142 }
143 }
144 }
145 n_ = r.n_;
147 return *this;
148}
149
151 n_ = r.n_;
152 constantData_ = r.constantData_;
153 if (data_) {
154 delete[] data_;
155 }
156 data_ = r.data_;
157 r.data_ = nullptr;
158 deterministic_ = r.deterministic_;
159 return *this;
160}
161
162Filter::Filter(const Size n, const bool value) : n_(n), constantData_(value), data_(nullptr), deterministic_(n != 0) {}
163
165 n_ = 0;
166 constantData_ = false;
167 if (data_) {
168 delete[] data_;
169 data_ = nullptr;
170 }
171 deterministic_ = false;
172}
173
175 if (deterministic_ || !initialised())
176 return;
177 resumeCalcStats();
178 for (Size i = 0; i < n_; ++i) {
179 if (data_[i] != constantData_) {
180 stopCalcStats(i);
181 return;
182 }
183 }
185 stopCalcStats(n_);
186}
187
188void Filter::setAll(const bool v) {
189 QL_REQUIRE(n_ > 0, "Filter::setAll(): dimension is zero");
190 if (data_) {
191 delete[] data_;
192 data_ = nullptr;
193 }
194 constantData_ = v;
195 deterministic_ = true;
196}
197
198void Filter::resetSize(const Size n) {
199 QL_REQUIRE(deterministic_, "Filter::resetSize(): only possible for deterministic variables.");
200 n_ = n;
201}
202
204 if (!deterministic_)
205 return;
206 deterministic_ = false;
207 resumeDataStats();
208 data_ = new bool[n_];
209 std::fill(data_, data_ + n_, constantData_);
210 stopDataStats(n_);
211}
212
213bool operator==(const Filter& a, const Filter& b) {
214 if (a.size() != b.size())
215 return false;
216 if (a.deterministic_ && b.deterministic_) {
217 return a.constantData_ == b.constantData_;
218 } else {
219 resumeCalcStats();
220 for (Size j = 0; j < a.size(); ++j)
221 if (a[j] != b[j]) {
222 stopCalcStats(j);
223 return false;
224 }
225 stopCalcStats(a.size());
226 }
227 return true;
228}
229
230bool operator!=(const Filter& a, const Filter& b) { return !(a == b); }
231
233 QL_REQUIRE(!x.initialised() || !y.initialised() || x.size() == y.size(),
234 "RandomVariable: x && y: x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
235 if (x.deterministic() && !x.constantData_)
236 return Filter(x.size(), false);
237 if (y.deterministic() && !y.constantData_)
238 return Filter(y.size(), false);
239 if (!x.initialised() || !y.initialised())
240 return Filter();
241 if (!y.deterministic_)
242 x.expand();
243 if (x.deterministic_) {
245 } else {
246 resumeCalcStats();
247 for (Size i = 0; i < x.size(); ++i) {
248 x.data_[i] = x.data_[i] && y[i];
249 }
250 stopCalcStats(x.size());
251 }
252 return x;
253}
254
256 QL_REQUIRE(!x.initialised() || !y.initialised() || x.size() == y.size(),
257 "RandomVariable: x || y: x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
258 if (x.deterministic() && x.constantData_)
259 return Filter(x.size(), true);
260 if (y.deterministic() && y.constantData_)
261 return Filter(y.size(), true);
262 if (!x.initialised() || !y.initialised())
263 return Filter();
264 if (!y.deterministic_)
265 x.expand();
266 if (x.deterministic_) {
268 } else {
269 resumeCalcStats();
270 for (Size i = 0; i < x.size(); ++i) {
271 x.data_[i] = x.data_[i] || y[i];
272 }
273 stopCalcStats(x.size());
274 }
275 return x;
276}
277
278Filter equal(Filter x, const Filter& y) {
279 if (!x.initialised() || !y.initialised())
280 return Filter();
281 QL_REQUIRE(x.size() == y.size(),
282 "RandomVariable: equal(x,y): x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
283 if (!y.deterministic_)
284 x.expand();
285 if (x.deterministic_) {
287 } else {
288 resumeCalcStats();
289 for (Size i = 0; i < x.size(); ++i) {
290 x.data_[i] = x.data_[i] == y[i];
291 }
292 stopCalcStats(x.size());
293 }
294 return x;
295}
296
298 if (x.deterministic_)
300 else {
301 resumeCalcStats();
302 for (Size i = 0; i < x.size(); ++i) {
303 x.data_[i] = !x.data_[i];
304 }
305 stopCalcStats(x.size());
306 }
307 return x;
308}
309
311
313 : n_(0), constantData_(0.0), data_(nullptr), deterministic_(false), time_(Null<Real>()) {}
314
316 n_ = r.n_;
318 if (r.data_) {
319 resumeDataStats();
320 data_ = new double[n_];
321 // std::memcpy(data_, r.data_, n_ * sizeof(double));
322 std::copy(r.data_, r.data_ + n_, data_);
323 stopDataStats(n_);
324 } else {
325 data_ = nullptr;
326 }
328 time_ = r.time_;
329}
330
332 n_ = r.n_;
333 constantData_ = r.constantData_;
334 data_ = r.data_;
335 r.data_ = nullptr;
336 deterministic_ = r.deterministic_;
337 time_ = r.time_;
338}
339
341 if (r.deterministic_) {
342 deterministic_ = true;
343 if (data_) {
344 delete[] data_;
345 data_ = nullptr;
346 }
347 } else {
348 deterministic_ = false;
349 if (r.n_ != 0) {
350 resumeDataStats();
351 if (n_ != r.n_) {
352 if (data_)
353 delete[] data_;
354 data_ = new double[r.n_];
355 }
356 // std::memcpy(data_, r.data_, r.n_ * sizeof(double));
357 std::copy(r.data_, r.data_ + r.n_, data_);
358 stopDataStats(r.n_);
359 } else {
360 if (data_) {
361 delete[] data_;
362 data_ = nullptr;
363 }
364 }
365 }
366 n_ = r.n_;
368 time_ = r.time_;
369 return *this;
370}
371
373 n_ = r.n_;
374 constantData_ = r.constantData_;
375 if (data_) {
376 delete[] data_;
377 }
378 data_ = r.data_;
379 r.data_ = nullptr;
380 deterministic_ = r.deterministic_;
381 time_ = r.time_;
382 return *this;
383}
384
385RandomVariable::RandomVariable(const Size n, const Real value, const Real time)
386 : n_(n), constantData_(value), data_(nullptr), deterministic_(n != 0), time_(time) {}
387
388RandomVariable::RandomVariable(const Filter& f, const Real valueTrue, const Real valueFalse, const Real time) {
389 if (!f.initialised()) {
390 data_ = nullptr;
391 clear();
392 return;
393 }
394 n_ = f.size();
395 if (f.deterministic()) {
396 data_ = nullptr;
397 setAll(f.at(0) ? valueTrue : valueFalse);
398 } else {
399 resumeDataStats();
400 constantData_ = 0.0;
401 deterministic_ = false;
402 data_ = new double[n_];
403 for (Size i = 0; i < n_; ++i)
404 set(i, f[i] ? valueTrue : valueFalse);
405 stopDataStats(n_);
406 }
407 time_ = time;
408}
409
410RandomVariable::RandomVariable(const Size n, const Real* const data, const Real time) {
411 n_ = n;
412 deterministic_ = false;
413 time_ = time;
414 if (n_ != 0) {
415 resumeDataStats();
416 data_ = new double[n_];
417 // std::memcpy(data_, array.begin(), n_ * sizeof(double));
418 std::copy(data, data + n_, data_);
419 stopDataStats(n_);
420 } else {
421 data_ = nullptr;
422 }
423 constantData_ = 0.0;
424}
425
426RandomVariable::RandomVariable(const std::vector<Real>& data, const Real time)
427 : RandomVariable(data.size(), &data[0], time) {}
428
429RandomVariable::RandomVariable(const QuantLib::Array& data, const Real time)
430 : RandomVariable(data.size(), data.begin(), time) {}
431
432void RandomVariable::copyToMatrixCol(QuantLib::Matrix& m, const Size j) const {
433 if (deterministic_)
434 std::fill(m.column_begin(j), std::next(m.column_end(j), n_), constantData_);
435 else if (n_ != 0) {
436 resumeDataStats();
437 std::copy(data_, data_ + n_, m.column_begin(j));
438 stopDataStats(n_);
439 }
440}
441
442void RandomVariable::copyToArray(QuantLib::Array& array) const {
443 if (deterministic_)
444 std::fill(array.begin(), array.end(), constantData_);
445 else if (n_ != 0) {
446 resumeDataStats();
447 // std::memcpy(array.begin(), data_, n_ * sizeof(double));
448 std::copy(data_, data_ + n_, array.begin());
449 stopDataStats(n_);
450 }
451}
452
454 n_ = 0;
455 constantData_ = 0.0;
456 if (data_) {
457 delete[] data_;
458 data_ = nullptr;
459 }
460 deterministic_ = false;
461 time_ = Null<Real>();
462}
463
465 if (deterministic_ || !initialised())
466 return;
467 for (Size i = 0; i < n_; ++i) {
468 resumeCalcStats();
469 if (!QuantLib::close_enough(data_[i], constantData_)) {
470 stopCalcStats(i);
471 return;
472 }
473 }
475 stopCalcStats(n_);
476}
477
478void RandomVariable::setAll(const Real v) {
479 QL_REQUIRE(n_ > 0, "RandomVariable::setAll(): dimension is zero");
480 if (data_) {
481 delete[] data_;
482 data_ = nullptr;
483 }
484 constantData_ = v;
485 deterministic_ = true;
486}
487
488void RandomVariable::resetSize(const Size n) {
489 QL_REQUIRE(deterministic_, "RandomVariable::resetSize(): only possible for deterministic variables.");
490 n_ = n;
491}
492
494 if (!deterministic_)
495 return;
496 deterministic_ = false;
497 resumeDataStats();
498 data_ = new double[n_];
499 std::fill(data_, data_ + n_, constantData_);
500 stopDataStats(n_);
501}
502
504 QL_REQUIRE((time_ == Null<Real>() || t == Null<Real>()) || QuantLib::close_enough(time_, t),
505 "RandomVariable: inconsistent times " << time_ << " and " << t);
506 if (time_ == Null<Real>())
507 time_ = t;
508}
509
511 QL_REQUIRE((x.time() == Null<Real>() || y.time() == Null<Real>()) || QuantLib::close_enough(x.time(), y.time()),
512 "got inconsistent random variable times (" << x.time() << ", " << y.time() << ")");
513}
514
515bool operator==(const RandomVariable& a, const RandomVariable& b) {
516 if (a.size() != b.size())
517 return false;
518 if (a.deterministic_ && b.deterministic_) {
519 return a.constantData_ == b.constantData_;
520 } else {
521 resumeCalcStats();
522 for (Size j = 0; j < a.size(); ++j)
523 if (a[j] != b[j]) {
524 stopCalcStats(j);
525 return false;
526 }
527 }
528 return QuantLib::close_enough(a.time(), b.time());
529}
530
531bool operator!=(const RandomVariable& a, const RandomVariable b) { return !(a == b); }
532
534 if (!y.initialised())
535 clear();
536 if (!initialised())
537 return *this;
538 QL_REQUIRE(size() == y.size(),
539 "RandomVariable: x += y: x size (" << size() << ") must be equal to y size (" << y.size() << ")");
541 if (!y.deterministic_)
542 expand();
543 else if (QuantLib::close_enough(y.constantData_, 0.0))
544 return *this;
545 if (deterministic_)
547 else {
548 resumeCalcStats();
549 for (Size i = 0; i < n_; ++i) {
550 data_[i] += y[i];
551 }
552 stopCalcStats(n_);
553 }
554 return *this;
555}
556
558 if (!y.initialised())
559 clear();
560 if (!initialised())
561 return *this;
562 QL_REQUIRE(size() == y.size(),
563 "RandomVariable: x -= y: x size (" << size() << ") must be equal to y size (" << y.size() << ")");
565 if (!y.deterministic_)
566 expand();
567 else if (QuantLib::close_enough(y.constantData_, 0.0))
568 return *this;
569 if (deterministic_)
571 else {
572 resumeCalcStats();
573 for (Size i = 0; i < n_; ++i) {
574 data_[i] -= y[i];
575 }
576 stopCalcStats(n_);
577 }
578 return *this;
579}
580
582 if (!y.initialised())
583 clear();
584 if (!initialised())
585 return *this;
586 QL_REQUIRE(size() == y.size(),
587 "RandomVariable: x *= y: x size (" << size() << ") must be equal to y size (" << y.size() << ")");
589 if (!y.deterministic_)
590 expand();
591 else if (QuantLib::close_enough(y.constantData_, 1.0))
592 return *this;
593 if (deterministic_)
595 else {
596 resumeCalcStats();
597 for (Size i = 0; i < n_; ++i) {
598 data_[i] *= y[i];
599 }
600 stopCalcStats(n_);
601 }
602 return *this;
603}
604
606 if (!y.initialised())
607 clear();
608 if (!initialised())
609 return *this;
610 QL_REQUIRE(size() == y.size(),
611 "RandomVariable: x /= y: x size (" << size() << ") must be equal to y size (" << y.size() << ")");
613 if (!y.deterministic_)
614 expand();
615 else if (QuantLib::close_enough(y.constantData_, 1.0))
616 return *this;
617 if (deterministic_)
619 else {
620 resumeCalcStats();
621 for (Size i = 0; i < n_; ++i) {
622 data_[i] /= y[i];
623 }
624 stopCalcStats(n_);
625 }
626 return *this;
627}
628
630 if (!x.initialised() || !y.initialised())
631 return RandomVariable();
632 x += y;
633 return x;
634}
635
637 if (!x.initialised() || !y.initialised())
638 return RandomVariable();
639 x -= y;
640 return x;
641}
642
644 if (!x.initialised() || !y.initialised())
645 return RandomVariable();
646 x *= y;
647 return x;
648}
649
651 if (!x.initialised() || !y.initialised())
652 return RandomVariable();
653 x /= y;
654 return x;
655}
656
658 if (!x.initialised() || !y.initialised())
659 return RandomVariable();
660 QL_REQUIRE(x.size() == y.size(),
661 "RandomVariable: max(x,y): x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
663 if (!y.deterministic_)
664 x.expand();
665 if (x.deterministic())
666 x.constantData_ = std::max(x.constantData_, y.constantData_);
667 else {
668 resumeCalcStats();
669 for (Size i = 0; i < x.size(); ++i) {
670 x.data_[i] = std::max(x.data_[i], y[i]);
671 }
672 stopCalcStats(x.size());
673 }
674 return x;
675}
676
678 if (!x.initialised() || !y.initialised())
679 return RandomVariable();
680 QL_REQUIRE(x.size() == y.size(),
681 "RandomVariable: min(x,y): x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
683 if (!y.deterministic_)
684 x.expand();
685 if (x.deterministic())
686 x.constantData_ = std::min(x.constantData_, y.constantData_);
687 else {
688 resumeCalcStats();
689 for (Size i = 0; i < x.size(); ++i) {
690 x.data_[i] = std::min(x.data_[i], y[i]);
691 }
692 stopCalcStats(x.size());
693 }
694 return x;
695}
696
698 if (!x.initialised() || !y.initialised())
699 return RandomVariable();
700 QL_REQUIRE(x.size() == y.size(),
701 "RandomVariable: pow(x,y): x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
703 if (!y.deterministic_)
704 x.expand();
705 else if (QuantLib::close_enough(y.constantData_, 1.0))
706 return x;
707 if (x.deterministic())
708 x.constantData_ = std::pow(x.constantData_, y.constantData_);
709 else {
710 resumeCalcStats();
711 for (Size i = 0; i < x.size(); ++i) {
712 x.data_[i] = std::pow(x.data_[i], y[i]);
713 }
714 stopCalcStats(x.size());
715 }
716 return x;
717}
718
720 if (x.deterministic_)
722 else {
723 resumeCalcStats();
724 for (Size i = 0; i < x.n_; ++i) {
725 x.data_[i] = -x.data_[i];
726 }
727 stopCalcStats(x.n_);
728 }
729 return x;
730}
731
733 if (x.deterministic_)
734 x.constantData_ = std::abs(x.constantData_);
735 else {
736 resumeCalcStats();
737 for (Size i = 0; i < x.n_; ++i) {
738 x.data_[i] = std::abs(x.data_[i]);
739 }
740 stopCalcStats(x.n_);
741 }
742 return x;
743}
744
746 if (x.deterministic_)
747 x.constantData_ = std::exp(x.constantData_);
748 else {
749 resumeCalcStats();
750 for (Size i = 0; i < x.n_; ++i) {
751 x.data_[i] = std::exp(x.data_[i]);
752 }
753 stopCalcStats(x.n_);
754 }
755 return x;
756}
757
759 if (x.deterministic_)
760 x.constantData_ = std::log(x.constantData_);
761 else {
762 resumeCalcStats();
763 for (Size i = 0; i < x.n_; ++i) {
764 x.data_[i] = std::log(x.data_[i]);
765 }
766 stopCalcStats(x.n_);
767 }
768 return x;
769}
770
772 if (x.deterministic_)
773 x.constantData_ = std::sqrt(x.constantData_);
774 else {
775 resumeCalcStats();
776 for (Size i = 0; i < x.n_; ++i) {
777 x.data_[i] = std::sqrt(x.data_[i]);
778 }
779 stopCalcStats(x.n_);
780 }
781 return x;
782}
783
785 if (x.deterministic_)
786 x.constantData_ = std::sin(x.constantData_);
787 else {
788 resumeCalcStats();
789 for (Size i = 0; i < x.n_; ++i) {
790 x.data_[i] = std::sin(x.data_[i]);
791 }
792 stopCalcStats(x.n_);
793 }
794 return x;
795}
796
798 if (x.deterministic_)
799 x.constantData_ = std::cos(x.constantData_);
800 else {
801 resumeCalcStats();
802 for (Size i = 0; i < x.n_; ++i) {
803 x.data_[i] = std::cos(x.data_[i]);
804 }
805 stopCalcStats(x.n_);
806 }
807 return x;
808}
809
811 static const boost::math::normal_distribution<double> n;
812 if (x.deterministic_)
813 x.constantData_ = boost::math::cdf(n, x.constantData_);
814 else {
815 resumeCalcStats();
816 for (Size i = 0; i < x.n_; ++i) {
817 x.data_[i] = boost::math::cdf(n, x.data_[i]);
818 }
819 stopCalcStats(x.n_);
820 }
821 return x;
822}
823
825 static const boost::math::normal_distribution<double> n;
826 if (x.deterministic_)
827 x.constantData_ = boost::math::pdf(n, x.constantData_);
828 else {
829 resumeCalcStats();
830 for (Size i = 0; i < x.n_; ++i) {
831 x.data_[i] = boost::math::pdf(n, x.data_[i]);
832 }
833 stopCalcStats(x.n_);
834 }
835 return x;
836}
837
839 if (!x.initialised() || !y.initialised())
840 return Filter();
841 QL_REQUIRE(x.size() == y.size(), "RandomVariable: close_enough(x,y): x size ("
842 << x.size() << ") must be equal to y size (" << y.size() << ")");
844 if (x.deterministic_ && y.deterministic_) {
845 return Filter(x.size(), QuantLib::close_enough(x.constantData_, y.constantData_));
846 }
847 resumeCalcStats();
848 Filter result(x.size(), false);
849 for (Size i = 0; i < x.size(); ++i) {
850 result.set(i, QuantLib::close_enough(x[i], y[i]));
851 }
852 stopCalcStats(x.size());
853 return result;
854}
855
857 QL_REQUIRE(x.size() == y.size(), "RandomVariable: close_enough_all(x,y): x size ("
858 << x.size() << ") must be equal to y size (" << y.size() << ")");
860 if (x.deterministic_ && y.deterministic_) {
861 return QuantLib::close_enough(x.constantData_, y.constantData_);
862 }
863 resumeCalcStats();
864 for (Size i = 0; i < x.size(); ++i) {
865 if (!QuantLib::close_enough(x[i], y[i]))
866 return false;
867 }
868 stopCalcStats(x.size());
869 return true;
870}
871
873 if (!f.initialised() || !x.initialised() || !y.initialised())
874 return RandomVariable();
875 QL_REQUIRE(f.size() == x.size(),
876 "conditionalResult(f,x,y): f size (" << f.size() << ") must match x size (" << x.size() << ")");
877 QL_REQUIRE(f.size() == y.size(),
878 "conditionalResult(f,x,y): f size (" << f.size() << ") must match y size (" << y.size() << ")");
880 if (f.deterministic())
881 return f.at(0) ? x : y;
882 resumeCalcStats();
883 x.expand();
884 for (Size i = 0; i < f.size(); ++i) {
885 if (!f[i])
886 x.set(i, y[i]);
887 }
888 stopCalcStats(f.size());
889 return x;
890}
891
892RandomVariable indicatorEq(RandomVariable x, const RandomVariable& y, const Real trueVal, const Real falseVal) {
893 if (!x.initialised() || !y.initialised())
894 return RandomVariable();
895 QL_REQUIRE(x.size() == y.size(), "RandomVariable: indicatorEq(x,y): x size ("
896 << x.size() << ") must be equal to y size (" << y.size() << ")");
898 if (!y.deterministic_)
899 x.expand();
900 if (x.deterministic()) {
901 x.constantData_ = QuantLib::close_enough(x.constantData_, y.constantData_) ? trueVal : falseVal;
902 } else {
903 resumeCalcStats();
904 for (Size i = 0; i < x.n_; ++i) {
905 x.data_[i] = QuantLib::close_enough(x.data_[i], y[i]) ? trueVal : falseVal;
906 }
907 stopCalcStats(x.n_);
908 }
909 return x;
910}
911
912RandomVariable indicatorGt(RandomVariable x, const RandomVariable& y, const Real trueVal, const Real falseVal,
913 const Real eps) {
914 if (!x.initialised() || !y.initialised())
915 return RandomVariable();
916 QL_REQUIRE(x.size() == y.size(), "RandomVariable: indicatorEq(x,y): x size ("
917 << x.size() << ") must be equal to y size (" << y.size() << ")");
919 if (!y.deterministic_)
920 x.expand();
921 if (eps != 0.0) {
922 Real delta = getDelta(x - y, eps);
923 if (!QuantLib::close_enough(delta, 0.0)) {
924 // logistic function
925 x.expand();
926 Real delta = getDelta(x - y, eps);
927 resumeCalcStats();
928 for (Size i = 0; i < x.n_; ++i) {
929 x.data_[i] = falseVal + (trueVal - falseVal) * 1.0 / (1.0 + std::exp(-x.data_[i] / delta));
930 }
931 stopCalcStats(x.n_);
932 return x;
933 }
934 }
935 // eps == 0.0 or delta == 0.0
936 if (x.deterministic()) {
937 x.constantData_ =
938 (x.constantData_ > y.constantData_ && !QuantLib::close_enough(x.constantData_, y.constantData_)) ? trueVal
939 : falseVal;
940 } else {
941 resumeCalcStats();
942 for (Size i = 0; i < x.n_; ++i) {
943 x.data_[i] = (x.data_[i] > y[i] && !QuantLib::close_enough(x.data_[i], y[i])) ? trueVal : falseVal;
944 }
945 stopCalcStats(x.n_);
946 }
947 return x;
948}
949
950RandomVariable indicatorGeq(RandomVariable x, const RandomVariable& y, const Real trueVal, const Real falseVal,
951 const Real eps) {
952 if (!x.initialised() || !y.initialised())
953 return RandomVariable();
954 QL_REQUIRE(x.size() == y.size(), "RandomVariable: indicatorEq(x,y): x size ("
955 << x.size() << ") must be equal to y size (" << y.size() << ")");
957 if (!y.deterministic_)
958 x.expand();
959 if (eps != 0.0) {
960 Real delta = getDelta(x - y, eps);
961 if (!QuantLib::close_enough(delta, 0.0)) {
962 // logistic function
963 x.expand();
964 Real delta = getDelta(x - y, eps);
965 resumeCalcStats();
966 for (Size i = 0; i < x.n_; ++i) {
967 x.data_[i] = falseVal + (trueVal - falseVal) * 1.0 / (1.0 + std::exp(-x.data_[i] / delta));
968 }
969 stopCalcStats(x.n_);
970 return x;
971 }
972 }
973 // eps == 0.0 or delta == 0.0
974 if (x.deterministic()) {
975 x.constantData_ =
976 (x.constantData_ > y.constantData_ || QuantLib::close_enough(x.constantData_, y.constantData_)) ? trueVal
977 : falseVal;
978 } else {
979 resumeCalcStats();
980 for (Size i = 0; i < x.n_; ++i) {
981 x.data_[i] = (x.data_[i] > y[i] || QuantLib::close_enough(x.data_[i], y[i])) ? trueVal : falseVal;
982 }
983 stopCalcStats(x.n_);
984 }
985 return x;
986}
987
989 if (!x.initialised() || !y.initialised())
990 return Filter();
991 QL_REQUIRE(x.size() == y.size(),
992 "RandomVariable: x < y: x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
994 if (x.deterministic_ && y.deterministic_) {
995 return Filter(x.size(),
996 x.constantData_ < y.constantData_ && !QuantLib::close_enough(x.constantData_, y.constantData_));
997 }
998 resumeCalcStats();
999 Filter result(x.size(), false);
1000 for (Size i = 0; i < x.size(); ++i) {
1001 result.set(i, x[i] < y[i] && !QuantLib::close_enough(x[i], y[i]));
1002 }
1003 stopCalcStats(x.size());
1004 return result;
1005}
1006
1008 if (!x.initialised() || !y.initialised())
1009 return Filter();
1010 QL_REQUIRE(x.size() == y.size(),
1011 "RandomVariable: x <= y: x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
1013 if (x.deterministic_ && y.deterministic_) {
1014 return Filter(x.size(),
1015 x.constantData_ < y.constantData_ || QuantLib::close_enough(x.constantData_, y.constantData_));
1016 }
1017 resumeCalcStats();
1018 Filter result(x.size(), false);
1019 for (Size i = 0; i < x.size(); ++i) {
1020 result.set(i, x[i] < y[i] || QuantLib::close_enough(x[i], y[i]));
1021 }
1022 stopCalcStats(x.size());
1023 return result;
1024}
1025
1027 if (!x.initialised() || !y.initialised())
1028 return Filter();
1029 QL_REQUIRE(x.size() == y.size(),
1030 "RandomVariable: x > y: x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
1032 if (x.deterministic_ && y.deterministic_) {
1033 return Filter(x.size(),
1034 x.constantData_ > y.constantData_ && !QuantLib::close_enough(x.constantData_, y.constantData_));
1035 }
1036 Filter result(x.size(), false);
1037 for (Size i = 0; i < x.size(); ++i) {
1038 result.set(i, x[i] > y[i] && !QuantLib::close_enough(x[i], y[i]));
1039 }
1040 return result;
1041}
1042
1044 if (!x.initialised() || !y.initialised())
1045 return Filter();
1046 QL_REQUIRE(x.size() == y.size(),
1047 "RandomVariable: x >= y: x size (" << x.size() << ") must be equal to y size (" << y.size() << ")");
1049 if (x.deterministic_ && y.deterministic_) {
1050 return Filter(x.size(),
1051 x.constantData_ > y.constantData_ || QuantLib::close_enough(x.constantData_, y.constantData_));
1052 }
1053 resumeCalcStats();
1054 Filter result(x.size(), false);
1055 for (Size i = 0; i < x.size(); ++i) {
1056 result.set(i, x[i] > y[i] || QuantLib::close_enough(x[i], y[i]));
1057 }
1058 stopCalcStats(x.size());
1059 return result;
1060}
1061
1063 if (!x.initialised())
1064 return x;
1065 QL_REQUIRE(!f.initialised() || f.size() == x.size(), "RandomVariable: applyFitler(x,f): filter size ("
1066 << f.size() << ") must be equal to x size (" << x.size()
1067 << ")");
1068 if (!f.initialised())
1069 return x;
1070 if (f.deterministic()) {
1071 if (!f[0])
1072 return RandomVariable(x.size(), 0.0, x.time());
1073 else
1074 return x;
1075 }
1076 if (x.deterministic_ && QuantLib::close_enough(x.constantData_, 0.0))
1077 return x;
1078 resumeCalcStats();
1079 for (Size i = 0; i < x.size(); ++i) {
1080 if (!f[i])
1081 x.set(i, 0.0);
1082 }
1083 stopCalcStats(x.size());
1084 return x;
1085}
1086
1088 if (!x.initialised())
1089 return x;
1090 QL_REQUIRE(!f.initialised() || f.size() == x.size(), "RandomVariable: applyFitler(x,f): filter size ("
1091 << f.size() << ") must be equal to x size (" << x.size()
1092 << ")");
1093 if (!f.initialised())
1094 return x;
1095 if (f.deterministic()) {
1096 if (f[0])
1097 return RandomVariable(x.size(), 0.0, x.time());
1098 else
1099 return x;
1100 }
1101 if (x.deterministic_ && QuantLib::close_enough(x.constantData_, 0.0))
1102 return x;
1103 resumeCalcStats();
1104 for (Size i = 0; i < x.size(); ++i) {
1105 if (f[i])
1106 x.set(i, 0.0);
1107 }
1108 stopCalcStats(x.size());
1109 return x;
1110}
1111
1112Matrix pcaCoordinateTransform(const std::vector<const RandomVariable*>& regressor, const Real varianceCutoff) {
1113 if (regressor.empty())
1114 return {};
1115
1116 Matrix cov(regressor.size(), regressor.size());
1117 for (Size i = 0; i < regressor.size(); ++i) {
1118 cov(i, i) = variance(*regressor[i]).at(0);
1119 for (Size j = 0; j < i; ++j) {
1120 cov(i, j) = cov(j, i) = covariance(*regressor[i], *regressor[j]).at(0);
1121 }
1122 }
1123
1124 QuantLib::SymmetricSchurDecomposition schur(cov);
1125 Real totalVariance = std::accumulate(schur.eigenvalues().begin(), schur.eigenvalues().end(), 0.0);
1126
1127 Size keep = 0;
1128 Real explainedVariance = 0.0;
1129 while (keep < schur.eigenvalues().size() && explainedVariance < totalVariance * (1.0 - varianceCutoff)) {
1130 explainedVariance += schur.eigenvalues()[keep++];
1131 }
1132
1133 Matrix result(keep, regressor.size());
1134 for (Size i = 0; i < keep; ++i) {
1135 std::copy(schur.eigenvectors().column_begin(i), schur.eigenvectors().column_end(i), result.row_begin(i));
1136 }
1137 return result;
1138}
1139
1140std::vector<RandomVariable> applyCoordinateTransform(const std::vector<const RandomVariable*>& regressor,
1141 const Matrix& transform) {
1142 QL_REQUIRE(transform.columns() == regressor.size(),
1143 "applyCoordinateTransform(): number of random variables ("
1144 << regressor.size() << ") does not match number of columns in transform (" << transform.columns());
1145 if (regressor.empty())
1146 return {};
1147 Size n = regressor.front()->size();
1148 std::vector<RandomVariable> result(transform.rows(), RandomVariable(n, 0.0));
1149 for (Size i = 0; i < transform.rows(); ++i) {
1150 for (Size j = 0; j < transform.columns(); ++j) {
1151 result[i] += RandomVariable(n, transform(i, j)) * (*regressor[j]);
1152 }
1153 }
1154 return result;
1155}
1156
1157std::vector<const RandomVariable*> vec2vecptr(const std::vector<RandomVariable>& values) {
1158 std::vector<const RandomVariable*> result(values.size());
1159 std::transform(values.begin(), values.end(), result.begin(), [](const RandomVariable& v) { return &v; });
1160 return result;
1161}
1162
1164 RandomVariable r, std::vector<const RandomVariable*> regressor,
1165 const std::vector<std::function<RandomVariable(const std::vector<const RandomVariable*>&)>>& basisFn,
1166 const Filter& filter, const RandomVariableRegressionMethod regressionMethod, const std::string& debugLabel) {
1167
1168 for (auto const reg : regressor) {
1169 QL_REQUIRE(reg->size() == r.size(),
1170 "regressor size (" << reg->size() << ") must match regressand size (" << r.size() << ")");
1171 }
1172
1173 QL_REQUIRE(filter.size() == 0 || filter.size() == r.size(),
1174 "filter size (" << filter.size() << ") must match regressand size (" << r.size() << ")");
1175
1176 QL_REQUIRE(r.size() >= basisFn.size(), "regressionCoefficients(): sample size ("
1177 << r.size() << ") must be geq basis fns size (" << basisFn.size()
1178 << ")");
1179
1180 resumeCalcStats();
1181
1182 Matrix A(r.size(), basisFn.size());
1183 for (Size j = 0; j < basisFn.size(); ++j) {
1184 RandomVariable a = basisFn[j](regressor);
1185 if (filter.initialised()) {
1186 a = applyFilter(a, filter);
1187 }
1188 if (a.deterministic())
1189 std::fill(A.column_begin(j), A.column_end(j), a[0]);
1190 else
1191 a.copyToMatrixCol(A, j);
1192 }
1193
1194 if (!debugLabel.empty()) {
1195 for (Size i = 0; i < r.size(); ++i) {
1196 std::cout << debugLabel << "," << r[i] << ",";
1197 for (Size j = 0; j < regressor.size(); ++j) {
1198 std::cout << regressor[j]->operator[](i) << (j == regressor.size() - 1 ? "\n" : ",");
1199 }
1200 }
1201 std::cout << std::flush;
1202 }
1203
1204 if (filter.size() > 0) {
1205 r = applyFilter(r, filter);
1206 }
1207
1208 Array b(r.size());
1209 if (r.deterministic())
1210 std::fill(b.begin(), b.end(), r[0]);
1211 else
1212 r.copyToArray(b);
1213
1214 Array res;
1215 if (regressionMethod == RandomVariableRegressionMethod::SVD) {
1216 SVD svd(A);
1217 const Matrix& V = svd.V();
1218 const Matrix& U = svd.U();
1219 const Array& w = svd.singularValues();
1220 Real threshold = r.size() * QL_EPSILON * svd.singularValues()[0];
1221 res = Array(basisFn.size(), 0.0);
1222 for (Size i = 0; i < basisFn.size(); ++i) {
1223 if (w[i] > threshold) {
1224 Real u = std::inner_product(U.column_begin(i), U.column_end(i), b.begin(), Real(0.0)) / w[i];
1225 for (Size j = 0; j < basisFn.size(); ++j) {
1226 res[j] += u * V[j][i];
1227 }
1228 }
1229 }
1230 } else if (regressionMethod == RandomVariableRegressionMethod::QR) {
1231 res = qrSolve(A, b);
1232 } else {
1233 QL_FAIL("regressionCoefficients(): unknown regression method, expected SVD or QR");
1234 }
1235
1236 // rough estimate, SVD is O(mn min(m,n))
1237 stopCalcStats(r.size() * basisFn.size() * std::min(r.size(), basisFn.size()));
1238 return res;
1239}
1240
1242 const std::vector<const RandomVariable*>& regressor,
1243 const std::vector<std::function<RandomVariable(const std::vector<const RandomVariable*>&)>>& basisFn,
1244 const Array& coefficients) {
1245 QL_REQUIRE(!regressor.empty(), "regressor vector is empty");
1246 Size n = regressor.front()->size();
1247 for (Size i = 1; i < regressor.size(); ++i) {
1248 QL_REQUIRE(regressor[i] != nullptr, "regressor #" << i << " is null.");
1249 QL_REQUIRE(n == regressor[i]->size(), "regressor #" << i << " size (" << regressor[i]->size()
1250 << ") must match regressor #0 size (" << n << ")");
1251 }
1252 QL_REQUIRE(basisFn.size() == coefficients.size(),
1253 "basisFn size (" << basisFn.size() << ") must match coefficients size (" << coefficients.size() << ")");
1254 RandomVariable r(n, 0.0);
1255 for (Size i = 0; i < coefficients.size(); ++i) {
1256 r = r + RandomVariable(n, coefficients[i]) * basisFn[i](regressor);
1257 }
1258 return r;
1259}
1260
1262 const RandomVariable& r, const std::vector<const RandomVariable*>& regressor,
1263 const std::vector<std::function<RandomVariable(const std::vector<const RandomVariable*>&)>>& basisFn,
1264 const Filter& filter, const RandomVariableRegressionMethod regressionMethod) {
1265 if (r.deterministic())
1266 return r;
1267 auto coeff = regressionCoefficients(r, regressor, basisFn, filter, regressionMethod);
1268 return conditionalExpectation(regressor, basisFn, coeff);
1269}
1270
1272 if (r.deterministic())
1273 return r;
1274 resumeCalcStats();
1275 boost::accumulators::accumulator_set<double, boost::accumulators::stats<boost::accumulators::tag::mean>> acc;
1276 for (Size i = 0; i < r.size(); ++i)
1277 acc(r[i]);
1278 return RandomVariable(r.size(), boost::accumulators::mean(acc));
1279}
1280
1282 if (r.deterministic())
1283 return RandomVariable(r.size(), 0.0);
1284 resumeCalcStats();
1285 boost::accumulators::accumulator_set<double, boost::accumulators::stats<boost::accumulators::tag::variance>> acc;
1286 for (Size i = 0; i < r.size(); ++i) {
1287 acc(r[i]);
1288 }
1289 stopCalcStats(r.size());
1290 return RandomVariable(r.size(), boost::accumulators::variance(acc));
1291}
1292
1294 QL_REQUIRE(r.size() == s.size(), "covariance(RandomVariable r, RandomVariable s): inconsistent sizes r ("
1295 << r.size() << "), s(" << s.size() << ")");
1296 if (r.deterministic() || s.deterministic())
1297 return RandomVariable(r.size(), 0.0);
1298 resumeCalcStats();
1299 boost::accumulators::accumulator_set<
1300 double,
1301 boost::accumulators::stats<boost::accumulators::tag::covariance<double, boost::accumulators::tag::covariate1>>>
1302 acc;
1303 for (Size i = 0; i < r.size(); ++i) {
1304 acc(r[i], boost::accumulators::covariate1 = s[i]);
1305 }
1306 stopCalcStats(r.size());
1307 return RandomVariable(r.size(), boost::accumulators::covariance(acc));
1308}
1309
1311 const RandomVariable& forward, const RandomVariable& impliedVol) {
1312 Filter zeroStrike = close_enough(strike, RandomVariable(omega.size(), 0.0));
1313 Filter call = omega > RandomVariable(omega.size(), 0.0);
1314 RandomVariable stdDev = impliedVol * sqrt(t);
1315 RandomVariable d1 = log(forward / strike) / stdDev + RandomVariable(omega.size(), 0.5) * stdDev;
1316 RandomVariable d2 = d1 - stdDev;
1317 return applyFilter(forward, zeroStrike && call) +
1318 applyInverseFilter(omega * (forward * normalCdf(omega * d1) - strike * normalCdf(omega * d2)), zeroStrike);
1319}
1320
1322 RandomVariable tmp(x.size(), 0.0);
1323
1324 // We follow section 4, eq 10 in
1325 // Fries, 2017: Automatic Backward Differentiation for American Monte-Carlo Algorithms -
1326 // ADD for Conditional Expectations and Indicator Functions
1327
1328 resumeCalcStats();
1329
1330 Real delta = getDelta(x, eps);
1331
1332 if (QuantLib::close_enough(delta, 0.0))
1333 return tmp;
1334
1335 // compute derivative
1336
1337 for (Size i = 0; i < tmp.size(); ++i) {
1338
1339 // linear approximation of step
1340 // Real ax = std::abs(x[i]);
1341 // if (ax < delta) {
1342 // tmp.set(i, 1.0 / (2.0 * delta));
1343 // }
1344
1345 // logistic function
1346 // f(x) = 1 / (1 + exp(-x / delta))
1347 // f'(x) = exp(-x/delta) / (delta * (1 + exp(-x / delta))^2), this is an even function
1348 tmp.set(i, std::exp(-1.0 / delta * x[i]) / (delta * std::pow(1.0 + std::exp(-1.0 / delta * x[i]), 2.0)));
1349 }
1350
1351 stopCalcStats(x.size() * 8);
1352
1353 return tmp;
1354}
1355
1356std::function<void(RandomVariable&)> RandomVariable::deleter =
1357 std::function<void(RandomVariable&)>([](RandomVariable& x) { x.clear(); });
1358
1359std::vector<std::function<RandomVariable(const std::vector<const RandomVariable*>&)>>
1360multiPathBasisSystem(Size dim, Size order, QuantLib::LsmBasisSystem::PolynomialType type, Size basisSystemSizeBound) {
1361 thread_local static std::map<std::pair<Size, Size>,
1362 std::vector<std::function<RandomVariable(const std::vector<const RandomVariable*>&)>>>
1363 cache;
1364 QL_REQUIRE(order > 0, "multiPathBasisSystem: order must be > 0");
1365 if (basisSystemSizeBound != Null<Size>()) {
1366 while (RandomVariableLsmBasisSystem::size(dim, order) > static_cast<Real>(basisSystemSizeBound) && order > 1) {
1367 --order;
1368 }
1369 }
1370 if (auto c = cache.find(std::make_pair(dim, order)); c != cache.end())
1371 return c->second;
1372 auto tmp = RandomVariableLsmBasisSystem::multiPathBasisSystem(dim, order, type);
1373 cache[std::make_pair(dim, order)] = tmp;
1374 return tmp;
1375}
1376
1377} // namespace QuantExt
static std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > multiPathBasisSystem(Size dim, Size order, QuantLib::LsmBasisSystem::PolynomialType type)
bool operator<(const Dividend &d1, const Dividend &d2)
BucketedDistribution operator+(const BucketedDistribution &lhs, const BucketedDistribution &rhs)
Sum probabilities in two bucketed distributions with equal buckets.
std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > multiPathBasisSystem(Size dim, Size order, QuantLib::LsmBasisSystem::PolynomialType type, Size basisSystemSizeBound)
bool operator!=(const Filter &a, const Filter &b)
RandomVariable sqrt(RandomVariable x)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
RandomVariable variance(const RandomVariable &r)
RandomVariable cos(RandomVariable x)
CompiledFormula exp(CompiledFormula x)
RandomVariable sin(RandomVariable x)
RandomVariableRegressionMethod
bool close_enough_all(const RandomVariable &x, const RandomVariable &y)
Filter operator!(Filter x)
RandomVariable conditionalResult(const Filter &f, RandomVariable x, const RandomVariable &y)
CompiledFormula min(CompiledFormula x, const CompiledFormula &y)
Filter operator>=(const RandomVariable &x, const RandomVariable &y)
RandomVariable indicatorDerivative(const RandomVariable &x, const double eps)
RandomVariable black(const RandomVariable &omega, const RandomVariable &t, const RandomVariable &strike, const RandomVariable &forward, const RandomVariable &impliedVol)
RandomVariable covariance(const RandomVariable &r, const RandomVariable &s)
bool operator==(const Dividend &d1, const Dividend &d2)
Compare dividends.
CompiledFormula pow(CompiledFormula x, const CompiledFormula &y)
std::vector< const RandomVariable * > vec2vecptr(const std::vector< RandomVariable > &values)
RandomVariable expectation(const RandomVariable &r)
RandomVariable normalCdf(RandomVariable x)
RandomVariable conditionalExpectation(const std::vector< const RandomVariable * > &regressor, const std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > &basisFn, const Array &coefficients)
Filter operator&&(Filter x, const Filter &y)
RandomVariable applyInverseFilter(RandomVariable x, const Filter &f)
RandomVariable indicatorGeq(RandomVariable x, const RandomVariable &y, const Real trueVal, const Real falseVal, const Real eps)
CompiledFormula max(CompiledFormula x, const CompiledFormula &y)
CompiledFormula abs(CompiledFormula x)
RandomVariable applyFilter(RandomVariable x, const Filter &f)
RandomVariable indicatorEq(RandomVariable x, const RandomVariable &y, const Real trueVal, const Real falseVal)
RandomVariable normalPdf(RandomVariable x)
Filter equal(Filter x, const Filter &y)
Filter operator||(Filter x, const Filter &y)
Matrix pcaCoordinateTransform(const std::vector< const RandomVariable * > &regressor, const Real varianceCutoff)
CompiledFormula log(CompiledFormula x)
void checkTimeConsistency(const RandomVariable &x, const RandomVariable &y)
Real sum(const Cash &c, const Cash &d)
Definition: bondbasket.cpp:107
CompiledFormula operator-(CompiledFormula x, const CompiledFormula &y)
CompiledFormula operator/(CompiledFormula x, const CompiledFormula &y)
Array regressionCoefficients(RandomVariable r, std::vector< const RandomVariable * > regressor, const std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > &basisFn, const Filter &filter, const RandomVariableRegressionMethod regressionMethod, const std::string &debugLabel)
Filter operator<=(const RandomVariable &x, const RandomVariable &y)
RandomVariable indicatorGt(RandomVariable x, const RandomVariable &y, const Real trueVal, const Real falseVal, const Real eps)
std::vector< RandomVariable > applyCoordinateTransform(const std::vector< const RandomVariable * > &regressor, const Matrix &transform)
BucketedDistribution operator*(Real factor, const BucketedDistribution &rhs)
bool operator>(const Currency &, const Currency &)
Definition: bondbasket.hpp:37
ql utility class for random variables
void set(const Size i, const bool v)
bool deterministic() const
void setAll(const bool v)
Size size() const
bool initialised() const
bool at(const Size i) const
Filter & operator=(const Filter &r)
void resetSize(const Size n)
static std::function< void(RandomVariable &)> deleter
void copyToMatrixCol(QuantLib::Matrix &, const Size j) const
RandomVariable & operator+=(const RandomVariable &)
void checkTimeConsistencyAndUpdate(const Real t)
Real at(const Size i) const
RandomVariable & operator=(const RandomVariable &r)
void set(const Size i, const Real v)
RandomVariable & operator-=(const RandomVariable &)
RandomVariable & operator*=(const RandomVariable &)
void copyToArray(QuantLib::Array &array) const
RandomVariable & operator/=(const RandomVariable &)
void setAll(const Real v)
void resetSize(const Size n)