v1.0.0 to v2.0.0
143 added, 29 removed. Audit A to A.
---
name: cold-start-handling-for-newly-listed-instruments
- description: Quantitative feature engineering and risk management module for handling
- newly listed instruments (IPOs, SPACs) using Bayesian volatility shrinkage, peer
- imputation, and position sizing caps during probation windows.
- domain: Portfolio & Risk Management
- subdomain: Feature Engineering & Risk
+ description: Use when an instrument's own price history is too short to estimate risk
+ from — IPOs, spin-offs, new listings, freshly launched tokens — and a rolling
+ volatility window would otherwise return NaN or a number built from five days of
+ noise; shrinks the short sample toward a peer prior in variance space with conjugate
+ degrees-of-freedom weighting, and ramps a separate size cap across the probation
+ window.
+ domain: algorithmic-trading
+ subdomain: risk-management
tags:
+ - risk-management
- cold-start
- ipo
- shrinkage
- - imputation
- - volatility
+ - volatility-estimation
- position-sizing
- brokers_frameworks:
- - NumPy
- - Pandas
- - Generic Quantitative Pipeline
- version: "1.0.0"
+ brokers_frameworks: []
+ version: "2.0.0"
author: algo-trading-skills-contributors
license: Apache-2.0
---
## When to Use
- Use this skill when integrating newly listed assets (e.g., recent IPOs, newly listed crypto tokens, or spin-offs) into systematic trading strategies. Newly listed assets lack sufficient historical track records ($N < N_{min\_warmup}$ days), causing standard rolling indicators (50-day moving average, 30-day volatility, Sharpe ratio) to produce `NaN` values or extreme noise. The Cold Start Handler applies Bayesian shrinkage toward peer-group priors and enforces strict capital allocation caps during a probationary period.
+ Invoke this skill when an instrument must be sized and risk-managed before it has enough
+ history to estimate from: a recent IPO or direct listing, a spin-off, a newly listed
+ token, a new futures contract month, or a symbol that has just re-listed. A 30-day
+ rolling volatility over 5 observations is not a small-sample estimate of volatility — for
+ i.i.d. normal returns the sample variance from `nu = n - 1` degrees of freedom has
+ relative variance `2 / nu`, so five days give a variance estimate with roughly 70%
+ relative standard error. Fed to a volatility-scaled or Kelly-style sizer, that noise
+ becomes leverage.
+ `ColdStartHandler` answers two questions that are deliberately kept apart:
+
+ 1. **What volatility should I use?** The sample variance is blended toward a peer-group
+ prior with the conjugate weight `w = nu / (nu + nu_0)`, applied to *variances*. `nu_0`
+ ("prior strength") is the prior's weight in units of this instrument's own days.
+ 2. **How much capital may it take?** A separate linear ramp, `min(1, n_obs / warmup)`,
+ times your base allocation. This is a risk-appetite policy, not an estimator.
+
+ ## When NOT to Use
+
+ - **As a pre-trade risk control.** This is a strategy-side sizing input that trusts its
+ own configuration. Where SEC Rule 15c3-5 or an equivalent applies, the hard limits must
+ sit in the broker-dealer's automated pre-trade layer; put this in front of that, never
+ instead of it. See `sec-rule-15c3-5-risk-controls-us`.
+ - **When no defensible peer group exists.** Shrinking toward an arbitrary prior is worse
+ than declining to trade the name: the output looks confident and is not. A newly listed
+ token with no comparable, or a first-of-its-kind structure, has no prior worth using.
+ - **When the short history is not the binding constraint.** If the instrument cannot be
+ borrowed, has no locate (`us-reg-sho-short-sale-locate-requirements`), trades in a
+ 10-lot a day, or is still inside its first-day auction, sizing is the wrong lever.
+ See `liquidity-adjusted-position-sizing`.
+ - **For the model's *features*, not its risk inputs.** Cold-starting a learned signal for
+ a new symbol is a different problem — see
+ `categorical-feature-encoding-for-instrument-identity` for identity encoding and
+ `transfer-learning-across-correlated-instruments` for borrowing a correlated
+ instrument's fitted structure.
+ - **When the sample is short for a reason other than newness.** A halted, suspended, or
+ thinly traded old instrument has a short *usable* sample but not a cold start; treat
+ stale data as stale, not as young.
+
## Prerequisites
- - Access to peer-group baseline metrics (e.g., sector ETF average volatility).
- - Historical observation count for each instrument.
+ - A count of **usable return observations**, not a calendar difference. Listing date
+ minus today over-counts: halts, no-trade sessions and missing bars are not
+ observations. See `references/workflows.md`.
+ - A peer prior that is a **single-name** volatility, not a sector-ETF volatility. An ETF
+ is diversified; its volatility is systematically below that of its constituents, so
+ using it as the prior shrinks a new listing toward a number no single stock realizes.
+ Use the median (not mean) realized volatility of comparable single names.
+ - Sample volatility and prior in the **same units** — both annualized, or neither. The
+ module cannot detect a units mismatch; it will happily blend a daily sigma with an
+ annualized one.
+ - A `nu_0` chosen from the prior's own uncertainty, not by feel: for a prior whose
+ estimate of `sigma**2` has relative variance `v`, `nu_0 = 2 / v`.
+ - A warmup window justified by something. Market-structure anchors beat round numbers:
+ IPO lock-up expiry (typically 180 days, contractual), index seasoning (S&P U.S.
+ indices: 12 months on an eligible exchange). See `references/standards.md`.
## Workflow
- 1. **Age Assessment**: Compute the number of available daily observations $N_{obs}$ for the target instrument.
- 2. **Probation Check**: If $N_{obs} < N_{min\_warmup}$ (e.g., 30 trading days), flag the instrument as `PROBATIONARY`.
- 3. **Bayesian Shrinkage Imputation**:
- - Compute observation weight: $w = \frac{N_{obs}}{N_{min\_warmup}}$.
- - Estimate volatility: $\sigma_{est} = w \cdot \sigma_{observed} + (1 - w) \cdot \sigma_{peer\_prior}$.
- 4. **Capital Allocation Cap**:
- - Limit max position size: $\text{Cap} = \text{Base\_Max\_Size} \times w$.
- 5. **Graduation**: Once $N_{obs} \ge N_{min\_warmup}$, transition instrument to `STANDARD` status with 100% weight on empirical data.
+ 1. **Count usable observations.** Count bars actually present with valid prices. Exclude
+ sessions the instrument was halted for the whole of, and exclude the listing auction
+ itself — the IPO cross is a price discovery event, not a return.
+ 2. **Select the peer group before you need it.** Same sector, comparable size, comparable
+ float, and — where relevant — same recency-of-listing cohort. Freeze the selection
+ rule; picking the peer group after seeing the instrument's early prints is a decision
+ made on the data you are trying to shrink.
+ 3. **Refuse rather than default.** If no prior is available, do not substitute zero and
+ do not substitute the index. `process_instrument` raises on a missing or
+ non-positive prior deliberately: a zero prior asserts a riskless instrument, and any
+ volatility-scaled sizer divides by it.
+ 4. **Estimate with `process_instrument(symbol, n_obs, observed_volatility,
+ peer_prior_volatility)`.** Below two observations there is no sample variance at all;
+ the observed value is ignored (including if it arrives as NaN) and the prior is
+ returned unchanged, with `used_observed_volatility=False` recording that.
+ 5. **Size against `estimated_volatility`, cap against `max_position_cap_pct`.** They are
+ independent controls. Note that the cap is a *ceiling*, not a target: a
+ volatility-scaled sizer will usually ask for less during probation anyway, and the cap
+ only binds when it does not.
+ 6. **Do not treat graduation as certainty.** `is_probationary` going False means the size
+ cap has reached the base allocation. It does not mean the volatility estimate is
+ unshrunk — with `nu_0 = 10`, an instrument with 250 observations still carries about
+ 4% prior weight, and that is correct. If you want the prior gone, lower `nu_0`.
+ 7. **Re-evaluate on every rebalance, not once at onboarding.** Both outputs move with
+ `n_obs`; a cached day-one decision keeps a stale cap for the rest of the ramp.
+ 8. **Watch for the events that reset the argument.** Lock-up expiry, index addition, and
+ the first earnings report all change the float and the volatility regime *after* the
+ instrument has technically graduated. A 30-day warmup that ends before the first
+ lock-up tranche unlocks has measured a float that no longer exists.
> Full procedure: see `references/workflows.md`.
- > Standards reference: see `references/standards.md`.
+ > Standards and sources: see `references/standards.md`.
> Printable pre-flight checklist: see `assets/checklist.md`.
## Common Pitfalls
- - **Unshrinked Sample Volatility**: Calculating 5-day realized volatility for a 5-day old IPO and using it for Kelly position sizing. Extreme early noise will cause massive over-leveraging or complete under-allocation.
- - **Dropping IPOs Entirely**: Rejecting all newly listed stocks for 60 days, missing early post-IPO drift or liquidity-driven alpha opportunities.
- - **Ignoring Peer Sector Priors**: Using zero as a fallback for missing volatility instead of imputing the sector ETF prior.
+ - **Blending standard deviations instead of variances.** `w * sigma_obs + (1 - w) *
+ sigma_peer` is not the conjugate posterior and, because the square root is concave, it
+ *understates* volatility whenever the sample and prior disagree. For a 5-day IPO at
+ `sigma_obs = 0.80` against a `0.20` prior, at the same weight `w = 4/14`, the
+ standard-deviation blend returns `0.37` where the variance blend returns `0.46`; the
+ pre-2.0 module returned `0.30`, lower still because it also weighted the sample by
+ `n / warmup`. A risk control should not be biased toward the low side. The
+ standard-deviation blend remains reachable via `shrink_in_variance_space=False`, for
+ comparison during migration only.
+ - **`0.0 * float("nan")` is `nan`, not `0.0`.** The natural "weight the sample by zero
+ when there is no sample" implementation emits NaN into the sizer for exactly the
+ instrument the skill exists for. Absence of a sample has to be a branch, not a weight.
+ - **Using a sector ETF as the single-name prior.** Diversification makes the ETF's
+ volatility structurally lower; every new listing is then shrunk toward a number no
+ constituent realizes, and probation systematically over-sizes.
+ - **Letting shrinkage end abruptly at the warmup boundary.** A weight of `n / N` says a
+ 29-day estimate is 97% trustworthy and a 30-day estimate is exact. Neither is true, and
+ the jump puts a discontinuity in the sizing of every instrument on its graduation day.
+ - **Counting calendar days as observations.** IPOs halt — LULD trading pauses in the
+ first sessions are routine — and a halted session contributes no return. Calendar
+ counting graduates the instrument early on data it does not have.
+ - **Treating the first-day price range as volatility.** The IPO cross and the first
+ session's price discovery are not draws from the return distribution you are trying to
+ estimate; including them inflates the sample and, once weighted, the blend.
+ - **Dropping newly listed names entirely for 60 days.** The opposite failure: a hard
+ exclusion forgoes post-IPO drift and liquidity-driven opportunity and, worse, hides the
+ onboarding path from testing until the day it silently switches on. Use
+ `probation_floor_pct` to throttle rather than exclude.
+ - **Forgetting the borrow side.** A newly listed name is frequently hard or impossible to
+ borrow; a shrunk volatility says nothing about whether the short leg is executable.
## Verification
- - Instantiate `ColdStartHandler` with $N_{min\_warmup}=30$. Feed an asset with 5 days of data ($\sigma_{obs} = 0.80$) and a sector prior ($\sigma_{peer} = 0.20$). Verify that the estimated volatility is smoothly shrunken toward the peer prior ($\sim 0.30$) and that position size is capped at $16.7\%$ ($5/30$).
- - Run `python scripts/test_cold_start_handler.py`.
+ - Run `cd skills/cold-start-handling-for-newly-listed-instruments/scripts && python -m
+ unittest discover -s . -p "test_*.py"` (29 tests; the module must be importable from
+ the working directory), or `python tools/run_all_tests.py` for the whole repo.
+ - Documented example: `ColdStartHandler(warmup_period_days=30, prior_strength_days=10.0)`
+ with `n_obs=5`, `observed_volatility=0.80`, `peer_prior_volatility=0.20` returns
+ `confidence_weight = 4/14 = 0.2857`, `estimated_volatility = sqrt((10*0.04 + 4*0.64) /
+ 14) = 0.4598`, and `max_position_cap_pct = 5/30 = 0.1667`.
+ - Feed `n_obs=0` with `observed_volatility=float("nan")` and confirm the returned
+ volatility is exactly the peer prior and `used_observed_volatility` is False.
+ - Sweep `n_obs` from 0 upward and confirm `max_position_cap_pct` is non-decreasing, never
+ exceeds the base allocation, and reaches it exactly at `warmup_period_days`.
+ - Confirm a zero or NaN peer prior raises rather than returning a zero or NaN volatility.
## Related Skills
- `categorical-feature-encoding-for-instrument-identity`
+ - `transfer-learning-across-correlated-instruments`
+ - `dynamic-position-sizing-based-on-realized-volatility`
+ - `liquidity-adjusted-position-sizing`
+ - `instrument-universe-change-detection-and-alerting`
+ - `point-in-time-index-constituent-tracking`
+ - `us-reg-sho-short-sale-locate-requirements`
- `new-strategy-onboarding-checklist`