| # Recursive Implementation Example | |
| This document provides a detailed example of how the recursive cognitive architecture works in Multi-Agent Debate. We'll walk through the complete lifecycle of a market decision, from data ingestion to trade execution, highlighting the recursive patterns and interpretability mechanisms at each stage. | |
| ## Overview | |
| <div align="center"> | |
| <img src="assets/images/recursive_flow_detailed.png" alt="Recursive Flow Detailed" width="800"/> | |
| </div> | |
| In this example, we'll follow a complete decision cycle focused on analyzing Tesla (TSLA) stock, showing how multiple philosophical agents evaluate the same data through different lenses, form consensus, and generate a final decision with full attribution. | |
| ## 1. Data Ingestion | |
| The process begins with market data ingestion from Yahoo Finance: | |
| ```python | |
| from multi_agent_debate.market.environment import MarketEnvironment | |
| # Initialize market environment | |
| market = MarketEnvironment(data_source="yahoo", tickers=["TSLA"]) | |
| # Get current market data | |
| market_data = market.get_current_market_data() | |
| ``` | |
| The market data includes: | |
| - Price history | |
| - Volume data | |
| - Fundamental metrics | |
| - Recent news sentiment | |
| - Technical indicators | |
| ## 2. Agent-Specific Processing | |
| Each philosophical agent processes this data through its unique cognitive lens. Let's look at three agents: | |
| ### Graham (Value) Agent | |
| ```python | |
| # Graham Agent processing | |
| graham_agent = GrahamAgent(reasoning_depth=3) | |
| graham_processed = graham_agent.process_market_data(market_data) | |
| ``` | |
| The Graham agent focuses on intrinsic value calculation: | |
| ```python | |
| # Internal implementation of Graham's intrinsic value calculation | |
| def _calculate_intrinsic_value(self, fundamentals, ticker_data): | |
| eps = fundamentals.get('eps', 0) | |
| book_value = fundamentals.get('book_value_per_share', 0) | |
| growth_rate = fundamentals.get('growth_rate', 0) | |
| # Graham's formula: IV = EPS * (8.5 + 2g) * 4.4 / Y | |
| bond_yield = ticker_data.get('economic_indicators', {}).get('aaa_bond_yield', 0.045) | |
| bond_factor = 4.4 / max(bond_yield, 0.01) | |
| growth_adjusted_pe = 8.5 + (2 * growth_rate) | |
| earnings_value = eps * growth_adjusted_pe * bond_factor if eps > 0 else 0 | |
| # Calculate book value with margin | |
| book_value_margin = book_value * 1.5 | |
| # Use the lower of the two values for conservatism | |
| if earnings_value > 0 and book_value_margin > 0: | |
| intrinsic_value = min(earnings_value, book_value_margin) | |
| else: | |
| intrinsic_value = earnings_value if earnings_value > 0 else book_value_margin | |
| return max(intrinsic_value, 0) | |
| ``` | |
| The agent calculates a margin of safety: | |
| ``` | |
| Ticker: TSLA | |
| Current Price: $242.15 | |
| Intrinsic Value: $180.32 | |
| Margin of Safety: -34.3% (negative margin indicates overvaluation) | |
| Analysis: TSLA appears overvalued compared to traditional value metrics. | |
| Recommendation: SELL | |
| Confidence: 0.78 | |
| ``` | |
| ### Wood (Innovation) Agent | |
| ```python | |
| # Wood Agent processing | |
| wood_agent = WoodAgent(reasoning_depth=4) | |
| wood_processed = wood_agent.process_market_data(market_data) | |
| ``` | |
| The Wood agent focuses on disruptive innovation and growth potential: | |
| ```python | |
| # Internal implementation of growth potential analysis | |
| def _analyze_growth_potential(self, ticker_data, market_context): | |
| # Analyze innovation factors | |
| innovation_score = self._calculate_innovation_score(ticker_data) | |
| # Analyze addressable market | |
| tam = self._calculate_total_addressable_market(ticker_data, market_context) | |
| # Project future growth | |
| growth_projection = self._project_exponential_growth( | |
| ticker_data, innovation_score, tam | |
| ) | |
| return { | |
| "innovation_score": innovation_score, | |
| "total_addressable_market": tam, | |
| "growth_projection": growth_projection, | |
| } | |
| ``` | |
| The agent's analysis shows: | |
| ``` | |
| Ticker: TSLA | |
| Innovation Score: 0.87 | |
| Total Addressable Market: $4.2T | |
| 5-Year CAGR Projection: 28.3% | |
| Analysis: TSLA is well-positioned in multiple disruptive fields including EVs, energy storage, AI, and robotics. | |
| Recommendation: BUY | |
| Confidence: 0.82 | |
| ``` | |
| ### Dalio (Macro) Agent | |
| ```python | |
| # Dalio Agent processing | |
| dalio_agent = DalioAgent(reasoning_depth=3) | |
| dalio_processed = dalio_agent.process_market_data(market_data) | |
| ``` | |
| The Dalio agent examines macroeconomic factors: | |
| ```python | |
| # Internal implementation of macroeconomic analysis | |
| def _analyze_macro_environment(self, ticker_data, economic_indicators): | |
| # Analyze interest rate impact | |
| interest_impact = self._calculate_interest_sensitivity(ticker_data, economic_indicators) | |
| # Analyze inflation impact | |
| inflation_impact = self._calculate_inflation_impact(ticker_data, economic_indicators) | |
| # Analyze growth cycle position | |
| cycle_position = self._determine_economic_cycle_position(economic_indicators) | |
| # Assess geopolitical risks | |
| geopolitical_risk = self._assess_geopolitical_risk(economic_indicators) | |
| return { | |
| "interest_impact": interest_impact, | |
| "inflation_impact": inflation_impact, | |
| "cycle_position": cycle_position, | |
| "geopolitical_risk": geopolitical_risk, | |
| } | |
| ``` | |
| The agent's analysis shows: | |
| ``` | |
| Ticker: TSLA | |
| Interest Rate Sensitivity: -0.65 (high negative sensitivity) | |
| Inflation Impact: -0.32 (moderate negative impact) | |
| Economic Cycle Position: Late Expansion | |
| Analysis: TSLA will face headwinds from high interest rates and potential economic slowdown. | |
| Recommendation: HOLD | |
| Confidence: 0.65 | |
| ``` | |
| ## 3. Reasoning Graph Execution | |
| Each agent's reasoning process is executed via a LangGraph reasoning structure. Here's a simplified view of the Wood agent's reasoning graph: | |
| ```python | |
| def _configure_reasoning_graph(self) -> None: | |
| """Configure the reasoning graph for disruptive innovation analysis.""" | |
| # Add custom reasoning nodes | |
| self.reasoning_graph.add_node( | |
| "innovation_analysis", | |
| self._innovation_analysis | |
| ) | |
| self.reasoning_graph.add_node( | |
| "growth_projection", | |
| self._growth_projection | |
| ) | |
| self.reasoning_graph.add_node( | |
| "competition_analysis", | |
| self._competition_analysis | |
| ) | |
| self.reasoning_graph.add_node( | |
| "valuation_adjustment", | |
| self._valuation_adjustment | |
| ) | |
| # Configure reasoning flow | |
| self.reasoning_graph.set_entry_point("innovation_analysis") | |
| self.reasoning_graph.add_edge("innovation_analysis", "growth_projection") | |
| self.reasoning_graph.add_edge("growth_projection", "competition_analysis") | |
| self.reasoning_graph.add_edge("competition_analysis", "valuation_adjustment") | |
| ``` | |
| Each reasoning node executes and passes state to the next node, building up a complete reasoning trace: | |
| ``` | |
| Step 1: Innovation Analysis | |
| - Assessed disruptive potential in key markets | |
| - Analyzed R&D pipeline and technological moats | |
| - Identified 4 significant innovation vectors | |
| Step 2: Growth Projection | |
| - Projected TAM expansion in core markets | |
| - Calculated penetration rates and growth curves | |
| - Estimated revenue CAGR of 28.3% over 5 years | |
| Step 3: Competition Analysis | |
| - Assessed competitive positioning in EV market | |
| - Analyzed first-mover advantages in energy storage | |
| - Identified emerging threats in autonomous driving | |
| Step 4: Valuation Adjustment | |
| - Applied growth-adjusted valuation metrics | |
| - Discounted future cash flows with risk adjustment | |
| - Compared valuation to traditional metrics | |
| ``` | |
| ## 4. Signal Generation | |
| Each agent generates investment signals based on its reasoning: | |
| ```python | |
| # Generate signals from each agent | |
| graham_signals = graham_agent.generate_signals(graham_processed) | |
| wood_signals = wood_agent.generate_signals(wood_processed) | |
| dalio_signals = dalio_agent.generate_signals(dalio_processed) | |
| ``` | |
| Each signal includes: | |
| - Action recommendation (buy/sell/hold) | |
| - Confidence level | |
| - Quantity recommendation | |
| - Complete reasoning chain | |
| - Value basis (philosophical foundation) | |
| - Attribution trace (causal links to evidence) | |
| Example of Wood agent's signal: | |
| ```json | |
| { | |
| "ticker": "TSLA", | |
| "action": "buy", | |
| "confidence": 0.82, | |
| "quantity": 41, | |
| "reasoning": "Tesla shows strong innovation potential across multiple verticals including EVs, energy storage, AI, and robotics. Their R&D pipeline demonstrates continued technological leadership with high growth potential in the coming decade.", | |
| "intent": "Capitalize on long-term disruptive innovation growth", | |
| "value_basis": "Disruptive innovation creates exponential growth and market expansion that traditional metrics fail to capture", | |
| "attribution_trace": { | |
| "innovation_score": 0.35, | |
| "growth_projection": 0.25, | |
| "competition_analysis": 0.20, | |
| "valuation_adjustment": 0.20 | |
| }, | |
| "drift_signature": { | |
| "interest_rates": -0.05, | |
| "regulation": -0.03, | |
| "competition": -0.02 | |
| } | |
| } | |
| ``` | |
| ## 5. Meta-Agent Arbitration | |
| The portfolio meta-agent receives signals from all philosophical agents: | |
| ```python | |
| # Create portfolio manager (meta-agent) | |
| portfolio = PortfolioManager( | |
| agents=[graham_agent, wood_agent, dalio_agent], | |
| arbitration_depth=2, | |
| show_trace=True | |
| ) | |
| # Process market data through meta-agent | |
| meta_result = portfolio.process_market_data(market_data) | |
| ``` | |
| ### Consensus Formation | |
| The meta-agent first attempts to find consensus on non-conflicting signals: | |
| ```python | |
| def _consensus_formation(self, state) -> Dict[str, Any]: | |
| """Form consensus from agent signals.""" | |
| # Extract signals by ticker | |
| ticker_signals = state.context.get("ticker_signals", {}) | |
| # Form consensus for each ticker | |
| consensus_decisions = [] | |
| for ticker, signals in ticker_signals.items(): | |
| # Collect buy/sell/hold signals | |
| buy_signals = [] | |
| sell_signals = [] | |
| hold_signals = [] | |
| for item in signals: | |
| signal = item.get("signal", {}) | |
| action = signal.action.lower() | |
| if action == "buy": | |
| buy_signals.append((item, signal)) | |
| elif action == "sell": | |
| sell_signals.append((item, signal)) | |
| elif action == "hold": | |
| hold_signals.append((item, signal)) | |
| # Skip if conflicting signals (handle in conflict resolution) | |
| if (buy_signals and sell_signals) or (not buy_signals and not sell_signals and not hold_signals): | |
| continue | |
| # Form consensus for non-conflicting signals | |
| if buy_signals: | |
| # Form buy consensus | |
| consensus = self._form_action_consensus(ticker, "buy", buy_signals) | |
| if consensus: | |
| consensus_decisions.append(consensus) | |
| elif sell_signals: | |
| # Form sell consensus | |
| consensus = self._form_action_consensus(ticker, "sell", sell_signals) | |
| if consensus: | |
| consensus_decisions.append(consensus) | |
| return { | |
| "context": { | |
| **state.context, | |
| "consensus_decisions": consensus_decisions, | |
| "consensus_tickers": [decision.get("ticker") for decision in consensus_decisions], | |
| }, | |
| "output": { | |
| "consensus_decisions": consensus_decisions, | |
| } | |
| } | |
| ``` | |
| ### Conflict Resolution | |
| For TSLA, we have a conflict: Graham (SELL) vs. Wood (BUY) vs. Dalio (HOLD). The meta-agent resolves this conflict: | |
| ```python | |
| def _resolve_ticker_conflict(self, ticker: str, action_signals: Dict[str, List[Tuple[Dict[str, Any], Any]]]) -> Optional[Dict[str, Any]]: | |
| """Resolve conflict for a specific ticker.""" | |
| # Calculate total weight for each action | |
| action_weights = {} | |
| action_confidences = {} | |
| for action, signals in action_signals.items(): | |
| total_weight = 0.0 | |
| weighted_confidence = for action, signals in action_signals.items(): | |
| total_weight = 0.0 | |
| weighted_confidence = 0.0 | |
| for item, signal in signals: | |
| agent_id = item.get("agent_id", "") | |
| # Skip if missing agent ID | |
| if not agent_id: | |
| continue | |
| # Get agent weight | |
| agent_weight = self.agent_weights.get(agent_id, 0) | |
| # Add to weighted confidence | |
| weighted_confidence += signal.confidence * agent_weight | |
| total_weight += agent_weight | |
| # Store action weight and confidence | |
| if total_weight > 0: | |
| action_weights[action] = total_weight | |
| action_confidences[action] = weighted_confidence / total_weight | |
| # Choose action with highest weight | |
| if not action_weights: | |
| return None | |
| best_action = max(action_weights.items(), key=lambda x: x[1])[0] | |
| # Check confidence threshold | |
| if action_confidences.get(best_action, 0) < self.consensus_threshold: | |
| return None | |
| # Get signals for best action | |
| best_signals = action_signals.get(best_action, []) | |
| # Form consensus for best action | |
| return self._form_action_consensus(ticker, best_action, best_signals) | |
| ``` | |
| In our case, after attributing current agent weights (based on historical performance): | |
| - Graham agent: 0.25 (weight) × 0.78 (confidence) = 0.195 (weighted confidence) | |
| - Wood agent: 0.40 (weight) × 0.82 (confidence) = 0.328 (weighted confidence) | |
| - Dalio agent: 0.35 (weight) × 0.65 (confidence) = 0.228 (weighted confidence) | |
| The Wood agent's BUY signal has the highest weighted confidence, so the meta-agent forms consensus around it. | |
| ### Position Sizing | |
| The meta-agent determines position size based on confidence and attribution: | |
| ```python | |
| def _calculate_position_size(self, ticker: str, action: str, confidence: float, | |
| attribution: Dict[str, float], portfolio_value: float) -> float: | |
| """Calculate position size based on confidence and attribution.""" | |
| # Base position size as percentage of portfolio | |
| base_size = self.min_position_size + (confidence * (self.max_position_size - self.min_position_size)) | |
| # Calculate attribution-weighted size | |
| if attribution: | |
| # Calculate agent performance scores | |
| performance_scores = {} | |
| for agent_id, weight in attribution.items(): | |
| # Find agent | |
| agent = None | |
| for a in self.agents: | |
| if a.id == agent_id: | |
| agent = a | |
| break | |
| if agent: | |
| # Use consistency score as proxy for performance | |
| performance_score = agent.state.consistency_score | |
| performance_scores[agent_id] = performance_score | |
| # Calculate weighted performance score | |
| weighted_score = 0 | |
| total_weight = 0 | |
| for agent_id, weight in attribution.items(): | |
| if agent_id in performance_scores: | |
| weighted_score += performance_scores[agent_id] * weight | |
| total_weight += weight | |
| # Adjust base size by performance | |
| if total_weight > 0: | |
| performance_factor = weighted_score / total_weight | |
| base_size *= (0.5 + (0.5 * performance_factor)) | |
| # Calculate currency amount | |
| target_size = portfolio_value * base_size | |
| return target_size | |
| ``` | |
| For TSLA: | |
| - Base position size: 0.01 + (0.82 × (0.20 - 0.01)) = 0.165 (16.5% of portfolio) | |
| - Adjusted for agent performance: 16.5% × 1.1 = 18.2% of portfolio | |
| - For a $1,000,000 portfolio: $182,000 position size | |
| - At current price of $242.15: 751 shares | |
| ### Meta Reflection | |
| The meta-agent performs a final reflection on its decision process: | |
| ```python | |
| def _meta_reflection(self, state) -> Dict[str, Any]: | |
| """Perform meta-reflection on decision process.""" | |
| # Extract decisions | |
| sized_decisions = state.context.get("sized_decisions", []) | |
| # Update meta state with arbitration record | |
| arbitration_record = { | |
| "id": str(uuid.uuid4()), | |
| "decisions": sized_decisions, | |
| "timestamp": datetime.datetime.now().isoformat(), | |
| } | |
| self.meta_state["arbitration_history"].append(arbitration_record) | |
| # Update agent weights based on performance | |
| self._update_agent_weights() | |
| # Calculate meta-confidence | |
| meta_confidence = sum(decision.get("confidence", 0) for decision in sized_decisions) / len(sized_decisions) if sized_decisions else 0.5 | |
| # Return final output | |
| return { | |
| "output": { | |
| "consensus_decisions": sized_decisions, | |
| "meta_confidence": meta_confidence, | |
| "agent_weights": self.agent_weights, | |
| "timestamp": datetime.datetime.now().isoformat(), | |
| }, | |
| "confidence": meta_confidence, | |
| } | |
| ``` | |
| The meta-agent final reflection includes: | |
| - Consensus tracking | |
| - Agent weight adjustment | |
| - Meta-confidence calculation | |
| - Temporal memory update | |
| ## 6. Trade Execution | |
| The final step is trade execution: | |
| ```python | |
| # Execute trades based on consensus decisions | |
| consensus_decisions = meta_result.get("meta_agent", {}).get("consensus_decisions", []) | |
| execution_results = portfolio.execute_trades(consensus_decisions) | |
| ``` | |
| The execution includes: | |
| - Position sizing | |
| - Order placement | |
| - Confirmation handling | |
| - Portfolio state update | |
| ```json | |
| { | |
| "trades": [ | |
| { | |
| "ticker": "TSLA", | |
| "action": "buy", | |
| "quantity": 751, | |
| "price": 242.15, | |
| "cost": 181853.65, | |
| "timestamp": "2024-04-17T14:23:45.123456" | |
| } | |
| ], | |
| "errors": [], | |
| "portfolio_update": { | |
| "timestamp": "2024-04-17T14:23:45.654321", | |
| "portfolio_value": 1000000.00, | |
| "cash": 818146.35, | |
| "positions": { | |
| "TSLA": { | |
| "ticker": "TSLA", | |
| "quantity": 751, | |
| "entry_price": 242.15, | |
| "current_price": 242.15, | |
| "market_value": 181853.65, | |
| "allocation": 0.182, | |
| "unrealized_gain": 0.0, | |
| "entry_date": "2024-04-17T14:23:45.123456" | |
| } | |
| }, | |
| "returns": { | |
| "total_return": 0.0, | |
| "daily_return": 0.0 | |
| }, | |
| "allocation": { | |
| "cash": 0.818, | |
| "TSLA": 0.182 | |
| } | |
| } | |
| } | |
| ``` | |
| ## 7. Attribution Tracing | |
| Throughout this process, complete attribution tracing is maintained: | |
| ```python | |
| # Generate attribution report | |
| attribution_report = portfolio.tracer.generate_attribution_report(meta_result.get("meta_agent", {}).get("consensus_decisions", [])) | |
| ``` | |
| The attribution report shows the complete decision provenance: | |
| ```json | |
| { | |
| "agent_name": "PortfolioMetaAgent", | |
| "timestamp": "2024-04-17T14:23:46.123456", | |
| "signals": 1, | |
| "attribution_summary": { | |
| "Wood": 0.45, | |
| "Dalio": 0.35, | |
| "Graham": 0.20 | |
| }, | |
| "confidence_summary": { | |
| "mean": 0.82, | |
| "median": 0.82, | |
| "min": 0.82, | |
| "max": 0.82 | |
| }, | |
| "top_factors": [ | |
| { | |
| "source": "innovation_score", | |
| "weight": 0.35 | |
| }, | |
| { | |
| "source": "growth_projection", | |
| "weight": 0.25 | |
| }, | |
| { | |
| "source": "economic_cycle_position", | |
| "weight": 0.15 | |
| }, | |
| { | |
| "source": "competition_analysis", | |
| "weight": 0.10 | |
| }, | |
| { | |
| "source": "intrinsic_value_calculation", | |
| "weight": 0.10 | |
| } | |
| ], | |
| "shell_patterns": [ | |
| { | |
| "pattern": "v07 CIRCUIT-FRAGMENT", | |
| "count": 1, | |
| "frequency": 1.0 | |
| } | |
| ] | |
| } | |
| ``` | |
| ## 8. Visualization | |
| The system provides multiple visualization tools for interpretability: | |
| ### Consensus Graph | |
| ```python | |
| # Generate consensus graph | |
| consensus_graph = portfolio.visualize_consensus_graph() | |
| ``` | |
| The consensus graph shows the flow of influence between agents and decisions: | |
| ```json | |
| { | |
| "nodes": [ | |
| { | |
| "id": "meta", | |
| "label": "Portfolio Meta-Agent", | |
| "type": "meta", | |
| "size": 20 | |
| }, | |
| { | |
| "id": "agent-1", | |
| "label": "Graham Agent", | |
| "type": "agent", | |
| "philosophy": "Value investing focused on margin of safety", | |
| "size": 15, | |
| "weight": 0.20 | |
| }, | |
| { | |
| "id": "agent-2", | |
| "label": "Wood Agent", | |
| "type": "agent", | |
| "philosophy": "Disruptive innovation investing", | |
| "size": 15, | |
| "weight": 0.45 | |
| }, | |
| { | |
| "id": "agent-3", | |
| "label": "Dalio Agent", | |
| "type": "agent", | |
| "philosophy": "Macroeconomic-based investing", | |
| "size": 15, | |
| "weight": 0.35 | |
| }, | |
| { | |
| "id": "position-TSLA", | |
| "label": "TSLA", | |
| "type": "position", | |
| "size": 10, | |
| "value": 181853.65 | |
| } | |
| ], | |
| "links": [ | |
| { | |
| "source": "agent-1", | |
| "target": "meta", | |
| "value": 0.20, | |
| "type": "influence" | |
| }, | |
| { | |
| "source": "agent-2", | |
| "target": "meta", | |
| "value": 0.45, | |
| "type": "influence" | |
| }, | |
| { | |
| "source": "agent-3", | |
| "target": "meta", | |
| "value": 0.35, | |
| "type": "influence" | |
| }, | |
| { | |
| "source": "meta", | |
| "target": "position-TSLA", | |
| "value": 1.0, | |
| "type": "allocation" | |
| }, | |
| { | |
| "source": "agent-2", | |
| "target": "position-TSLA", | |
| "value": 0.45, | |
| "type": "attribution" | |
| }, | |
| { | |
| "source": "agent-3", | |
| "target": "position-TSLA", | |
| "value": 0.35, | |
| "type": "attribution" | |
| }, | |
| { | |
| "source": "agent-1", | |
| "target": "position-TSLA", | |
| "value": 0.20, | |
| "type": "attribution" | |
| } | |
| ], | |
| "timestamp": "2024-04-17T14:23:46.987654" | |
| } | |
| ``` | |
| ### Agent Conflict Map | |
| ```python | |
| # Generate agent conflict map | |
| conflict_map = portfolio.visualize_agent_conflict_map() | |
| ``` | |
| The conflict map visualizes the specific disagreements between agents: | |
| ```json | |
| { | |
| "nodes": [ | |
| { | |
| "id": "agent-1", | |
| "label": "Graham Agent", | |
| "type": "agent", | |
| "philosophy": "Value investing focused on margin of safety", | |
| "size": 15 | |
| }, | |
| { | |
| "id": "agent-2", | |
| "label": "Wood Agent", | |
| "type": "agent", | |
| "philosophy": "Disruptive innovation investing", | |
| "size": 15 | |
| }, | |
| { | |
| "id": "agent-3", | |
| "label": "Dalio Agent", | |
| "type": "agent", | |
| "philosophy": "Macroeconomic-based investing", | |
| "size": 15 | |
| }, | |
| { | |
| "id": "position-TSLA", | |
| "label": "TSLA", | |
| "type": "position", | |
| "size": 10 | |
| } | |
| ], | |
| "links": [ | |
| { | |
| "source": "agent-1", | |
| "target": "agent-2", | |
| "value": 1.0, | |
| "type": "conflict", | |
| "ticker": "TSLA" | |
| }, | |
| { | |
| "source": "agent-2", | |
| "target": "agent-3", | |
| "value": 1.0, | |
| "type": "conflict", | |
| "ticker": "TSLA" | |
| }, | |
| { | |
| "source": "agent-1", | |
| "target": "agent-3", | |
| "value": 1.0, | |
| "type": "conflict", | |
| "ticker": "TSLA" | |
| } | |
| ], | |
| "conflict_zones": [ | |
| { | |
| "id": "conflict-1", | |
| "ticker": "TSLA", | |
| "agents": ["agent-1", "agent-2", "agent-3"], | |
| "resolution": "resolved", | |
| "timestamp": "2024-04-17T14:23:44.567890" | |
| } | |
| ], | |
| "timestamp": "2024-04-17T14:23:47.654321" | |
| } | |
| ``` | |
| ### Shell Failure Map | |
| ```python | |
| # Create shell diagnostics | |
| shell_diagnostics = ShellDiagnostics( | |
| agent_id="portfolio", | |
| agent_name="Portfolio", | |
| tracing_tools=TracingTools( | |
| agent_id="portfolio", | |
| agent_name="Portfolio", | |
| tracing_mode=TracingMode.DETAILED, | |
| ) | |
| ) | |
| # Create shell failure map | |
| failure_map = ShellFailureMap() | |
| # Analyze each agent's state for shell failures | |
| for agent in [graham_agent, wood_agent, dalio_agent]: | |
| agent_state = agent.get_state_report() | |
| # Simulate shell failures based on agent state | |
| for shell_pattern in [ShellPattern.CIRCUIT_FRAGMENT, ShellPattern.META_FAILURE]: | |
| failure_data = shell_diagnostics.simulate_shell_failure( | |
| shell_pattern=shell_pattern, | |
| context=agent_state, | |
| ) | |
| # Add to failure map | |
| failure_map.add_failure( | |
| agent_id=agent.id, | |
| agent_name=agent.name, | |
| shell_pattern=shell_pattern, | |
| failure_data=failure_data, | |
| ) | |
| # Generate visualization | |
| shell_failure_viz = failure_map.generate_failure_map_visualization() | |
| ``` | |
| The shell failure map visualizes interpretability patterns detected in the agents: | |
| ```json | |
| { | |
| "nodes": [ | |
| { | |
| "id": "agent-1", | |
| "label": "Graham Agent", | |
| "type": "agent", | |
| "size": 15, | |
| "failure_count": 1 | |
| }, | |
| { | |
| "id": "agent-2", | |
| "label": "Wood Agent", | |
| "type": "agent", | |
| "size": 15, | |
| "failure_count": 2 | |
| }, | |
| { | |
| "id": "agent-3", | |
| "label": "Dalio Agent", | |
| "type": "agent", | |
| "size": 15, | |
| "failure_count": 1 | |
| }, | |
| { | |
| "id": "v07 CIRCUIT-FRAGMENT", | |
| "label": "CIRCUIT-FRAGMENT", | |
| "type": "pattern", | |
| "size": 10, | |
| "failure_count": 3 | |
| }, | |
| { | |
| "id": "v10 META-FAILURE", | |
| "label": "META-FAILURE", | |
| "type": "pattern", | |
| "size": 10, | |
| "failure_count": 1 | |
| }, | |
| { | |
| "id": "failure-1", | |
| "label": "Failure 3f4a9c", | |
| "type": "failure", | |
| "size": 5, | |
| "timestamp": "2024-04-17T14:23:48.123456" | |
| }, | |
| { | |
| "id": "failure-2", | |
| "label": "Failure b7d5e2", | |
| "type": "failure", | |
| "size": 5, | |
| "timestamp": "2024-04-17T14:23:48.234567" | |
| }, | |
| { | |
| "id": "failure-3", | |
| "label": "Failure 9c6f1a", | |
| "type": "failure", | |
| "size": 5, | |
| "timestamp": "2024-04-17T14:23:48.345678" | |
| }, | |
| { | |
| "id": "failure-4", | |
| "label": "Failure 2e8d7f", | |
| "type": "failure", | |
| "size": 5, | |
| "timestamp": "2024-04-17T14:23:48.456789" | |
| } | |
| ], | |
| "links": [ | |
| { | |
| "source": "agent-1", | |
| "target": "failure-1", | |
| "type": "agent_failure" | |
| }, | |
| { | |
| "source": "v07 CIRCUIT-FRAGMENT", | |
| "target": "failure-1", | |
| "type": "pattern_failure" | |
| }, | |
| { | |
| "source": "agent-2", | |
| "target": "failure-2", | |
| "type": "agent_failure" | |
| }, | |
| { | |
| "source": "v07 CIRCUIT-FRAGMENT", | |
| "target": "failure-2", | |
| "type": "pattern_failure" | |
| }, | |
| { | |
| "source": "agent-2", | |
| "target": "failure-3", | |
| "type": "agent_failure" | |
| }, | |
| { | |
| "source": "v10 META-FAILURE", | |
| "target": "failure-3", | |
| "type": "pattern_failure" | |
| }, | |
| { | |
| "source": "agent-3", | |
| "target": "failure-4", | |
| "type": "agent_failure" | |
| }, | |
| { | |
| "source": "v07 CIRCUIT-FRAGMENT", | |
| "target": "failure-4", | |
| "type": "pattern_failure" | |
| } | |
| ], | |
| "timestamp": "2024-04-17T14:23:49.000000" | |
| } | |
| ``` | |
| ## 9. Agent Memory & Learning | |
| After each trading cycle, agents update their internal state: | |
| ```python | |
| # Update agent states based on market feedback | |
| market_feedback = { | |
| 'portfolio_value': execution_results['portfolio_update']['portfolio_value'], | |
| 'performance': {'TSLA': 0.02}, # Example: 2% return | |
| 'decisions': consensus_decisions, | |
| 'avg_confidence': 0.82, | |
| } | |
| # Update each agent's state | |
| for agent in [graham_agent, wood_agent, dalio_agent]: | |
| agent.update_state(market_feedback) | |
| ``` | |
| Each agent processes the feedback differently based on its philosophy: | |
| ### Wood Agent Memory Update | |
| ```python | |
| def _update_beliefs(self, market_feedback: Dict[str, Any]) -> None: | |
| """Update agent's belief state based on market feedback.""" | |
| # Extract relevant signals | |
| if 'performance' in market_feedback: | |
| performance = market_feedback['performance'] | |
| # Record decision outcomes | |
| if 'decisions' in market_feedback: | |
| for decision in market_feedback['decisions']: | |
| self.state.decision_history.append({ | |
| 'decision': decision, | |
| 'outcome': performance.get(decision.get('ticker'), 0), | |
| 'timestamp': datetime.datetime.now() | |
| }) | |
| # For Wood Agent, reinforce innovation beliefs on positive outcomes | |
| if performance.get(decision.get('ticker'), 0) > 0: | |
| ticker = decision.get('ticker') | |
| # Strengthen innovation belief | |
| current_belief = self.state.belief_state.get(f"{ticker}_innovation", 0.5) | |
| self.state.belief_state[f"{ticker}_innovation"] = min(1.0, current_belief + 0.05) | |
| # Update industry trend belief | |
| industry = self._get_ticker_industry(ticker) | |
| if industry: | |
| industry_belief = self.state.belief_state.get(f"{industry}_trend", 0.5) | |
| self.state.belief_state[f"{industry}_trend"] = min(1.0, industry_belief + 0.03) | |
| # Update general belief state based on performance | |
| for ticker, perf in performance.items(): | |
| general_belief_key = f"{ticker}_general" | |
| current_belief = self.state.belief_state.get(general_belief_key, 0.5) | |
| # Wood Agent weights positive outcomes more heavily for innovative companies | |
| if self._is_innovative_company(ticker): | |
| update_weight = 0.3 # Higher weight for innovative companies | |
| else: | |
| update_weight = 0.1 # Lower weight for traditional companies | |
| # Update belief | |
| updated_belief = current_belief * (1 - update_weight) + np.tanh(perf) * update_weight | |
| self.state.belief_state[general_belief_key] = updated_belief | |
| # Track belief drift | |
| if general_belief_key in self.state.belief_state: | |
| drift = updated_belief - current_belief | |
| self.state.drift_vector[general_belief_key] = drift | |
| # Wood Agent's drift pattern analysis | |
| self._analyze_drift_pattern(ticker, drift) | |
| ``` | |
| ## 10. Command Interface | |
| Throughout the system, the symbolic command interface enables deeper introspection: | |
| ```python | |
| # Get a reflection trace from the Graham agent | |
| reflection_trace = graham_agent.execute_command( | |
| command="reflect.trace", | |
| depth=3 | |
| ) | |
| # Generate signals from alternative sources | |
| alt_signals = wood_agent.execute_command( | |
| command="fork.signal", | |
| source="beliefs" | |
| ) | |
| # Check for decision collapse | |
| collapse_check = dalio_agent.execute_command( | |
| command="collapse.detect", | |
| threshold=0.7, | |
| reason="consistency" | |
| ) | |
| # Attribute weight to a justification | |
| attribution = portfolio.execute_command( | |
| command="attribute.weight", | |
| justification="Tesla's innovation in AI and robotics represents a paradigm shift that traditional valuation metrics fail to capture." | |
| ) | |
| # Track belief drift | |
| drift_observation = wood_agent.execute_command( | |
| command="drift.observe", | |
| vector={"TSLA_innovation": 0.05, "AI_trend": 0.03, "EV_market": 0.02}, | |
| bias=0.01 | |
| ) | |
| ``` | |
| These commands form the foundation of the system's interpretability architecture, enabling detailed tracing and analysis of decision processes. | |
| ## Conclusion | |
| This example demonstrates the recursive cognitive architecture of Multi-Agent Debate in action. From market data ingestion to trade execution, the system maintains complete transparency and interpretability through: | |
| 1. Agent-specific cognitive lenses | |
| 2. Recursive reasoning graphs | |
| 3. Attribution tracing | |
| 4. Meta-agent arbitration | |
| 5. Position sizing | |
| 6. Trade execution | |
| 7. Memory and learning | |
| Each component is designed to enable deeper introspection into the decision-making process, creating a truly transparent and interpretable multi-agent market cognition system. | |
| The symbolic command interface and visualization tools provide multiple ways to understand and analyze the system's behavior, making it both effective and explainable. | |