from hermes_mcp.decision_engine import assess_wallet_state, make_decision, normalize_strategy_snapshot, score_strategy_fit def test_assess_wallet_state_detects_depleted_base_side(): concern = {"account_id": "a1", "market_symbol": "xrpusd", "base_currency": "XRP", "quote_currency": "USD"} account_info = { "balances": [ {"asset_code": "XRP", "available": 1}, {"asset_code": "USD", "available": 1000}, ] } wallet = assess_wallet_state(account_info=account_info, concern=concern, price=2.0) assert wallet["inventory_state"] == "depleted_base_side" assert wallet["rebalance_needed"] is True assert wallet["grid_ready"] is False def test_score_strategy_fit_penalizes_grid_when_wallet_unbalanced(): strategy = normalize_strategy_snapshot({ "id": "grid-1", "strategy_type": "grid_trader", "mode": "active", "account_id": "a1", "state": {}, "config": {}, }) narrative = {"stance": "constructive_bullish", "opportunity_map": {"continuation": 0.7, "mean_reversion": 0.1, "reversal": 0.1, "wait": 0.1}} wallet_state = {"inventory_state": "depleted_base_side", "rebalance_needed": True} fit = score_strategy_fit(strategy=strategy, narrative=narrative, wallet_state=wallet_state) assert fit["score"] < 0 assert any("grid" in block or "wallet" in block for block in fit["blocks"]) def test_make_decision_replaces_grid_when_directional_and_unbalanced(): concern = {"id": "c1", "account_id": "a1", "market_symbol": "xrpusd", "base_currency": "XRP", "quote_currency": "USD"} narrative = { "stance": "constructive_bullish", "confidence": 0.72, "opportunity_map": {"continuation": 0.75, "mean_reversion": 0.1, "reversal": 0.05, "wait": 0.1}, } wallet_state = { "inventory_state": "base_heavy", "rebalance_needed": True, "grid_ready": False, "base_ratio": 0.8, "quote_ratio": 0.2, } strategies = [ {"id": "grid-1", "strategy_type": "grid_trader", "mode": "active", "account_id": "a1", "state": {}, "config": {}}, {"id": "trend-1", "strategy_type": "trend_follower", "mode": "off", "account_id": "a1", "state": {}, "config": {}}, {"id": "protect-1", "strategy_type": "exposure_protector", "mode": "off", "account_id": "a1", "state": {}, "config": {}}, ] decision = make_decision(concern=concern, narrative_payload=narrative, wallet_state=wallet_state, strategies=strategies) assert decision.mode == "act" assert decision.action == "replace_with_exposure_protector" assert decision.target_strategy == "protect-1"