21#include <ql/cashflows/cashflows.hpp>
22#include <ql/math/optimization/constraint.hpp>
23#include <ql/math/optimization/costfunction.hpp>
24#include <ql/math/optimization/simplex.hpp>
25#include <ql/pricingengines/bond/bondfunctions.hpp>
26#include <ql/termstructures/yield/fittedbonddiscountcurve.hpp>
27#include <ql/time/daycounters/simpledaycounter.hpp>
28#include <ql/utilities/dataformatters.hpp>
35 class FittedBondDiscountCurve::FittingMethod::FittingCost
36 :
public CostFunction {
37 friend class FittedBondDiscountCurve::FittingMethod;
40 FittedBondDiscountCurve::FittingMethod* fittingMethod);
41 Real value(
const Array& x)
const override;
42 Array values(
const Array& x)
const override;
45 FittedBondDiscountCurve::FittingMethod* fittingMethod_;
52 vector<ext::shared_ptr<BondHelper> > bondHelpers,
59 Size maxStationaryStateIterations)
61 maxEvaluations_(maxEvaluations), simplexLambda_(simplexLambda),
62 maxStationaryStateIterations_(maxStationaryStateIterations), guessSolution_(
std::move(guess)),
63 bondHelpers_(
std::move(bondHelpers)), fittingMethod_(fittingMethod) {
70 const Date& referenceDate,
71 vector<ext::shared_ptr<BondHelper> > bondHelpers,
78 Size maxStationaryStateIterations)
80 maxEvaluations_(maxEvaluations), simplexLambda_(simplexLambda),
81 maxStationaryStateIterations_(maxStationaryStateIterations), guessSolution_(
std::move(guess)),
82 bondHelpers_(
std::move(bondHelpers)), fittingMethod_(fittingMethod) {
91 QL_REQUIRE(!
bondHelpers_.empty(),
"no bondHelpers given");
101 bond->maturityDate() <<
") has an invalid price quote");
102 Date bondSettlement = bond->settlementDate();
103 QL_REQUIRE(bondSettlement>=refDate,
105 bondSettlement <<
") before curve reference date (" <<
109 bondSettlement <<
" settlement date (maturity"
110 " being " << bond->maturityDate() <<
")");
121 bool constrainAtZero,
122 const Array& weights,
123 ext::shared_ptr<OptimizationMethod> optimizationMethod,
125 const Real minCutoffTime,
126 const Real maxCutoffTime)
127 : constrainAtZero_(constrainAtZero), weights_(weights), l2_(
std::move(l2)),
128 calculateWeights_(weights.empty()), optimizationMethod_(
std::move(optimizationMethod)),
129 minCutoffTime_(minCutoffTime), maxCutoffTime_(maxCutoffTime) {}
137 Size n = curve_->bondHelpers_.size();
138 costFunction_ = ext::make_shared<FittingCost>(
this);
140 for (
auto& bondHelper : curve_->bondHelpers_) {
141 bondHelper->setTermStructure(curve_);
144 if (calculateWeights_) {
145 if (weights_.empty())
148 Real squaredSum = 0.0;
149 for (
Size i=0; i<curve_->bondHelpers_.size(); ++i) {
150 ext::shared_ptr<Bond> bond = curve_->bondHelpers_[i]->bond();
152 Real cleanPrice = curve_->bondHelpers_[i]->quote()->value();
154 Date bondSettlement = bond->settlementDate();
156 yieldDC, yieldComp, yieldFreq,
160 yieldDC, yieldComp, yieldFreq,
163 weights_[i] = 1.0/dur;
164 squaredSum += weights_[i]*weights_[i];
166 weights_ /= std::sqrt(squaredSum);
169 QL_REQUIRE(weights_.size() == n,
170 "Given weights do not cover all boostrapping helpers");
173 QL_REQUIRE(l2_.size() == size(),
174 "Given penalty factors do not cover all parameters");
180 FittingCost& costFunction = *costFunction_;
184 Array x(size(), 0.0);
185 if (!curve_->guessSolution_.empty()) {
186 x = curve_->guessSolution_;
189 if (curve_->maxEvaluations_ == 0)
197 QL_REQUIRE(!curve_->guessSolution_.empty(),
"no guess provided");
199 solution_ = curve_->guessSolution_;
201 numberOfIterations_ = 0;
202 costValue_ = costFunction.value(solution_);
209 ext::shared_ptr<OptimizationMethod> optimization = optimizationMethod_;
211 optimization = ext::make_shared<Simplex>(curve_->simplexLambda_);
213 Problem problem(costFunction, constraint, x);
215 Real rootEpsilon = curve_->accuracy_;
216 Real functionEpsilon = curve_->accuracy_;
217 Real gradientNormEpsilon = curve_->accuracy_;
220 curve_->maxStationaryStateIterations_,
223 gradientNormEpsilon);
225 errorCode_ = optimization->minimize(problem,endCriteria);
232 curve_->guessSolution_ = solution_;
236 FittedBondDiscountCurve::FittingMethod::FittingCost::FittingCost(
241 Real FittedBondDiscountCurve::FittingMethod::FittingCost::value(
242 const Array& x)
const {
243 Real squaredError = 0.0;
244 Array vals = values(x);
245 for (
Real val : vals) {
251 Array FittedBondDiscountCurve::FittingMethod::FittingCost::values(
const Array &x)
const {
260 for (
Size i=0; i<n; ++i) {
261 ext::shared_ptr<BondHelper> helper =
fittingMethod_->curve_->bondHelpers_[i];
262 Real error = helper->impliedQuote() - helper->quote()->value();
264 values[i] = weightedError * weightedError;
268 for (
Size i = 0; i < N; ++i) {
1-D array used in linear algebra.
static Date minDate()
earliest allowed date
Criteria to end optimization process:
Base fitting method used to construct a fitted bond discount curve.
virtual void init()
rerun every time instruments/referenceDate changes
FittingMethod(bool constrainAtZero=true, const Array &weights=Array(), ext::shared_ptr< OptimizationMethod > optimizationMethod=ext::shared_ptr< OptimizationMethod >(), Array l2=Array(), Real minCutoffTime=0.0, Real maxCutoffTime=QL_MAX_REAL)
constructors
Discount curve fitted to a set of fixed-coupon bonds.
void performCalculations() const override
std::vector< ext::shared_ptr< BondHelper > > bondHelpers_
Clone< FittingMethod > fittingMethod_
FittedBondDiscountCurve(Natural settlementDays, const Calendar &calendar, std::vector< ext::shared_ptr< BondHelper > > bonds, const DayCounter &dayCounter, const FittingMethod &fittingMethod, Real accuracy=1.0e-10, Size maxEvaluations=10000, Array guess=Array(), Real simplexLambda=1.0, Size maxStationaryStateIterations=100)
reference date based on current evaluation date
Constrained optimization problem.
const Array & currentValue() const
current value of the local minimum
Real functionValue() const
value of cost function
Integer functionEvaluation() const
number of evaluation of cost function
virtual const Date & referenceDate() const
the date at which discount = 1.0 and/or variance = 0.0
Interest-rate term structure.
Frequency
Frequency of events.
detail::ordinal_holder ordinal(Size)
outputs naturals as 1st, 2nd, 3rd...
Real Time
continuous quantity with 1-year units
unsigned QL_INTEGER Natural
positive integer
std::size_t Size
size of a container
Compounding
Interest rate coumpounding rule.
static Rate yield(const Bond &bond, Real price, const DayCounter &dayCounter, Compounding compounding, Frequency frequency, Date settlementDate=Date(), Real accuracy=1.0e-10, Size maxIterations=100, Rate guess=0.05, Bond::Price::Type priceType=Bond::Price::Clean)
static bool isTradable(const Bond &bond, Date settlementDate=Date())
static Time duration(const Bond &bond, const InterestRate &yield, Duration::Type type=Duration::Modified, Date settlementDate=Date())