Assertions: private API
In order to increase correctness, robustness, and safety, we make extensive use of defensive programming. The following functions perform some of these validations and are usually called at variable instantiation.
PortfolioOptimisers.assert_resource_cap — Function
assert_resource_cap(val::Integer, cap::Integer, sym::Sym_Str, knob::Sym_Str)Assert that an untrusted sizing integer val does not exceed the active RESOURCE_LIMITS ceiling cap, failing closed with a DomainError otherwise.
sym names the offending field in the message (e.g. :n_sim) and knob names the ResourceLimits field to raise (e.g. :max_n_sim), so the error tells the caller both what was rejected and how to allow it deliberately.
Arguments
val: The requested size.cap: The active ceiling.sym: Symbolic name of the offending field.knob: Symbolic name of theResourceLimitsfield that raises the ceiling.
Validation
val <= cap, which raises aDomainErrornamingval,sym,capandknob.
Returns
nothing.
Related
PortfolioOptimisers.assert_ep_grid_size — Function
assert_ep_grid_size(K::Integer)Assert that K, the number of grid points of a grid tail view formulation, is odd, positive and within the active RESOURCE_LIMITS ceiling max_ep_grid.
Every grid point is one binary variable of the mixed-integer program an upper-bound or equality view builds, and one dense row over the posterior probabilities, so K is an untrusted sizing integer of the class assert_resource_cap guards. The parity rule keeps the centre of the grid a point of the grid. Both grid formulations state one rule, so both call this one assertion.
Arguments
K: The requested number of grid points.
Validation
isodd(K)and1 <= K <= RESOURCE_LIMITS[].max_ep_grid(every grid point is one binary variable of the mixed-integer program an upper-bound or equality view builds; seeRESOURCE_LIMITS).
Returns
nothing.
Related
PortfolioOptimisers.resolve_rng — Function
resolve_rng(rng::Random.AbstractRNG, seed::Option{<:Integer})Resolve which random number generator to draw from given an optional seed.
A supplied seed yields a fresh, private generator — a copy of rng reseeded with seed via Random.seed! — so a seeded estimator is reproducible without reseeding, and thereby silently derandomising, the task-global RNG the caller may also own (the default rng is Random.default_rng(), a shared object). When seed is nothing, rng is returned unchanged and used as-is.
Copying rng before seeding (rather than constructing a fixed generator type such as Random.Xoshiro(seed)) preserves both the caller's generator object — it is never mutated — and its type, so a caller-supplied portable generator (e.g. StableRNGs.StableRNG) keeps producing the same stream Random.seed!(rng, seed) did in place. The observable draws are thus identical to the old in-place seeding; only the side effect on the caller's stream disappears.
Arguments
rng: Fallback random number generator, used verbatim whenseedisnothing.seed: Optional seed. If set, a privateRandom.seed!(copy(rng), seed)is returned instead of touchingrng.
Algorithm
- Return
rngunchanged whenseedisnothing, so the caller's generator is used as it stands. - Otherwise copy
rng, reseed the copy withseed, and return the copy. The caller's own generator is never mutated.
Returns
Random.AbstractRNG: the generator to draw from.
Related
PortfolioOptimisers.assert_nonempty — Function
assert_nonempty(
val::Union{AbstractDict, AbstractArray{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}, AbstractVector{<:Pair}}
)
assert_nonempty(
val::Union{AbstractDict, AbstractArray{<:Union{var"#s136", var"#s53"} where {var"#s136"<:Number, var"#s53"<:AbstractJuMPScalar}}, AbstractVector{<:Pair}},
sym::Union{AbstractString, Symbol}
)
Assert that val is non-empty.
No-op for Pair and Number inputs; emptiness does not apply to scalars.
Arguments
val: Container to check; one ofAbstractDict,VecPair, orArrNum.sym: Symbolic name used in the error message.
Validation
!isempty(val), which raises anIsEmptyErrornamingsym.
Returns
nothing.
Related
assert_nonempty(::Union{Number, Pair})
assert_nonempty(
::Union{Number, Pair},
::Union{AbstractString, Symbol}
)
No-op overload of assert_nonempty for scalar inputs.
Emptiness does not apply to Pair or Number values.
Arguments
::Union{<:Pair, <:Number}: Scalar value, not read.::Sym_Str = :val: Symbolic name, not read.
Returns
nothing.
Related
PortfolioOptimisers.assert_finite — Function
assert_finite(val::AbstractDict)
assert_finite(
val::AbstractDict,
sym::Union{AbstractString, Symbol}
)
Assert that every element of val is finite.
Algorithm
The method Julia selects on the type of val is the algorithm. Each method checks one predicate and raises a DomainError that names sym and the predicate it failed.
- An
AbstractDictchecksall(isfinite, values(val)), so the keys are not read. - A
VecPairchecksall(isfinite, getindex.(val, 2)), so the second element of each pair is the value. - An
ArrNumchecksall(isfinite, val). - A
Pairchecksisfinite(val[2]). - A
Numberchecksisfinite(val).
Arguments
val: Value to check.sym: Symbolic name used in the error message.
Validation
- Every element of
valis finite, under the predicate that its type selects. ANaNand an infinity both breach it, and a breach raises aDomainError.
Returns
nothing.
Related
PortfolioOptimisers.assert_nonneg — Function
assert_nonneg(val::AbstractDict)
assert_nonneg(
val::AbstractDict,
sym::Union{AbstractString, Symbol}
)
Assert that all elements of val are non-negative (>= 0).
Algorithm
The method Julia selects on the type of val is the algorithm. Each method checks one predicate and raises a DomainError that names sym and the predicate it failed.
- An
AbstractDictchecksall(x -> 0 <= x, values(val)), so the keys are not read. - A
VecPairchecksall(x -> 0 <= x[2], val), so the second element of each pair is the value. - An
ArrNumchecksall(x -> 0 <= x, val). - A
Pairchecks0 <= val[2]. - A
Numberchecks0 <= val.
Arguments
val: Value to check.sym: Symbolic name used in the error message.
Validation
- Every element of
valis non-negative, under the predicate that its type selects. A breach raises aDomainError.
Returns
nothing.
Related
PortfolioOptimisers.assert_gt0 — Function
assert_gt0(val::AbstractDict)
assert_gt0(
val::AbstractDict,
sym::Union{AbstractString, Symbol}
)
Assert that all elements of val are strictly positive (> 0).
Algorithm
The method Julia selects on the type of val is the algorithm. Each method checks one predicate and raises a DomainError that names sym and the predicate it failed.
- An
AbstractDictchecksall(x -> 0 < x, values(val)), so the keys are not read. - A
VecPairchecksall(x -> 0 < x[2], val), so the second element of each pair is the value. - An
ArrNumchecksall(x -> 0 < x, val). - A
Pairchecks0 < val[2]. - A
Numberchecks0 < val.
Arguments
val: Value to check.sym: Symbolic name used in the error message.
Validation
- Every element of
valis strictly positive, under the predicate that its type selects. A breach raises aDomainError.
Returns
nothing.
Related
PortfolioOptimisers.assert_nonempty_nonneg_finite_val — Function
assert_nonempty_nonneg_finite_val(
val::Union{<:AbstractDict, <:VecPair, <:ArrNum, Pair, Number},
val_sym::Union{Symbol,<:AbstractString} = :val
)
assert_nonempty_nonneg_finite_val(args...)Validate that the input value is non-empty, non-negative and finite.
Algorithm
- Call
assert_nonempty, thenassert_finite, thenassert_nonneg, each onvalandval_sym. The order is the order of the raises, so the first rule a value breaks is the one it is told about. - A value of any other type selects the
args...method, which checks nothing. That is what lets a caller validate an optional field without a branch of its own.
Arguments
val: Input value to validate.val_sym: Symbolic name used in the error messages.
Validation
Each rule is the one that val's own type selects in the three functions of step 1.
::AbstractDict:!isempty(val),all(isfinite, values(val)),all(x -> x >= 0, values(val)).::VecPair:!isempty(val),all(isfinite, getindex.(val, 2)),all(x -> x[2] >= 0, val).::ArrNum:!isempty(val),all(isfinite, val),all(x -> x >= 0, val).::Pair:isfinite(val[2])andval[2] >= 0.::Number:isfinite(val)andval >= 0.- Any other type: no rule, so the call always passes.
Returns
nothing.
Related
PortfolioOptimisers.assert_nonempty_gt0_finite_val — Function
assert_nonempty_gt0_finite_val(
val::Union{<:AbstractDict, <:VecPair, <:ArrNum, Pair, Number},
val_sym::Union{Symbol,<:AbstractString} = :val
)
assert_nonempty_gt0_finite_val(args...)Validate that the input value is non-empty, greater than zero, and finite.
Algorithm
- Call
assert_nonempty, thenassert_finite, thenassert_gt0, each onvalandval_sym. The order is the order of the raises, so the first rule a value breaks is the one it is told about. - A value of any other type selects the
args...method, which checks nothing. That is what lets a caller validate an optional field without a branch of its own.
Arguments
val: Input value to validate.val_sym: Symbolic name used in the error messages.
Validation
Each rule is the one that val's own type selects in the three functions of step 1.
::AbstractDict:!isempty(val),all(isfinite, values(val)),all(x -> x > 0, values(val)).::VecPair:!isempty(val),all(isfinite, getindex.(val, 2)),all(x -> x[2] > 0, val).::ArrNum:!isempty(val),all(isfinite, val),all(x -> x > 0, val).::Pair:isfinite(val[2])andval[2] > 0.::Number:isfinite(val)andval > 0.- Any other type: no rule, so the call always passes.
Returns
nothing.
Related
PortfolioOptimisers.assert_nonempty_finite_val — Function
assert_nonempty_finite_val(
val::Union{<:AbstractDict, <:VecPair, <:ArrNum, Pair, Number},
val_sym::Union{Symbol,<:AbstractString} = :val
)
assert_nonempty_finite_val(args...)Validate that the input value is non-empty and finite.
Algorithm
- Call
assert_nonempty, thenassert_finite, each onvalandval_sym. The order is the order of the raises, so the first rule a value breaks is the one it is told about. - A value of any other type selects the
args...method, which checks nothing. That is what lets a caller validate an optional field without a branch of its own.
Arguments
val: Input value to validate.val_sym: Symbolic name used in the error messages.
Validation
Each rule is the one that val's own type selects in the two functions of step 1.
::AbstractDict:!isempty(val),all(isfinite, values(val)).::VecPair:!isempty(val),all(isfinite, getindex.(val, 2)).::ArrNum:!isempty(val),all(isfinite, val).::Pair:isfinite(val[2]).::Number:isfinite(val).- Any other type: no rule, so the call always passes.
Returns
nothing.
Related
PortfolioOptimisers.assert_matrix_issquare — Function
assert_matrix_issquare(X::MatNum, X_sym::Symbol = :X)Assert that the input matrix is square.
Arguments
X: Input matrix to validate.X_sym: Symbolic name used in error messages.
Validation
size(X, 1) == size(X, 2), which raises aDimensionMismatchnamingX_symand both sizes.
Returns
nothing.
Related
PortfolioOptimisers.assert_unit_interval — Function
assert_unit_interval(val::Number, sym::Union{Symbol,<:AbstractString} = :val)
assert_unit_interval(args...)Assert that val lies strictly inside the open unit interval (0 < val < 1).
A value of any other type selects the args... method, which checks nothing. That is what lets a caller validate a slot whose bound admits more than a number without a branch of its own, on the terms assert_nonempty_gt0_finite_val already sets. A Calibration Rule (AbstractCalibrationAlgorithm) states no number at construction, so the range is checked when the rebuild runs, against the number the rule returned.
Arguments
val: Value to check.sym: Symbolic name used in the error message.
Validation
::Number:0 < val < 1, which raises aDomainErrornamingsymandval.- Any other type: no rule, so the call always passes.
Returns
nothing.
Related
PortfolioOptimisers.assert_closed_unit_interval — Function
assert_closed_unit_interval(val::Number, sym::Union{Symbol,<:AbstractString} = :val)
assert_closed_unit_interval(args...)Assert that val lies inside the closed unit interval (0 <= val <= 1).
This is the closed sibling of assert_unit_interval, and the two differ only in whether the ends belong to the interval. A weight that a template may switch off entirely, or hand its full value to, reaches both ends, so it needs this rule and not the open one.
A value of any other type selects the args... method, which checks nothing, on the terms assert_unit_interval already sets.
Arguments
val: Value to check.sym: Symbolic name used in the error message.
Validation
::Number:0 <= val <= 1, which raises aDomainErrornamingsymandval.- Any other type: no rule, so the call always passes.
Returns
nothing.
Related
PortfolioOptimisers.assert_all_finite — Function
assert_all_finite(val::ArrNum, sym::Sym_Str = :val)Assert that every element of val is finite, failing closed with an IsNonFiniteError otherwise.
assert_finite checks the same predicate and raises a DomainError alongside its assert_nonneg and assert_gt0 siblings; this one raises an IsNonFiniteError and reports where the breach is, so a caller can find the offending entry without the message quoting the data. It guards the comparison-based covariance estimators (GerberCovariance, SmythBrobyCovariance): their X .>= sd / X .<= -sd comparisons silently evaluate a NaN entry as false, masking it as "no co-movement" and yielding a finite, plausible, wrong covariance rather than an error. Clean returns first with an asset selector (e.g. CompleteAssetSelector) or MissingDataFilter — non-finite entries in a returns matrix are a supported input to those, but not to a comparison-based estimator. The message reports the count of offending entries and the first offending index only — never the data values.
Arguments
val: Array to check.sym: Symbolic name used in the error message.
Validation
all(isfinite, val), which raises anIsNonFiniteError. The message carries the count of offending entries and the first offending index, and never a data value.
Returns
nothing.
Related
PortfolioOptimisers.assert_source_selector — Function
assert_source_selector(src::Symbol)
assert_source_selector(
src::Symbol,
sym::Union{AbstractString, Symbol}
)
Assert that a matrix-source selector names one of the two carriers.
Source selectors pick which of the two carriers a matrix is read from: :prior reads the prior result, :data reads the raw returns result. x_src selects the returns matrix X.
Arguments
src: Selector to check.sym: Symbolic name used in the error message.
Validation
src in (:prior, :data), which raises anArgumentErrornamingsymandsrc.
Returns
nothing.
Related
PortfolioOptimisers.assert_returns_result_dims — Function
assert_returns_result_dims(dims::Integer)
assert_returns_result_dims(
dims::Integer,
sym::Union{AbstractString, Symbol}
)
Assert that dims names the one layout a ReturnsResult can hold.
A ReturnsResult is always observations × assets, so its asset axis is always 2, whatever dims a caller passes. This assertion refuses dims == 2 instead of flipping the axis, and names prices_to_returns as the way to build a ReturnsResult in a different layout.
Arguments
dims: Dimension selector to check.sym: Symbolic name used in the error message.
Validation
dims in (1, 2), byassert_dims, which raises aDomainErrornamingsymanddims.dims == 1, which raises aConflictingArgumentErrornamingsym,dimsandprices_to_returns.
Returns
nothing.
Related