Spaces:
Sleeping
Sleeping
| """ | |
| Portfolio Runner β Orchestrates the CGAE Adaptive Portfolio Manager demo. | |
| Flow: | |
| 1. Create sub-agents (RegimeDetector, Rebalancer, YieldOptimizer) | |
| 2. Run portfolio management cycles | |
| 3. Adversarial agent attacks each cycle β all blocked by CGAE | |
| 4. Display results | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import logging | |
| import time | |
| import urllib.request | |
| from typing import Optional | |
| from dotenv import load_dotenv | |
| load_dotenv() | |
| from cgae_engine.gate import GateFunction, RobustnessVector, Tier | |
| from cgae_engine.llm_agent import create_llm_agents | |
| from cgae_engine.models_config import CONTESTANT_MODELS | |
| from cgae_engine.audit import AuditOrchestrator | |
| from agents.portfolio import ( | |
| PortfolioOrchestrator, RegimeDetector, Rebalancer, | |
| YieldOptimizer, SubAgent, Allocation, Regime, | |
| ) | |
| from agents.adversarial import AdversarialAgent | |
| logger = logging.getLogger(__name__) | |
| def fetch_market_data() -> dict: | |
| """Fetch live market data for regime detection.""" | |
| try: | |
| url = "https://api.coingecko.com/api/v3/simple/price?ids=ethereum,bitcoin&vs_currencies=usd&include_24hr_change=true" | |
| req = urllib.request.Request(url, headers={"Accept": "application/json"}) | |
| with urllib.request.urlopen(req, timeout=10) as resp: | |
| data = json.loads(resp.read()) | |
| return { | |
| "eth_change_24h": data["ethereum"].get("usd_24h_change", 0), | |
| "btc_change_24h": data["bitcoin"].get("usd_24h_change", 0), | |
| "volatility": abs(data["ethereum"].get("usd_24h_change", 0)) * 0.5, | |
| "funding_rate": 0.01, | |
| "fear_greed": 55, | |
| } | |
| except Exception as e: | |
| logger.warning(f"Market data fetch failed: {e}") | |
| return {"eth_change_24h": 1.5, "btc_change_24h": 0.8, "volatility": 3.0, "funding_rate": 0.01, "fear_greed": 55} | |
| def create_portfolio_system() -> tuple[PortfolioOrchestrator, AdversarialAgent]: | |
| """Create the full portfolio system with all sub-agents.""" | |
| gate = GateFunction() | |
| models = {m["model_name"]: m for m in CONTESTANT_MODELS} | |
| llm_agents = create_llm_agents(list(models.values())) | |
| # Fetch real robustness scores from framework APIs where available | |
| orchestrator_audit = AuditOrchestrator() | |
| agent_scores = {} | |
| for name in ["nova-pro", "DeepSeek-V3.2", "Kimi-K2.5", "MiniMax-M2.5"]: | |
| result = orchestrator_audit.audit_from_results(name, name) | |
| agent_scores[name] = result.robustness | |
| defaults = result.defaults_used | |
| tier = gate.evaluate(result.robustness) | |
| logger.info(f" {name}: CC={result.robustness.cc:.3f} ER={result.robustness.er:.3f} " | |
| f"AS={result.robustness.as_:.3f} IH={result.robustness.ih:.3f} β T{tier.value}" | |
| f"{' (defaults: ' + ','.join(defaults) + ')' if defaults else ''}") | |
| regime_r = agent_scores["nova-pro"] | |
| rebal_r = agent_scores["Kimi-K2.5"] | |
| yield_r = agent_scores["DeepSeek-V3.2"] | |
| regime_detector = RegimeDetector( | |
| name="nova-pro", role="regime_detector", | |
| llm=llm_agents["nova-pro"], | |
| tier=gate.evaluate(regime_r), | |
| robustness=regime_r, | |
| ) if "nova-pro" in llm_agents else None | |
| rebalancer = Rebalancer( | |
| name="Kimi-K2.5", role="rebalancer", | |
| llm=llm_agents["Kimi-K2.5"], | |
| tier=gate.evaluate(rebal_r), | |
| robustness=rebal_r, | |
| ) if "Kimi-K2.5" in llm_agents else None | |
| yield_optimizer = YieldOptimizer( | |
| name="DeepSeek-V3.2", role="yield_optimizer", | |
| llm=llm_agents["DeepSeek-V3.2"], | |
| tier=gate.evaluate(yield_r), | |
| robustness=yield_r, | |
| ) if "DeepSeek-V3.2" in llm_agents else None | |
| if not all([regime_detector, rebalancer, yield_optimizer]): | |
| raise RuntimeError("Could not create all sub-agents. Check AWS credentials.") | |
| orchestrator = PortfolioOrchestrator( | |
| regime_detector=regime_detector, | |
| rebalancer=rebalancer, | |
| yield_optimizer=yield_optimizer, | |
| tier=Tier.T4, # Orchestrator has highest tier | |
| ) | |
| # MiniMax-M2.5 as adversary β uses its real (low) robustness scores | |
| minimax_r = agent_scores["MiniMax-M2.5"] | |
| minimax_tier = gate.evaluate(minimax_r) | |
| adversary = AdversarialAgent(tier=minimax_tier, robustness=minimax_r) | |
| return orchestrator, adversary | |
| def run_demo(rounds: int = 2, interval: int = 5): | |
| """Run the full portfolio management demo with adversary attacks.""" | |
| logging.basicConfig(level=logging.INFO, format="%(message)s") | |
| print("=" * 65) | |
| print(" CGAE Adaptive Portfolio Manager β Arc Γ Circle (RFB 04)") | |
| print("=" * 65) | |
| orchestrator, adversary = create_portfolio_system() | |
| # Print agent roster | |
| print(f"\n{'β' * 65}") | |
| print(" AGENT ROSTER") | |
| print(f"{'β' * 65}") | |
| agents = [ | |
| ("Orchestrator", "coordinator", Tier.T4), | |
| (orchestrator.regime_detector.name, "regime_detector", orchestrator.regime_detector.tier), | |
| (orchestrator.rebalancer.name, "rebalancer", orchestrator.rebalancer.tier), | |
| (orchestrator.yield_optimizer.name, "yield_optimizer", orchestrator.yield_optimizer.tier), | |
| ("adversary", "adversarial", adversary.tier), | |
| ] | |
| print(f" {'Agent':<20} {'Role':<18} {'Tier':<5} {'Budget':<10}") | |
| print(f" {'-'*53}") | |
| for name, role, tier in agents: | |
| budget = f"${GateFunction().budget_ceiling(tier)}" | |
| print(f" {name:<20} {role:<18} T{tier.value:<4} {budget}") | |
| # Run cycles | |
| for i in range(rounds): | |
| print(f"\n{'β' * 65}") | |
| print(f" CYCLE {i+1}/{rounds}") | |
| print(f"{'β' * 65}") | |
| # Portfolio management | |
| print(f"\n π Portfolio Management") | |
| print(f" {'β' * 40}") | |
| market = fetch_market_data() | |
| result = orchestrator.run_cycle(market) | |
| # Adversary attacks | |
| print(f"\n π΄ Adversary Attacks") | |
| print(f" {'β' * 40}") | |
| attacks = adversary.run_all_attacks() | |
| for attack in attacks: | |
| status = "β BLOCKED" if attack.blocked else "β οΈ PASSED" | |
| print(f" {status}: {attack.attack_type.value}") | |
| print(f" ββ {attack.description}") | |
| if i < rounds - 1: | |
| time.sleep(interval) | |
| # Final summary | |
| print(f"\n{'β' * 65}") | |
| print(" FINAL STATE") | |
| print(f"{'β' * 65}") | |
| ps = orchestrator.summary() | |
| print(f"\n Portfolio: ${ps['aum']:.2f} AUM | Regime: {ps['regime']}") | |
| print(f" Allocation: ETH={ps['allocation']['eth']:.0f}% BTC={ps['allocation']['btc']:.0f}% " | |
| f"USDC={ps['allocation']['usdc']:.0f}% USYC={ps['allocation']['usyc']:.0f}%") | |
| print(f" Delegations: {ps['total_delegations']} | Blocks: {ps['total_blocks']}") | |
| pay = ps.get("payments", {}) | |
| if pay: | |
| print(f"\n πΈ Nanopayments (x402 via Gateway):") | |
| print(f" Spent: ${pay.get('spent', 0):.4f} / ${pay.get('budget_ceiling', 0)} ceiling") | |
| print(f" Payments: {pay.get('payments_made', 0)} made, {pay.get('payments_blocked', 0)} blocked") | |
| adv = adversary.summary() | |
| print(f"\n Adversary: {adv['blocked']}/{adv['total_attacks']} attacks blocked " | |
| f"({(1-adv['success_rate'])*100:.0f}% defense rate)") | |
| print(f" Theorems enforced: {', '.join(set(a['theorem'][:20]+'...' for a in adv['attacks']))}") | |
| return {"portfolio": ps, "adversary": adv} | |
| if __name__ == "__main__": | |
| run_demo() | |