2016-08-17 2 views
2

Ich verwende QL in Python und habe Teile der Beispieldatei übersetzt http://quantlib.org/reference/_fitted_bond_curve_8cpp-example.html#_a25; , wie man eine Zinskurve mit Anleihen anpasst, um eine Nelson-Siegel- Zinskurve an eine Menge gegebener Kalibrierungsbonds anzupassen.Parametereinschränkungen für die Nelson-Siegel-Renditekurve in quantlib

Wie bei einer solchen nichtlinearen Anpassung üblich, hängen die Ergebnisse stark von unter den Anfangsbedingungen ab und es existieren viele (wirtschaftlich bedeutungslose) Minima der Zielfunktion. Aus diesem Grund sind Einschränkungen für die Parameter unerlässlich für den Erfolg. Um ein Beispiel zu geben, bekomme ich manchmal negative Tau/Lambda-Parameter und meine Renditekurve divergiert.

Ich habe nicht gefunden, wie diese Parameterbeschränkungen in die NelsonSiegelFitting oder die FittedBondDiscountCurve Klassen angegeben werden können. Ich könnte vorstellen, dass jemand, der die NS-Anpassung in QL durchführt, auf dasselbe Problem stoßen wird.

Antwort

2

Dank Andres Hernandez für die Antwort ein:

Derzeit ist es nicht möglich. Es ist jedoch sehr einfach, QL zu erweitern, um es zu erlauben, aber ich denke, dass es auf dem C++ getan werden muss. Also, obwohl Sie QL in Python verwenden, können Sie den C++ Code ändern und eine neue Bindung exportieren? Wenn ja, dann können Sie den folgenden Code verwenden, wenn nicht, dann könnte ich es einfach in den Code einchecken, aber es wird einige Zeit dauern, bis die Pull-Anfrage akzeptiert wird. Falls Sie den Code berühren können, können Sie so etwas wie hinzufügen:

in 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_; 
    }; 

in 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; 
} 

Anschließend müssen Sie es hinzufügen zu die Swig-Schnittstelle, aber es sollte trivial sein, dies zu tun.

Verwandte Themen