Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Types | Public Member Functions | Protected Member Functions | Private Attributes | List of all members
LocalVolModelBuilder Class Reference

#include <ored/model/localvolmodelbuilder.hpp>

+ Inheritance diagram for LocalVolModelBuilder:
+ Collaboration diagram for LocalVolModelBuilder:

Public Types

enum class  Type { Dupire , DupireFloored , AndreasenHuge }
 

Public Member Functions

 LocalVolModelBuilder (const std::vector< Handle< YieldTermStructure > > &curves, const std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > &processes, const std::set< Date > &simulationDates={}, const std::set< Date > &addDates={}, const Size timeStepsPerYear=1, const Type lvType=Type::Dupire, const std::vector< Real > &calibrationMoneyness={ -2.0, -1.0, 0.0, 1.0, 2.0 }, const bool dontCalibrate=false)
 
 LocalVolModelBuilder (const Handle< YieldTermStructure > &curve, const ext::shared_ptr< GeneralizedBlackScholesProcess > &process, const std::set< Date > &simulationDates={}, const std::set< Date > &addDates={}, const Size timeStepsPerYear=1, const Type lvType=Type::Dupire, const std::vector< Real > &calibrationMoneyness={ -2.0, -1.0, 0.0, 1.0, 2.0 }, const bool dontCalibrate=false)
 
std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > getCalibratedProcesses () const override
 
- Public Member Functions inherited from BlackScholesModelBuilderBase
 BlackScholesModelBuilderBase (const std::vector< Handle< YieldTermStructure > > &curves, const std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > &processes, const std::set< Date > &simulationDates, const std::set< Date > &addDates, const Size timeStepsPerYear)
 
 BlackScholesModelBuilderBase (const Handle< YieldTermStructure > &curve, const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &process, const std::set< Date > &simulationDates, const std::set< Date > &addDates, const Size timeStepsPerYear)
 
Handle< BlackScholesModelWrappermodel () const
 
void forceRecalculate () override
 
bool requiresRecalibration () const override
 
- Public Member Functions inherited from ModelBuilder
void recalibrate () const
 
virtual void forceRecalculate ()
 
virtual bool requiresRecalibration () const=0
 

Protected Member Functions

std::vector< std::vector< Real > > getCurveTimes () const override
 
std::vector< std::vector< std::pair< Real, Real > > > getVolTimesStrikes () const override
 
- Protected Member Functions inherited from BlackScholesModelBuilderBase
 BlackScholesModelBuilderBase (const Handle< YieldTermStructure > &curve, const QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > &process)
 
virtual void setupDatesAndTimes () const
 
void performCalculations () const override
 
bool calibrationPointsChanged (const bool updateCache) const
 

Private Attributes

const Type lvType_
 
const std::vector< Real > calibrationMoneyness_
 
const bool dontCalibrate_
 

Additional Inherited Members

- Protected Attributes inherited from BlackScholesModelBuilderBase
const std::vector< Handle< YieldTermStructure > > curves_
 
const std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
 
const std::set< Date > simulationDates_
 
const std::set< Date > addDates_
 
const Size timeStepsPerYear_
 
std::set< Date > effectiveSimulationDates_
 
TimeGrid discretisationTimeGrid_
 
RelinkableHandle< BlackScholesModelWrappermodel_
 
bool forceCalibration_ = false
 
QuantLib::ext::shared_ptr< MarketObservermarketObserver_
 
std::vector< Handle< BlackVolTermStructure > > vols_
 
std::vector< Handle< YieldTermStructure > > allCurves_
 
CalibrationPointCache cache_
 

Detailed Description

Definition at line 33 of file localvolmodelbuilder.hpp.

Member Enumeration Documentation

◆ Type

enum class Type
strong

Constructor & Destructor Documentation

◆ LocalVolModelBuilder() [1/2]

LocalVolModelBuilder ( const std::vector< Handle< YieldTermStructure > > &  curves,
const std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > &  processes,
const std::set< Date > &  simulationDates = {},
const std::set< Date > &  addDates = {},
const Size  timeStepsPerYear = 1,
const Type  lvType = Type::Dupire,
const std::vector< Real > &  calibrationMoneyness = { -2.0, -1.0, 0.0, 1.0, 2.0 },
const bool  dontCalibrate = false 
)

Definition at line 40 of file localvolmodelbuilder.cpp.

45 : BlackScholesModelBuilderBase(curves, processes, simulationDates, addDates, timeStepsPerYear), lvType_(lvType),
46 calibrationMoneyness_(calibrationMoneyness), dontCalibrate_(dontCalibrate) {
47 // we have to observe the whole vol surface for the Dupire implementation unfortunately; we can specify the time
48 // steps that are relevant, but not a set of discrete strikes
49 if (lvType == Type::Dupire) {
50 for (auto const& p : processes_) {
51 marketObserver_->registerWith(p->blackVolatility());
52 }
53 }
54}
BlackScholesModelBuilderBase(const std::vector< Handle< YieldTermStructure > > &curves, const std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > &processes, const std::set< Date > &simulationDates, const std::set< Date > &addDates, const Size timeStepsPerYear)
QuantLib::ext::shared_ptr< MarketObserver > marketObserver_
const std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
const std::vector< Real > calibrationMoneyness_

◆ LocalVolModelBuilder() [2/2]

LocalVolModelBuilder ( const Handle< YieldTermStructure > &  curve,
const ext::shared_ptr< GeneralizedBlackScholesProcess > &  process,
const std::set< Date > &  simulationDates = {},
const std::set< Date > &  addDates = {},
const Size  timeStepsPerYear = 1,
const Type  lvType = Type::Dupire,
const std::vector< Real > &  calibrationMoneyness = { -2.0, -1.0, 0.0, 1.0, 2.0 },
const bool  dontCalibrate = false 
)

Definition at line 44 of file localvolmodelbuilder.hpp.

46 {},
47 const std::set<Date>& addDates = {},
48 const Size timeStepsPerYear = 1,
49 const Type lvType = Type::Dupire,
50 const std::vector<Real>& calibrationMoneyness = { -2.0, -1.0, 0.0, 1.0, 2.0 },
51 const bool dontCalibrate = false)
52 : LocalVolModelBuilder(std::vector<Handle<YieldTermStructure>>{curve},
53 std::vector<ext::shared_ptr<GeneralizedBlackScholesProcess>>{process}, simulationDates,
54 addDates, timeStepsPerYear, lvType, calibrationMoneyness, dontCalibrate) {}
LocalVolModelBuilder(const std::vector< Handle< YieldTermStructure > > &curves, const std::vector< ext::shared_ptr< GeneralizedBlackScholesProcess > > &processes, const std::set< Date > &simulationDates={}, const std::set< Date > &addDates={}, const Size timeStepsPerYear=1, const Type lvType=Type::Dupire, const std::vector< Real > &calibrationMoneyness={ -2.0, -1.0, 0.0, 1.0, 2.0 }, const bool dontCalibrate=false)

Member Function Documentation

◆ getCalibratedProcesses()

std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > getCalibratedProcesses ( ) const
overridevirtual

Implements BlackScholesModelBuilderBase.

Definition at line 56 of file localvolmodelbuilder.cpp.

56 {
57
58 QL_REQUIRE(lvType_ != Type::AndreasenHuge || !calibrationMoneyness_.empty(), "no calibration moneyness provided");
59
60 calculate();
61
62 std::vector<QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess>> processes;
63
64 for (Size l = 0; l < processes_.size(); ++l) {
65
66 Handle<LocalVolTermStructure> localVol;
67 if (dontCalibrate_) {
68 localVol = Handle<LocalVolTermStructure>(
69 QuantLib::ext::make_shared<LocalConstantVol>(0, NullCalendar(), 0.10, ActualActual(ActualActual::ISDA)));
70 } else if (lvType_ == Type::AndreasenHuge) {
71 // for checking arbitrage free input prices, just for logging purposes at this point
72 // notice that we need a uniform strike grid here, so this is not the same as the one below
73 // we choose the strike grid to be the one for the last calibration point
74 std::vector<Real> checkMaturities, checkMoneynesses, atmForwards;
75 std::vector<std::vector<Real>> callPrices;
76
77 // set up Andreasen Huge Volatility interpolation for each underyling
78 // we choose the calibration set to be OTM options on the effective future simulation dates
79 // with strikes given in terms of moneyness K / atmForward
80 AndreasenHugeVolatilityInterpl::CalibrationSet calSet;
81 for (auto const& d : effectiveSimulationDates_) {
82 if (d <= curves_.front()->referenceDate())
83 continue;
84 Real t = processes_.front()->riskFreeRate()->timeFromReference(d);
85 checkMaturities.push_back(t);
86 Real atmLevel =
87 atmForward(processes_[l]->x0(), processes_[l]->riskFreeRate(), processes_[l]->dividendYield(), t);
88 Real atmMarketVol = std::max(1e-4, processes_[l]->blackVolatility()->blackVol(t, atmLevel));
89 callPrices.push_back(std::vector<Real>());
90 atmForwards.push_back(atmLevel);
91 for (Size i = 0; i < calibrationMoneyness_.size(); ++i) {
92 Real strike = atmLevel * std::exp(calibrationMoneyness_[i] * atmMarketVol * std::sqrt(t));
93 Real marketVol = processes_[l]->blackVolatility()->blackVol(t, strike);
94 // skip option with effective moneyness < 0.0001 or > 0.9999 (TODO, hardcoded limits here?)
95 if (std::fabs(calibrationMoneyness_[i]) > 3.72)
96 continue;
97 auto option =
98 QuantLib::ext::make_shared<VanillaOption>(QuantLib::ext::make_shared<PlainVanillaPayoff>(Option::Call, strike),
99 QuantLib::ext::make_shared<EuropeanExercise>(d));
100 calSet.push_back(std::make_pair(option, QuantLib::ext::make_shared<SimpleQuote>(marketVol)));
101 option->setPricingEngine(QuantLib::ext::make_shared<AnalyticEuropeanEngine>(processes_[l]));
102 callPrices.back().push_back(option->NPV());
103 if (d == *effectiveSimulationDates_.rbegin()) {
104 checkMoneynesses.push_back(strike / atmLevel);
105 }
106 }
107 }
108
109 // arbitrage check
110 QuantExt::CarrMadanSurface cmCheck(checkMaturities, checkMoneynesses, processes_[l]->x0(), atmForwards,
111 callPrices);
112 if (!cmCheck.arbitrageFree()) {
113 WLOG("Andreasen-Huge local vol calibration for process #" << l
114 << ":, input vol is not arbitrage free:");
115 DLOG("time,moneyness,callSpread,butterfly,calendar");
116 for (Size i = 0; i < checkMaturities.size(); ++i)
117 for (Size j = 0; j < checkMoneynesses.size(); ++j)
118 DLOG(checkMaturities[i] << "," << checkMoneynesses[i] << "," << std::boolalpha
119 << cmCheck.callSpreadArbitrage()[i][j] << ","
120 << cmCheck.butterflyArbitrage()[i][j] << ","
121 << cmCheck.calendarArbitrage()[i][j]);
122 }
123
124 // TODO using some hardcoded values here, expose to configuration?
125 auto ah = QuantLib::ext::make_shared<AndreasenHugeVolatilityInterpl>(
126 calSet, processes_[l]->stateVariable(), processes_[l]->riskFreeRate(), processes_[l]->dividendYield(),
127 AndreasenHugeVolatilityInterpl::CubicSpline, AndreasenHugeVolatilityInterpl::Call, 500, Null<Real>(),
128 Null<Real>());
129 localVol = Handle<LocalVolTermStructure>(QuantLib::ext::make_shared<AndreasenHugeLocalVolAdapter>(ah));
130 //localVol->enableExtrapolation();
131 DLOG("Andreasen-Huge local vol calibration for process #"
132 << l
133 << ": "
134 "calibration error min="
135 << std::scientific << std::setprecision(6) << QuantLib::ext::get<0>(ah->calibrationError()) << " max="
136 << QuantLib::ext::get<1>(ah->calibrationError()) << " avg=" << QuantLib::ext::get<2>(ah->calibrationError()));
137 } else if (lvType_ == Type::Dupire) {
138 localVol = Handle<LocalVolTermStructure>(
139 QuantLib::ext::make_shared<LocalVolSurface>(processes_[l]->blackVolatility(), processes_[l]->riskFreeRate(),
140 processes_[l]->dividendYield(), processes_[l]->stateVariable()));
141 } else if (lvType_ == Type::DupireFloored) {
142 localVol = Handle<LocalVolTermStructure>(
143 QuantLib::ext::make_shared<NoExceptLocalVolSurface>(processes_[l]->blackVolatility(), processes_[l]->riskFreeRate(),
144 processes_[l]->dividendYield(), processes_[l]->stateVariable(),
145 0.0));
146 } else {
147 QL_FAIL("unexpected local vol type");
148 }
149
150 processes.push_back(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(
151 processes_[l]->stateVariable(), processes_[l]->dividendYield(), processes_[l]->riskFreeRate(),
152 processes_[l]->blackVolatility(), localVol));
153 }
154
155 return processes;
156}
const std::vector< Handle< YieldTermStructure > > curves_
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
Real atmForward(const Real s0, const Handle< YieldTermStructure > &r, const Handle< YieldTermStructure > &q, const Real t)
helper function that computes the atm forward
Definition: utilities.cpp:483
+ Here is the call graph for this function:

◆ getCurveTimes()

std::vector< std::vector< Real > > getCurveTimes ( ) const
overrideprotectedvirtual

Implements BlackScholesModelBuilderBase.

Definition at line 158 of file localvolmodelbuilder.cpp.

158 {
159 std::vector<Real> timesExt(discretisationTimeGrid_.begin() + 1, discretisationTimeGrid_.end());
160 for (auto const& d : addDates_) {
161 if (d > curves_.front()->referenceDate()) {
162 timesExt.push_back(curves_.front()->timeFromReference(d));
163 }
164 }
165 std::sort(timesExt.begin(), timesExt.end());
166 auto it = std::unique(timesExt.begin(), timesExt.end(),
167 [](const Real x, const Real y) { return QuantLib::close_enough(x, y); });
168 timesExt.resize(std::distance(timesExt.begin(), it));
169 return std::vector<std::vector<Real>>(allCurves_.size(), timesExt);
170}
std::vector< Handle< YieldTermStructure > > allCurves_

◆ getVolTimesStrikes()

std::vector< std::vector< std::pair< Real, Real > > > getVolTimesStrikes ( ) const
overrideprotectedvirtual

Implements BlackScholesModelBuilderBase.

Definition at line 172 of file localvolmodelbuilder.cpp.

172 {
173 std::vector<std::vector<std::pair<Real, Real>>> volTimesStrikes;
174 // for the Dupire implementation we observe the whole vol surface anyhow (see ctor above)
175 if (lvType_ == Type::Dupire)
176 return volTimesStrikes;
177 std::vector<Real> times;
179 for (auto const& d : effectiveSimulationDates_) {
180 if (d > curves_.front()->referenceDate())
181 times.push_back(processes_.front()->riskFreeRate()->timeFromReference(d));
182 }
183 } else {
184 times = std::vector<Real>(discretisationTimeGrid_.begin() + 1, discretisationTimeGrid_.end());
185 }
186 for (auto const& p : processes_) {
187 volTimesStrikes.push_back(std::vector<std::pair<Real, Real>>());
188 for (auto const t : times) {
189 Real atmLevel = atmForward(p->x0(), p->riskFreeRate(), p->dividendYield(), t);
190 Real atmMarketVol = std::max(1e-4, p->blackVolatility()->blackVol(t, atmLevel));
191 for (auto const m : calibrationMoneyness_) {
192 Real strike = atmLevel * std::exp(m * atmMarketVol * std::sqrt(t));
193 volTimesStrikes.back().push_back(std::make_pair(t, strike));
194 }
195 }
196 }
197 return volTimesStrikes;
198}
+ Here is the call graph for this function:

Member Data Documentation

◆ lvType_

const Type lvType_
private

Definition at line 63 of file localvolmodelbuilder.hpp.

◆ calibrationMoneyness_

const std::vector<Real> calibrationMoneyness_
private

Definition at line 64 of file localvolmodelbuilder.hpp.

◆ dontCalibrate_

const bool dontCalibrate_
private

Definition at line 65 of file localvolmodelbuilder.hpp.