feat(alpha): reserve ISV slot block 539..550 for alpha trading system
12 contiguous slots reserved for durable alpha-system infrastructure: - 539-542: diagnostics (Q-spread, action entropy, return-vs-random, early-Q-movement EMAs) — read by Phase E kill criteria - 543-546: stacker-threshold controller (threshold, target, observed-rate, Kelly attenuation) — engagement-rate self-correction - 547-548: random-uniform baseline (mean, std) — anchor for kill criterion 541 - 549-550: reserved spare (absorb growth without bumping ISV_TOTAL_DIM) Named `alpha_isv_slots` rather than `phase_e_isv_slots` because these slots are intended to outlive any individual Phase E/F/G milestone — the SP4..SP22 naming was iteration-scoped, but this block is system-scoped infrastructure. ISV_TOTAL_DIM bumped to 551. All indices validated in 4 unit tests (bounds, membership, uniqueness, total-dim coverage). Audit doc docs/isv-slots.md updated per Invariant-7.
This commit is contained in:
117
crates/ml/src/cuda_pipeline/alpha_isv_slots.rs
Normal file
117
crates/ml/src/cuda_pipeline/alpha_isv_slots.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
//! Alpha trading system ISV slot block.
|
||||
//!
|
||||
//! Reserves indices 539..=550 (12 slots, contiguous) for durable
|
||||
//! infrastructure of the alpha trading system: stacker/execution-policy
|
||||
//! diagnostics, controller anchors, and population baselines. Unlike the
|
||||
//! SP4..SP22 slot files (which were per-iteration milestone-scoped), this
|
||||
//! block is named for the *system* — these slots are intended to outlive
|
||||
//! any individual Phase E/F/G milestone.
|
||||
//!
|
||||
//! Consumers read via the standard sentinel-bootstrap pattern:
|
||||
//! `if isv[idx] <= ALPHA_SENTINEL + ALPHA_SENTINEL_EPS { fallback }`.
|
||||
//!
|
||||
//! Slot layout:
|
||||
//!
|
||||
//! | Index | Name | Role | Update cadence | Producer kernel |
|
||||
//! |-------|------------------------------|--------------|-----------------|------------------------------------------|
|
||||
//! | 539 | Q_SPREAD_EMA_INDEX | Diagnostic | per-rollout-step| phase_e_kill_criteria.cu |
|
||||
//! | 540 | ACTION_ENTROPY_EMA_INDEX | Diagnostic | per-rollout-step| phase_e_kill_criteria.cu |
|
||||
//! | 541 | RETURN_VS_RANDOM_EMA_INDEX | Diagnostic | per-trade-close | phase_e_kill_criteria.cu |
|
||||
//! | 542 | EARLY_Q_MOVEMENT_EMA_INDEX | Diagnostic | per-epoch | phase_e_kill_criteria.cu |
|
||||
//! | 543 | STACKER_THRESHOLD_INDEX | Controller | per-rollout-step| stacker_threshold_controller.cu |
|
||||
//! | 544 | TRADE_RATE_TARGET_INDEX | Anchor | static | host init |
|
||||
//! | 545 | TRADE_RATE_OBSERVED_EMA_INDEX| Diagnostic | per-rollout-step| stacker_threshold_controller.cu |
|
||||
//! | 546 | STACKER_KELLY_ATTENUATION_IX | Controller | per-trade-close | stacker_threshold_controller.cu |
|
||||
//! | 547 | RANDOM_BASELINE_MEAN_INDEX | Anchor | per-fold | host computes once per fold |
|
||||
//! | 548 | RANDOM_BASELINE_STD_INDEX | Anchor | per-fold | host computes once per fold |
|
||||
//! | 549 | (reserved spare) | — | — | — |
|
||||
//! | 550 | (reserved spare) | — | — | — |
|
||||
//!
|
||||
//! Reservation discipline (per the alpha-system ISV research memo): slots 549..550
|
||||
//! are intentionally unused at first-commit to absorb growth without bumping
|
||||
//! `ISV_TOTAL_DIM` again. Add new alpha-system slots HERE first, not by extending
|
||||
//! past 550 ad-hoc.
|
||||
|
||||
pub const ALPHA_ISV_BLOCK_LO: usize = 539;
|
||||
pub const ALPHA_ISV_BLOCK_HI: usize = 550; // inclusive upper
|
||||
|
||||
// Diagnostics (read-only for circuit breakers; not controllers)
|
||||
pub const Q_SPREAD_EMA_INDEX: usize = 539;
|
||||
pub const ACTION_ENTROPY_EMA_INDEX: usize = 540;
|
||||
pub const RETURN_VS_RANDOM_EMA_INDEX: usize = 541;
|
||||
pub const EARLY_Q_MOVEMENT_EMA_INDEX: usize = 542;
|
||||
|
||||
// Stacker-threshold controller (engagement-rate self-correction)
|
||||
pub const STACKER_THRESHOLD_INDEX: usize = 543;
|
||||
pub const TRADE_RATE_TARGET_INDEX: usize = 544;
|
||||
pub const TRADE_RATE_OBSERVED_EMA_INDEX: usize = 545;
|
||||
pub const STACKER_KELLY_ATTENUATION_INDEX: usize = 546;
|
||||
|
||||
// Random-uniform baseline (computed once per fold; used by kill criterion 541)
|
||||
pub const RANDOM_BASELINE_MEAN_INDEX: usize = 547;
|
||||
pub const RANDOM_BASELINE_STD_INDEX: usize = 548;
|
||||
|
||||
// Sentinels: zero by convention. Fallbacks use the first-observation
|
||||
// bootstrap pattern (see pearl_first_observation_bootstrap.md).
|
||||
pub const ALPHA_SENTINEL: f32 = 0.0;
|
||||
pub const ALPHA_SENTINEL_EPS: f32 = 1e-9;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_block_bounds_consistent() {
|
||||
assert!(ALPHA_ISV_BLOCK_HI >= ALPHA_ISV_BLOCK_LO);
|
||||
let block_size = ALPHA_ISV_BLOCK_HI - ALPHA_ISV_BLOCK_LO + 1;
|
||||
assert_eq!(block_size, 12, "alpha-system reserved 12 contiguous slots");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_indices_inside_block() {
|
||||
let indices = [
|
||||
Q_SPREAD_EMA_INDEX,
|
||||
ACTION_ENTROPY_EMA_INDEX,
|
||||
RETURN_VS_RANDOM_EMA_INDEX,
|
||||
EARLY_Q_MOVEMENT_EMA_INDEX,
|
||||
STACKER_THRESHOLD_INDEX,
|
||||
TRADE_RATE_TARGET_INDEX,
|
||||
TRADE_RATE_OBSERVED_EMA_INDEX,
|
||||
STACKER_KELLY_ATTENUATION_INDEX,
|
||||
RANDOM_BASELINE_MEAN_INDEX,
|
||||
RANDOM_BASELINE_STD_INDEX,
|
||||
];
|
||||
for &i in &indices {
|
||||
assert!(i >= ALPHA_ISV_BLOCK_LO && i <= ALPHA_ISV_BLOCK_HI,
|
||||
"slot {i} out of alpha-system block");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_indices_unique() {
|
||||
let indices = [
|
||||
Q_SPREAD_EMA_INDEX,
|
||||
ACTION_ENTROPY_EMA_INDEX,
|
||||
RETURN_VS_RANDOM_EMA_INDEX,
|
||||
EARLY_Q_MOVEMENT_EMA_INDEX,
|
||||
STACKER_THRESHOLD_INDEX,
|
||||
TRADE_RATE_TARGET_INDEX,
|
||||
TRADE_RATE_OBSERVED_EMA_INDEX,
|
||||
STACKER_KELLY_ATTENUATION_INDEX,
|
||||
RANDOM_BASELINE_MEAN_INDEX,
|
||||
RANDOM_BASELINE_STD_INDEX,
|
||||
];
|
||||
let mut sorted: Vec<usize> = indices.to_vec();
|
||||
sorted.sort();
|
||||
sorted.dedup();
|
||||
assert_eq!(sorted.len(), indices.len(), "duplicate slot index");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_total_dim_covers_block() {
|
||||
// The parent ISV_TOTAL_DIM must be at least ALPHA_ISV_BLOCK_HI + 1.
|
||||
use crate::cuda_pipeline::gpu_dqn_trainer::ISV_TOTAL_DIM;
|
||||
assert!(ISV_TOTAL_DIM > ALPHA_ISV_BLOCK_HI,
|
||||
"ISV_TOTAL_DIM ({ISV_TOTAL_DIM}) must exceed ALPHA_ISV_BLOCK_HI ({ALPHA_ISV_BLOCK_HI})");
|
||||
}
|
||||
}
|
||||
@@ -2744,7 +2744,7 @@ const ISV_NETWORK_DIM: usize = 23;
|
||||
/// (and the C-side mirrors in `state_layout.cuh`). Bump this constant in the
|
||||
/// SAME commit that adds the new range, and update `layout_fingerprint_seed`
|
||||
/// to register the new slot names.
|
||||
pub(crate) const ISV_TOTAL_DIM: usize = 539; // SP22 H6 vNext Phase F-3 (2026-05-14) adds 1 slot [538..539) for AUX_TRADE_OUTCOME_CE_EMA_INDEX (K=3 trade-outcome head's sparse-CE EMA — observability of head training during smoke). SP22 H6 Phase 3 (2026-05-13) adds 2 slots [536..538) for the aux→policy bypass: REWARD_AUX_ALIGN_EMA_INDEX (7th reward component EMA, anchor for SP11 controller's w_aux_align) and SP22_AUX_ALIGN_SCALE_INDEX (controller-emitted adaptive scale_β consumed by β producers at training and eval). SP21 Phase 7.5 added 8 slots [528..536) for CURRICULUM_WEIGHT_{0..8} (per_insert_pa per-segment priority boost); Phase 7 added 1 slot [527..528); Phase 5+6 added 2 slots [525..527); Phase 4 added 4 slots [521..525); Phase 3 added 1 slot [520..521)
|
||||
pub(crate) const ISV_TOTAL_DIM: usize = 551; // Alpha trading system (2026-05-15, Phase E intro commit) reserves 12 slots [539..551) for durable infrastructure: diagnostics + stacker-threshold controller + random-baseline anchors. 2 slots [549..551) intentionally spare to absorb growth. See alpha_isv_slots.rs. SP22 H6 vNext Phase F-3 (2026-05-14) added 1 slot [538..539) for AUX_TRADE_OUTCOME_CE_EMA_INDEX (K=3 trade-outcome head's sparse-CE EMA — observability of head training during smoke). SP22 H6 Phase 3 (2026-05-13) added 2 slots [536..538) for the aux→policy bypass: REWARD_AUX_ALIGN_EMA_INDEX (7th reward component EMA, anchor for SP11 controller's w_aux_align) and SP22_AUX_ALIGN_SCALE_INDEX (controller-emitted adaptive scale_β consumed by β producers at training and eval). SP21 Phase 7.5 added 8 slots [528..536) for CURRICULUM_WEIGHT_{0..8} (per_insert_pa per-segment priority boost); Phase 7 added 1 slot [527..528); Phase 5+6 added 2 slots [525..527); Phase 4 added 4 slots [521..525); Phase 3 added 1 slot [520..521)
|
||||
/// Legacy alias preserved for call sites that haven't been audited for the
|
||||
/// network-vs-total split. New code should pick `ISV_NETWORK_DIM` (for weight
|
||||
/// tensor sizing) or `ISV_TOTAL_DIM` (for the broadcast bus buffer).
|
||||
|
||||
@@ -67,6 +67,7 @@ pub mod sp14_isv_slots;
|
||||
pub mod sp15_isv_slots;
|
||||
pub mod sp21_isv_slots;
|
||||
pub mod sp22_isv_slots;
|
||||
pub mod alpha_isv_slots;
|
||||
pub mod lob_bar;
|
||||
pub use sp4_isv_slots::{
|
||||
TARGET_Q_BOUND_INDEX, ATOM_POS_BOUND_BASE, WEIGHT_BOUND_BASE,
|
||||
|
||||
@@ -502,3 +502,38 @@ work stream and establishes the slot base for upcoming components:
|
||||
**Producers/consumers status:** Pre.2 lands the slot reservation only; Pre.3 registers in state reset machinery; all 10 slots are zero-initialized until subsequent SP20 phases land producers (per-epoch ISV seeds + GPU kernels) and consumer migration. Mirrors the SP4/SP5/SP11/SP15 pre-allocation pattern.
|
||||
|
||||
**ISV_TOTAL_DIM:** 510 → 520 (Pre.2 adds 10 slots).
|
||||
|
||||
## Alpha trading system — durable infrastructure block (2026-05-15)
|
||||
|
||||
Phase E intro commit reserves 12 contiguous slots at `[539..551)` for **system-scoped** infrastructure of the alpha trading stack (stacker / execution-policy diagnostics, controller anchors, population baselines). Unlike the per-iteration SP4..SP22 reservations, this block is named for the *system* — slots are intended to outlive any individual Phase E/F/G milestone. New slots in this range should be added in `alpha_isv_slots.rs` first; spares at 549..550 absorb growth without bumping `ISV_TOTAL_DIM`.
|
||||
|
||||
| Index | Name constant | Role | Producer (initial commit) | Update cadence | Notes |
|
||||
|-------|-------------------------------------|--------------|----------------------------------------|----------------------|-------|
|
||||
| 539 | `Q_SPREAD_EMA_INDEX` | Diagnostic | (none; Phase E.1 kill-criteria kernel) | per-rollout-step | `std(Q, axis=action) / |mean(Q)|`; kill-criterion #1 |
|
||||
| 540 | `ACTION_ENTROPY_EMA_INDEX` | Diagnostic | (none; Phase E.1 kill-criteria kernel) | per-rollout-step | `H(action_dist)` over recent rollouts; kill-criterion #2 |
|
||||
| 541 | `RETURN_VS_RANDOM_EMA_INDEX` | Diagnostic | (none; Phase E.1 kill-criteria kernel) | per-trade-close | `(rollout_R − random_R) / σ_random`; kill-criterion #3 |
|
||||
| 542 | `EARLY_Q_MOVEMENT_EMA_INDEX` | Diagnostic | (none; Phase E.1 kill-criteria kernel) | per-epoch | `|Q(s_early) − Q_init|/|Q_init|`; kill-criterion #4 |
|
||||
| 543 | `STACKER_THRESHOLD_INDEX` | Controller | (none; Phase E.2 stacker controller) | per-rollout-step | Confidence threshold for trade eligibility; engagement-rate self-correction |
|
||||
| 544 | `TRADE_RATE_TARGET_INDEX` | Anchor | host init at training start | static | Target trade-rate fraction (e.g. 0.08) |
|
||||
| 545 | `TRADE_RATE_OBSERVED_EMA_INDEX` | Diagnostic | (none; Phase E.2 stacker controller) | per-rollout-step | Observed trade-rate EMA |
|
||||
| 546 | `STACKER_KELLY_ATTENUATION_INDEX` | Controller | (none; Phase E.2 stacker controller) | per-trade-close | Multiplied with `KELLY_F_SMOOTH_INDEX=280` before contract-cap; bounded [0.1, 1.0] per `pearl_blend_formulas_must_have_permanent_floor` |
|
||||
| 547 | `RANDOM_BASELINE_MEAN_INDEX` | Anchor | host computes once per fold | per-fold | Mean reward of uniform-random execution policy at the given horizon |
|
||||
| 548 | `RANDOM_BASELINE_STD_INDEX` | Anchor | host computes once per fold | per-fold | Std of same — used to compute `RETURN_VS_RANDOM_EMA` σ-distance |
|
||||
| 549 | (reserved spare) | — | — | — | Absorb growth; do not use ad-hoc |
|
||||
| 550 | (reserved spare) | — | — | — | Absorb growth; do not use ad-hoc |
|
||||
|
||||
**Files touched (intro commit, slot reservation only):**
|
||||
- `crates/ml/src/cuda_pipeline/alpha_isv_slots.rs` (new) — 10 `pub const *_INDEX` constants + `ALPHA_ISV_BLOCK_LO=539`/`ALPHA_ISV_BLOCK_HI=550` bookends + 4 unit tests (bounds, membership, uniqueness, total-dim coverage)
|
||||
- `crates/ml/src/cuda_pipeline/mod.rs` — adds `pub mod alpha_isv_slots;`
|
||||
- `crates/ml/src/cuda_pipeline/gpu_dqn_trainer.rs` — `ISV_TOTAL_DIM: 539 → 551`; comment updated to reference `alpha_isv_slots.rs`
|
||||
|
||||
**Producers/consumers status:** intro commit is reservation-only. Producers land later in Phase E:
|
||||
- Phase E.1: `phase_e_kill_criteria.cu` writes slots 539-542
|
||||
- Phase E.2: `stacker_threshold_controller.cu` writes slots 543, 545, 546 (reads 544 as anchor)
|
||||
- Phase E.0: host writes 544 (trade-rate target) at training start and 547, 548 (baselines) per fold
|
||||
|
||||
State-reset-registry dispatch arms for all 10 active slots land in the immediately-following commit (Phase E Task 2), per `feedback_registry_entries_need_dispatch_arms`.
|
||||
|
||||
**Naming rationale:** SP4..SP22 reservations are *milestone-scoped* (a specific SP iteration); this block is *system-scoped* (alpha trading system across Phase E/F/G/...). The naming difference is intentional — future alpha-system additions go in `alpha_isv_slots.rs`, not in a per-phase file.
|
||||
|
||||
**ISV_TOTAL_DIM:** 539 → 551 (12 slots reserved, 10 active, 2 spare).
|
||||
|
||||
Reference in New Issue
Block a user