You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
4.4 KiB
Python
128 lines
4.4 KiB
Python
"""Helpers for shadow-only non-core allocator v2 diagnostics."""
|
|
from __future__ import annotations
|
|
|
|
import math
|
|
|
|
|
|
def compute_native_rank_pct(rank_index: int, total: int) -> float:
|
|
if total <= 1:
|
|
return 1.0
|
|
clamped_index = max(0, min(rank_index, total - 1))
|
|
return max(0.0, 1.0 - (clamped_index / float(total - 1)))
|
|
|
|
|
|
def normalize_hold_days_est(hold_days_est: int | float | None) -> float:
|
|
hold_days = max(0.0, float(hold_days_est or 0.0))
|
|
return min(hold_days, 30.0) / 30.0
|
|
|
|
|
|
def normalize_liquidity_penalty(
|
|
requested_cash_est: int | float | None,
|
|
avg_dollar_volume: int | float | None,
|
|
) -> float:
|
|
requested_cash = max(0.0, float(requested_cash_est or 0.0))
|
|
adv = max(0.0, float(avg_dollar_volume or 0.0))
|
|
denom = max(adv * 0.02, 1.0)
|
|
return min(requested_cash / denom, 1.0)
|
|
|
|
|
|
def classify_parking_class(parking_symbol: str | None) -> str:
|
|
normalized = str(parking_symbol or "").strip().lower()
|
|
if normalized == "sgov":
|
|
return "cash"
|
|
if normalized == "gld":
|
|
return "gold"
|
|
if normalized in {"qqqm", "qqq", "tqqq", "spy"}:
|
|
return "equity_beta"
|
|
return "cash"
|
|
|
|
|
|
def classify_non_core_overlap_class(
|
|
family: str,
|
|
*,
|
|
trade_symbol_mode: str | None = None,
|
|
engine_id: str | None = None,
|
|
symbol: str | None = None,
|
|
) -> str:
|
|
normalized_family = str(family or "").strip().lower()
|
|
normalized_engine = str(engine_id or "").strip().lower()
|
|
normalized_symbol = str(symbol or "").strip().lower()
|
|
normalized_mode = str(trade_symbol_mode or "").strip().lower()
|
|
|
|
if normalized_family == "risk_off_alpha" and normalized_symbol == "gld":
|
|
return "gold"
|
|
if normalized_family == "idle_alpha" and (
|
|
normalized_engine == "idle_macro_breadth_smh_postalloc"
|
|
or normalized_mode == "sector_etf"
|
|
or normalized_symbol == "smh"
|
|
):
|
|
return "equity_beta_high"
|
|
if normalized_family in {"idle_alpha", "form4", "ownership"}:
|
|
return "equity_beta_med"
|
|
if normalized_family == "risk_off_alpha":
|
|
return "gold" if normalized_symbol == "gld" else "cash"
|
|
return "cash"
|
|
|
|
|
|
def compute_overlap_penalty(candidate_class: str, parking_class: str) -> float:
|
|
candidate = str(candidate_class or "").strip().lower()
|
|
parking = str(parking_class or "").strip().lower()
|
|
if parking == "cash" or candidate == "cash":
|
|
return 0.0
|
|
if candidate == "gold" and parking == "gold":
|
|
return 1.0
|
|
if candidate == "equity_beta_high" and parking == "equity_beta":
|
|
return 1.0
|
|
if candidate == "equity_beta_med" and parking == "equity_beta":
|
|
return 0.6
|
|
return 0.0
|
|
|
|
|
|
def normalize_parking_proxy(
|
|
parking_symbol: str | None,
|
|
*,
|
|
parking_momentum_20: int | float | None,
|
|
hold_days_est: int | float | None,
|
|
sgov_annual_rate: int | float | None,
|
|
) -> float:
|
|
normalized_symbol = str(parking_symbol or "").strip().lower()
|
|
hold_days = max(0.0, float(hold_days_est or 0.0))
|
|
if normalized_symbol == "sgov":
|
|
annual_rate = max(0.0, float(sgov_annual_rate or 0.0))
|
|
return min(((annual_rate * hold_days / 252.0) / 0.02), 1.0)
|
|
|
|
momentum = max(0.0, float(parking_momentum_20 or 0.0))
|
|
scaled_momentum = momentum * (min(hold_days, 20.0) / 20.0)
|
|
return min(scaled_momentum / 0.10, 1.0)
|
|
|
|
|
|
def compute_marginal_score(
|
|
*,
|
|
native_rank_pct: int | float | None,
|
|
hold_norm: int | float | None,
|
|
liquidity_penalty_norm: int | float | None,
|
|
overlap_penalty_norm: int | float | None,
|
|
parking_proxy_norm: int | float | None,
|
|
native_strength: int | float = 1.0,
|
|
hold_penalty: int | float = 0.20,
|
|
liquidity_penalty: int | float = 0.25,
|
|
overlap_penalty: int | float = 0.20,
|
|
parking_opportunity_penalty: int | float = 0.35,
|
|
) -> float:
|
|
values = (
|
|
float(native_rank_pct or 0.0),
|
|
float(hold_norm or 0.0),
|
|
float(liquidity_penalty_norm or 0.0),
|
|
float(overlap_penalty_norm or 0.0),
|
|
float(parking_proxy_norm or 0.0),
|
|
)
|
|
if any(math.isnan(value) or math.isinf(value) for value in values):
|
|
return 0.0
|
|
return (
|
|
float(native_strength) * float(native_rank_pct or 0.0)
|
|
- float(hold_penalty) * float(hold_norm or 0.0)
|
|
- float(liquidity_penalty) * float(liquidity_penalty_norm or 0.0)
|
|
- float(overlap_penalty) * float(overlap_penalty_norm or 0.0)
|
|
- float(parking_opportunity_penalty) * float(parking_proxy_norm or 0.0)
|
|
)
|