format: veil.promotion-request.v0
dataset: replace-with-project-dataset
hypothesis_ref: replace-with-veil-memory-reference
factor:
  code_root: .veil/artifact
  files:
    - factor.mjs
  runtime:
    id: veil-node
    constraint: ">=20.10.0,<30"
  entry:
    file: factor.mjs
    callable: compute
params_locked:
  lookback_days: 20
declared_literals: {}
trials_declared: 1
development_read_sets:
  - sha256:replace-with-a-read-set-id
protocol:
  mode: rolling
  folds: 2
  train_days: 60
  oos_days: 20
  purge_days: 5
  embargo_days: 5
  hold_days: 5
  execution_lag_days: 1
# Supply every ordered UTC session, not one timestamp per fold. The protocol above requires exactly
# 60 + 5 + 5 + (2 * 20) = 110 entries. Replace the empty list after choosing an honest protocol.
decision_schedule: []
columns:
  - ticker
  - close
  - volume
# This is a registered logical id, not a filesystem path or locator URI.
cost_model: replace-with-registered-cost-model
stage4:
  signal_column: signal
  price_column: close
  market_columns: [volume]
  periods_per_year: 252
  portfolio_kind: long-short-quantile
  quantile: 0.2
  # Use a positive artifact-output column for trailing-information sizing, otherwise null.
  weight_column: null
  capacity:
    portfolio_nav: 1000000
    volume_column: volume
    maximum_participation_rate: 0.05
  null_generator: replace-with-registered-null-generator
  trial_budget: 12
  # Record the originating model's knowledge cutoff. Use null only when genuinely unavailable;
  # doing so makes the optional contamination gate unavailable and the Experiment degraded.
  knowledge_cutoff: 2025-12-31T00:00:00.000Z
