quantlib 中 Nelson-Siegel 收益率曲线的参数限制
Parameter restrictions for Nelson-Siegel yield curve in quantlib
我在 Python 中使用 QL 并翻译了部分示例文件
http://quantlib.org/reference/_fitted_bond_curve_8cpp-example.html#_a25;
如何用债券拟合收益率曲线以拟合 Nelson-Siegel
一组给定校准债券的收益率曲线。
像往常一样执行这种非线性拟合时,结果强烈依赖于
在初始条件和许多(经济上无意义的)最小值
objective 函数存在。这就是为什么要对参数施加约束
对成功至关重要。举个例子,有时我会变得消极
tau/lambda 参数和我的收益率曲线不同。
我没有找到如何在中指定这些参数约束
NelsonSiegelFitting 或 FittedBondDiscountCurve 类。我可以
想象一下,在QL中进行NS拟合的任何人都会遇到同样的情况
问题。
感谢 Andres Hernandez 的回答:
目前不可以。然而,扩展 QL 以允许它非常容易,但我认为它需要在 c++ 上完成。因此,即使您在 python 中使用 QL,您是否可以修改 c++ 代码并导出新的绑定?如果是,那么你可以使用下面的代码,如果不是,那么我可以将它签入代码,但是 pull request 需要一些时间才能被接受。如果您可以触摸代码,可以添加如下内容:
在nonlinearfittingmethods.hpp中:
class NelsonSiegelConstrainedFitting
: public FittedBondDiscountCurve::FittingMethod {
public:
NelsonSiegelConstrainedFitting(const Array& lower, const Array& upper,
const Array& weights = Array(),
boost::shared_ptr<OptimizationMethod> optimizationMethod
= boost::shared_ptr<OptimizationMethod>());
std::auto_ptr<FittedBondDiscountCurve::FittingMethod> clone() const;
private:
Size size() const;
DiscountFactor discountFunction(const Array& x, Time t) const;
Array lower_, upper_;
};
在nonlinearfittingmethods.cpp中:
NelsonSiegelConstrainedFitting::NelsonSiegelConstrainedFitting(
const Array& lower, const Array& upper, const Array& weights,
boost::shared_ptr<OptimizationMethod> optimizationMethod)
: FittedBondDiscountCurve::FittingMethod(true, weights, optimizationMethod),
lower_(lower), upper_(upper){
QL_REQUIRE(lower_.size() == 4, "Lower constraint must have 4 elements");
QL_REQUIRE(upper_.size() == 4, "Lower constraint must have 4 elements");
}
std::auto_ptr<FittedBondDiscountCurve::FittingMethod>
NelsonSiegelConstrainedFitting::clone() const {
return std::auto_ptr<FittedBondDiscountCurve::FittingMethod>(
new NelsonSiegelFitting(*this));
}
Size NelsonSiegelConstrainedFitting::size() const {
return 4;
}
DiscountFactor NelsonSiegelConstrainedFitting::discountFunction(const Array& x,
Time t) const {
///extreme values of kappa result in colinear behaviour of x[1] and x[2], so it should be constrained not only
///to be positive, but also not very extreme
Real kappa = lower_[3] + upper_[3]/(1.0+exp(-x[3]));
Real x0 = lower_[0] + upper_[0]/(1.0+exp(-x[0])),
x1 = lower_[1] + upper_[1]/(1.0+exp(-x[1])),
x2 = lower_[2] + upper_[2]/(1.0+exp(-x[2])),;
Real zeroRate = x0 + (x1 + x2)*
(1.0 - std::exp(-kappa*t))/
((kappa+QL_EPSILON)*(t+QL_EPSILON)) -
x2*std::exp(-kappa*t);
DiscountFactor d = std::exp(-zeroRate * t) ;
return d;
}
然后您需要将它添加到 swig 界面,但这样做应该很简单。
我在 Python 中使用 QL 并翻译了部分示例文件 http://quantlib.org/reference/_fitted_bond_curve_8cpp-example.html#_a25; 如何用债券拟合收益率曲线以拟合 Nelson-Siegel 一组给定校准债券的收益率曲线。
像往常一样执行这种非线性拟合时,结果强烈依赖于 在初始条件和许多(经济上无意义的)最小值 objective 函数存在。这就是为什么要对参数施加约束 对成功至关重要。举个例子,有时我会变得消极 tau/lambda 参数和我的收益率曲线不同。
我没有找到如何在中指定这些参数约束 NelsonSiegelFitting 或 FittedBondDiscountCurve 类。我可以 想象一下,在QL中进行NS拟合的任何人都会遇到同样的情况 问题。
感谢 Andres Hernandez 的回答:
目前不可以。然而,扩展 QL 以允许它非常容易,但我认为它需要在 c++ 上完成。因此,即使您在 python 中使用 QL,您是否可以修改 c++ 代码并导出新的绑定?如果是,那么你可以使用下面的代码,如果不是,那么我可以将它签入代码,但是 pull request 需要一些时间才能被接受。如果您可以触摸代码,可以添加如下内容:
在nonlinearfittingmethods.hpp中:
class NelsonSiegelConstrainedFitting
: public FittedBondDiscountCurve::FittingMethod {
public:
NelsonSiegelConstrainedFitting(const Array& lower, const Array& upper,
const Array& weights = Array(),
boost::shared_ptr<OptimizationMethod> optimizationMethod
= boost::shared_ptr<OptimizationMethod>());
std::auto_ptr<FittedBondDiscountCurve::FittingMethod> clone() const;
private:
Size size() const;
DiscountFactor discountFunction(const Array& x, Time t) const;
Array lower_, upper_;
};
在nonlinearfittingmethods.cpp中:
NelsonSiegelConstrainedFitting::NelsonSiegelConstrainedFitting(
const Array& lower, const Array& upper, const Array& weights,
boost::shared_ptr<OptimizationMethod> optimizationMethod)
: FittedBondDiscountCurve::FittingMethod(true, weights, optimizationMethod),
lower_(lower), upper_(upper){
QL_REQUIRE(lower_.size() == 4, "Lower constraint must have 4 elements");
QL_REQUIRE(upper_.size() == 4, "Lower constraint must have 4 elements");
}
std::auto_ptr<FittedBondDiscountCurve::FittingMethod>
NelsonSiegelConstrainedFitting::clone() const {
return std::auto_ptr<FittedBondDiscountCurve::FittingMethod>(
new NelsonSiegelFitting(*this));
}
Size NelsonSiegelConstrainedFitting::size() const {
return 4;
}
DiscountFactor NelsonSiegelConstrainedFitting::discountFunction(const Array& x,
Time t) const {
///extreme values of kappa result in colinear behaviour of x[1] and x[2], so it should be constrained not only
///to be positive, but also not very extreme
Real kappa = lower_[3] + upper_[3]/(1.0+exp(-x[3]));
Real x0 = lower_[0] + upper_[0]/(1.0+exp(-x[0])),
x1 = lower_[1] + upper_[1]/(1.0+exp(-x[1])),
x2 = lower_[2] + upper_[2]/(1.0+exp(-x[2])),;
Real zeroRate = x0 + (x1 + x2)*
(1.0 - std::exp(-kappa*t))/
((kappa+QL_EPSILON)*(t+QL_EPSILON)) -
x2*std::exp(-kappa*t);
DiscountFactor d = std::exp(-zeroRate * t) ;
return d;
}
然后您需要将它添加到 swig 界面,但这样做应该很简单。