19#include <ql/experimental/fx/blackdeltacalculator.hpp>
20#include <ql/math/optimization/levenbergmarquardt.hpp>
21#include <ql/quotes/simplequote.hpp>
41FxBsBuilder::FxBsBuilder(
const QuantLib::ext::shared_ptr<ore::data::Market>& market,
const QuantLib::ext::shared_ptr<FxBsData>& data,
42 const std::string& configuration,
const std::string& referenceCalibrationGrid)
43 : market_(market), configuration_(configuration), data_(
data), referenceCalibrationGrid_(referenceCalibrationGrid) {
49 std::string ccyPair = ccy.code() + domesticCcy.code();
51 LOG(
"Start building FxBs model for " << ccyPair);
67 alwaysForwardNotifications();
70 if (
data->calibrateSigma()) {
76 Array sigmaTimes, sigma;
78 QL_REQUIRE(
data->sigmaTimes().size() == 0,
"empty sigma tme grid expected");
79 QL_REQUIRE(
data->sigmaValues().size() == 1,
"initial sigma grid size 1 expected");
80 sigmaTimes = Array(0);
81 sigma = Array(
data_->sigmaValues().begin(),
data_->sigmaValues().end());
86 sigma = Array(sigmaTimes.size() + 1,
data->sigmaValues()[0]);
89 sigmaTimes = Array(
data_->sigmaTimes().begin(),
data_->sigmaTimes().end());
90 sigma = Array(
data_->sigmaValues().begin(),
data_->sigmaValues().end());
91 QL_REQUIRE(sigma.size() == sigmaTimes.size() + 1,
"sigma grids do not match");
95 DLOG(
"sigmaTimes before calibration: " << sigmaTimes);
96 DLOG(
"sigma before calibration: " << sigma);
100 QuantLib::ext::make_shared<QuantExt::FxBsPiecewiseConstantParametrization>(ccy,
fxSpot_, sigmaTimes, sigma);
104 QL_FAIL(
"interpolation type not supported for FX");
122 return data_->calibrateSigma() &&
144 BlackDeltaCalculator bdc(Option::Type::Call, DeltaVolQuote::DeltaType::Spot,
fxSpot_->value(),
146 fxVol_->blackVol(expiryDate, Null<Real>()) *
sqrt(
fxVol_->timeFromReference(expiryDate)));
150 strikeValue = bdc.atmStrike(DeltaVolQuote::AtmFwd);
152 strikeValue = strike.
value;
154 QL_FAIL(
"strike type ATMF or Absolute expected");
155 Handle<Quote> quote(QuantLib::ext::make_shared<SimpleQuote>(
fxVol_->blackVol(expiryDate, strikeValue)));
160 Date today = Settings::instance().evaluationDate();
161 std::string expiryString =
data_->optionExpiries()[j];
162 bool expiryDateBased;
166 Date expiryDate = expiryDateBased ? expiryDb : today + expiryPb;
171 bool hasUpdated =
false;
177 Size optionCounter = 0;
178 for (Size j = 0; j <
data_->optionExpiries().
size(); j++) {
193 QL_REQUIRE(
data_->optionExpiries().size() ==
data_->optionStrikes().size(),
"fx option vector size mismatch");
196 Date lastRefCalDate = Date::minDate();
197 std::vector<Date> referenceCalibrationDates;
202 std::vector<Time> expiryTimes;
203 for (Size j = 0; j <
data_->optionExpiries().
size(); j++) {
208 std::lower_bound(referenceCalibrationDates.begin(), referenceCalibrationDates.end(), expiryDate);
209 if (refCalDate == referenceCalibrationDates.end() || *refCalDate > lastRefCalDate) {
212 Handle<Quote> quote(QuantLib::ext::make_shared<SimpleQuote>(
fxVol_->blackVol(expiryDate, strikeValue)));
213 QuantLib::ext::shared_ptr<QuantExt::FxEqOptionHelper>
helper = QuantLib::ext::make_shared<QuantExt::FxEqOptionHelper>(
216 helper->performCalculations();
217 expiryTimes.push_back(
ytsDom_->timeFromReference(
helper->option()->exercise()->date(0)));
218 DLOG(
"Added FxEqOptionHelper " << (
data_->foreignCcy() +
data_->domesticCcy()) <<
" "
219 << QuantLib::io::iso_date(expiryDate) <<
" " <<
helper->strike() <<
" "
221 if (refCalDate != referenceCalibrationDates.end())
222 lastRefCalDate = *refCalDate;
228 std::sort(expiryTimes.begin(), expiryTimes.end());
229 auto itExpiryTime = unique(expiryTimes.begin(), expiryTimes.end());
230 expiryTimes.resize(distance(expiryTimes.begin(), itExpiryTime));
233 for (Size j = 0; j < expiryTimes.size(); j++)
virtual void forceRecalculate()
const std::vector< QuantLib::Date > & dates() const
QuantLib::ext::shared_ptr< QuantExt::FxBsParametrization > parametrization_
const std::string configuration_
void forceRecalculate() override
void performCalculations() const override
bool volSurfaceChanged(const bool updateCache) const
Handle< YieldTermStructure > ytsFor_
QuantLib::ext::shared_ptr< QuantExt::MarketObserver > marketObserver_
std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > optionBasket() const
Handle< BlackVolTermStructure > fxVol_
const QuantLib::ext::shared_ptr< FxBsData > data_
Real optionStrike(const Size j) const
std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > optionBasket_
void setCalibrationDone() const
std::vector< QuantLib::Real > fxVolCache_
Handle< YieldTermStructure > ytsDom_
QuantLib::ext::shared_ptr< QuantExt::FxBsParametrization > parametrization() const
Date optionExpiry(const Size j) const
bool requiresRecalibration() const override
const QuantLib::ext::shared_ptr< ore::data::Market > market_
const std::string referenceCalibrationGrid_
Real error() const
Return calibration error.
void buildOptionBasket() const
std::vector< bool > optionActive_
FxBsBuilder(const QuantLib::ext::shared_ptr< ore::data::Market > &market, const QuantLib::ext::shared_ptr< FxBsData > &data, const std::string &configuration=Market::defaultConfiguration, const std::string &referenceCalibrationGrid="")
Constructor.
Builder for a Lognormal FX model component.
Strike parseStrike(const std::string &s)
Convert text to Strike.
boost::variant< QuantLib::Date, QuantLib::Period > parseDateOrPeriod(const string &s)
Convert text to QuantLib::Period or QuantLib::Date.
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Classes and functions for log message handling.
#define LOG(text)
Logging Macro (Level = Notice)
#define DLOG(text)
Logging Macro (Level = Debug)
RandomVariable sqrt(RandomVariable x)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Size size(const ValueType &v)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper