diag(rl): emit risk-stack ISVs to JSONL

Added `risk_stack` section to alpha_rl_train.rs diag emitter so the five
risk-management layers introduced in 285d42aa7 are observable from the
diag JSONL. Without this the kernels run but the output is invisible.

  cmdp           session_pnl_usd, session_dd_triggered, consec_loss_*,
                 cooldown_*, max_open_units, net_inventory_limit_usd
  iqn_tau        action_tau, tau_min, dd_sensitivity
  inventory      penalty_beta, variance_ema
  kelly          fraction, win_rate_ema, avg_win/loss_usd_ema,
                 safety_frac, min_trades_for_release, cumulative_dones
  trail_factors  tighten, loosen

Pure additive emission — no kernel changes, no perturbation of training
state. Local 5-step smoke b=16 confirms every field appears with values
that match the spec math (e.g. IQN τ adapts linearly with drawdown).

Doesn't affect the in-flight alpha-rl-2bm59 (pinned SHA 285d42aa7);
takes effect on the next submission.
This commit is contained in:
jgrusewski
2026-05-30 21:24:22 +02:00
parent 285d42aa7b
commit 6e0f568160

View File

@@ -94,6 +94,21 @@ use ml_alpha::rl::isv_slots::{
RL_OUTCOME_AUX_LAMBDA_INDEX,
RL_SAC_ALPHA_INDEX, RL_SAC_ENTROPY_TARGET_INDEX,
RL_ACTION_ENTROPY_EMA_INDEX,
// Risk-management stack (spec 2026-05-30-adaptive-risk-management-design).
// Per `feedback_wire_everything_up`: the kernels write these slots;
// diag has to surface them or the run is half-blind.
RL_SESSION_PNL_USD_INDEX, RL_SESSION_DD_LIMIT_USD_INDEX, RL_SESSION_DD_TRIGGERED_INDEX,
RL_CONSEC_LOSS_LIMIT_INDEX, RL_CONSEC_LOSS_COUNT_INDEX,
RL_COOLDOWN_REMAINING_STEPS_INDEX, RL_COOLDOWN_DURATION_INDEX,
RL_MAX_OPEN_UNITS_INDEX, RL_NET_INVENTORY_LIMIT_USD_INDEX,
RL_IQN_ACTION_TAU_INDEX, RL_IQN_ACTION_TAU_MIN_INDEX,
RL_IQN_ACTION_TAU_DD_SENSITIVITY_INDEX,
RL_INVENTORY_PENALTY_BETA_INDEX, RL_INVENTORY_VARIANCE_EMA_INDEX,
RL_KELLY_FRACTION_INDEX, RL_WIN_RATE_EMA_INDEX,
RL_AVG_WIN_USD_EMA_INDEX, RL_AVG_LOSS_USD_EMA_INDEX,
RL_KELLY_SAFETY_FRAC_INDEX, RL_KELLY_MIN_TRADES_FOR_RELEASE_INDEX,
RL_TRAIL_TIGHTEN_FACTOR_INDEX, RL_TRAIL_LOOSEN_FACTOR_INDEX,
RL_CUMULATIVE_DONES_INDEX,
};
use ml_alpha::trainer::diag_staging::DiagStaging;
use ml_alpha::trainer::integrated::{
@@ -822,6 +837,51 @@ fn main() -> Result<()> {
"stale": isv[RL_LR_V_STEPS_SINCE_BEST_INDEX],
"warmup": isv[RL_LR_V_WARMUP_COUNTER_INDEX] },
},
// Adaptive risk-management stack state — five orthogonal layers.
// Every slot here is written by a kernel; diag surfaces them so
// controller behaviour, gate firing, and bootstrap state are
// observable without re-reading device memory.
"risk_stack": {
// Layer 1 — CMDP hard constraints.
"cmdp": {
"session_pnl_usd": isv[RL_SESSION_PNL_USD_INDEX],
"session_dd_limit_usd": isv[RL_SESSION_DD_LIMIT_USD_INDEX],
"session_dd_triggered": isv[RL_SESSION_DD_TRIGGERED_INDEX],
"consec_loss_count": isv[RL_CONSEC_LOSS_COUNT_INDEX],
"consec_loss_limit": isv[RL_CONSEC_LOSS_LIMIT_INDEX],
"cooldown_remaining_steps": isv[RL_COOLDOWN_REMAINING_STEPS_INDEX],
"cooldown_duration": isv[RL_COOLDOWN_DURATION_INDEX],
"max_open_units": isv[RL_MAX_OPEN_UNITS_INDEX],
"net_inventory_limit_usd": isv[RL_NET_INVENTORY_LIMIT_USD_INDEX],
},
// Layer 2 — IQN risk-averse action τ.
"iqn_tau": {
"action_tau": isv[RL_IQN_ACTION_TAU_INDEX],
"tau_min": isv[RL_IQN_ACTION_TAU_MIN_INDEX],
"dd_sensitivity": isv[RL_IQN_ACTION_TAU_DD_SENSITIVITY_INDEX],
},
// Layer 3 — Avellaneda-Stoikov inventory penalty β.
"inventory": {
"penalty_beta": isv[RL_INVENTORY_PENALTY_BETA_INDEX],
"variance_ema": isv[RL_INVENTORY_VARIANCE_EMA_INDEX],
},
// Layer 4 — Half-Kelly position sizing + its EMA inputs.
"kelly": {
"fraction": isv[RL_KELLY_FRACTION_INDEX],
"win_rate_ema": isv[RL_WIN_RATE_EMA_INDEX],
"avg_win_usd_ema": isv[RL_AVG_WIN_USD_EMA_INDEX],
"avg_loss_usd_ema": isv[RL_AVG_LOSS_USD_EMA_INDEX],
"safety_frac": isv[RL_KELLY_SAFETY_FRAC_INDEX],
"min_trades_for_release": isv[RL_KELLY_MIN_TRADES_FOR_RELEASE_INDEX],
"cumulative_dones": isv[RL_CUMULATIVE_DONES_INDEX],
},
// Layer D — trail tighten/loosen factors (kernel-side
// counters are already in `trail.{tightened,loosened}_count_*`).
"trail_factors": {
"tighten": isv[RL_TRAIL_TIGHTEN_FACTOR_INDEX],
"loosen": isv[RL_TRAIL_LOOSEN_FACTOR_INDEX],
},
},
"replay_len": trainer.gpu_replay.capacity.min(step + 1),
// Post-scale, POST-clamp reward stats — what V regression
// and Q distributional projection actually saw this step.