Skip to content
18

Search cross-validation

Tuning a pipeline widens the search boundary to the entire workflow: preprocessing hyperparameters (imputation statistics, missing-data thresholds) are searched jointly with prior, constraint, and optimiser hyperparameters, and every candidate is fitted per fold so stateful preprocessing never sees the test window. Lens keys address steps by name ("impute.stat"), by position (an integer key swaps the whole step), or by raw property path ("steps[2].stat").

PortfolioOptimisers.search_cross_validation Method
julia
search_cross_validation(pipe::Pipeline, gscv::GridSearchCrossValidation, data::Prices_RR)
search_cross_validation(pipe::Pipeline, rscv::RandomisedSearchCrossValidation, data::Prices_RR)

Tune a Pipeline by grid (or randomised) search cross-validation on price- or returns-level input data.

The input is split into contiguous observation windows by gscv.cv (price-level splits keep stateful preprocessing inside the fold); for each candidate the lens grid is applied to the pipeline (keys resolved by pipeline_lens, so step names, step positions, and raw property paths all address steps), the whole workflow is fitted on the training window and scored on the test window via fit_and_score, and the scorer picks the winner. The randomised form samples the grid and delegates, exactly as for plain optimisers.

TimeDependent schedules resolve against the tuning folds: when a candidate is time-dependent, its schedules are sized to the tuning scheme's fold count (asserted per candidate — a grid value may swap a whole schedule in or out), and tuning fold j swaps in entry j via the pipeline-level update_time_dependent_estimator before fit_and_score runs. Lenses need no schedule-specific semantics: naming the step swaps the whole schedule as a grid value, and raw property paths address entries.

Arguments

  • pipe: The pipeline to tune.

  • gscv/rscv: The search cross-validation estimator.

  • data: Price- or returns-level input data (Prices_RR).

Returns

  • res::SearchCrossValidationResult: The tuned pipeline (res.opt), score matrices, lens/value grids, and selected index.

Related

source
PortfolioOptimisers.search_cross_validation Method
julia
search_cross_validation(pipe::Pipeline, gscv::GridSearchCrossValidation{<:Any, <:CombinatorialCrossValidation}, data::AbstractReturnsResult)

Grid search cross-validation of a Pipeline over a CombinatorialCrossValidation scheme.

Combinatorial recombines its disjoint test groups into full-length backtest paths, so — like the plain-optimiser combinatorial method — scoring is per-path, not per-split: scoring a split in isolation would mix groups belonging to different paths. For each candidate the whole workflow runs through cross_val_predict (splits fitted, groups recombined by sort_predictions! into a PopulationPredictionResult), and expected_risk yields one score per path; the score matrix is therefore n_paths × n_candidates and the scorer selects across candidates as usual.

train_scores (only when gscv.train_score) keeps every per-fold in-sample score: a Vector of n_paths matrices, one per path, each folds_in_path × n_candidates (test scores stay one-per-path because a path's out-of-sample returns pool into one series, while its folds train on distinct in-sample windows).

Combinatorial runs at both levels here. At the price level a split's training rows are non-contiguous (gaps where the held-out groups sit), so the fold's PricesToReturns produces one spurious return per gap boundary — an accepted approximation in exchange for the combinatorial paths (see cross_val_predict(pipe::Pipeline, data::Prices_RR, cv::CombinatorialCrossValidation)). The randomised form delegates here through its grid.

Related

source
PortfolioOptimisers.fit_and_score Method
julia
fit_and_score(pipe::Pipeline,
                   scv::Union{<:GridSearchCrossValidation{<:Any, <:Any},
                              <:RandomisedSearchCrossValidation{<:Any, <:Any}},
                   cv::CrossValidationResult, rd::Prices_RR, i::Integer)

Fit a Pipeline on the training window and score it on the test window for search cross-validation.

The whole workflow is fitted per fold: stateful preprocessing (universe, imputation parameters) is learned on the training window only, and predict replays it on the test window before the score is computed — no test information leaks into the preprocessing, which is the point of the pipeline (ADR 0028).

Arguments

  • pipe: The pipeline candidate.

  • scv: The search cross-validation estimator carrying the risk measure, options, and train-score flag.

  • data: Price- or returns-level input data.

  • train_idx: Observation indices of the training window.

  • test_idx: Observation indices of the test window.

Returns

  • (test_score, train_score): Signed scores; train_score is nothing unless requested.

Related

source
PortfolioOptimisers.pipeline_lens Function
julia
pipeline_lens(pipe::Pipeline, key) -> lens

Resolve a tuning key into an Accessors.jl lens on a Pipeline.

A leading step name resolves to the step's position (name → index → property path): "impute.stat" targets the stat field of the step named "impute", and a bare step name ("impute", :impute) or an integer position targets the whole step — swapping entire estimators as grid values needs no extra syntax. Keys whose leading segment is not a step name fall through to parse_lens, so raw property paths ("steps[2].stat") and prebuilt lenses keep working.

Arguments

  • pipe: The pipeline being tuned.

  • key: A GSCVKey: step name with optional trailing property path, integer step position, raw property path, Expr/Symbol, or a prebuilt lens.

Returns

  • lens: A composed Accessors.jl lens rooted at the pipeline.

Related

source
PortfolioOptimisers.pipeline_lens_val_grid Function
julia
pipeline_lens_val_grid(
    pipe::Pipeline,
    estval::AbstractVector{<:Pair{<:Any, <:AbstractVector}}
) -> Tuple{Any, Any}

Build the (lens, value) grid for tuning a Pipeline — the pipeline-aware counterpart of lens_val_grid, resolving keys through pipeline_lens so step names and positions address steps.

Arguments

  • pipe: The pipeline being tuned.

  • estval: The parameter grid: key => values pairs, a dict, or a vector of either (independent grids concatenated).

Returns

  • (lenses, vals): Per-candidate lens vectors and value tuples.

Related

source
PortfolioOptimisers.pipeline_data_view Function
julia
pipeline_data_view(pr::AbstractPricesResult, idx) -> Any
pipeline_data_view(
    pr::AbstractPricesResult,
    idx,
    idx2
) -> Any

Return the observation-window view of price- or returns-level data used by pipeline search cross-validation.

Arguments

Returns

  • data′: The windowed data at the same level.

Related

source
PortfolioOptimisers.cv_data_eltype Function
julia
cv_data_eltype(rd::AbstractReturnsResult) -> Any

Return the element type search-CV score matrices use for the given data level.

Related

source