24#ifndef quantext_stabilised_glls_hpp
25#define quantext_stabilised_glls_hpp
27#include <ql/math/array.hpp>
28#include <ql/math/comparison.hpp>
29#include <ql/math/generallinearleastsquares.hpp>
31#include <boost/accumulators/accumulators.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/make_shared.hpp>
36#include <boost/type_traits.hpp>
42using namespace boost::accumulators;
58 template <
class xContainer,
class yContainer,
class vContainer>
72 Size
size()
const {
return glls_->residuals().size(); }
73 Size
dim()
const {
return glls_->coefficients().size(); }
76 template <
class xType,
class vContainer>
77 Real
eval(xType x, vContainer& v,
typename boost::enable_if<
typename boost::is_arithmetic<xType>::type>::type* = 0);
80 template <
class xType,
class vContainer>
81 Real
eval(xType x, vContainer& v,
82 typename boost::disable_if<
typename boost::is_arithmetic<xType>::type>::type* = 0);
88 QuantLib::ext::shared_ptr<GeneralLinearLeastSquares>
glls_;
90 template <
class xContainer,
class yContainer,
class vContainer>
92 xContainer x, yContainer y, vContainer v,
93 typename boost::enable_if<
typename boost::is_arithmetic<typename xContainer::value_type>::type>::type* = 0);
95 template <
class xContainer,
class yContainer,
class vContainer>
97 xContainer x, yContainer y, vContainer v,
98 typename boost::disable_if<
typename boost::is_arithmetic<typename xContainer::value_type>::type>::type* = 0);
101template <
class xContainer,
class yContainer,
class vContainer>
104 :
a_(v.end() - v.begin(), 0.0), err_(v.end() - v.begin(), 0.0), residuals_(y.end() - y.begin()),
105 standardErrors_(v.end() - v.begin()), method_(method) {
109template <
class xContainer,
class yContainer,
class vContainer>
111 xContainer x, yContainer y, vContainer v,
112 typename boost::enable_if<
typename boost::is_arithmetic<typename xContainer::value_type>::type>::type*) {
114 std::vector<Real> xData(x.end() - x.begin(), 0.0), yData(y.end() - y.begin(), 0.0);
124 Real mx = 0.0, my = 0.0;
125 for (Size i = 0; i < static_cast<Size>(x.end() - x.begin()); ++i) {
126 mx = std::max(std::abs(x[i]), mx);
128 if (!QuantLib::close_enough(mx, 0.0))
130 for (Size i = 0; i < static_cast<Size>(y.end() - y.begin()); ++i) {
131 my = std::max(std::abs(y[i]), my);
133 if (!QuantLib::close_enough(my, 0.0))
138 accumulator_set<Real, stats<boost::accumulators::tag::mean, boost::accumulators::tag::variance> > acc;
139 for (Size i = 0; i < static_cast<Size>(x.end() - x.begin()); ++i) {
143 Real tmp = boost::accumulators::variance(acc);
144 if (!QuantLib::close_enough(tmp, 0.0))
146 accumulator_set<Real, stats<boost::accumulators::tag::mean, boost::accumulators::tag::variance> > acc2;
147 for (Size i = 0; i < static_cast<Size>(y.end() - y.begin()); ++i) {
151 Real tmp2 = boost::accumulators::variance(acc2);
152 if (!QuantLib::close_enough(tmp2, 0.0))
157 QL_FAIL(
"unknown stabilisation method");
160 for (Size i = 0; i < static_cast<Size>(x.end() - x.begin()); ++i) {
163 for (Size i = 0; i < static_cast<Size>(y.end() - y.begin()); ++i) {
167 glls_ = QuantLib::ext::make_shared<GeneralLinearLeastSquares>(xData, yData, v);
170template <
class xContainer,
class yContainer,
class vContainer>
172 xContainer x, yContainer y, vContainer v,
173 typename boost::disable_if<
typename boost::is_arithmetic<typename xContainer::value_type>::type>::type*) {
175 QL_REQUIRE(x.end() - x.begin() > 0,
"StabilisedGLLS::calculate(): x container is empty");
176 QL_REQUIRE(x[0].end() - x[0].begin() > 0,
"StabilisedGLLS:calculate(): x contains empty point(s)");
178 std::vector<Array> xData(x.end() - x.begin(), Array(x[0].end() - x[0].begin(), 0.0));
179 std::vector<Real> yData(y.end() - y.begin(), 0.0);
181 xShift_ = Array(x[0].end() - x[0].begin(), 0.0);
189 Array m(x[0].end() - x[0].begin(), 0.0);
191 for (Size i = 0; i < static_cast<Size>(x.end() - x.begin()); ++i) {
192 for (Size j = 0; j < m.size(); ++j) {
193 m[j] = std::max(std::abs(x[i][j]), m[j]);
196 for (Size j = 0; j < m.size(); ++j) {
197 if (!QuantLib::close_enough(m[j], 0.0))
200 for (Size i = 0; i < static_cast<Size>(y.end() - y.begin()); ++i) {
201 my = std::max(std::abs(y[i]), my);
203 if (!QuantLib::close_enough(my, 0.0))
208 std::vector<accumulator_set<Real, stats<boost::accumulators::tag::mean, boost::accumulators::tag::variance> > > acc(x[0].end() - x[0].begin());
209 for (Size i = 0; i < static_cast<Size>(x.end() - x.begin()); ++i) {
210 for (Size j = 0; j < acc.size(); ++j) {
214 for (Size j = 0; j < acc.size(); ++j) {
216 Real tmp = boost::accumulators::variance(acc[j]);
217 if (!QuantLib::close_enough(tmp, 0.0))
220 accumulator_set<Real, stats<boost::accumulators::tag::mean, boost::accumulators::tag::variance> > acc2;
221 for (Size i = 0; i < static_cast<Size>(y.end() - y.begin()); ++i) {
225 Real tmp2 = boost::accumulators::variance(acc2);
226 if (!QuantLib::close_enough(tmp2, 0.0))
231 QL_FAIL(
"unknown stabilisation method");
235 for (Size i = 0; i < static_cast<Size>(x.end() - x.begin()); ++i) {
240 for (Size i = 0; i < static_cast<Size>(y.end() - y.begin()); ++i) {
244 glls_ = QuantLib::ext::make_shared<GeneralLinearLeastSquares>(xData, yData, v);
247template <
class xType,
class vContainer>
249 typename boost::enable_if<
typename boost::is_arithmetic<xType>::type>::type*) {
250 QL_REQUIRE(v.size() ==
glls_->dim(),
251 "StabilisedGLLS::eval(): v size (" << v.size() <<
") must be equal to dim (" <<
glls_->dim());
253 for (Size i = 0; i < v.size(); ++i) {
259template <
class xType,
class vContainer>
261 typename boost::disable_if<
typename boost::is_arithmetic<xType>::type>::type*) {
262 QL_REQUIRE(v.size() ==
glls_->dim(),
263 "StabilisedGLLS::eval(): v size (" << v.size() <<
") must be equal to dim (" <<
glls_->dim());
265 for (Size i = 0; i < v.size(); ++i) {
266 xType xNew(x.end() - x.begin());
267 for (Size j = 0; j < static_cast<Size>(x.end() - x.begin()); ++j) {
270 tmp +=
glls_->coefficients()[i] * v[i](xNew);
Numerically stabilised general linear least squares.
const Real yShift() const
void calculate(xContainer x, yContainer y, vContainer v, typename boost::enable_if< typename boost::is_arithmetic< typename xContainer::value_type >::type >::type *=0)
const Array & transformedStandardErrors() const
const Array & transformedCoefficients() const
Real eval(xType x, vContainer &v, typename boost::enable_if< typename boost::is_arithmetic< xType >::type >::type *=0)
evaluate regression function in terms of original x, y
const Real yMultiplier() const
const Array & xMultiplier() const
Transformation parameters (u => (u + shift) * multiplier for u = x, y)
const Array & transformedResiduals() const
const Array & xShift() const
const Array & transformedError() const
StabilisedGLLS(const xContainer &x, const yContainer &y, const vContainer &v, const Method method=MeanStdDev)
QuantLib::ext::shared_ptr< GeneralLinearLeastSquares > glls_