Cross-Sectional Exposure IC: private API

Functions

PortfolioOptimisers.exposure_forward_mean_return — Function
exposure_forward_mean_return(R::MatNum, horizon::Integer)

Return the forward mean asset return of every observation but the last horizon of them.

The information coefficient scores an exposure against what the asset earned after the exposure was known, and this verb builds that target. An observation whose forward window carries no finite return gets NaN, and the verb averages a window that is part finite over the finite part alone.

Mathematical definition

\[\begin{align} y_{ti} &= \frac{1}{|\mathcal{H}_{ti}|} \sum_{h \in \mathcal{H}_{ti}} r_{t+h,i}\,. \end{align}\]

Where:

  • $y_{ti}$: Forward mean return of asset $i$ at observation $t$, NaN when $\mathcal{H}_{ti}$ is empty.
  • $r_{ti}$: Return of asset $i$ at observation $t$.
  • $\mathcal{H}_{ti}$: The offsets $1 \le h \le H$ at which $r_{t+h,i}$ is finite.
  • $H$: Forward window, in observations.

Arguments

  • R: Asset return history observations × assets.
  • horizon: Forward window, in observations.

Validation

  • size(R, 1) > horizon.

Returns

  • y::MatNum: Forward mean return (observations - horizon) × assets. Row t averages the returns of observations t + 1 to t + horizon.

Related

source
PortfolioOptimisers.exposure_ic_factor_summary — Function
exposure_ic_factor_summary(ic::MatNum, k::Integer; lags::Integer = 0,
                           window::Real = lags + 1,
                           mt::AbstractMeanTestEstimator = WildBootstrapMeanTest(),
                           rng = mean_test_rng(mt))

Return the eight summary numbers of one factor's information coefficient series.

The mean, the standard deviation and the hit rate read the observations at which the coefficient is finite, so an observation with no coefficient is in no denominator and the three agree on their sample. A series with no finite coefficient has no hit rate. The ratio has no answer where either of its two terms has none, and none where the standard deviation is zero. The t-statistic, the p-value and the confidence interval of the mean come from the Mean Test mt, and they state whether the mean is far enough from zero to believe over the evidence there was.

forecast_ic_summary calls this function too, so a coefficient of a factor exposure and a coefficient of a Return Forecast have the same summary.

The test reads the dependence of the rows

A coefficient scored against a forward window that is longer than the stride between two scores reads the same returns at consecutive rows. The rows that overlap a given row are the $L$ on each side of it, where $L$ is one less than the number of strides a window spans. A persistent ranking of the assets correlates the rows across the overlap. A persistent coefficient correlates them past it too, and a change of the volatility over time changes the law of the statistic. A test that treats the rows as independent then overstates the evidence.

The default WildBootstrapMeanTest reads the dependence at every lag up to a bandwidth that is a fixed fraction of the series, and reads the p-value off a wild bootstrap of the statistic. It does not read lags. OverlapMeanTest reads the overlap alone, at the order lags, and compares the statistic with the Student law. At lags = 0 its statistic is $\mathrm{IR} \sqrt{n}$. The history rule of a Mean Test reads window.

The test reads the rows at their positions in ic. A row whose coefficient is NaN is in no pair, and the lag between two rows is their distance in the series, not in its finite subsequence. A long-run variance that is not positive gives a NaN t-statistic and a NaN p-value. The function does not clamp it, because a clamped value would report a certainty that the series does not carry.

Arguments

  • ic: Information coefficient series pairs × factors.
  • k: Position of the factor.
  • lags: Number of rows on each side of a given row whose windows overlap it, 0 for independent rows. forecast_ic_lags derives it from a window and a stride.
  • window: Number of rows that one forward window spans, lags + 1 by default. forecast_ic_window derives it exactly from a window and a stride.
  • mt: The Mean Test of the t-statistic, the p-value and the interval.
  • rng: The generator of the test. A caller that summarises many series resolves it once with mean_test_rng, so a seeded test is reproducible and the series take different draws.

Validation

Returns

  • m::NamedTuple: (; mean_ic, std_ic, ic_ir, t_stat, p_value, mean_ci_lower, mean_ci_upper, hit_rate), eight numbers.

Related

source
PortfolioOptimisers.exposure_ic_data — Function
exposure_ic_data(csfm::CrossSectionalFactorModel, rd::Nothing, reduced::Bool)
exposure_ic_data(csfm::CrossSectionalFactorModel, rd::ReturnsResult, reduced::Bool)

Return the exposure history, the asset returns and the regression weights the information coefficient reads off a factor model block.

Without rd, the function reconstructs the asset returns from the systematic return of the fit and the residual, because the block carries no asset returns. The reconstruction exists from observation $\ell + 1$, so the answer starts at observation $\max(1, \ell)$. The return row of that first observation is NaN, and no score reads it, because the information coefficient scores an exposure against the returns that follow it. With rd, the function reads the asset returns of the rows of the block off rd with exposure_ic_returns. It reads no fit, so the answer covers every row of the block.

Algorithm

  1. Refuse a block that carries no exposure history, or without rd no cross-sectional fit.
  2. With rd, read the returns of the rows of the block, and skip step 3.
  3. Reconstruct the return of each observation as $\mathbf{B}_{t-\ell} \boldsymbol{f}_{t} + \boldsymbol{\varepsilon}_{t}$, and write NaN where the lag leaves it undefined. The reconstruction runs on the axis the fit ran on: the exposures on the reduced axis when the block carries a family re-basis, and the factor returns of cross_sectional_factor_returns, which put the observed factors after the estimated ones. So it gives back the returns of every asset, the part the observed factors carry included. Trim all three histories to the observations from $\max(1, \ell)$.
  4. Map the exposures through the family re-basis when reduced.

Arguments

  • csfm: A cross-sectional factor model block.
  • rd: The returns data that the prior read, or nothing to reconstruct the asset returns from the fit of the block.
  • reduced: Map the exposures through the family re-basis of the block.

Validation

  • csfm.Ms is not nothing. Otherwise the verb raises an IsNothingError that names Ms.
  • Without rd, csfm.csr is not nothing. Otherwise the verb raises an IsNothingError that names csr.
  • Without rd, size(csfm.Ms, 1) > csfm.lag, and the factor returns carry the observation axis of csfm.Ms and the factor axis of its reduced exposures.
  • With rd, the rules of exposure_ic_returns.

Returns

  • B::Arr3Num: Exposure history of the observation axis of the answer.
  • R::MatNum: Asset returns of the same axis, reconstructed without rd.
  • w::Option{<:MatNum}: Regression weights of the same axis, or nothing.

Related

source
PortfolioOptimisers.exposure_ic_returns — Function
exposure_ic_returns(idx, X::Nothing, T::Integer)
exposure_ic_returns(idx::Nothing, X::MatNum, T::Integer)
exposure_ic_returns(idx::VecInt, X::MatNum, T::Integer)

Return the asset returns of the rows of a factor model block, read off the returns data that the prior read.

The prior records the position of each row of the block in its returns data in idx, so the function reads those rows. A block that records no position, for example one built by hand, states no map from its rows to the returns. Its returns must then be the returns of its own rows, and the function reads X whole. It does not align the two at their tail, because a wrong alignment scores each exposure against the returns of another observation, and no check could find it. exposure_ic checks the shape of the answer against the exposure history.

Arguments

  • idx: The idx field of a CrossSectionalFactorModel, or nothing.
  • X: The asset returns of the returns data observations × assets, or nothing.
  • T: Number of rows of the block.

Validation

  • X is not nothing. Otherwise the verb raises an IsNothingError that names rd.X.
  • Without idx, size(X, 1) == T. Raises a DimensionMismatch.
  • With idx, length(idx) == T, and every entry of idx is a row of X. Raises a DimensionMismatch or a BoundsError.

Returns

  • R::MatNum: Asset returns T × assets, a view of X when idx is given.

Related

source
PortfolioOptimisers.exposure_ic_exposures — Function
exposure_ic_exposures(fcb::Nothing, Ms::Arr3Num, reduced::Bool)
exposure_ic_exposures(fcb::FactorFamilyBasis, Ms::Arr3Num, reduced::Bool)

Return the exposure history the information coefficient scores, on the raw axis or on the reduced one.

A block that carries no family re-basis has one axis, so that case returns the history unchanged whatever reduced states.

Arguments

  • fcb: The fcb field of a CrossSectionalFactorModel, or nothing.
  • Ms: Unlagged exposure history observations × assets × factors.
  • reduced: Map the history through the re-basis.

Returns

  • B::Arr3Num: The history, on the reduced axis when a re-basis is set and reduced is true.

Related

source