test_decision_engine.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. from hermes_mcp.decision_engine import assess_wallet_state, make_decision, normalize_strategy_snapshot, score_strategy_fit
  2. def test_assess_wallet_state_detects_depleted_base_side():
  3. concern = {"account_id": "a1", "market_symbol": "xrpusd", "base_currency": "XRP", "quote_currency": "USD"}
  4. account_info = {
  5. "balances": [
  6. {"asset_code": "XRP", "available": 1},
  7. {"asset_code": "USD", "available": 1000},
  8. ]
  9. }
  10. wallet = assess_wallet_state(account_info=account_info, concern=concern, price=2.0)
  11. assert wallet["inventory_state"] == "depleted_base_side"
  12. assert wallet["rebalance_needed"] is True
  13. assert wallet["grid_ready"] is False
  14. def test_score_strategy_fit_penalizes_grid_when_wallet_unbalanced():
  15. strategy = normalize_strategy_snapshot({
  16. "id": "grid-1",
  17. "strategy_type": "grid_trader",
  18. "mode": "active",
  19. "account_id": "a1",
  20. "state": {},
  21. "config": {},
  22. })
  23. narrative = {"stance": "constructive_bullish", "opportunity_map": {"continuation": 0.7, "mean_reversion": 0.1, "reversal": 0.1, "wait": 0.1}}
  24. wallet_state = {"inventory_state": "depleted_base_side", "rebalance_needed": True}
  25. fit = score_strategy_fit(strategy=strategy, narrative=narrative, wallet_state=wallet_state)
  26. assert fit["score"] < 0
  27. assert any("grid" in block or "wallet" in block for block in fit["blocks"])
  28. def test_make_decision_replaces_grid_when_directional_and_unbalanced():
  29. concern = {"id": "c1", "account_id": "a1", "market_symbol": "xrpusd", "base_currency": "XRP", "quote_currency": "USD"}
  30. narrative = {
  31. "stance": "constructive_bullish",
  32. "confidence": 0.72,
  33. "opportunity_map": {"continuation": 0.75, "mean_reversion": 0.1, "reversal": 0.05, "wait": 0.1},
  34. }
  35. wallet_state = {
  36. "inventory_state": "base_heavy",
  37. "rebalance_needed": True,
  38. "grid_ready": False,
  39. "base_ratio": 0.8,
  40. "quote_ratio": 0.2,
  41. }
  42. strategies = [
  43. {"id": "grid-1", "strategy_type": "grid_trader", "mode": "active", "account_id": "a1", "state": {}, "config": {}},
  44. {"id": "trend-1", "strategy_type": "trend_follower", "mode": "off", "account_id": "a1", "state": {}, "config": {}},
  45. {"id": "protect-1", "strategy_type": "exposure_protector", "mode": "off", "account_id": "a1", "state": {}, "config": {}},
  46. ]
  47. decision = make_decision(concern=concern, narrative_payload=narrative, wallet_state=wallet_state, strategies=strategies)
  48. assert decision.mode == "act"
  49. assert decision.action == "replace_with_exposure_protector"
  50. assert decision.target_strategy == "protect-1"