1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2014 Jose Aparicio 5 6 This file is part of QuantLib, a free-software/open-source library 7 for financial quantitative analysts and developers - http://quantlib.org/ 8 9 QuantLib is free software: you can redistribute it and/or modify it 10 under the terms of the QuantLib license. You should have received a 11 copy 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 15 This program is distributed in the hope that it will be useful, but WITHOUT 16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 17 FOR A PARTICULAR PURPOSE. See the license for more details. 18 */ 19 20 #ifndef quantlib_tcopula_policy_hpp 21 #define quantlib_tcopula_policy_hpp 22 23 #include <ql/errors.hpp> 24 #include <ql/utilities/disposable.hpp> 25 #include <ql/experimental/math/convolvedstudentt.hpp> 26 #include <ql/functional.hpp> 27 #include <boost/math/distributions/students_t.hpp> 28 #include <vector> 29 30 namespace QuantLib { 31 32 /*! \brief Student-T Latent Model's copula policy. 33 34 Describes the copula of a set of normalized Student-T independent random 35 factors to be fed into the latent variable model. 36 The latent model requires the independent variables to be of unit variance 37 so the policy expects the factors coefficients to be as usual and the T 38 variables to be normalized, the normalization is performed by the policy. 39 To normalize the random variables they are divided by the square root of 40 the variance of each T (\f$ \frac{\nu}{\nu-2}\f$) 41 */ 42 class TCopulaPolicy { 43 public: 44 /*! Stores the parameters defining the factors random variable 45 T-distributions. As it is now the latent models are restricted to 46 having the same distribution for all idiosyncratic factors, so only 47 one parameter is needed for them. 48 */ 49 typedef 50 struct { 51 std::vector<Integer> tOrders; 52 } initTraits; 53 54 /*! Delayed initialization of the distribution parameters and caches. 55 To be called by the latent model. */ 56 /* \todo 57 Explore other constructors, with different vector dimensions, defining 58 simpler combinations (only one correlation, only one variable) might 59 simplify memory. 60 */ 61 explicit TCopulaPolicy( 62 const std::vector<std::vector<Real> >& factorWeights = 63 std::vector<std::vector<Real> >(), 64 const initTraits& vals = initTraits()); 65 66 //! Number of independent random factors. numFactors() const67 Size numFactors() const { 68 return latentVarsInverters_.size() + varianceFactors_.size() - 1; 69 } 70 71 //! returns a copy of the initialization arguments 72 //... better to have a cache? getInitTraits() const73 initTraits getInitTraits() const { 74 initTraits data; 75 data.tOrders.resize(distributions_.size()); 76 for (Size i=0; i<distributions_.size(); ++i) { 77 data.tOrders[i] = static_cast<Integer>( 78 distributions_[i].degrees_of_freedom()); 79 } 80 return data; 81 } varianceFactors() const82 const std::vector<Real>& varianceFactors() const { 83 return varianceFactors_; 84 } 85 /*! Cumulative probability of a given latent variable. 86 The iVariable parameter is the index of the requested variable. 87 */ cumulativeY(Real val,Size iVariable) const88 Probability cumulativeY(Real val, Size iVariable) const { 89 #if defined(QL_EXTRA_SAFETY_CHECKS) 90 QL_REQUIRE(iVariable < latentVarsCumul_.size(), 91 "Latent variable index out of bounds."); 92 #endif 93 return latentVarsCumul_[iVariable](val); 94 } 95 //! Cumulative probability of the idiosyncratic factors (all the same) cumulativeZ(Real z) const96 Probability cumulativeZ(Real z) const { 97 return boost::math::cdf(distributions_.back(), z / 98 varianceFactors_.back()); 99 } 100 /*! Probability density of a given realization of values of the systemic 101 factors (remember they are independent). 102 Intended to be used in numerical integration of an arbitrary function 103 depending on those values. 104 */ density(const std::vector<Real> & m) const105 Probability density(const std::vector<Real>& m) const { 106 #if defined(QL_EXTRA_SAFETY_CHECKS) 107 QL_REQUIRE(m.size() == distributions_.size()-1, 108 "Incompatible sample and latent model sizes"); 109 #endif 110 Real prodDensities = 1.; 111 for(Size i=0; i<m.size(); i++) 112 prodDensities *= boost::math::pdf(distributions_[i], 113 m[i] /varianceFactors_[i]) /varianceFactors_[i]; 114 // accumulate lambda 115 return prodDensities; 116 } 117 /*! Returns the inverse of the cumulative distribution of the (modelled) 118 latent variable (as indexed by iVariable). Involves the convolution 119 of the factors' distributions. 120 */ inverseCumulativeY(Probability p,Size iVariable) const121 Real inverseCumulativeY(Probability p, Size iVariable) const { 122 #if defined(QL_EXTRA_SAFETY_CHECKS) 123 QL_REQUIRE(iVariable < latentVarsCumul_.size(), 124 "Latent variable index out of bounds."); 125 #endif 126 return latentVarsInverters_[iVariable](p); 127 } 128 /*! Returns the inverse of the cumulative distribution of the 129 idiosincratic factor. The LM here is limited to all idiosincratic 130 factors following the same distribution. 131 */ inverseCumulativeZ(Probability p) const132 Real inverseCumulativeZ(Probability p) const { 133 return boost::math::quantile(distributions_.back(), p) 134 * varianceFactors_.back(); 135 } 136 /*! Returns the inverse of the cumulative distribution of the 137 systemic factor iFactor. 138 */ inverseCumulativeDensity(Probability p,Size iFactor) const139 Real inverseCumulativeDensity(Probability p, Size iFactor) const { 140 #if defined(QL_EXTRA_SAFETY_CHECKS) 141 QL_REQUIRE(iFactor < distributions_.size()-1, 142 "Random factor variable index out of bounds."); 143 #endif 144 return boost::math::quantile(distributions_[iFactor], p) 145 * varianceFactors_[iFactor]; 146 } 147 //to use this (by default) version, the generator must be a uniform one. 148 Disposable<std::vector<Real> > 149 allFactorCumulInverter(const std::vector<Real>& probs) const; 150 private: 151 mutable std::vector<boost::math::students_t_distribution<> > 152 distributions_; 153 mutable std::vector<Real> varianceFactors_; 154 mutable std::vector<CumulativeBehrensFisher> latentVarsCumul_; 155 mutable std::vector<InverseCumulativeBehrensFisher> 156 latentVarsInverters_; 157 }; 158 159 } 160 161 #endif 162