21#include <boost/make_shared.hpp>
22#include <boost/test/unit_test.hpp>
27#include <ql/math/comparison.hpp>
32using boost::unit_test_framework::test_suite;
36BOOST_AUTO_TEST_SUITE(TransitionMatrix)
39template <
class I> Real normEucl(I begin, I end) {
41 for (I it = begin; it != end; ++it)
43 return std::sqrt(
sum);
46template <
class I> Real normMax(I begin, I end) {
48 for (I it = begin; it != end; ++it)
49 m = std::max(std::abs(*it), m);
53template <
class I> Real normMad(I begin, I end) {
55 for (I it = begin; it != end; ++it)
57 return sum /
static_cast<Real
>(end - begin);
68 BOOST_TEST_MESSAGE(
"Testing transition matrix generator computation...");
74 Real transDataRaw[] = {
76 0.8588, 0.0976, 0.0048, 0.0000, 0.0003, 0.0000, 0.0000, 0.0000,
77 0.0092, 0.8487, 0.0964, 0.0036, 0.0015, 0.0002, 0.0000, 0.0004,
78 0.0008, 0.0224, 0.8624, 0.0609, 0.0077, 0.0021, 0.0000, 0.0002,
79 0.0008, 0.0037, 0.0602, 0.7916, 0.0648, 0.0130, 0.0011, 0.0019,
80 0.0003, 0.0008, 0.0046, 0.0402, 0.7676, 0.0788, 0.0047, 0.0140,
81 0.0001, 0.0004, 0.0016, 0.0053, 0.0586, 0.7607, 0.0274, 0.0660,
82 0.0000, 0.0000, 0.0000, 0.0100, 0.0279, 0.0538, 0.5674, 0.2535,
83 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 1.0000
86 std::vector<Real> transData(transDataRaw, transDataRaw + 8 * 8);
88 Matrix trans(8, 8, 0.0);
89 for (Size i = 0; i < 8; ++i) {
90 for (Size j = 0; j < 8; ++j) {
91 trans[i][j] = transData[i * 8 + j];
94 BOOST_TEST_MESSAGE(
"Original Transition Matrix =\n" << trans);
98 Matrix transSan(trans);
100 BOOST_TEST_MESSAGE(
"Sanitised Transition Matrix =\n" << transSan);
101 for (Size i = 0; i < transSan.rows(); ++i) {
103 for (Size j = 0; j < transSan.columns(); ++j) {
105 BOOST_CHECK_CLOSE(trans[i][j], transSan[i][j], 1E-8);
106 sum += transSan[i][j];
108 BOOST_CHECK_CLOSE(
sum, 1.0, 1E-8);
115 BOOST_TEST_MESSAGE(
"Log Transition Matrix=\n" << ltr);
118 BOOST_TEST_MESSAGE(
"Generator =\n" << gen);
124 BOOST_TEST_MESSAGE(
"Approximate Transition Matrix =\n" << approx1y);
129 Real rowDist[] = {6.769E-4, 0.032E-4, 1.021E-4, 0.0, 0.0, 0.0, 6.475E-4, 0.0};
130 Matrix diff1 = gen - ltr;
132 for (Size i = 0; i < 7; ++i) {
133 Real dist = normEucl(diff1.row_begin(i), diff1.row_end(i));
134 BOOST_TEST_MESSAGE(
"row " << i <<
" reference result " << rowDist[i] <<
" actual result " << dist);
135 if (QuantLib::close_enough(rowDist[i], 0.0)) {
136 BOOST_CHECK(dist < 100 * QL_EPSILON);
139 BOOST_CHECK_CLOSE(dist, rowDist[i], 2.0);
144 Matrix diff2 = approx1y - transSan;
146 BOOST_CHECK_CLOSE(normMax(diff2.begin(), diff2.end()), 4.599E-4, 1.0);
147 BOOST_CHECK_CLOSE(normMad(diff2.begin(), diff2.end()), 0.382E-4, 1.0);
151BOOST_AUTO_TEST_SUITE_END()
153BOOST_AUTO_TEST_SUITE_END()
QuantLib::Matrix Logm(const QuantLib::Matrix &m)
QuantLib::Matrix Expm(const QuantLib::Matrix &m)
void checkTransitionMatrix(const Matrix &t)
check if the matrix is a transition matrix, i.e. row sums are 1 and entries are non-negative
void checkGeneratorMatrix(const Matrix &g)
check if the matrix is a generator matirx, i.e. row sums are 0 and non-diagonal elements are non-nega...
Real sum(const Cash &c, const Cash &d)
Matrix generator(const Matrix &t, const Real horizon)
void sanitiseTransitionMatrix(Matrix &m)
BOOST_AUTO_TEST_CASE(testGenerator)
Fixture that can be used at top level.
utility functions for transition matrices and generators