from hermes_mcp.state_engine import extract_regime_features, synthesize_state def test_extract_regime_features_preserves_structure(): regime = { "symbol": "XRP", "timeframe": "5m", "price": 1.4189, "trend": {"ema_fast": 1.409869, "ema_slow": 1.411053, "sma_long": 1.405942, "state": "range"}, "momentum": {"rsi": 59.64, "macd_histogram": 0.001331, "state": "neutral"}, "volatility": {"atr": 0.006216, "atr_percent": 0.4381}, "bands": {"bollinger": {"middle": 1.410125, "upper": 1.431226, "lower": 1.389024}}, "vwap": 1.411719, "reversal": {"direction": "none", "score": 0, "triggers": []}, } features = extract_regime_features(regime) assert features["trend"]["alignment"] in {"mixed", "bullish_pullback", "fully_bullish"} assert features["momentum"]["rsi_zone"] == "neutral" assert features["volatility"]["regime"] == "normal" assert features["location"]["auction_state"] def test_synthesize_state_builds_scoped_state(): concern = {"id": "c1", "account_id": "a1", "market_symbol": "BTCUSD", "status": "active"} regimes = [ {"timeframe": "1m", "price": 101, "trend": {"ema_fast": 100, "ema_slow": 99, "sma_long": 98, "state": "bull"}, "momentum": {"rsi": 62, "macd_histogram": 0.02, "state": "bull"}, "volatility": {"atr_percent": 0.5}, "bands": {"bollinger": {"middle": 100, "upper": 102, "lower": 98}}, "vwap": 100.2, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "5m", "price": 102, "trend": {"ema_fast": 101, "ema_slow": 100, "sma_long": 99, "state": "bull"}, "momentum": {"rsi": 63, "macd_histogram": 0.018, "state": "bull"}, "volatility": {"atr_percent": 0.6}, "bands": {"bollinger": {"middle": 101, "upper": 103, "lower": 99}}, "vwap": 101.1, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "15m", "price": 103, "trend": {"ema_fast": 102, "ema_slow": 101, "sma_long": 99.5, "state": "bull"}, "momentum": {"rsi": 60, "macd_histogram": 0.012, "state": "neutral"}, "volatility": {"atr_percent": 0.8}, "bands": {"bollinger": {"middle": 102, "upper": 104, "lower": 100}}, "vwap": 102.0, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "1h", "price": 104, "trend": {"ema_fast": 103, "ema_slow": 102, "sma_long": 100, "state": "bull"}, "momentum": {"rsi": 58, "macd_histogram": 0.01, "state": "neutral"}, "volatility": {"atr_percent": 0.9}, "bands": {"bollinger": {"middle": 103, "upper": 105, "lower": 101}}, "vwap": 103.0, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "4h", "price": 106, "trend": {"ema_fast": 104, "ema_slow": 103, "sma_long": 101, "state": "bull"}, "momentum": {"rsi": 57, "macd_histogram": 0.009, "state": "neutral"}, "volatility": {"atr_percent": 1.1}, "bands": {"bollinger": {"middle": 104, "upper": 107, "lower": 101}}, "vwap": 104.5, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "1d", "price": 110, "trend": {"ema_fast": 108, "ema_slow": 106, "sma_long": 103, "state": "bull"}, "momentum": {"rsi": 61, "macd_histogram": 0.008, "state": "bull"}, "volatility": {"atr_percent": 1.4}, "bands": {"bollinger": {"middle": 107, "upper": 112, "lower": 102}}, "vwap": 108.0, "reversal": {"direction": "none", "score": 0}}, ] state = synthesize_state(concern=concern, regimes=regimes) assert state.market_regime == "bull" assert state.sentiment_pressure == "bullish" assert state.payload["scoped_state"]["macro"]["bias"] == "bullish" assert state.payload["scoped_state"]["micro"]["impulse"] == "up" assert state.payload["cross_scope_summary"]["alignment"] in {"micro_meso_macro_aligned", "partial_alignment"} assert state.confidence > 0.5 def test_synthesize_state_carries_argus_context_without_rewriting_market_state(): concern = {"id": "c1", "account_id": "a1", "market_symbol": "BTCUSD", "status": "active"} regimes = [ {"timeframe": "1m", "price": 101, "trend": {"ema_fast": 100, "ema_slow": 99, "sma_long": 98, "state": "bull"}, "momentum": {"rsi": 62, "macd_histogram": 0.02, "state": "bull"}, "volatility": {"atr_percent": 0.5}, "bands": {"bollinger": {"middle": 100, "upper": 102, "lower": 98}}, "vwap": 100.2, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "5m", "price": 102, "trend": {"ema_fast": 101, "ema_slow": 100, "sma_long": 99, "state": "bull"}, "momentum": {"rsi": 63, "macd_histogram": 0.018, "state": "bull"}, "volatility": {"atr_percent": 0.6}, "bands": {"bollinger": {"middle": 101, "upper": 103, "lower": 99}}, "vwap": 101.1, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "15m", "price": 103, "trend": {"ema_fast": 102, "ema_slow": 101, "sma_long": 99.5, "state": "bull"}, "momentum": {"rsi": 60, "macd_histogram": 0.012, "state": "neutral"}, "volatility": {"atr_percent": 0.8}, "bands": {"bollinger": {"middle": 102, "upper": 104, "lower": 100}}, "vwap": 102.0, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "1h", "price": 104, "trend": {"ema_fast": 103, "ema_slow": 102, "sma_long": 100, "state": "bull"}, "momentum": {"rsi": 58, "macd_histogram": 0.01, "state": "neutral"}, "volatility": {"atr_percent": 0.9}, "bands": {"bollinger": {"middle": 103, "upper": 105, "lower": 101}}, "vwap": 103.0, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "4h", "price": 106, "trend": {"ema_fast": 104, "ema_slow": 103, "sma_long": 101, "state": "bull"}, "momentum": {"rsi": 57, "macd_histogram": 0.009, "state": "neutral"}, "volatility": {"atr_percent": 1.1}, "bands": {"bollinger": {"middle": 104, "upper": 107, "lower": 101}}, "vwap": 104.5, "reversal": {"direction": "none", "score": 0}}, {"timeframe": "1d", "price": 110, "trend": {"ema_fast": 108, "ema_slow": 106, "sma_long": 103, "state": "bull"}, "momentum": {"rsi": 61, "macd_histogram": 0.008, "state": "bull"}, "volatility": {"atr_percent": 1.4}, "bands": {"bollinger": {"middle": 107, "upper": 112, "lower": 102}}, "vwap": 108.0, "reversal": {"direction": "none", "score": 0}}, ] state = synthesize_state( concern=concern, regimes=regimes, argus_snapshot={ "regime": "risk_off", "confidence": 0.74, "summary": "precious metals firm while crypto beta is selective", "components": {"stress": 0.42}, }, argus_regime={ "regime": "real_asset_pressure", "confidence": 0.81, "summary": "gold and silver continue to confirm macro stress", "components": {"compression": 0.18, "real_asset_pressure": 0.67}, }, ) assert state.market_regime == "bull" assert state.payload["argus_context"]["regime"] == "real_asset_pressure" assert state.payload["argus_context"]["snapshot_regime"] == "risk_off" assert state.payload["argus_context"]["snapshot_components"]["stress"] == 0.42 assert state.payload["argus_context"]["regime_components"]["real_asset_pressure"] == 0.67