Implied Volatility

PortfolioOptimisers.ImpliedVolatilityAlgorithmType
abstract type ImpliedVolatilityAlgorithm <: AbstractAlgorithm

Abstract supertype for all implied volatility algorithms.

All concrete and/or abstract types implementing implied volatility estimation algorithms should be subtypes of ImpliedVolatilityAlgorithm.

Interfaces

In order to implement a new concrete type that works seamlessly with the library, subtype ImpliedVolatilityAlgorithm and implement the following method:

Required method name

  • predict_realised_vols(alg::ImpliedVolatilityAlgorithm, iv::MatNum, X::MatNum, ivpa::Any): Predict the realised volatility of the period that follows the sample, one value per asset.

Arguments

The implied volatilities are the second positional argument and the returns the third. The two are matrices of the same size, so a call that swaps them is well typed and silently wrong.

  • alg: The concrete subtype instance.
  • iv: Implied volatility matrix observations × assets, already divided by $\sqrt{\mathrm{af}}$ by the caller.
  • X: Asset returns matrix observations × assets.
  • ivpa: Implied volatility premium adjustment factor. It is nothing when the caller supplies none, so an algorithm that needs one raises on that method.

Returns

  • rv_p::VecNum: Predicted realised volatility, one entry per asset, in the units of X.

Examples

julia> struct MyImpliedVolatilityAlgorithm <: PortfolioOptimisers.ImpliedVolatilityAlgorithm endjulia> function PortfolioOptimisers.predict_realised_vols(::MyImpliedVolatilityAlgorithm,                                                          iv::PortfolioOptimisers.MatNum, ::Any,                                                          ::Any)           return vec(iv[end, :])       endjulia> cov(ImpliedVolatility(; alg = MyImpliedVolatilityAlgorithm(), af = 1),           [0.1 0.2; 0.3 0.1; 0.2 0.4]; iv = [0.5 0.6; 0.4 0.7; 0.3 0.8])2×2 Matrix{Float64}:  0.09       -0.0785584 -0.0785584   0.64

Related

References

  • [39] T. G. Andersen, T. Bollerslev, P. F. Christoffersen and F. X. Diebold. Volatility and correlation forecasting. In: Handbook of Economic Forecasting, Vol. 1, edited by G. Elliott, C. W. Granger and A. Timmermann (North-Holland, 2006); Chapter 15, pp. 777–878.
source
PortfolioOptimisers.ImpliedVolatilityRegressionType
struct ImpliedVolatilityRegression{__T_ve, __T_ws, __T_re} <: ImpliedVolatilityAlgorithm

Implied volatility algorithm that predicts realised volatility via regression on implied volatility.

ImpliedVolatilityRegression fits a regression model relating implied and realised volatility over rolling windows, then uses the fitted model to predict the next period's realised volatility from the most recent implied volatility observation. The model, the steps that fit it and the number of windows it needs are stated by predict_realised_vols, which is the method this tag selects.

Fields

  • ve: Variance estimator.
  • ws: Window size for computing rolling realised volatility. It also sets the number of windows, div(size(X, 1), ws), and the regression needs more than two of them.
  • re: Regression model target.

Constructors

ImpliedVolatilityRegression(;    ve::AbstractVarianceEstimator = SimpleVariance(),    ws::Number = 20,    re::AbstractRegressionTarget = LinearModel()) -> ImpliedVolatilityRegression

Keywords correspond to the struct's fields.

Validation

  • ws > 2.

Propagated parameters

When factory is called on this type, the following @fprop-tagged fields are automatically propagated:

  • ve: Recursively updated via factory.

Examples

julia> ImpliedVolatilityRegression()ImpliedVolatilityRegression  ve ┼ SimpleVariance     │          me ┼ SimpleExpectedReturns     │             │   w ┴ nothing     │           w ┼ nothing     │   corrected ┴ Bool: true  ws ┼ Int64: 20  re ┼ LinearModel     │   kwargs ┴ @NamedTuple{}: NamedTuple()

Related

References

  • [40] B. J. Christensen and N. R. Prabhala. The relation between implied and realized volatility. Journal of Financial Economics 50, 125–150 (1998).
  • [41] B. J. Christensen and C. S. Hansen. New evidence on the implied-realized volatility relation. The European Journal of Finance 8, 187–205 (2002).
  • [39] T. G. Andersen, T. Bollerslev, P. F. Christoffersen and F. X. Diebold. Volatility and correlation forecasting. In: Handbook of Economic Forecasting, Vol. 1, edited by G. Elliott, C. W. Granger and A. Timmermann (North-Holland, 2006); Chapter 15, pp. 777–878.
source
PortfolioOptimisers.ImpliedVolatilityPremiumType
struct ImpliedVolatilityPremium <: ImpliedVolatilityAlgorithm

Implied volatility algorithm that divides the latest implied volatility by a volatility risk premium adjustment.

The adjustment factor is not a field of this type. The caller passes it as the ivpa keyword of the cov and cor methods of ImpliedVolatility, as a scalar or as one value per asset. The factor is mandatory: ivpa = nothing raises an ArgumentError. Every entry of it must be finite and strictly positive, and one that is not raises a DomainError, because a non-positive factor makes a negative volatility whose sign StatsBase.cor2cov! then hides. The closed form of the branch, and the rules it enforces, are stated by predict_realised_vols, which is the method this tag selects.

Constructors

ImpliedVolatilityPremium() -> ImpliedVolatilityPremium

Examples

julia> ImpliedVolatilityPremium()ImpliedVolatilityPremium()

Related

References

  • [42] T. Egbers and L. Swinkels. Can implied volatility predict returns on the currency carry trade?. Journal of Banking & Finance 59, 14–26 (2015).
source
PortfolioOptimisers.ImpliedVolatilityType
struct ImpliedVolatility{__T_ce, __T_mp, __T_alg, __T_af} <: AbstractCovarianceEstimator

Covariance estimator based on implied volatility scaling.

ImpliedVolatility computes a covariance matrix by combining a base correlation estimator with predicted realised volatilities derived from implied volatility data. It supports two algorithms: ImpliedVolatilityRegression, which fits a regression model to predict realised volatility from implied volatility, and ImpliedVolatilityPremium, which scales implied volatility by a user-supplied factor.

Fields

  • ce: Covariance estimator.
  • mp: Matrix processing estimator.
  • alg: Implied volatility algorithm for predicting realised volatility.
  • af: Annualisation factor for converting annualised implied volatility to the data frequency. The cov and cor methods divide the implied volatilities by sqrt(af) before the algorithm reads them.

Constructors

ImpliedVolatility(;    ce::StatsBase.CovarianceEstimator = Covariance(),    mp::AbstractMatrixProcessingEstimator = MatrixProcessing(),    alg::ImpliedVolatilityAlgorithm = ImpliedVolatilityRegression(),    af::Number = 252) -> ImpliedVolatility

Keywords correspond to the struct's fields.

Validation

  • af > 0.

Propagated parameters

When factory is called on this type, the following @fprop-tagged fields are automatically propagated:

  • ce: Recursively updated via factory.
  • alg: Recursively updated via factory.

View parameters

When port_opt_view is called on this type, the following @vprop-tagged fields are automatically subset to the selected indices:

Examples

julia> ImpliedVolatility()ImpliedVolatility   ce ┼ Covariance      │    me ┼ SimpleExpectedReturns      │       │   w ┴ nothing      │    ce ┼ GeneralCovariance      │       │   ce ┼ StatsBase.SimpleCovariance: StatsBase.SimpleCovariance(true)      │       │    w ┴ nothing      │   alg ┼ FullMoment()      │     w ┴ nothing   mp ┼ MatrixProcessing      │     pdm ┼ Posdef      │         │      alg ┼ UnionAll: NearestCorrelationMatrix.Newton      │         │   kwargs ┴ @NamedTuple{}: NamedTuple()      │      dn ┼ nothing      │      dt ┼ nothing      │     alg ┼ nothing      │   order ┴ NTuple{4, Symbol}: (:pdm, :dn, :dt, :alg)  alg ┼ ImpliedVolatilityRegression      │   ve ┼ SimpleVariance      │      │          me ┼ SimpleExpectedReturns      │      │             │   w ┴ nothing      │      │           w ┼ nothing      │      │   corrected ┴ Bool: true      │   ws ┼ Int64: 20      │   re ┼ LinearModel      │      │   kwargs ┴ @NamedTuple{}: NamedTuple()   af ┴ Int64: 252

Related

References

  • [39] T. G. Andersen, T. Bollerslev, P. F. Christoffersen and F. X. Diebold. Volatility and correlation forecasting. In: Handbook of Economic Forecasting, Vol. 1, edited by G. Elliott, C. W. Granger and A. Timmermann (North-Holland, 2006); Chapter 15, pp. 777–878.
source
PortfolioOptimisers.predict_realised_volsMethod
predict_realised_vols(::ImpliedVolatilityPremium, iv::MatNum, ::Any, ivpa::Nothing)

Error method: ImpliedVolatilityPremium requires an implied volatility premium adjustment factor.

The adjustment factor is not a field of ImpliedVolatilityPremium, so a caller that selects that algorithm and passes no ivpa reaches this method.

Arguments

The implied volatilities are the second positional argument and the returns the third.

  • ::ImpliedVolatilityPremium: Implied volatility premium algorithm.
  • iv: Implied volatility matrix (unused).
  • ::Any: Asset returns matrix (unused).
  • ivpa::Nothing: Implied volatility premium adjustment (must not be nothing).

Validation

  • ivpa is not nothing. This method is the failing branch, and it raises an ArgumentError.

Related

source
PortfolioOptimisers.predict_realised_volsMethod
predict_realised_vols(::ImpliedVolatilityPremium, iv::MatNum, ::Any,
                      ivpa::Num_VecNum)

Predict realised volatilities by scaling the latest implied volatility row by the premium adjustment factor.

The row read is the last row of iv itself, not the last row of a window, so this method needs no window size and no returns.

Mathematical definition

\[\begin{align} \hat{\sigma}^{\mathrm{rv}}_i &= \frac{\sigma^{\mathrm{iv}}_{T,\,i}}{\mathrm{ivpa}_i}\,. \end{align}\]

Where:

  • $\hat{\sigma}^{\mathrm{rv}}_i$: Predicted realised volatility of asset $i$ for the period that follows the sample.
  • $\sigma^{\mathrm{iv}}_{T,\,i}$: Implied volatility of asset $i$ at the last observation.
  • $\mathrm{ivpa}_i$: Implied volatility premium adjustment factor for asset $i$. A scalar applies to every asset.
  • $T$: Number of observations.

Arguments

The implied volatilities are the second positional argument and the returns the third.

  • ::ImpliedVolatilityPremium: Implied volatility premium algorithm.
  • iv: Implied volatility matrix (observations × assets); the last row is used.
  • ::Any: Asset returns matrix (unused).
  • ivpa: Implied volatility premium adjustment factor (scalar or vector).

Validation

  • Every entry of ivpa is finite and strictly positive. A non-positive factor turns a volatility negative, and StatsBase.cor2cov! hides the sign: it squares the factor on the diagonal, so a negative scalar returns the matrix its absolute value returns, and a negative entry of a vector flips the sign of every covariance of that asset alone. Both answers stay positive definite, so matrix_processing! finds nothing to repair and no later step sees the defect.
  • A vector ivpa carries one entry per asset. A wrong length raises a DimensionMismatch from the broadcast.

Returns

  • rv::AbstractArray: Predicted realised volatilities (last row of iv divided by ivpa).

Examples

julia> PortfolioOptimisers.predict_realised_vols(ImpliedVolatilityPremium(),                                                 [0.1 0.2; 0.3 0.1; 0.2 0.4; 0.1 0.1;                                                  0.4 0.2; 0.2 0.3], nothing, 1.25)2-element Vector{Float64}: 0.16 0.24

Related

References

  • [42] T. Egbers and L. Swinkels. Can implied volatility predict returns on the currency carry trade?. Journal of Banking & Finance 59, 14–26 (2015).
source
PortfolioOptimisers.predict_realised_volsMethod
predict_realised_vols(alg::ImpliedVolatilityRegression, iv::MatNum, X::MatNum, ::Any)

Predict realised volatilities using a regression model fitted on implied and realised volatility.

For each asset, this function fits a regression model relating the implied volatility and the realised volatility of one window to the realised volatility of the next window, then predicts from the last window. The windows are the blocks of realised_vol and the rows of implied_vol, so both series are read over the same rows of the sample.

Mathematical definition

Write $C$ for the number of windows, $\mathrm{div}(T, w_s)$. For asset $i$, fit the log-linear model over the windows $c = 1, \ldots, C-1$:

\[\begin{align} \ln \sigma^{\mathrm{rv}}_{c+1,\,i} &= \beta_0 + \beta_1 \ln \sigma^{\mathrm{iv}}_{c,\,i} + \beta_2 \ln \sigma^{\mathrm{rv}}_{c,\,i} + \varepsilon_c\,. \end{align}\]

Then predict from the last window:

\[\begin{align} \hat{\sigma}^{\mathrm{rv}}_i &= \exp\!\left(\hat{\beta}_0 + \hat{\beta}_1 \ln \sigma^{\mathrm{iv}}_{C,\,i} + \hat{\beta}_2 \ln \sigma^{\mathrm{rv}}_{C,\,i}\right)\,. \end{align}\]

Where:

  • $\hat{\sigma}^{\mathrm{rv}}_i$: Predicted realised volatility of asset $i$ for the period that follows the sample.
  • $\sigma^{\mathrm{rv}}_{c,\,i}$: Realised volatility of asset $i$ over window $c$.
  • $\sigma^{\mathrm{iv}}_{c,\,i}$: Implied volatility of asset $i$ at the last row of window $c$.
  • $\beta_0, \beta_1, \beta_2$: Regression coefficients.
  • $\varepsilon_c$: Regression residual.
  • $T$: Number of observations.

The fit takes $C - 1$ rows, so $C$ must exceed two for the model to have more rows than coefficients.

Algorithm

  1. Read T and N from size(X), and set chunk to div(T, alg.ws).
  2. Check that chunk exceeds two.
  3. Call realised_vol with alg.ve, giving rv, the realised volatility of every window.
  4. Call implied_vol on iv, giving iv, the implied volatility at the last row of every window. The window count comes from X, so iv is read over the rows of the returns sample.
  5. Check that rv and iv have the same size.
  6. Replace rv and iv by their natural logarithms.
  7. Build ovec, the intercept column of ones, of length T2 - 1.
  8. For each asset i, build the design matrix X_t from ovec and the first T2 - 1 rows of iv and rv, the response y_t from rows 2:T2 of rv, and the prediction row X_p from row T2.
  9. Fit alg.re on X_t and y_t, giving fri, then predict from X_p and exponentiate, giving rv_p[i].
  10. Return rv_p.

Arguments

The implied volatilities are the second positional argument and the returns the third. Both are matrices of the same size, so a call that swaps them is well typed and silently wrong.

  • alg: Implied volatility regression algorithm specifying the variance estimator, the window size and the regression target.
  • iv: Implied volatility matrix (observations × assets).
  • X: Asset returns matrix (observations × assets) used to compute realised volatility. It also fixes the window count, so iv must have as many rows as X.
  • ::Any: Ignored (placeholder for ivpa).

Validation

  • chunk > 2 (i.e., there must be more than 2 windows of data to fit the regression).
  • size(rv) == size(iv), one realised volatility per implied volatility.

Returns

  • rv_p::Vector{<:Number}: Predicted next-period realised volatilities (one per asset).

Related

References

  • [40] B. J. Christensen and N. R. Prabhala. The relation between implied and realized volatility. Journal of Financial Economics 50, 125–150 (1998).
  • [41] B. J. Christensen and C. S. Hansen. New evidence on the implied-realized volatility relation. The European Journal of Finance 8, 187–205 (2002).
  • [39] T. G. Andersen, T. Bollerslev, P. F. Christoffersen and F. X. Diebold. Volatility and correlation forecasting. In: Handbook of Economic Forecasting, Vol. 1, edited by G. Elliott, C. W. Granger and A. Timmermann (North-Holland, 2006); Chapter 15, pp. 777–878.
source
Statistics.covMethod
Statistics.cov(ce::ImpliedVolatility, X::MatNum; dims::Int = 1, mean = nothing,
               iv::MatNum, ivpa::Option{<:Num_VecNum} = nothing, kwargs...)

Compute the covariance matrix using implied volatility scaling.

This method computes the correlation matrix of X using the base estimator in ce, then predicts realised volatilities from iv using the implied volatility algorithm in ce.alg. The predicted realised volatilities are used to convert the correlation matrix to a covariance matrix, which is then post-processed by the matrix processing estimator ce.mp.

Mathematical definition

\[\begin{align} \hat{\mathbf{\Sigma}} &= \mathrm{diag}(\hat{\boldsymbol{\sigma}}^{\mathrm{rv}}) \hat{\boldsymbol{\rho}} \,\mathrm{diag}(\hat{\boldsymbol{\sigma}}^{\mathrm{rv}})\,. \end{align}\]

Where:

  • $\hat{\mathbf{\Sigma}}$: Estimated covariance matrix.
  • $\hat{\boldsymbol{\rho}} = \operatorname{cor}(\mathbf{X})$: Correlation matrix from asset returns, computed by ce.ce.
  • $\hat{\boldsymbol{\sigma}}^{\mathrm{rv}}$: Predicted realised volatilities, from $\mathbf{iv} / \sqrt{\mathrm{af}}$.

The diagonal of $\hat{\mathbf{\Sigma}}$ is therefore the square of the predicted realised volatility of each asset, and never a unit.

Algorithm

  1. Orient X and iv to observations × assets with dims_oriented, which validates dims and transposes both when dims is 2.
  2. Check that X and iv have the same size, so row t of iv is the implied volatility of observation t of X.
  3. Call Statistics.cor(ce.ce, X; dims = 1, mean = mean, iv = iv, kwargs...), giving sigma, the base correlation matrix. The oriented iv is forwarded so that a base estimator that reads its own implied volatility series, such as a nested ImpliedVolatility, receives it. Every other shipped estimator absorbs it into its own kwargs... and ignores it.
  4. Divide iv by sqrt(ce.af), converting the annualised implied volatility to the frequency of X.
  5. Call predict_realised_vols with ce.alg, giving iv, one predicted realised volatility per asset. The implied volatilities are the second argument and the returns the third.
  6. Scale sigma in place with StatsBase.cor2cov!, which applies the closed form above.
  7. Post-process sigma in place with matrix_processing! and ce.mp.

Arguments

  • ce: Implied volatility covariance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • dims: Dimension along which to perform the computation.
  • mean: Optional pre-computed mean (passed to the base estimator).
  • iv: Implied volatility matrix, annualised, oriented as X and of the same size.
  • ivpa: Optional implied volatility premium adjustment factor (required for ImpliedVolatilityPremium).
  • kwargs...: Additional keyword arguments passed to the base estimator.

Validation

Returns

  • sigma::MatNum: Covariance matrix assets x assets.

Related

source
Statistics.corMethod
Statistics.cor(ce::ImpliedVolatility, X::MatNum; dims::Int = 1, mean = nothing,
               iv::MatNum, ivpa::Option{<:Num_VecNum} = nothing, kwargs...)

Compute the correlation matrix using implied volatility scaling.

This method computes the correlation matrix of X using the base estimator in ce, normalises it, then post-processes it with the matrix processing estimator ce.mp.

A correlation is scale free, so the predicted realised volatilities cannot move the answer, and the returned matrix is the base correlation of X. The volatility model runs even so, because cor must refuse every configuration cov refuses: a ce.alg that cannot answer the call raises here as it does in cov. Its prediction is discarded, and never multiplied into rho and divided back out again.

That round trip was the identity in exact arithmetic alone. In floating point the round-off of one multiplication and one division moved an off-diagonal entry, and a predicted volatility of zero made the second call divide zero by zero. One asset whose last implied volatility was zero therefore turned a whole row and column of the correlation into NaN, and matrix_processing! raised on a matrix that carried no defect of its own.

Algorithm

  1. Orient X and iv to observations × assets with dims_oriented, which validates dims and transposes both when dims is 2.
  2. Check that X and iv have the same size, so row t of iv is the implied volatility of observation t of X.
  3. Call Statistics.cor(ce.ce, X; dims = 1, mean = mean, iv = iv, kwargs...), giving rho, the base correlation matrix. The oriented iv is forwarded so that a base estimator that reads its own implied volatility series, such as a nested ImpliedVolatility, receives it.
  4. Call predict_realised_vols with ce.alg and iv / sqrt(ce.af), and discard the result. The call runs for its raises alone, and iv is divided by sqrt(ce.af) for it exactly as it is in cov.
  5. Normalise rho in place with StatsBase.cov2cor!, which divides the entry in row i and column j by the square roots of the diagonal entries i and j. The call also mirrors the lower triangle into the upper one, clamps every off-diagonal entry into [-1, 1], and sets the diagonal to exactly one. The exact diagonal is what step 6 needs: matrix_processing! reads the value of the diagonal to decide whether it holds a correlation matrix or a covariance matrix.
  6. Post-process rho in place with matrix_processing! and ce.mp.

Arguments

  • ce: Implied volatility covariance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • dims: Dimension along which to perform the computation.
  • mean: Optional pre-computed mean (passed to the base estimator).
  • iv: Implied volatility matrix, annualised, oriented as X and of the same size.
  • ivpa: Optional implied volatility premium adjustment factor (required for ImpliedVolatilityPremium).
  • kwargs...: Additional keyword arguments passed to the base estimator.

Validation

Returns

  • rho::MatNum: Correlation matrix assets x assets.

Related

source
Statistics.covMethod
Statistics.cov(ce::ImpliedVolatility, X::MatNum, pnl::Option{<:AssetPanel};
               dims::Int = 1, mean = nothing, iv::MatNum,
               ivpa::Option{<:Num_VecNum} = nothing, kwargs...) -> MatNum
Statistics.cor(ce::ImpliedVolatility, X::MatNum, pnl::Option{<:AssetPanel};
               dims::Int = 1, mean = nothing, iv::MatNum,
               ivpa::Option{<:Num_VecNum} = nothing, kwargs...) -> MatNum

Fit an implied volatility estimate on the Coverage Universe, and expand it to the full asset universe.

ImpliedVolatility overrides the reduce-and-expand root of its verb because it reads two more per-asset inputs than the root knows about: the implied volatility surface iv, which is observations × assets, and the premium ivpa, which is one number per asset where it is a vector. Both take the slice X takes, so that the three inputs describe the same universe.

The surface also narrows that universe. An implied volatility is padded NaN where it is silent, exactly as a return is, so the Coverage Universe of this fit is the one coverage_mask derives: an asset whose returns are complete but whose implied volatilities are not is excluded from the fit, and expand_moment writes its NaN row and column.

Algorithm

  1. Check dims, and orient X and iv to observations × assets.
  2. Derive the Coverage Universe of X and iv with coverage_mask.
  3. Slice X, iv and ivpa onto it.
  4. Call the two-argument method on the clean block.
  5. Expand the matrix with expand_moment.

Arguments

  • ce: Covariance estimator.
  • X: Data matrix observations × assets if the dims keyword does not exist or dims = 1, assets × observations when dims = 2.
  • pnl: Optional AssetPanel, whose active mask the Coverage Universe of the fit is derived from. nothing makes the rule finiteness alone.
  • dims: Dimension along which to perform the computation.
  • mean: Optional mean value to use for centering.
  • iv: Implied volatility surface observations × assets.
  • ivpa: Implied volatility premium adjustment.
  • kwargs...: Additional keyword arguments passed to the two-argument method.

Validation

  • dims in (1, 2).
  • size(X) == size(iv).
  • At least one asset must be covered.

Returns

  • sigma::MatNum: The covariance matrix, or the correlation matrix, on the full asset universe.

Related

source

References

[39]
T. G. Andersen, T. Bollerslev, P. F. Christoffersen and F. X. Diebold. Volatility and correlation forecasting. In: Handbook of Economic Forecasting, Vol. 1, edited by G. Elliott, C. W. Granger and A. Timmermann (North-Holland, Amsterdam, 2006); Chapter 15, pp. 777–878.
[40]
B. J. Christensen and N. R. Prabhala. The relation between implied and realized volatility. Journal of Financial Economics 50, 125–150 (1998).
[41]
B. J. Christensen and C. S. Hansen. New evidence on the implied-realized volatility relation. The European Journal of Finance 8, 187–205 (2002).
[42]
T. Egbers and L. Swinkels. Can implied volatility predict returns on the currency carry trade? Journal of Banking & Finance 59, 14–26 (2015).