Cross-Sectional Carry Histories: private API
The carry fold of a CrossSectionalFactorPrior appends the rows of each step to its histories in place, into the spare rows of a backing array. Under observed factors the exposure history and the observed exposures share one backing, so the call with no data reads the joined history with no copy. The functions below make the append, join the two exposure histories in one backing, find the backing that the append writes into, and copy a state that a later step passed before the state takes a step. The last function of the first group rebuilds a state with some of its fields replaced.
PortfolioOptimisers.cross_sectional_fold_append — Function
cross_sectional_fold_append(_::Nothing, b) -> Any
Appends the rows of a block to a history, or starts the history with them.
A history that a step appended to is a view of the first rows of a backing array, whose other rows are spare. The append writes the rows of the block into the spare rows in place, and gives a longer view of the same backing, so a step costs the rows of the block and no copy of the history. A backing with too few spare rows is replaced by one of twice the rows, as reserve_sample_buffer grows the backing of a SampleBufferState. Each state keeps the view of its own rows, so an earlier state reads its own rows after a later step. The caller makes sure that the state is the newest one of its lineage, with cross_sectional_carry_own, so no append writes a row that another state reads.
Arguments
a: The history, ornothing.b: The rows of the block.
Returns
h:afollowed bybalong the observation axis.
Related
PortfolioOptimisers.cross_sectional_fold_join — Function
cross_sectional_fold_join(Ms, obs, b::AbstractArray, bo::Nothing) -> NamedTuple
cross_sectional_fold_join(Ms::Nothing, obs::Nothing, b::AbstractArray{<:Any, 3},
bo::NamedTuple) -> NamedTuple
cross_sectional_fold_join(Ms::AbstractArray{<:Any, 3}, obs::NamedTuple,
b::AbstractArray{<:Any, 3}, bo::NamedTuple) -> NamedTupleAppends the rows of a block to the exposure history and to the observed factors that the carry fold of a Cross-Sectional Factor Prior carries.
The call with no data reads the exposure history with the observed exposures after the estimated ones, as cross_sectional_observed_append joins them. So under observed factors the two exposure histories are views of one backing, whose factor axis holds the estimated factors and then the observed ones. cross_sectional_joined_exposures then reads the joined history of the fitted observations as a view of the backing, and no step and no call with no data copies it. The join appends the joined rows of the block with cross_sectional_fold_append, into the spare rows of the backing. Two histories that share no backing, as after the first block, join by a copy into a new backing, once. The observed returns append with cross_sectional_fold_append, and the names and the family labels stay those of the first block.
Arguments
Ms: The exposure history of the estimated factors, ornothingbefore the first block.obs: The observed factors(; Z, R, lv, nf, fam)of the history, ornothing.b: The exposures of the estimated factors of the block.bo: The observed factors of the block, ornothingwithout an observed factor, when the method overNothingappendsbalone.
Returns
h::NamedTuple:(; Ms, obs), the two histories followed by the rows of the block.
Related
PortfolioOptimisers.cross_sectional_fold_split — Function
cross_sectional_fold_split(
J::AbstractArray{<:Any, 3},
K::Integer,
R::AbstractMatrix,
o::NamedTuple
) -> NamedTuple{(:Ms, :obs), <:Tuple{Any, NamedTuple{(:Z, :R, :lv, :nf, :fam), <:Tuple{Any, AbstractMatrix, Any, Any, Any}}}}
Splits a joined exposure history into the history of the estimated factors and the observed factors.
Both histories are views of the backing of J with a Base.OneTo row index, so the next append finds the spare rows of the backing, as cross_sectional_spare_backing states. A view of a view would carry a UnitRange row index, which marks no backing of the library.
Arguments
J: The joined exposure history,observations × assets × factors, the estimated factors first.K: The number of estimated factors.R: The observed returns of the history.o: The observed factors whose names and family labels the history keeps.
Returns
h::NamedTuple:(; Ms, obs), ascross_sectional_fold_joinstates it.
Related
PortfolioOptimisers.cross_sectional_spare_backing — Function
cross_sectional_spare_backing(a::AbstractArray, T::Type, k::Integer)
cross_sectional_spare_backing(a::SubArray{<:Any, <:Any, <:Union{Array, BitArray},
<:Tuple{Base.OneTo{Int}, Vararg{Base.Slice}}},
T::Type, k::Integer)Returns the backing array of a history when it holds k rows of element type T, or nothing.
cross_sectional_fold_append makes every backing, and gives a view of its first rows with a Base.OneTo row index. Only such a view has a backing that the append can write into. Any other array, a history that a fit of every observation made or a view of the caller's data, has none, so the append copies it into a new backing.
Arguments
a: The history.T: The element type of the history after the append.k: The number of rows of the history after the append.
Returns
P::Option{<:AbstractArray}: The backing array, ornothing.
Related
PortfolioOptimisers.cross_sectional_carry_own — Function
cross_sectional_carry_own(
st::CrossSectionalCarryState
) -> CrossSectionalCarryState
Makes the state of the carry fold of a Cross-Sectional Factor Prior the newest state of its lineage, before a step.
A step appends to the histories and to the buffer buf in place, into the spare rows of their backings, with cross_sectional_fold_append. A state that a later step passed shares those backings with the later state, whose rows sit in the spare rows of the earlier one. So a step of the earlier state takes a copy of it first, which starts a lineage of its own. The later state and every Result read out of it keep their rows. The factor prior and the variance estimators fold in place, as every fold does, so the copy holds their state after the later step. To fold one state into two streams, copy it with partial_fit before the first of them.
Arguments
st: The state before the step.
Returns
st::CrossSectionalCarryState:stwhen itstipcounts its own observations, and a copy of it otherwise.
Related
PortfolioOptimisers.cross_sectional_carry_with — Function
cross_sectional_carry_with(
st::CrossSectionalCarryState,
kw::NamedTuple
) -> Union{CrossSectionalCarryState{__T_buf, Nothing, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, __T_seed, _X, _Y, _Z, _Z1, _Z2, _Z3, _Z4, _Z5, _Z6, Base.RefValue{Int64}} where {__T_buf<:SampleBufferState, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, __T_seed<:Integer, _X, _Y, _Z, _Z1, _Z2, _Z3, _Z4, _Z5, _Z6}, CrossSectionalCarryState{__T_buf, __T_win, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, __T_seed, _X, _Y, _Z, _Z1, _Z2, _Z3, _Z4, _Z5, _Z6, Base.RefValue{Int64}} where {__T_buf<:SampleBufferState, __T_win<:ReturnsResult, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, __T_seed<:Integer, _X, _Y, _Z, _Z1, _Z2, _Z3, _Z4, _Z5, _Z6}}
Rebuilds a CrossSectionalCarryState with some of its fields replaced.
Arguments
st: The state.kw: The fields to replace, by name.
Returns
st::CrossSectionalCarryState: The new state.
Related
A step that moves the dropped member of a family of factors under a BatchChoice rewrites the histories in the new basis, and solves again only the observations that are rank-deficient. The functions below decide whether the move folds, rewrite the basis from its own ratios, mark the Empty Factors in the new basis, solve again each observation whose answer depends on the basis, and fold the factor prior again over the factor returns of the new basis.
PortfolioOptimisers.cross_sectional_fold_move — Function
cross_sectional_fold_move(
pe::CrossSectionalFactorPrior,
st::CrossSectionalCarryState,
families::Union{Nothing, AbstractVector{<:Pair}},
m::Integer
) -> Union{Nothing, CrossSectionalCarryState}
Folds a move of the dropped member of a Factor Family into the state of the carry fold of a Cross-Sectional Factor Prior, before the step fits its new observations.
A move runs no regression again over the observations of full rank. The raw factor returns of such an observation do not depend on the dropped member, as cross_sectional_move_basis states, so the factor returns under the new members are the columns of the raw factor returns that the new basis keeps. cross_sectional_move_solve solves each rank-deficient observation again in the new basis: an observation with an Unseen Member under SolvedUnseenMember, or one with a dependent factor set. The residuals, the regression weights, the idiosyncratic variance, the standardised idiosyncratic returns and the Return Forecast rows do not depend on the dropped member either, so the state keeps them. The factor prior folds again over the new factor returns, because the default factor covariance is not separable by column: its regime multiplier reads every column. That fold reads every fitted observation, so its cost grows with the stream, and so does the test of the rank of cross_sectional_move_solve. cross_sectional_move_marks gives the marks of the Empty Factors.
The state equals the state of cross_sectional_fold_refit under the new members to rounding, on each fitted observation whose design has full rank on its columns that are not zero, and on each observation that the fold solves again. Under a CrossSectionalTargetRegression of a GeneralisedLinearModel, the fit is iterative, and the two states agree to rounding when the two bases stop at the same iterate. GLM stops when the change in the deviance falls below max(rtol * deviance, atol), with rtol = 1e-6 and atol = 1e-6 by default, and the kwargs of the target set them. A tolerance near the rounding of the deviance lets rounding stop the two bases one iteration apart at an observation, and the states then differ by that iteration there.
Algorithm
- Answer
nothingwhenpe.vedoes not fold, assupports_partial_fitanswers, because the step then fits every observation again. Answerstwhen no dropped member moved. - Rewrite the basis of the observations before the step with
cross_sectional_move_basis. Answernothingwhen the move does not fold, or when a new dropped member has a zero benchmark-weighted exposure, so the fit of every observation refuses it as the batch fit does.cross_sectional_rebase_statetakes steps 3 to 7. - Expand the factor returns of the fitted observations onto the raw axis with
cross_sectional_expand, and keep the columns of the new basis. - Mark the Empty Factors with
cross_sectional_move_marks. - Solve the observations whose answer depends on the basis again, with
cross_sectional_move_solve. - Fold the factor prior over the factor returns of
cross_sectional_fold_factor_returnswithcross_sectional_refold_factors. - Reduce the exposures of the last
lagobservations in the new basis, which the regression of the new observations reads.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state, whose histories hold the new observations as their lastmrows.families: The families with their dropped members named, ornothing.m: Number of new observations.
Returns
st::Option{CrossSectionalCarryState}: The state in the basis offamilies, ornothingwhen the step fits every observation again.
Related
PortfolioOptimisers.cross_sectional_move_basis — Function
cross_sectional_move_basis(unseen::Union{ZeroUnseenMember, SolvedUnseenMember},
cre::CrossSectionalLinearRegression, st, families)
-> Option{<:FactorFamilyBasis}
cross_sectional_move_basis(unseen::Union{ZeroUnseenMember, SolvedUnseenMember},
cre::CrossSectionalTargetRegression, st, families)
-> Option{<:FactorFamilyBasis}
cross_sectional_move_basis(unseen::AbstractUnseenMemberRule,
cre::AbstractCrossSectionalRegressionEstimator, st, families)
-> nothingReturns the basis of the fitted observations under the dropped members that moved, when the move folds on the carry fold of a Cross-Sectional Factor Prior, and nothing otherwise.
The zero-sum condition of a family is the same set of factor returns for every dropped member. So a regression that minimises the weighted squared residuals gives the same raw factor returns in every basis, on each observation whose design has full rank. ZeroUnseenMember makes every observation with an Unseen Member identified, so its answer does not depend on the dropped member. SolvedUnseenMember keeps such an observation rank-deficient, and a dependent factor set makes an observation rank-deficient under every rule. The answer of a rank-deficient observation depends on the dropped member under every AbstractCrossSectionalSolveAlgorithm that answers it: the answer of least norm reads the coordinates of the basis, and so does the pivot of DependentColumnDrop. So cross_sectional_move_solve solves it again in the new basis. A CrossSectionalTargetRegression fits a target, and a target can penalise its coefficients, so its answer can depend on the basis. is_basis_invariant answers for the target. A target that answers true, such as LinearModel, gives the same raw factor returns in every basis on an observation of full rank, as a least-squares fit does. GeneralisedLinearModel answers true: its iterative fit takes the same iterates in every basis, so it gives the same raw factor returns to rounding. On a rank-deficient observation the answer of a target depends on the basis too, under each solve algorithm of the target, and cross_sectional_move_solve solves such an observation again through the target. So a move folds under CrossSectionalLinearRegression, and under a target that answers true, with the two Unseen Member rules of the library. Every other pair fits every observation again.
Algorithm
The method that Julia selects is the algorithm.
- Under
ZeroUnseenMemberorSolvedUnseenMember, withCrossSectionalLinearRegression, rewrite the basis withcross_sectional_rebase. - Under the same rules, with
CrossSectionalTargetRegression, rewrite the basis as step 1 does whenis_basis_invariantanswerstrueforcre.tgt, and answernothingotherwise. - Under any other pair, answer
nothing.
Arguments
unseen: The Unseen Member rule of the prior.cre: The cross-sectional regression estimator of the prior.st: The state, whosefcbis the basis of the last fit.families: The families with their dropped members named.
Returns
fcb::Option{<:FactorFamilyBasis}: The basis underfamilies, ornothingwhen the move does not fold.
Related
PortfolioOptimisers.cross_sectional_rebase_state — Function
cross_sectional_rebase_state(pe::CrossSectionalFactorPrior, st::CrossSectionalCarryState,
fcb::Nothing, m::Integer) -> nothing
cross_sectional_rebase_state(pe::CrossSectionalFactorPrior, st::CrossSectionalCarryState,
fcb::FactorFamilyBasis, m::Integer) -> CrossSectionalCarryStateRewrites the state of the carry fold of a Cross-Sectional Factor Prior in a new Factor Family Basis, as steps 3 to 7 of cross_sectional_fold_move state. The state records the dropped members of the basis with cross_sectional_dropped_names, as the fit of every observation records them.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state, whose histories hold the new observations as their lastmrows.fcb: The basis of the observations before the step under the new dropped members, ornothingwhen the move does not fold.m: Number of new observations.
Returns
st::Option{CrossSectionalCarryState}: The state in the basisfcb, ornothingwithout a basis.
Related
PortfolioOptimisers.cross_sectional_rebase — Function
cross_sectional_rebase(
fcb::FactorFamilyBasis,
families::AbstractVector{<:Pair},
nf::AbstractVector{<:AbstractString}
) -> Union{Nothing, FactorFamilyBasis{var"#s185", var"#s1851", var"#s1852", <:AbstractMatrix{var"#s153"}, <:Integer} where {var"#s153"<:AbstractString, var"#s185"<:AbstractVector{var"#s153"}, var"#s3652"<:(AbstractVector{<:Integer}), var"#s1851"<:AbstractVector{var"#s3652"}, var"#s3650"<:Integer, var"#s1852"<:AbstractVector{var"#s3650"}, var"#s153"<:(Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar})}}
Rewrites a Factor Family Basis with new dropped members, from its own ratios.
The ratio of a member is its benchmark-weighted exposure over the exposure of the dropped member. So the ratios under a new dropped member $k^{\prime}$ are the old ratios over the old ratio of $k^{\prime}$, and the ratio of the old dropped member $k$ is the inverse of that ratio. The function reads no exposure, and its ratios equal the ratios of factor_family_basis to rounding.
Mathematical definition
\[\begin{align} r^{\prime}_{t}(j) &= \frac{r_{t}(j)}{r_{t}(k^{\prime})}\,, \quad j \in \mathcal{F} \setminus \{k, k^{\prime}\}\,, \\ r^{\prime}_{t}(k) &= \frac{1}{r_{t}(k^{\prime})}\,. \end{align}\]
Where:
- $\mathcal{F}$: Raw factors of one family.
- $r_{t}(j) = c_{t}(j) / c_{t}(k)$: Ratio of the benchmark-weighted exposure of member $j$ of a constrained Factor Family to that of the member $k$ the family drops, at observation $t$.
- $r^{\prime}_{t}(j)$: Ratio of member $j$ at observation $t$ under the new dropped member $k^{\prime}$.
Arguments
fcb: The Factor Family Basis.families: Pairs offamily label => dropped member, in the order offcb.fnm, each member named.nf: Names of the raw factor axis.
Returns
fcb::Option{<:FactorFamilyBasis}: The basis with the new dropped members, ornothingwhen a new dropped member has a zero benchmark-weighted exposure at an observation, wherefactor_family_basisrefuses it.
Related
PortfolioOptimisers.cross_sectional_rebase_family — Function
cross_sectional_rebase_family(
fcb::FactorFamilyBasis,
j::Integer,
d::Integer
) -> Any
Returns the block of the ratios of one Factor Family under a new dropped member, as cross_sectional_rebase states it.
Algorithm
- Write the ratios of the family into a block with one column per member, and a column of ones at the old dropped member, whose ratio to itself is one.
- Answer
nothingwhen the column of the new dropped member holds a zero. - Divide every column but that one by it. A family whose member did not move divides by a column of ones, which gives its ratios unchanged.
Arguments
fcb: The Factor Family Basis.j: Position of the family infcb.fnm.d: Position of the new dropped member infcb.fi[j].
Returns
R::Option{<:Matrix}: The block, one column per retained member in the order offcb.fi[j], ornothingwhen the old ratio of the new dropped member is zero at an observation.
Related
PortfolioOptimisers.cross_sectional_move_marks — Function
cross_sectional_move_marks(
pe::CrossSectionalFactorPrior,
st::CrossSectionalCarryState,
fcb::FactorFamilyBasis
) -> NamedTuple{(:lv1, :lv), <:Tuple{Any, Any}}
Marks the factors that are not empty in each regression pass of the carry fold of a Cross-Sectional Factor Prior, under a basis whose dropped members moved.
A factor outside a Factor Family that moved keeps its column of the design, so it keeps its marks. The design of a family that moved changes, so the function builds the design of each fitted observation in the new basis, from the first one, until each member of such a family is marked in both passes. The first observations mark each member that the sample sees, so the function reads every observation only when a member stays empty.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state, whosefcb,lv1andlvare those of the old basis.fcb: The new basis, over the rows ofst.fcb.
Returns
marks::NamedTuple:lv1andlv, the marks of the two passes on the new reduced axis.
Related
PortfolioOptimisers.cross_sectional_move_row_marks — Function
cross_sectional_move_row_marks(
pe::CrossSectionalFactorPrior,
st::CrossSectionalCarryState,
fcb::FactorFamilyBasis,
s::Integer
) -> @NamedTuple{lv1::BitVector, lv::BitVector}
Marks the factors that are not empty at one fitted observation of the carry fold of a Cross-Sectional Factor Prior, in a basis, in each regression pass.
The function runs the steps of cross_sectional_fold_regression that the marks read, on the one observation: the lagged exposures reduced in the basis, the eligibility mask, the first-pass weights, and the design of unseen_member_design. The last pass reads the weights that the state carries, because they read the residuals, which do not depend on the basis.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state.fcb: The basis, over the rows ofst.fcb.s: The fitted observation, as a row ofst.W.
Returns
marks::NamedTuple:lv1andlv, the marks of the observation in the two passes.
Related
PortfolioOptimisers.cross_sectional_move_solve — Function
cross_sectional_move_solve(
pe::CrossSectionalFactorPrior,
st::CrossSectionalCarryState,
mv::NamedTuple
) -> Any
Solves again, in a new Factor Family Basis, each fitted observation whose factor returns depend on the dropped members, on the carry fold of a Cross-Sectional Factor Prior.
A change of the dropped member is an invertible change of the coefficients of the family. So the old and the new reduced design of an observation span the same columns, and the fitted values, the residuals and the regression weights do not depend on the dropped member. On an observation of full rank, the factor returns do not depend on it either.
On a rank-deficient observation PseudoInverseFallback takes the answer of least norm, and the norm reads the coordinates of the basis. The pivot of DependentColumnDrop reads them too. So the answer in the new basis is not a selection of the answer in the old basis, and the function solves such an observation again with the last-pass weights st.W, which the stored regression read, on the factors that mv.lv marks, as the batch fit solves it. Two cases make such an observation. Under SolvedUnseenMember an observation with an Unseen Member is rank-deficient. A dependent factor set makes it rank-deficient under every rule, for example a beta that shrinks to the mean of its industry: where every industry shrinks fully, the style column is a function of the industry columns.
A column that is zero at an observation is an Unseen Member under ZeroUnseenMember, or a factor that no eligible asset loads on there. The solve gives it a return of zero in every basis, so the test leaves it out, and a design whose other columns have full rank keeps its factor returns. The test reads the exposures of every fitted observation, so its cost grows with the stream.
Algorithm
- Build the design of each fitted observation
sinmv.fcbwithunseen_member_design, on the factors thatmv.lvmarks, and scale its rows of positive weight inst.W[s, :]by the square root of the weight. - Keep the factor returns of the observation when
cross_sectional_rankof the columns of that design that are not zero equals their number. - Otherwise, regress the returns of the observation with
cross_sectional_live_regression, under the policy ofpe.cre, afters - 1fitted observations, so a refusal names the observations, as the batch fit does. Map the answer withunseen_member_returns. Write the factor returns into the rowsofmv.f. - When
mv.dcis a mask, write the dropped columns of the observation into its rows. An observation that step 2 keeps drops exactly its zero columns, because its other columns have full rank, and a zero column takes the last pivot. An observation that step 3 solves again takes the mask of its new fit.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state, whosefcbis the basis of the last fit.mv: The move,(; fcb, f, lv, dc): the new basis over the rows ofst.fcb; the factor returns of the fitted observations infcb, the columns of the raw factor returns thatfcbkeeps, which the function modifies in place; the mark of the factors that are not empty in the last pass, infcb; and the dropped-column mask of the fitted observations infcb, allfalseon entry, which the function writes in place, ornothingwhen the fit states no mask.
Returns
f::MatNum: The factor returns inmv.fcb.
Related
PortfolioOptimisers.cross_sectional_move_dropped! — Function
cross_sectional_move_dropped!(dc::Nothing, s::Integer, args...) -> Nothing
cross_sectional_move_dropped!(dc::AbstractMatrix{Bool}, s::Integer,
lv::AbstractVector{Bool}, nz::AbstractVector{Bool}) -> Nothing
cross_sectional_move_dropped!(dc::AbstractMatrix{Bool}, s::Integer,
ds::AbstractMatrix{Bool}) -> NothingWrite the dropped columns of one observation in a new Factor Family Basis, on the carry fold of a Cross-Sectional Factor Prior.
cross_sectional_move_solve states the rule.
Arguments
dc: Dropped-column mask of the fitted observations in the new basis, written in place, ornothing.s: Row of the observation.lv: The mark of the factors that are not empty, in the new basis.nz: Whether each column of the design of the factors thatlvmarks is not zero.ds: The dropped-column mask of the new fit of the observation, one row.
Returns
nothing.
Related
PortfolioOptimisers.cross_sectional_refold_factors — Function
cross_sectional_refold_factors(
pe::AbstractPriorEstimator,
f::AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}},
seed::Integer
) -> Any
Folds the factor prior of the carry fold of a Cross-Sectional Factor Prior over the factor returns of every fitted observation: the first seed observations as one block, and every later observation alone, as the first fit folds them.
Arguments
pe: The factor prior with no fold.f: The factor returns of every fitted observation, on the factors that are not empty.seed: Number of fitted observations to fold as one block.
Returns
pe: The factor prior after every fitted observation.
Related
A step where a factor that was empty at every fitted observation comes alive keeps those observations, because the factor had a return of zero at each of them. The functions below decide whether the regression estimator keeps the answer of an observation whose design gains a zero column, and fold the factor prior over the factor returns of the step, or again over every fitted factor return when a factor comes alive.
PortfolioOptimisers.cross_sectional_alive_folds — Function
cross_sectional_alive_folds(cre::AbstractCrossSectionalRegressionEstimator) -> Bool
cross_sectional_alive_folds(cre::Union{CrossSectionalLinearRegression,
CrossSectionalTargetRegression}) -> Bool
cross_sectional_alive_folds(alg::AbstractCrossSectionalSolveAlgorithm) -> Bool
cross_sectional_alive_folds(alg::Union{PseudoInverseFallback, MinimumNormSolve,
DependentColumnDrop}) -> BoolAnswers whether a step of the carry fold of a Cross-Sectional Factor Prior folds a factor that comes alive, under the regression estimator cre, or under its solve algorithm alg.
A factor that comes alive at a step was empty at every fitted observation: its exposure was zero at every pair of positive weight. So the batch fit regresses each fitted observation over a design with a zero column, where the step fitted it without that column. The fold keeps the answer of the step when the zero column does not change it.
- Under
PseudoInverseFallbackthe design with the zero column is rank-deficient, and the solve takes its answer of least norm. A zero column adds nothing to the norm or to the fit, so that answer equals the answer without the column to rounding, and gives the column a return of zero.MinimumNormSolvetakes the same answer. ACrossSectionalTargetRegressionunderPseudoInverseFallbackprojects its answer onto the row space of the weighted design, which holds a zero at the zero column, so it gives the same answer. DependentColumnDropdrops the zero column by the pivot of its rank test, and gives it a return of zero. It fits the columns that remain, in their order, which are the columns of the step.RankDeficiencyRefusalrefuses the design with the zero column.UncheckedSolvethrows on such a design when it is square, and hands it to the target of aCrossSectionalTargetRegressionunchecked. So the batch fit can refuse, or answer otherwise, where the fold would keep the answer. Every other estimator and algorithm is not known to keep the answer. The function answersfalsefor them, and the step fits every carried observation again, as the batch fit does.
Algorithm
The method that Julia selects is the algorithm.
- A
CrossSectionalLinearRegressionor aCrossSectionalTargetRegressionanswers for its solve algorithmcre.alg:trueunderPseudoInverseFallback,MinimumNormSolveandDependentColumnDrop, andfalseunder every other algorithm. - Every other estimator answers
false.
Arguments
cre: The cross-sectional regression estimator of the prior.alg: Its solve algorithm.
Returns
folds::Bool:truewhen the step keeps the fitted observations.
Related
PortfolioOptimisers.cross_sectional_step_factors — Function
cross_sectional_step_factors(
pe::CrossSectionalFactorPrior,
st::CrossSectionalCarryState,
csr::CrossSectionalRegression,
lv::AbstractVector{Bool}
) -> Any
Folds the factor returns of a step into the factor prior of the carry fold of a Cross-Sectional Factor Prior.
The factor prior folds the factor returns of the factors that are not empty. A step that marks no other factor folds the factor returns of its new observations into the folded prior. A step where a factor comes alive adds a column to the factor returns. The default factor covariance is not separable by column, so the function folds the factor prior again over every fitted factor return, with a return of zero for the new factor at each observation before the step. That fold reads every fitted observation, so its cost grows with the stream, and it happens at most once for each factor.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state before the step, whose histories hold the new observations as their last rows.csr: The regression of every fitted observation, the new observations last.lv: The mark of the factors that are not empty in the last pass, after the step.
Returns
pe: The factor prior after the step.
Related
PortfolioOptimisers.cross_sectional_carry_append — Function
cross_sectional_carry_append(
pe::CrossSectionalFactorPrior,
st::CrossSectionalCarryState
) -> NamedTuple{(:r, :ca), <:Tuple{Any, Union{NamedTuple{(:f, :L, :Ms, :nf, :fam, :fcb, :fx), <:Tuple{AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}, AbstractMatrix{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}}, AbstractArray{<:Union{var"#s152", var"#s69"} where {var"#s152"<:Number, var"#s69"<:AbstractJuMPScalar}, 3}, AbstractVector{<:AbstractString}, AbstractVector{<:AbstractString}, Union{Nothing, AbstractFactorFamilyBasis}, Nothing}}, NamedTuple{(:f, :L, :Ms, :nf, :fam, :fcb, :fx), <:Tuple{Any, Any, Any, Any, Any, Union{Nothing, FactorFamilyBasis}, Any}}}}}
Appends the observed factors to the fitted factors of the carry fold of a Cross-Sectional Factor Prior.
Algorithm
- Take the observed factors of the fitted observations with
cross_sectional_observed_block. - Append them to the fitted factors with
cross_sectional_observed_append, giving the raw exposures of the fitted observations and the reduced loadings of the last one. The two exposure histories share one backing, so the raw exposures are a view of it, ascross_sectional_joined_exposuresstates.
Arguments
pe: Cross-Sectional Factor Prior estimator.st: The state of its carry fold, after its first fit.
Returns
r::UnitRange: The fitted observations among the observations after the warm-up.ca::NamedTuple: The answer ofcross_sectional_observed_append.
Related