Using Parameter and Constraint classes
I have this simple setup :
class Model
{
double myRate;
double myVol;
std::vector<double*> params_pointers;
void setParamsPointers()
{
params_pointers[0] = &myRate;
params_pointers[1] = &myVol;
}
public:
Model(double rate, double vol) : myRate(rate), myVol(vol), params_pointers(2)
{
setParamsPointers();
}
double rate() const
{
return myRate;
}
double vol() const
{
return myVol;
}
const std::vector<double*>& parameters()
{
return params_pointers;
}
};
int main()
{
Model model(0.05, 0.025);
const std::vector<double*> parameters = model.parameters();
const size_t n = parameters.size();
//bumping
for (size_t i = 0; i < n; ++i)
{
*parameters[i] += 1;
}
std::cout << model.rate() << std::endl; // prints 1.05
std::cout << model.vol() << std::endl; // prints 1.025
}
The nature (double) of my parameters is very limitating so that I dediced to use QuantLib's Parameter class instead. The changes in my client code are straightforward :
std::vector<Parameter*> params_pointers;
void setParamsPointers()
{
params_pointers[0] = new ConstantParameter(myrate, NoConstraint());
params_pointers[1] = new PositiveParameter(myVol, PositiveConstraint());
}
I added in Parameter's implementation class Impl (the class Parameter will carry a (shared) pointer to) :
virtual void tilt_up (std::vector<double>& params, const double bumpSize = 1e-8) = 0;
virtual void tilt_down(std::vector<double>& params, const double bumpSize = 1e-8) = 0;
and I added :
void tilt_up(const double bumpSize = 1e-8)
{
return impl_->tilt_up(parameter_values_, bumpSize);
}
void tilt_down(const double bumpSize = 1e-8)
{
return impl_->tilt_down(parameter_values_, bumpSize);
}
in Parameter. I have then overriden tilt_up and tilt_down in the appropriate derived classes (basically I bump up or down the values with bumpSize)
These changes done, I remark that the bumps up and down indeed do affect the parameters[i] and what they point to, but have no effect anymore at all on my model's data member myRate and myVol anymore as they had in my naïve initial setup
ConstantParameter makes a copy of myrate, this is why the link to the original member variable is broken.
I would do something like this instead:
class Model
{
std::vector<Parameter*> params_pointers;
public:
Model(double rate, double vol) : params_pointers(2)
{
params_pointers[0] = new ConstantParameter(rate, NoConstraint());
params_pointers[1] = new ConstantParameter(vol, PositiveConstraint());
}
double rate() const
{
return params_pointers[0](0.0);
}
double vol() const
{
return params_pointers[1](0.0);
}
};
which is more or less what we do in our models. This way, the rate() and vol() methods return the calibrated values.
(I would also use some kind of smart pointers instead of raw Parameter* so you don't have to remember to delete them.)
I would do something like this instead:
class Model { std::vector<Parameter*> params_pointers; public: Model(double rate, double vol) : params_pointers(2) { params_pointers[0] = new ConstantParameter(rate, NoConstraint()); params_pointers[1] = new ConstantParameter(vol, PositiveConstraint()); } double rate() const { return params_pointers[0](0.0); } double vol() const { return params_pointers[1](0.0); } };which is more or less what we do in our models. This way, the
rate()andvol()methods return the calibrated values.
I indeed tried that as well but it did not solve my issue, especially because of what pcaspers pointed out.
(I would also use some kind of smart pointers instead of raw
Parameter*so you don't have to remember to delete them.)
Indeed, I was lazily using raw pointers because using smart ones would have forced me to circumvent the non-covariance of smart pointers as a return type.
ConstantParametermakes a copy of myrate, this is why the link to the original member variable is broken.
Yes ... Would you see how to circumvent that ? or is my initial design (vector of Parameter*) simply not compatible with QL's Parameter ?
Sorry, I'm not sure what it is exactly that you're trying to reproduce from your original example. The member variables myrate and myvol are private in your code, so users of your class would access them through the corresponding methods; and those return the updated values if they use the parameter instances. If your class itself needs to access the values, it can use the methods, too. Do you have an example of a use case that isn't working?
This issue was automatically marked as stale because it has been open 60 days with no activity. Remove stale label or comment, or this will be closed in two weeks.
This issue was automatically closed because it has been stalled for two weeks with no further activity.