Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | List of all members
ApoFutureSurface Class Reference

Average future price option (APO) surface derived from a future option surface. More...

#include <qle/termstructures/aposurface.hpp>

+ Inheritance diagram for ApoFutureSurface:
+ Collaboration diagram for ApoFutureSurface:

Public Member Functions

 ApoFutureSurface (const QuantLib::Date &referenceDate, const std::vector< QuantLib::Real > &moneynessLevels, const QuantLib::ext::shared_ptr< CommodityIndex > &index, const QuantLib::Handle< PriceTermStructure > &pts, const QuantLib::Handle< QuantLib::YieldTermStructure > &yts, const QuantLib::ext::shared_ptr< FutureExpiryCalculator > &expCalc, const QuantLib::Handle< QuantLib::BlackVolTermStructure > &baseVts, const QuantLib::ext::shared_ptr< FutureExpiryCalculator > &baseExpCalc, QuantLib::Real beta=0.0, bool flatStrikeExtrapolation=true, const boost::optional< QuantLib::Period > &maxTenor=boost::none)
 
TermStructure interface
QuantLib::Date maxDate () const override
 
VolatilityTermStructure interface
QuantLib::Real minStrike () const override
 
QuantLib::Real maxStrike () const override
 
Visitability
void accept (QuantLib::AcyclicVisitor &v) override
 
Observer interface
void update () override
 
LazyObject interface
void performCalculations () const override
 
Inspectors
const QuantLib::ext::shared_ptr< BlackVarianceSurfaceMoneyness > & vts () const
 

BlackVolatilityTermStructure

QuantLib::ext::shared_ptr< CommodityIndexindex_
 
QuantLib::ext::shared_ptr< FutureExpiryCalculatorbaseExpCalc_
 
std::vector< QuantLib::Date > apoDates_
 The APO schedule dates. More...
 
std::vector< std::vector< QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > > > vols_
 This will keep a handle on the APO vol quotes that are calculated. More...
 
QuantLib::ext::shared_ptr< BlackVarianceSurfaceMoneynessvts_
 The surface that is created to do the work. More...
 
QuantLib::ext::shared_ptr< CommodityAveragePriceOptionBaseEngineapoEngine_
 The engine for valuing the APOs. More...
 
QuantLib::Volatility blackVolImpl (QuantLib::Time t, QuantLib::Real strike) const override
 

Detailed Description

Average future price option (APO) surface derived from a future option surface.

Definition at line 40 of file aposurface.hpp.

Constructor & Destructor Documentation

◆ ApoFutureSurface()

ApoFutureSurface ( const QuantLib::Date &  referenceDate,
const std::vector< QuantLib::Real > &  moneynessLevels,
const QuantLib::ext::shared_ptr< CommodityIndex > &  index,
const QuantLib::Handle< PriceTermStructure > &  pts,
const QuantLib::Handle< QuantLib::YieldTermStructure > &  yts,
const QuantLib::ext::shared_ptr< FutureExpiryCalculator > &  expCalc,
const QuantLib::Handle< QuantLib::BlackVolTermStructure > &  baseVts,
const QuantLib::ext::shared_ptr< FutureExpiryCalculator > &  baseExpCalc,
QuantLib::Real  beta = 0.0,
bool  flatStrikeExtrapolation = true,
const boost::optional< QuantLib::Period > &  maxTenor = boost::none 
)

Definition at line 30 of file aposurface.cpp.

37 : BlackVolatilityTermStructure(referenceDate, baseVts->calendar(), baseVts->businessDayConvention(),
38 baseVts->dayCounter()),
39 index_(index), baseExpCalc_(baseExpCalc), vols_(moneynessLevels.size()) {
40
41 // Checks.
42 QL_REQUIRE(!pts.empty(), "The price term structure should not be empty.");
43 QL_REQUIRE(!yts.empty(), "The yield term structure should not be empty.");
44 QL_REQUIRE(expCalc, "The expiry calculator should not be null.");
45 QL_REQUIRE(!baseVts.empty(), "The base volatility term structure should not be empty.");
46 QL_REQUIRE(!index_->priceCurve().empty(), "The commodity index should have a base price curve.");
47 QL_REQUIRE(baseExpCalc_, "The base expiry calculator should not be null.");
48
49 // Register with dependent term structures.
50 registerWith(pts);
51 registerWith(yts);
52 registerWith(baseVts);
53
54 // Determine the maximum expiry of the APO surface that we will build
55 Date maxDate;
56 if (maxTenor) {
57 // If maxTenor is provided, use it.
58 maxDate = referenceDate + *maxTenor;
59 } else {
60 maxDate = baseVts->maxDate();
61 if (maxDate == Date::maxDate() || maxDate == Date()) {
62 maxDate = pts->maxDate();
63 QL_REQUIRE(maxDate != Date::maxDate() && maxDate != Date(),
64 "Could not determine a maximum date for the ApoFutureSurface");
65 }
66 }
67 QL_REQUIRE(maxDate > referenceDate, "Expected the max date, " << io::iso_date(maxDate)
68 << ", to be greater than the reference date, "
69 << io::iso_date(referenceDate) << ".");
70
71 // Get the start and end dates of each APO that will be used to create the APO surface in the expiry direction.
72 // Here, we use the expiry calculator, expCalc. This expiry calculator will generally be from the corresponding
73 // averaging future contracts. We will be using this APO surface to price these averaging futures as standard
74 // non-averaging commodity options. The averaging future contract expiry will equal the APO expiry.
75 apoDates_ = { expCalc->priorExpiry(true, referenceDate) };
76 vector<Time> apoTimes;
77 while (apoDates_.back() < maxDate) {
78 apoDates_.push_back(expCalc->nextExpiry(false, apoDates_.back()));
79 apoTimes.push_back(timeFromReference(apoDates_.back()));
80 }
81
82 // Spot quote based on the price curve and adapted yield term structure
83 Handle<Quote> spot(QuantLib::ext::make_shared<DerivedPriceQuote>(pts));
84 Handle<YieldTermStructure> pyts =
85 Handle<YieldTermStructure>(QuantLib::ext::make_shared<PriceTermStructureAdapter>(*pts, *yts));
86 pyts->enableExtrapolation();
87
88 // Hard-code this to false.
89 bool stickyStrike = false;
90
91 // Initialise the matrix of quotes for use in vts_. These will be populated/updated in performCalculations by
92 // pricing all of the APOs and extracting the volatility from each of them. Rows are moneyness levels and columns
93 // are expiry times in the matrix of quotes that are fed to vts_'s ctor.
94 vector<vector<Handle<Quote> > > vols(moneynessLevels.size());
95 for (Size i = 0; i < moneynessLevels.size(); i++) {
96 for (Size j = 0; j < apoTimes.size(); j++) {
97 vols_[i].push_back(QuantLib::ext::make_shared<SimpleQuote>(0.0));
98 vols[i].push_back(Handle<Quote>(vols_[i].back()));
99 }
100 }
101
102 // Initialise the underlying helping volatility structure.
103 vts_ = QuantLib::ext::make_shared<BlackVarianceSurfaceMoneynessForward>(calendar_, spot, apoTimes, moneynessLevels, vols,
104 baseVts->dayCounter(), pyts, yts, stickyStrike,
105 flatStrikeExtrapolation);
106
107 vts_->enableExtrapolation();
108
109 // Initialise the engine for performing the APO valuations.
110 apoEngine_ = QuantLib::ext::make_shared<CommodityAveragePriceOptionAnalyticalEngine>(yts, baseVts, beta);
111}
std::vector< std::vector< QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > > > vols_
This will keep a handle on the APO vol quotes that are calculated.
Definition: aposurface.hpp:97
QuantLib::ext::shared_ptr< BlackVarianceSurfaceMoneyness > vts_
The surface that is created to do the work.
Definition: aposurface.hpp:100
QuantLib::ext::shared_ptr< CommodityIndex > index_
Definition: aposurface.hpp:90
QuantLib::Date maxDate() const override
Definition: aposurface.cpp:113
std::vector< QuantLib::Date > apoDates_
The APO schedule dates.
Definition: aposurface.hpp:94
QuantLib::ext::shared_ptr< CommodityAveragePriceOptionBaseEngine > apoEngine_
The engine for valuing the APOs.
Definition: aposurface.hpp:103
QuantLib::ext::shared_ptr< FutureExpiryCalculator > baseExpCalc_
Definition: aposurface.hpp:91
+ Here is the call graph for this function:

Member Function Documentation

◆ maxDate()

Date maxDate ( ) const
override

Definition at line 113 of file aposurface.cpp.

113{ return vts_->maxDate(); }
+ Here is the caller graph for this function:

◆ minStrike()

Real minStrike ( ) const
override

Definition at line 115 of file aposurface.cpp.

115{ return vts_->minStrike(); }

◆ maxStrike()

Real maxStrike ( ) const
override

Definition at line 117 of file aposurface.cpp.

117{ return vts_->maxStrike(); }

◆ accept()

void accept ( QuantLib::AcyclicVisitor &  v)
override

Definition at line 119 of file aposurface.cpp.

119 {
120 if (auto v1 = dynamic_cast<Visitor<ApoFutureSurface>*>(&v))
121 v1->visit(*this);
122 else
123 QL_FAIL("Not an ApoFutureSurface visitor");
124}

◆ update()

void update ( )
override

Definition at line 126 of file aposurface.cpp.

126 {
127 TermStructure::update();
128 LazyObject::update();
129}

◆ performCalculations()

void performCalculations ( ) const
override

Definition at line 131 of file aposurface.cpp.

131 {
132
133 // Quantity is 1.0 everywhere below.
134 Real quantity = 1.0;
135
136 for (Size j = 1; j < apoDates_.size(); j++) {
137
138 // Set up the APO cashflow with from apoDates_[j-1] to apoDates_[j]
139 auto cf =
140 QuantLib::ext::make_shared<CommodityIndexedAverageCashFlow>(quantity, apoDates_[j - 1], apoDates_[j], apoDates_[j],
141 index_, Calendar(), 0.0, 1.0, true, 0, 0, baseExpCalc_);
142
143 // The APO cashflow forward rate is the amount
144 Real forward = cf->amount();
145
146 // Some of the sigmas will be Null<Real>() in the first APO period if the accrued is already greater than the
147 // strike. So store the sigmas in a vector in the first step and then update the quotes as a second step.
148 // idx will point to the first element in sigmas not equal to Null<Real>().
149 vector<Real> sigmas(vts_->moneyness().size());
150 for (Size i = 0; i < vts_->moneyness().size(); i++) {
151
152 // "exercise date" is just the last date of the APO cashflow.
153 auto exercise = QuantLib::ext::make_shared<EuropeanExercise>(apoDates_[j]);
154
155 // Apply moneyness to forward rate to get current strike
156 Real strike = vts_->moneyness()[i] * forward;
157
158 // Create the APO and call NPV() to trigger population of results.
159 CommodityAveragePriceOption apo(cf, exercise, 1.0, strike, Option::Call);
160 apo.setPricingEngine(apoEngine_);
161 apo.NPV();
162
163 auto it = apo.additionalResults().find("sigma");
164 if (it != apo.additionalResults().end())
165 sigmas[i] = boost::any_cast<Real>(it->second);
166 else
167 sigmas[i] = Null<Real>();
168 }
169
170 QL_REQUIRE(sigmas.back() != Null<Real>(), "All of the sigmas are null.");
171
172 for (Size i = vts_->moneyness().size(); i > 0; i--) {
173
174 // Know already that the last sigma is not null.
175 if (sigmas[i - 1] == Null<Real>())
176 sigmas[i - 1] = sigmas[i];
177
178 // Update the quote
179 vols_[i - 1][j - 1]->setValue(sigmas[i - 1]);
180 }
181 }
182}

◆ vts()

const QuantLib::ext::shared_ptr< BlackVarianceSurfaceMoneyness > & vts ( ) const

Definition at line 184 of file aposurface.cpp.

184{ return vts_; }

◆ blackVolImpl()

Volatility blackVolImpl ( QuantLib::Time  t,
QuantLib::Real  strike 
) const
overrideprotected

Definition at line 186 of file aposurface.cpp.

186 {
187 calculate();
188 return vts_->blackVol(t, strike, true);
189}

Member Data Documentation

◆ index_

QuantLib::ext::shared_ptr<CommodityIndex> index_
private

Definition at line 90 of file aposurface.hpp.

◆ baseExpCalc_

QuantLib::ext::shared_ptr<FutureExpiryCalculator> baseExpCalc_
private

Definition at line 91 of file aposurface.hpp.

◆ apoDates_

std::vector<QuantLib::Date> apoDates_
private

The APO schedule dates.

Definition at line 94 of file aposurface.hpp.

◆ vols_

std::vector<std::vector<QuantLib::ext::shared_ptr<QuantLib::SimpleQuote> > > vols_
private

This will keep a handle on the APO vol quotes that are calculated.

Definition at line 97 of file aposurface.hpp.

◆ vts_

QuantLib::ext::shared_ptr<BlackVarianceSurfaceMoneyness> vts_
private

The surface that is created to do the work.

Definition at line 100 of file aposurface.hpp.

◆ apoEngine_

QuantLib::ext::shared_ptr<CommodityAveragePriceOptionBaseEngine> apoEngine_
private

The engine for valuing the APOs.

Definition at line 103 of file aposurface.hpp.