packages feed

hasquant-0.8.0.0: cbits/qlTermStructureAux.h

#include "qlCallback.hpp"
#include "qlStdCompat.h"
#include <ql/termstructures/yield/all.hpp>
#include <ql/termstructures/globalbootstrap.hpp>
#include <ql/termstructures/localbootstrap.hpp>
#include <ql/math/interpolations/all.hpp>
#include <ql/time/calendar.hpp>
#include <ql/termstructures/credit/interpolateddefaultdensitycurve.hpp>
#include <ql/termstructures/credit/interpolatedhazardratecurve.hpp>
#include <ql/termstructures/credit/interpolatedsurvivalprobabilitycurve.hpp>
#include <ql/termstructures/credit/piecewisedefaultcurve.hpp>
#include <ql/termstructures/credit/defaultprobabilityhelpers.hpp>
#include <ql/experimental/credit/interpolatedaffinehazardratecurve.hpp>
#include <ql/termstructures/inflation/piecewisezeroinflationcurve.hpp>
#include <ql/termstructures/inflation/piecewiseyoyinflationcurve.hpp>
#include <ql/termstructures/inflation/interpolatedyoyinflationcurve.hpp>
#include <ql/termstructures/inflation/interpolatedzeroinflationcurve.hpp>
#include <ql/termstructures/volatility/equityfx/blackvariancecurve.hpp>
#include <ql/termstructures/volatility/equityfx/blackvariancesurface.hpp>
#include <ql/termstructures/volatility/zabrsmilesection.hpp>
#include <ql/termstructures/volatility/zabrinterpolatedsmilesection.hpp>
#include <functional>
#include <ql/experimental/inflation/cpicapfloortermpricesurface.hpp>
#include <ql/experimental/inflation/yoycapfloortermpricesurface.hpp>
#include <ql/experimental/inflation/interpolatedyoyoptionletstripper.hpp>
#include <ql/experimental/inflation/kinterpolatedyoyoptionletvolatilitysurface.hpp>
#include <ql/pricingengines/inflation/inflationcapfloorengines.hpp>
#include <ql/experimental/credit/constantlosslatentmodel.hpp>
#include <ql/experimental/math/gaussiancopulapolicy.hpp>
#include <ql/experimental/math/tcopulapolicy.hpp>

// Every IterativeBootstrap constructor parameter (ql/termstructures/iterativebootstrap.hpp),
// as one flat POD so the piecewise-curve entry points don't grow nine more positional
// scalars each. Mirrors QuantLib-SWIG's _IterativeBootstrap struct + make_bootstrap<Curve>()
// shape (SWIG/piecewiseyieldcurve.i). accuracy/minValue/maxValue take qlNullReal() to mean
// "upstream's default", matching their Null<Real>() defaults; dontThrow is an int because
// this header is consumed from C.
struct QlIterativeBootstrapOpts {
  double accuracy, minValue, maxValue;
  unsigned maxAttempts;
  double maxFactor, minFactor;
  int dontThrow;
  unsigned dontThrowSteps, maxEvaluations;
};

QuantLib::YieldTermStructure *qlPiecewiseYieldCurveAux(
  const QuantLib::Date &date,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int trait, int interpolator, int approximator, int approximatorArg,
  const QlIterativeBootstrapOpts& bootstrapOpts);

QuantLib::YieldTermStructure *qlPiecewiseYieldCurveGlobalBootstrapAux(
  const QuantLib::Date &date,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int trait, int interpolator, double accuracy,
  const std::vector<double>& instrumentWeights, const QlCallback& initialGuess = {});

// bootstrap: 0 = IterativeBootstrap (existing behaviour, default), 1 = GlobalBootstrap,
// wired up only for trait=Discount/interpolator=LogLinear and trait=SimpleZeroYield/
// interpolator=Linear (see qlTermStructureAux.cpp).
// This is a cbits-internal dispatch value, never exposed as a Haskell enum. The C shim entry
// points hardcode the applicable literal.
// accuracy and instrumentWeights are only used by the GlobalBootstrap branch (instrumentWeights
// empty means upstream's default, equal weighting); conversely bootstrapOpts is only used by the
// IterativeBootstrap branch.
//
// The Haskell `piecewiseYieldCurve` dispatcher selects the matching C shim for each
// `Bootstrap` constructor. This integer therefore remains limited to 0 and 1; local bootstrap
// uses its separate shim.
QuantLib::YieldTermStructure *qlPiecewiseYieldCurveAux1(
  unsigned settl, const QuantLib::Calendar &cal,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int trait, int interpolator, int approximator, int approximatorArg,
  int bootstrap, double accuracy, const std::vector<double>& instrumentWeights,
  const QlIterativeBootstrapOpts& bootstrapOpts, const QlCallback& initialGuess = {});

// PiecewiseYieldCurve<SimpleZeroYield, Linear, GlobalBootstrap> built via
// GlobalBootstrap's functor-callback constructor (additionalHelpers/additionalDates, with
// AdditionalErrors/AdditionalDates constructed internally -- see qlTermStructureAux.cpp).
// additionalDates.size() must equal additionalHelpers.size() - 2 (QL_REQUIRE'd inside).
QuantLib::YieldTermStructure *qlPiecewiseYieldCurveGlobalBootstrapFullAux(
  const QuantLib::Date& date,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& additionalHelpers,
  const std::vector<QuantLib::Date>& additionalDates,
  double accuracy, const std::vector<double>& instrumentWeights, const QlCallback& initialGuess = {});

QuantLib::YieldTermStructure *qlPiecewiseYieldCurveGlobalBootstrapFullAux(
  unsigned settl, const QuantLib::Calendar &cal,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& additionalHelpers,
  const std::vector<QuantLib::Date>& additionalDates,
  double accuracy, const std::vector<double>& instrumentWeights, const QlCallback& initialGuess = {});

// PiecewiseYieldCurve<Trait, ConvexMonotone, LocalBootstrap>, dispatched over
// ForwardRate/ZeroYield/SimpleZeroYield -- Discount is rejected (QL_FAIL) at trait=Discount:
// verified numerically incorrect with this bootstrapper/interpolator pair, see
// qlTermStructureAux.cpp. ConvexMonotone is the only upstream interpolator LocalBootstrap works
// with -- see qlTermStructureAux.cpp for why -- so it's implicit, not a Haskell-visible choice;
// quadraticity/monotonicity/convexForcePositive are its own constructor params, distinct from
// localisation/forcePositive/accuracy (LocalBootstrap's own).
QuantLib::YieldTermStructure *qlPiecewiseYieldCurveLocalBootstrapAux1(
  unsigned settl, const QuantLib::Calendar &cal,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int trait, QuantLib::Size localisation, bool forcePositive, double accuracy,
  double quadraticity, double monotonicity, bool convexForcePositive);

QuantLib::YieldTermStructure *qlPiecewiseYieldCurveLocalBootstrapAux(
  const QuantLib::Date& date,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  const QuantLib::DayCounter& dayCount,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int trait, QuantLib::Size localisation, bool forcePositive, double accuracy,
  double quadraticity, double monotonicity, bool convexForcePositive);

QuantLib::YieldTermStructure *qlInterpolatedDiscountCurveAux(
  const std::vector<QuantLib::Date>& dates,
  const std::vector<double>& dfs,
  const QuantLib::DayCounter& dayCount,
  const QuantLib::Calendar& cal,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int interpolator, int approximator, int approximatorArg);

QuantLib::YieldTermStructure *qlInterpolatedForwardCurveAux(
  const std::vector<QuantLib::Date>& dates,
  const std::vector<double>& fwds,
  const QuantLib::DayCounter& dayCount,
  const QuantLib::Calendar& cal,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int interpolator, int approximator, int approximatorArg);

QuantLib::YieldTermStructure *qlInterpolatedZeroCurveAux(
  const std::vector<QuantLib::Date>& dates,
  const std::vector<double>& yields,
  const QuantLib::DayCounter& dayCount,
  const QuantLib::Calendar& cal,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int interpolator, int approximator, int approximatorArg);

QuantLib::YieldTermStructure *qlInterpolatedSimpleZeroCurveAux(
  const std::vector<QuantLib::Date>& dates,
  const std::vector<double>& yields,
  const QuantLib::DayCounter& dayCount,
  const QuantLib::Calendar& cal,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
  const std::vector<QuantLib::Date>& jumpDates,
  int interpolator, int approximator, int approximatorArg);

QuantLib::YieldTermStructure *qlInterpolatedSpreadDiscountCurveAux(
  const QuantLib::Handle<QuantLib::YieldTermStructure>& baseCurve,
  const std::vector<QuantLib::Date>& dates,
  const std::vector<double>& dfs,
  int interpolator, int approximator, int approximatorArg);

QuantLib::YieldTermStructure *qlPiecewiseZeroSpreadedTermStructureAux(
  const QuantLib::Handle<QuantLib::YieldTermStructure>& baseCurve,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& spreads,
  const std::vector<QuantLib::Date>& dates,
  QuantLib::Compounding comp, QuantLib::Frequency freq,
  int interpolator, int approximator, int approximatorArg);

// Rejects LogLinear/LogCubic: the zero rate integrates the spread, and log interpolations have
// no primitive.
QuantLib::YieldTermStructure *qlPiecewiseForwardSpreadedTermStructureAux(
  const QuantLib::Handle<QuantLib::YieldTermStructure>& baseCurve,
  const std::vector<QuantLib::Handle<QuantLib::Quote> >& spreads,
  const std::vector<QuantLib::Date>& dates,
  int interpolator, int approximator, int approximatorArg);

// PiecewiseSpreadYieldCurve<Discount, Interpolator, IterativeBootstrap>.
QuantLib::YieldTermStructure *qlPiecewiseSpreadYieldCurveAux(
  const QuantLib::Handle<QuantLib::YieldTermStructure>& baseCurve,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  int interpolator, int approximator, int approximatorArg,
  const QlIterativeBootstrapOpts& bootstrapOpts);

// PiecewiseSpreadYieldCurve<Discount, LogLinear, GlobalBootstrap>.
QuantLib::YieldTermStructure *qlPiecewiseSpreadYieldCurveGlobalBootstrapAux(
  const QuantLib::Handle<QuantLib::YieldTermStructure>& baseCurve,
  const std::vector<QuantLib::ext::shared_ptr<QuantLib::RateHelper> >& instr,
  double accuracy, const std::vector<double>& instrumentWeights, const QlCallback& initialGuess = {});

// some credit stuff
QuantLib::DefaultProbabilityTermStructure *qlInterpolatedDefaultDensityCurveAux(
            const std::vector<QuantLib::Date>& dates,
            const std::vector<double>& densities,
            const QuantLib::DayCounter& dayCounter,
            const QuantLib::Calendar& calendar,
            const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
            const std::vector<QuantLib::Date>& jumpDates,
            int interpolator, int approximator, int approximatorArg);

QuantLib::DefaultProbabilityTermStructure *qlInterpolatedHazardRateCurveAux(
            const std::vector<QuantLib::Date>& dates,
            const std::vector<double>& hazardRates,
            const QuantLib::DayCounter& dayCounter,
            const QuantLib::Calendar& cal,
            const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
            const std::vector<QuantLib::Date>& jumpDates,
            int interpolator, int approximator, int approximatorArg);

QuantLib::OneFactorAffineSurvivalStructure *qlInterpolatedAffineHazardRateCurveAux(
            const std::vector<QuantLib::Date>& dates,
            const std::vector<double>& hazardRates,
            const QuantLib::DayCounter& dayCounter,
            const QuantLib::ext::shared_ptr<QuantLib::OneFactorAffineModel>& model,
            const QuantLib::Calendar& cal,
            const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
            const std::vector<QuantLib::Date>& jumpDates,
            int interpolator, int approximator, int approximatorArg);

QuantLib::DefaultProbabilityTermStructure *qlInterpolatedSurvivalProbabilityCurveAux(
            const std::vector<QuantLib::Date>& dates,
            const std::vector<double>& probabilities,
            const QuantLib::DayCounter& dayCounter,
            const QuantLib::Calendar& calendar,
            const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps,
            const std::vector<QuantLib::Date>& jumpDates,
            int interpolator, int approximator, int approximatorArg);

QuantLib::DefaultProbabilityTermStructure* qlPiecewiseDefaultCurveAux(const QuantLib::Date &referenceDate,
    const std::vector<QuantLib::ext::shared_ptr<QuantLib::DefaultProbabilityHelper> >& instruments,
    QuantLib::DayCounter& dayCounter,
    const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps, const std::vector<QuantLib::Date>& jumpDates,
    int trait,int interpolator, int approximator, int approximatorArg,
    const QlIterativeBootstrapOpts& bootstrapOpts);

QuantLib::DefaultProbabilityTermStructure* qlPiecewiseDefaultCurveAux1(unsigned settlementDays,
    const QuantLib::Calendar& calendar,
    const std::vector<QuantLib::ext::shared_ptr<QuantLib::DefaultProbabilityHelper> >& instruments,
    QuantLib::DayCounter& dayCounter,
    const std::vector<QuantLib::Handle<QuantLib::Quote> >& jumps, const std::vector<QuantLib::Date>& jumpDates,
    int trait,int interpolator, int approximator, int approximatorArg,
    const QlIterativeBootstrapOpts& bootstrapOpts);

// ConstantLossModel<CopulaPolicy>, only the Handle<Quote>/nVariables (one-factor) constructor.
// tOrders empty -> GaussianCopulaPolicy (initTraits is a bare int upstream, unused here);
// tOrders non-empty -> TCopulaPolicy, whose initTraits::tOrders takes exactly these degrees of
// freedom (one per latent factor, plus one for the idiosyncratic factor -- for this one-factor
// constructor that's always 2 elements; TCopulaPolicy's own constructor QL_REQUIREs the exact
// count). See qlTermStructureAux.cpp for the dispatcher itself.
QuantLib::DefaultLossModel* qlConstantLossModelAux(const QuantLib::Handle<QuantLib::Quote>& mktCorrel,
    const std::vector<QuantLib::Real>& recoveries,
    QuantLib::LatentModelIntegrationType::LatentModelIntegrationType integralType,
    QuantLib::Size nVariables, const std::vector<QuantLib::Integer>& tOrders);

QuantLib::ZeroInflationTermStructure *qlPiecewiseZeroInflationCurveAux(
    const QuantLib::Date &referenceDate,
    const QuantLib::Date &baseDate,
    QuantLib::Frequency frequency,
    const QuantLib::DayCounter& dayCounter,
    const std::vector<QuantLib::ext::shared_ptr<QuantLib::BootstrapHelper<QuantLib::ZeroInflationTermStructure> > >& instruments,
    const QuantLib::ext::shared_ptr<QuantLib::Seasonality>& seasonality,
    int interpolator, int approximator, int approximatorArg);

QuantLib::YoYInflationTermStructure *qlPiecewiseYoYInflationCurveAux(
    const QuantLib::Date &referenceDate,
    const QuantLib::Date &baseDate,
    QuantLib::Rate baseYoYRate,
    QuantLib::Frequency frequency,
    const QuantLib::DayCounter& dayCounter,
    const std::vector<QuantLib::ext::shared_ptr<QuantLib::BootstrapHelper<QuantLib::YoYInflationTermStructure> > >& instruments,
    const QuantLib::ext::shared_ptr<QuantLib::Seasonality>& seasonality,
    int interpolator, int approximator, int approximatorArg);

QuantLib::YoYInflationTermStructure *qlInterpolatedYoYInflationCurveAux(
    const QuantLib::Date &referenceDate,
    const std::vector<QuantLib::Date> &dates,
    const std::vector<QuantLib::Rate> &rates,
    QuantLib::Frequency frequency,
    const QuantLib::DayCounter& dayCounter,
    const QuantLib::ext::shared_ptr<QuantLib::Seasonality>& seasonality,
    int interpolator, int approximator, int approximatorArg);

QuantLib::ZeroInflationTermStructure *qlInterpolatedZeroInflationCurveAux(
    const QuantLib::Date &referenceDate,
    const std::vector<QuantLib::Date> &dates,
    const std::vector<QuantLib::Rate> &rates,
    QuantLib::Frequency frequency,
    const QuantLib::DayCounter& dayCounter,
    const QuantLib::ext::shared_ptr<QuantLib::Seasonality>& seasonality,
    int interpolator, int approximator, int approximatorArg);

// Keep per-interpolation template instantiation in this auxiliary translation unit. These entry
// points absorb the enum dispatch so callers pass raw values and never name interpolator types.

// BlackVarianceCurve/BlackVarianceSurface configure their interpolation after construction rather
// than through a template parameter, so these are setters rather than factories; the
// instantiation cost is the same, one member-template body per Interpolation.
void qlSetBlackVarianceCurveInterpolationAux(QuantLib::BlackVarianceCurve *o,
    int interpolator, int approximator, int approximatorArg);
void qlSetBlackVarianceSurfaceInterpolationAux(QuantLib::BlackVarianceSurface *o, int interpolator);

QuantLib::CPICapFloorTermPriceSurface *qlCPICapFloorTermPriceSurfaceAux(
    double nominal, double baseRate, const QuantLib::Period &observationLag, const QuantLib::Calendar &cal,
    QuantLib::BusinessDayConvention bdc, const QuantLib::DayCounter &dc,
    const QuantLib::ext::shared_ptr<QuantLib::ZeroInflationIndex> &zii,
    QuantLib::CPI::InterpolationType interpolationType,
    const QuantLib::Handle<QuantLib::YieldTermStructure> &yts,
    const std::vector<QuantLib::Rate> &cStrikes, const std::vector<QuantLib::Rate> &fStrikes,
    const std::vector<QuantLib::Period> &cfMaturities,
    const QuantLib::Matrix &cPrice, const QuantLib::Matrix &fPrice,
    int interpolator2D);

// Two interpolator axes: the 2-D cap/floor price grid, and the 1-D per-maturity curve.
QuantLib::YoYCapFloorTermPriceSurface *qlYoYCapFloorTermPriceSurfaceAux(
    QuantLib::Natural fixingDays, const QuantLib::Period &yyLag,
    const QuantLib::ext::shared_ptr<QuantLib::YoYInflationIndex> &yii,
    QuantLib::CPI::InterpolationType interpolation,
    const QuantLib::Handle<QuantLib::YieldTermStructure> &nominal,
    const QuantLib::DayCounter &dc, const QuantLib::Calendar &cal, QuantLib::BusinessDayConvention bdc,
    const std::vector<QuantLib::Rate> &cStrikes, const std::vector<QuantLib::Rate> &fStrikes,
    const std::vector<QuantLib::Period> &cfMaturities,
    const QuantLib::Matrix &cPrice, const QuantLib::Matrix &fPrice,
    int interpolator2D, int interpolator1D, int approximator, int approximatorArg);

// Builds the InterpolatedYoYOptionletStripper and the KInterpolatedYoYOptionletVolatilitySurface
// over it, both on the same Interpolator1D. LogCubic is rejected -- see qlTermStructureAux.cpp.
QuantLib::YoYOptionletVolatilitySurface *qlKInterpolatedYoYOptionletVolatilitySurfaceAux(
    unsigned settlementDays, const QuantLib::Calendar &cal, QuantLib::BusinessDayConvention bdc,
    const QuantLib::DayCounter &dc,
    const QuantLib::ext::shared_ptr<QuantLib::YoYCapFloorTermPriceSurface> &capFloorPrices,
    const QuantLib::ext::shared_ptr<QuantLib::YoYInflationCapFloorEngine> &engine, double slope,
    int interpolator1D, int approximator, int approximatorArg);

// ZabrSmileSection<Evaluation> is templated over the evaluation-tag axis (4 type-only tags, no
// runtime state) -- dispatched here rather than in qlTermStructure.cpp, same rule as every other
// "runtime enum selects a template argument" case. Returns the generic SmileSection base, same
// shape as qlSviSmileSection/qlNoArbSabrSmileSection (no dedicated leaf: ZabrSmileSection's only
// extra getter, model(), isn't exposed -- see qlTermStructure.cpp).
QuantLib::SmileSection *qlZabrSmileSectionAux(
    int evaluation, double timeToExpiry, double forward,
    const std::vector<QuantLib::Real> &params, const std::vector<QuantLib::Real> &moneyness,
    QuantLib::Size fdRefinement);
QuantLib::SmileSection *qlZabrSmileSectionAux1(
    int evaluation, const QuantLib::Date &d, double forward,
    const std::vector<QuantLib::Real> &params, const QuantLib::DayCounter &dc,
    const std::vector<QuantLib::Real> &moneyness, QuantLib::Size fdRefinement);

// ZabrInterpolatedSmileSection<Evaluation> is templated over the same evaluation-tag axis as
// ZabrSmileSection above, but unlike ZabrSmileSection it has its own calibration-diagnostic
// getters (alpha/beta/nu/rho/gamma/rmsError/maxError/endCriteria) declared directly on the
// template class, not through any virtual SmileSection slot -- a type-erased
// shared_ptr<SmileSection> alone can't reach them, and there is no single concrete C++ type to
// alias a leaf pointer to (each Evaluation is a distinct instantiation). This handle captures the
// diagnostics as closures over the concrete instantiation at construction time (inside the
// dispatch lambda in qlTermStructureAux.cpp, where the type is known), alongside the type-erased
// SmileSection base for AsSmileSection/pricing use -- avoids any dynamic_cast or a caller-supplied
// discriminant re-dispatch on every accessor call. qlaux.h only forward-declares this (to stay
// free of the zabrinterpolatedsmilesection.hpp include); qlTermStructure.cpp includes both headers
// so the complete type is visible wherever the handle is actually dereferenced.
struct ZabrInterpolatedSmileSectionHandle {
  QuantLib::ext::shared_ptr<QuantLib::SmileSection> section;
  std::function<QuantLib::Real()> alphaFn, betaFn, nuFn, rhoFn, gammaFn, rmsErrorFn, maxErrorFn;
  std::function<QuantLib::EndCriteria::Type()> endCriteriaFn;
};

// ZabrInterpolatedSmileSection<Evaluation>'s own evaluation-tag dispatch, same rule as
// qlZabrSmileSectionAux above.
ZabrInterpolatedSmileSectionHandle *qlZabrInterpolatedSmileSectionAux(
    int evaluation, const QuantLib::Date &optionDate, const QuantLib::Handle<QuantLib::Quote> &forward,
    const std::vector<QuantLib::Rate> &strikes, bool hasFloatingStrikes,
    const QuantLib::Handle<QuantLib::Quote> &atmVolatility,
    const std::vector<QuantLib::Handle<QuantLib::Quote>> &volHandles,
    QuantLib::Real alpha, QuantLib::Real beta, QuantLib::Real nu, QuantLib::Real rho, QuantLib::Real gamma,
    bool isAlphaFixed, bool isBetaFixed, bool isNuFixed, bool isRhoFixed, bool isGammaFixed,
    bool vegaWeighted, const QuantLib::ext::shared_ptr<QuantLib::EndCriteria> &endCriteria,
    const QuantLib::ext::shared_ptr<QuantLib::OptimizationMethod> &method, const QuantLib::DayCounter &dc);

// The fixed-date deposit and FRA helpers, as hasquant builds them. They are the only deposit and
// FRA forms that read a stored fixing -- impliedQuote() is iborIndex_->fixing(fixingDate_, true),
// which reads the store once the fixing date is before the evaluation date -- and QuantLib keeps
// the fixing date, the index and useIndexedCoupon private, where no pointer-to-member peek
// reaches. So the subclass keeps its own copy of what the fixing walk
// (qlRateHelperFixingDependencies) reports, taken from the constructor's arguments, and accept()
// offers a visitor the subclass before falling back to the base class's own dispatch. Neither
// date moves: both forms pass updateDates = false.
class FixedDateDepositRateHelper : public QuantLib::DepositRateHelper {
 public:
  FixedDateDepositRateHelper(const QuantLib::Handle<QuantLib::Quote>& rate, const QuantLib::Date& fixingDate,
                             const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& iborIndex)
  : DepositRateHelper(rate, fixingDate, iborIndex), indexName_(iborIndex->name()), fixingDate_(fixingDate) {}
  void accept(QuantLib::AcyclicVisitor& v) override {
    if (auto* v1 = dynamic_cast<QuantLib::Visitor<FixedDateDepositRateHelper>*>(&v)) v1->visit(*this);
    else DepositRateHelper::accept(v);
  }
  const std::string& indexName() const {return indexName_;}
  const QuantLib::Date& fixingDate() const {return fixingDate_;}
 private:
  std::string indexName_;
  QuantLib::Date fixingDate_;
};

// The FRA fixes where FraRateHelper::initializeDates puts it, iborIndex->fixingDate(startDate),
// and reads that fixing only with useIndexedCoupon; otherwise it prices off the curve.
class FixedDateFraRateHelper : public QuantLib::FraRateHelper {
 public:
  FixedDateFraRateHelper(const QuantLib::Handle<QuantLib::Quote>& rate, const QuantLib::Date& startDate,
                         const QuantLib::Date& endDate, const QuantLib::ext::shared_ptr<QuantLib::IborIndex>& iborIndex,
                         QuantLib::Pillar::Choice pillar, const QuantLib::Date& customPillarDate, bool useIndexedCoupon)
  : FraRateHelper(rate, startDate, endDate, iborIndex, pillar, customPillarDate, useIndexedCoupon),
    indexName_(iborIndex->name()), fixingDate_(iborIndex->fixingDate(startDate)), useIndexedCoupon_(useIndexedCoupon) {}
  void accept(QuantLib::AcyclicVisitor& v) override {
    if (auto* v1 = dynamic_cast<QuantLib::Visitor<FixedDateFraRateHelper>*>(&v)) v1->visit(*this);
    else FraRateHelper::accept(v);
  }
  const std::string& indexName() const {return indexName_;}
  const QuantLib::Date& fixingDate() const {return fixingDate_;}
  bool useIndexedCoupon() const {return useIndexedCoupon_;}
 private:
  std::string indexName_;
  QuantLib::Date fixingDate_;
  bool useIndexedCoupon_;
};

/* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */