#!/usr/bin/env python3 """ Shared eigen-scan normalizer. BLUE is canonical. This module converts NG7 nested Hazelcast payloads into the flat shape the production engines expect. """ from __future__ import annotations import math from typing import Any, Dict def normalize_ng7_scan(scan: Dict[str, Any]) -> Dict[str, Any]: """ Promote an NG7 nested scan to the BLUE-compatible flat dict. Expected input: scan["result"]["multi_window_results"]["50"]["tracking_data"]["lambda_max_velocity"] scan["result"]["pricing_data"]["current_prices"] """ if not isinstance(scan, dict): return {} result = scan.get("result") or {} mw = result.get("multi_window_results") or {} def _velocity(window: int) -> float: tracking = (mw.get(str(window)) or {}).get("tracking_data", {}) value = tracking.get("lambda_max_velocity") try: velocity = float(value) return velocity if math.isfinite(velocity) else 0.0 except (TypeError, ValueError): return 0.0 v50 = _velocity(50) v750 = _velocity(750) current_prices = (result.get("pricing_data") or {}).get("current_prices") or {} assets = [asset for asset in current_prices if asset != "BTCUSDT"] if "BTCUSDT" in current_prices: assets.append("BTCUSDT") asset_prices = [float(current_prices[asset]) for asset in assets] if assets else [] instability = float((result.get("regime_prediction") or {}).get("instability_score") or 0.0) return { **scan, "vel_div": v50 - v750, "w50_velocity": v50, "w750_velocity": v750, "assets": assets, "asset_prices": asset_prices, "instability_50": instability, }