|
From: Laurent M. <lau...@gm...> - 2016-08-18 09:18:02
|
Dear Andres, thanks a lot for the answer. I will try and change my local C++ code following your instructions and recompile. However my C++ skills being limited, for the overall improvement of the library, I would be grateful if you could have a go at it. There are a number of further features that are quite handy when fitting NS/NSS curves, which I currently cannot find (please correct me if I missed it) in QuantLib: 1) Constraints on combination of parameters. If one wants to constrain the long end of the curve, constraining c0 is enough. To constrain the short end one has to constrain a combination of parameters. 2) Speaking of which, the explicit formula given here (http://quantlib.org/ reference/class_quant_lib_1_1_nelson_siegel_fitting.html) is lacking a parenthesis and is not consistent with the one implemented in the code here (https://github.com/lballabio/QuantLib/blob/053689252a9d4137d8ac47dbfb8871 7b0c369d35/ql/termstructures/yield/nonlinearfittingmethods.cpp). The short end of the curve is given by c0+c1 (which is the combination one would like to constrain as well). 3) Setting the number of iteration. That can be done via the FittedBondDiscountCurve constructor. However it is not possible to have him iterate only once (to graphically check the initial conditions, say) because maxStationaryStateIterations_ must be less than maxIterations_ without it being possible (maybe only in Pyhton) to control maxStationaryStateIterations_. 4) Fitting prices vs fitting yields. In some cases it is useful to define the objective/cost function as the sum of yield-to-maturity differences rather than the sum of price differences. Computations are slightly more complex in that case 5) Also, it would of course be great if one could create a YieldCurve object by simply inputting NS or NSS parameters. 6) Finally, from here (http://quant.stackexchange.com/a/29464/24022) I understand it is not yet possible to set the minimisation method from within Python (so the Simplex optimisation process is used by default). Again, I juste wanted to post these remarks from a user's perspective and would gladly hear that I overlooked some features. Kind regards, Laurent On 18 August 2016 at 08:45, Andres Hernandez <and...@de...> wrote: > Hi Laurent, > > currently it is not possible. However, it is very easy to extend QL to > allow it, but I think it needs to be done on the c++. So even though you > are using QL in python, can you modify the c++ code and export a new > binding? There are two ways that could be done, one is to give a new > parameter to the FittedBondDiscountCurve with the constraint. This would > anyway be a good long-term idea. However, I prefer a second option of > having a nelson siegel fitting method which rescales the parameters from > (-infinity, infinity) to (lower, higher) so that the optimizer can do > unconstrianed optimization, as not all optimizers can handle all types of > constraints. If you can touch the c++ code, then you can use the following > code, if not then I could just check it into the code, but it will take > some time for the pull request to be accepted. In case you can touch the > code, you can add something like this: > > 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<Optimization > Method>()); > 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; > } > > > You then need to add it to the swig interface, but it should be trivial to > do so. > > cheers, > Andres > > > > ----- Original message ----- > From: Laurent Millischer <lau...@gm...> > To: qua...@li... > Cc: > Subject: [Quantlib-users] Nelson Siegel with constraints > Date: Wed, Aug 17, 2016 12:18 PM > Dear all, > > I am using QL in Python and have translated parts of the example file > <http://quantlib.org/reference/_fitted_bond_curve_8cpp-example.html#_a25> > of how to fit a yield curve with bonds in order to fit a Nelson-Siegel > yield curve to a set of given calibration bonds. > > As usual when performing such a non-linear fit, the results depend > strongly on the initial conditions and many (economically meaningless) > minima of the objective function exist. This is why putting constraints on > the parameters is essential for success. To give an example, at times I get > negative tau/lambda parameters and my yield curve diverges. > > I did not find how these parameter contraints can be specified in > the NelsonSiegelFitting or the FittedBondDiscountCurve classes. I could > imagine that anyone performing NS fitting in QL will encounter the same > issue. > > Thanks a lot in advance for your help. > > Regards, > Laurent > ------------------------------------------------------------ > ------------------ > _______________________________________________ > QuantLib-users mailing list > Qua...@li... > https://lists.sourceforge.net/lists/listinfo/quantlib-users > > > > |