Spaces:
Runtime error
Runtime error
| """Feature extraction for liquidity prediction.""" | |
| from typing import Dict, List | |
| from ..utils.config import config | |
| class FeatureExtractor: | |
| """ | |
| Extracts liquidity-related features from the current market state | |
| for use by the LiquidityShockPredictor. | |
| """ | |
| def __init__( | |
| self, | |
| baseline_spread: float = config.baseline_spread, | |
| baseline_depth: float = config.baseline_depth, | |
| baseline_volatility: float = config.baseline_volatility, | |
| ) -> None: | |
| self.baseline_spread = baseline_spread | |
| self.baseline_depth = baseline_depth | |
| self.baseline_volatility = baseline_volatility | |
| def extract_liquidity_features( | |
| self, market_state: Dict, lookback: int = 60 | |
| ) -> Dict[str, float]: | |
| """ | |
| Extract 6 liquidity features from current market state. | |
| Returns: | |
| Dict with keys: spread_ratio, depth_ratio, volatility_ratio, | |
| mm_inventory_stress, active_mm_count, time_to_close | |
| """ | |
| mid_price = market_state.get("mid_price", 100.0) | |
| spread = market_state.get("spread", 0.0) | |
| total_depth = market_state.get("total_depth", 0) | |
| volatility = market_state.get("volatility", 0.0) | |
| time_to_close = market_state.get("time_to_close", 23400.0) | |
| agents = market_state.get("agents", {}) | |
| # Spread ratio: normalised spread relative to baseline | |
| current_spread_ratio = (spread / mid_price) if mid_price > 0 else 0.0 | |
| spread_ratio = current_spread_ratio / self.baseline_spread if self.baseline_spread > 0 else 0.0 | |
| # Depth ratio: total depth / baseline | |
| depth_ratio = total_depth / self.baseline_depth if self.baseline_depth > 0 else 0.0 | |
| # Volatility ratio | |
| volatility_ratio = volatility / self.baseline_volatility if self.baseline_volatility > 0 else 0.0 | |
| # Market maker inventory stress | |
| mm_agents = { | |
| k: v for k, v in agents.items() | |
| if v.get("type") == "MarketMaker" | |
| } | |
| if mm_agents: | |
| mm_inventory_stress = sum( | |
| abs(v.get("inventory_ratio", 0.0)) for v in mm_agents.values() | |
| ) / len(mm_agents) | |
| # Count active MMs (not near max capacity) | |
| active_mm_count = sum( | |
| 1 for v in mm_agents.values() | |
| if abs(v.get("position", 0)) < 4500 | |
| ) | |
| else: | |
| mm_inventory_stress = 0.0 | |
| active_mm_count = 0 | |
| return { | |
| "spread_ratio": round(spread_ratio, 6), | |
| "depth_ratio": round(depth_ratio, 6), | |
| "volatility_ratio": round(volatility_ratio, 6), | |
| "mm_inventory_stress": round(mm_inventory_stress, 6), | |
| "active_mm_count": active_mm_count, | |
| "time_to_close": time_to_close, | |
| } | |