Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions QuantLib.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1727,6 +1727,8 @@
<ClInclude Include="ql\termstructures\volatility\equityfx\blackconstantvol.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvariancecurve.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvariancesurface.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvariancetimeextrapolation.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvolsurfacedelta.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvoltermstructure.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\fixedlocalvolsurface.hpp" />
<ClInclude Include="ql\termstructures\volatility\equityfx\gridmodellocalvolsurface.hpp" />
Expand Down Expand Up @@ -2753,6 +2755,7 @@
<ClCompile Include="ql\termstructures\volatility\equityfx\andreasenhugevolatilityinterpl.cpp" />
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvariancecurve.cpp" />
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvariancesurface.cpp" />
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvolsurfacedelta.cpp" />
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvoltermstructure.cpp" />
<ClCompile Include="ql\termstructures\volatility\equityfx\fixedlocalvolsurface.cpp" />
<ClCompile Include="ql\termstructures\volatility\equityfx\gridmodellocalvolsurface.cpp" />
Expand Down
9 changes: 9 additions & 0 deletions QuantLib.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -2049,6 +2049,12 @@
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvariancesurface.hpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClInclude>
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvariancetimeextrapolation.hpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClInclude>
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvolsurfacedelta.hpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClInclude>
<ClInclude Include="ql\termstructures\volatility\equityfx\blackvoltermstructure.hpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClInclude>
Expand Down Expand Up @@ -5600,6 +5606,9 @@
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvariancesurface.cpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClCompile>
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvolsurfacedelta.cpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClCompile>
<ClCompile Include="ql\termstructures\volatility\equityfx\blackvoltermstructure.cpp">
<Filter>termstructures\volatility\equityfx</Filter>
</ClCompile>
Expand Down
3 changes: 3 additions & 0 deletions ql/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ set(QL_SOURCES
termstructures/volatility/equityfx/andreasenhugevolatilityinterpl.cpp
termstructures/volatility/equityfx/blackvariancecurve.cpp
termstructures/volatility/equityfx/blackvariancesurface.cpp
termstructures/volatility/equityfx/blackvolsurfacedelta.cpp
termstructures/volatility/equityfx/blackvoltermstructure.cpp
termstructures/volatility/equityfx/fixedlocalvolsurface.cpp
termstructures/volatility/equityfx/gridmodellocalvolsurface.cpp
Expand Down Expand Up @@ -2103,6 +2104,8 @@ set(QL_HEADERS
termstructures/volatility/equityfx/blackconstantvol.hpp
termstructures/volatility/equityfx/blackvariancecurve.hpp
termstructures/volatility/equityfx/blackvariancesurface.hpp
termstructures/volatility/equityfx/blackvariancetimeextrapolation.hpp
termstructures/volatility/equityfx/blackvolsurfacedelta.hpp
termstructures/volatility/equityfx/blackvoltermstructure.hpp
termstructures/volatility/equityfx/fixedlocalvolsurface.hpp
termstructures/volatility/equityfx/gridmodellocalvolsurface.hpp
Expand Down
3 changes: 3 additions & 0 deletions ql/termstructures/volatility/equityfx/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ this_include_HEADERS = \
blackconstantvol.hpp \
blackvariancecurve.hpp \
blackvariancesurface.hpp \
blackvariancetimeextrapolation.hpp \
blackvolsurfacedelta.hpp \
blackvoltermstructure.hpp \
fixedlocalvolsurface.hpp \
gridmodellocalvolsurface.hpp \
Expand All @@ -27,6 +29,7 @@ cpp_files = \
andreasenhugevolatilityadapter.cpp \
blackvariancecurve.cpp \
blackvariancesurface.cpp \
blackvolsurfacedelta.cpp \
blackvoltermstructure.cpp \
fixedlocalvolsurface.cpp \
gridmodellocalvolsurface.cpp \
Expand Down
18 changes: 12 additions & 6 deletions ql/termstructures/volatility/equityfx/blackvariancecurve.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include <ql/math/interpolations/linearinterpolation.hpp>
#include <ql/termstructures/volatility/equityfx/blackvariancecurve.hpp>
#include <ql/termstructures/volatility/equityfx/blackvariancetimeextrapolation.hpp>
#include <utility>

namespace QuantLib {
Expand All @@ -28,9 +29,10 @@ namespace QuantLib {
const std::vector<Date>& dates,
const std::vector<Volatility>& blackVolCurve,
DayCounter dayCounter,
bool forceMonotoneVariance)
bool forceMonotoneVariance,
BlackVolTimeExtrapolation timeExtrapolation)
: BlackVarianceTermStructure(referenceDate), dayCounter_(std::move(dayCounter)),
maxDate_(dates.back()) {
maxDate_(dates.back()), timeExtrapolation_(timeExtrapolation) {

QL_REQUIRE(dates.size()==blackVolCurve.size(),
"mismatch between date vector and black vol vector");
Expand Down Expand Up @@ -62,11 +64,15 @@ namespace QuantLib {
}

Real BlackVarianceCurve::blackVarianceImpl(Time t, Real) const {
if (t<=times_.back()) {
return varianceCurve_(t, true);
} else {
if (t <= times_.back() || timeExtrapolation_ == BlackVolTimeExtrapolation::UseInterpolatorVariance) {
return std::max(varianceCurve_(t, true), 0.0);
} else if (timeExtrapolation_ == BlackVolTimeExtrapolation::FlatVolatility) {
// extrapolate with flat vol
return varianceCurve_(times_.back(), true)*t/times_.back();
return timeExtrapolatationBlackVarianceFlat(t, times_, varianceCurve_);
} else if (timeExtrapolation_ == BlackVolTimeExtrapolation::UseInterpolatorVolatility) {
return timeExtrapolatationBlackVarianceInVolatility(t, times_, varianceCurve_);
} else {
QL_FAIL("Unknown time extrapolation method");
}
}

Expand Down
4 changes: 3 additions & 1 deletion ql/termstructures/volatility/equityfx/blackvariancecurve.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ namespace QuantLib {
const std::vector<Date>& dates,
const std::vector<Volatility>& blackVolCurve,
DayCounter dayCounter,
bool forceMonotoneVariance = true);
bool forceMonotoneVariance = true,
BlackVolTimeExtrapolation timeExtrapolation = BlackVolTimeExtrapolation::FlatVolatility);
//! \name TermStructure interface
//@{
DayCounter dayCounter() const override { return dayCounter_; }
Expand Down Expand Up @@ -84,6 +85,7 @@ namespace QuantLib {
std::vector<Time> times_;
std::vector<Real> variances_;
Interpolation varianceCurve_;
BlackVolTimeExtrapolation timeExtrapolation_;
};


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/*
Copyright (C) 2025 AcadiaSoft Inc.

This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/

QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<[email protected]>. The license is also available online at
<http://quantlib.org/license.shtml>.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/

/*! \file blackvariancetimeextrapolation.hpp
\brief Utility function for time extrapolation in Black volatility in black variance term structures
*/
#pragma once

#include <array>
#include <functional>
#include <ql/math/comparison.hpp>
#include <ql/math/interpolation.hpp>
#include <ql/math/interpolations/interpolation2d.hpp>
#include <ql/math/interpolations/linearinterpolation.hpp>

namespace QuantLib {

namespace {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An anonymous namespace in a header file doesn't make a lot of sense—namespace detail is better.

Real linearExtrapolation(const double t, const std::array<double, 2>& times, const std::array<double, 2>& variances);

inline Real linearExtrapolation(const double t, const std::array<double, 2>& times,
const std::array<double, 2>& variances) {
QL_REQUIRE(t > times[1], "t must be greater than times[1]");
QL_REQUIRE(times[1] > times[0], "times must be sorted");
QL_REQUIRE(variances[1] >= variances[0], "variances must be non-decreasing");
std::array<double, 2> vols;
vols[0] = close_enough(times[0], 0.0) ? 0.0 : std::sqrt(variances[0] / times[0]);
vols[1] = close_enough(times[1], 0.0) ? 0.0 : std::sqrt(variances[1] / times[1]);
LinearInterpolation interpolation(times.begin(), times.end(), vols.begin());
return std::max(interpolation(t, true), 0.0);
}
} // namespace



//! Extrapolate black variance using flat vol extrapolation in time direction
Real timeExtrapolatationBlackVarianceFlat(const Time t, const std::vector<double>& times,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"extrapolatation" (here and everywhere)

const Interpolation& varianceCurve);

//! Extrapolate black variance using flat vol extrapolation in time direction
template <typename F>
Real timeExtrapolatationBlackVarianceFlat(const Time t, const Real strike, const std::vector<double>& times,
const F& varianceSurface) {
return std::max(varianceSurface(times.back(), strike, true), 0.0) / times.back() * t;
}


//! Extrapolate black variance in vol space and time direction using interpolation
//! Takes black variances convert them to volatilities and then linearly extrapolates
//! the volatilities in time direction
Real timeExtrapolatationBlackVarianceInVolatility(const Time t, const std::vector<double>& times,
const Interpolation& varianceCurve);

//! Extrapolate black variance in vol space and time direction using interpolation
//! Takes black variances convert them to volatilities and then linearly extrapolates
//! the volatilities in time direction
template <typename F>
Real timeExtrapolatationBlackVarianceInVolatility(const Time t, const Real strike, const std::vector<double>& times,
const F& varianceSurface) {
Size ind1 = times.size() - 2;
Size ind2 = times.size() - 1;
std::array<Real, 2> xs{times[ind1], times[ind2]};
std::array<Real, 2> variances;
variances[0] = varianceSurface(xs[0], strike, true);
variances[1] = varianceSurface(xs[1], strike, true);
Real v = linearExtrapolation(t, xs, variances);
return v * v * t;
}

inline Real timeExtrapolatationBlackVarianceFlat(const Time t, const std::vector<double>& times,
const Interpolation& varianceCurve) {
return std::max(varianceCurve(times.back(), true), 0.0) / times.back() * t;
}

inline Real timeExtrapolatationBlackVarianceInVolatility(const Time t, const std::vector<double>& times,
const Interpolation& varianceCurve) {
Size ind1 = times.size() - 2;
Size ind2 = times.size() - 1;
std::array<Real, 2> xs{times[ind1], times[ind2]};
std::array<Real, 2> variances;
variances[0] = varianceCurve(xs[0], true);
variances[1] = varianceCurve(xs[1], true);
Real v = linearExtrapolation(t, xs, variances);
return v * v * t;
}
} // namespace QuantLib
Loading
Loading