19#include <ql/exercise.hpp>
31 const QuantLib::ext::shared_ptr<CommodityIndex>& index,
32 const Handle<PriceTermStructure>& pts,
const Handle<YieldTermStructure>& yts,
33 const QuantLib::ext::shared_ptr<FutureExpiryCalculator>& expCalc,
34 const Handle<BlackVolTermStructure>& baseVts,
35 const QuantLib::ext::shared_ptr<FutureExpiryCalculator>& baseExpCalc, Real beta,
36 bool flatStrikeExtrapolation,
const boost::optional<Period>& maxTenor)
37 : BlackVolatilityTermStructure(referenceDate, baseVts->calendar(), baseVts->businessDayConvention(),
38 baseVts->dayCounter()),
39 index_(index), baseExpCalc_(baseExpCalc), vols_(moneynessLevels.size()) {
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.");
52 registerWith(baseVts);
58 maxDate = referenceDate + *maxTenor;
64 "Could not determine a maximum date for the ApoFutureSurface");
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) <<
".");
75 apoDates_ = { expCalc->priorExpiry(
true, referenceDate) };
76 vector<Time> apoTimes;
79 apoTimes.push_back(timeFromReference(
apoDates_.back()));
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();
89 bool stickyStrike =
false;
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()));
103 vts_ = QuantLib::ext::make_shared<BlackVarianceSurfaceMoneynessForward>(calendar_, spot, apoTimes, moneynessLevels, vols,
104 baseVts->dayCounter(), pyts, yts, stickyStrike,
105 flatStrikeExtrapolation);
107 vts_->enableExtrapolation();
110 apoEngine_ = QuantLib::ext::make_shared<CommodityAveragePriceOptionAnalyticalEngine>(yts, baseVts, beta);
120 if (
auto v1 =
dynamic_cast<Visitor<ApoFutureSurface>*
>(&v))
123 QL_FAIL(
"Not an ApoFutureSurface visitor");
127 TermStructure::update();
128 LazyObject::update();
136 for (Size j = 1; j <
apoDates_.size(); j++) {
144 Real forward = cf->amount();
149 vector<Real> sigmas(
vts_->moneyness().size());
150 for (Size i = 0; i <
vts_->moneyness().size(); i++) {
153 auto exercise = QuantLib::ext::make_shared<EuropeanExercise>(
apoDates_[j]);
156 Real strike =
vts_->moneyness()[i] * forward;
163 auto it = apo.additionalResults().find(
"sigma");
164 if (it != apo.additionalResults().end())
165 sigmas[i] = boost::any_cast<Real>(it->second);
167 sigmas[i] = Null<Real>();
170 QL_REQUIRE(sigmas.back() != Null<Real>(),
"All of the sigmas are null.");
172 for (Size i =
vts_->moneyness().size(); i > 0; i--) {
175 if (sigmas[i - 1] == Null<Real>())
176 sigmas[i - 1] = sigmas[i];
179 vols_[i - 1][j - 1]->setValue(sigmas[i - 1]);
188 return vts_->blackVol(t, strike,
true);
Average future price option surface derived from future option surface.
std::vector< std::vector< QuantLib::ext::shared_ptr< QuantLib::SimpleQuote > > > vols_
This will keep a handle on the APO vol quotes that are calculated.
void performCalculations() const override
QuantLib::Volatility blackVolImpl(QuantLib::Time t, QuantLib::Real strike) const override
void accept(QuantLib::AcyclicVisitor &v) override
QuantLib::ext::shared_ptr< BlackVarianceSurfaceMoneyness > vts_
The surface that is created to do the work.
QuantLib::Real minStrike() const override
const QuantLib::ext::shared_ptr< BlackVarianceSurfaceMoneyness > & vts() const
QuantLib::ext::shared_ptr< CommodityIndex > index_
QuantLib::Date maxDate() const override
std::vector< QuantLib::Date > apoDates_
The APO schedule dates.
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)
QuantLib::Real maxStrike() const override
QuantLib::ext::shared_ptr< CommodityAveragePriceOptionBaseEngine > apoEngine_
The engine for valuing the APOs.
QuantLib::ext::shared_ptr< FutureExpiryCalculator > baseExpCalc_
Commodity Average Price Option.
Cash flow dependent on the average commodity spot price or future's settlement price over a period....
PriceTermStructure adapter.