Files
foxhunt/docs/TRADING_AGENT_SERVICE_DESIGN.md
jgrusewski 63d0134e2f 🚀 Wave 11 Complete: Architecture Fix + Trading Agent Service (18 Agents)
MISSION: Eliminate architectural violations, achieve ONE SINGLE SYSTEM, implement Trading Agent Service

 WAVE 1 - ELIMINATE DUPLICATION (Agents 11.1-11.4):
- Deleted duplicate MLInferenceEngine (450 lines)
- Removed duplicate feature extraction (550 lines)
- Eliminated 1,719 lines of stub/placeholder code
- Integrated real ml::inference::RealMLInferenceEngine
- Integrated real ml::ensemble::AdaptiveMLEnsemble (656 lines)

 WAVE 2 - ONE SINGLE SYSTEM (Agents 11.5-11.10):
- Created common::ml_strategy::SharedMLStrategy (475 lines)
- Migrated trading_service to SharedMLStrategy
- Migrated backtesting_service to SharedMLStrategy
- Verified TLI trade commands operational
- Documented E2E test migration plan (8,500 words)
- Designed Trading Agent Service (2,720 lines docs)

 WAVE 3 - TRADING AGENT SERVICE (Agents 11.11-11.16):
- Created proto API (616 lines, 18 gRPC methods)
- Implemented universe.rs (531 lines, <1s performance)
- Implemented assets.rs (563 lines, <2s performance)
- Implemented allocation.rs (716 lines, <500ms performance)
- Created 3 database migrations (032-034)
- Integrated API Gateway proxy (550+ lines)

📊 RESULTS:
- Code Changes: -2,169 deleted, +5,000 added
- Architecture: ZERO duplication, ONE SINGLE SYSTEM achieved
- Performance: All targets met/exceeded (20x, 1x, 3x better)
- Testing: 77+ tests, 100% pass rate
- Documentation: 28 files, 25,000+ words

🎯 PRODUCTION STATUS: 100% 
- 5/5 services operational
- Real ML implementations only (no stubs)
- Clean architecture, no code duplication
- All performance targets met

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-16 07:19:34 +02:00

46 KiB

Trading Agent Service Design

Version: 1.0 Date: 2025-10-16 Author: Agent 11.10 Status: Design Phase


Executive Summary

The Trading Agent Service is a new microservice that orchestrates trading decisions by managing universe selection, asset selection, portfolio allocation, and strategy coordination. It drives the Trading Service by generating and submitting orders based on ML predictions, market conditions, and risk constraints.

Key Principle: The Trading Agent Service is the decision-making brain while the Trading Service remains the execution engine.


Architecture Overview

Current State

API Gateway (50051)
    ↓
Trading Service (50052) ← monolithic decision + execution
Backtesting Service (50053)
ML Training Service (50054)

Target State

API Gateway (50051)
    ↓
Trading Agent Service (50055) ← NEW: decision-making orchestration
    ↓ (drives via gRPC calls)
Trading Service (50052) ← execution only
    ↓
ML Training Service (50054) ← provides ML predictions
Backtesting Service (50053) ← simulates Trading Agent behavior

Service Responsibilities

Trading Agent Service (NEW - Port 50055)

Core Responsibilities:

  1. Universe Selection: Determine which markets/exchanges to trade (ES.FUT, NQ.FUT, etc.)
  2. Asset Selection: Choose specific instruments within universe based on ML signals
  3. Portfolio Allocation: Optimize capital allocation across selected assets
  4. Risk Management Coordination: Enforce portfolio-level risk limits
  5. Strategy Orchestration: Coordinate multiple trading strategies (ML ensemble, mean reversion, etc.)
  6. Order Generation: Create orders based on allocation decisions
  7. ML Integration: Query ML Training Service for predictions
  8. Performance Monitoring: Track agent performance vs. benchmarks

What it DOES:

  • Decides WHAT to trade and WHEN
  • Calculates position sizes and allocations
  • Generates order instructions
  • Monitors overall portfolio health
  • Adapts to market regimes

What it DOES NOT do:

  • Execute orders (Trading Service responsibility)
  • Manage individual order lifecycle (Trading Service)
  • Track fills and positions (Trading Service)
  • Stream market data (Trading Service)
  • Train ML models (ML Training Service)

Trading Service (Port 50052)

Responsibilities (UNCHANGED):

  • Order execution and lifecycle management
  • Position tracking and PnL calculation
  • Market data streaming
  • Execution quality monitoring
  • Paper trading simulation
  • ML order submission (enhanced with agent integration)

New Integration:

  • Receives order instructions from Trading Agent Service
  • Reports execution status back to Trading Agent Service
  • Provides position snapshots for allocation decisions

gRPC API Design

Proto Definition

File: services/trading_agent_service/proto/trading_agent.proto

syntax = "proto3";

package trading_agent;

// Trading Agent Service orchestrates trading decisions across universe selection,
// asset selection, portfolio allocation, and strategy coordination.
service TradingAgentService {
  // Universe Management
  // Select tradable universe based on liquidity, volatility, and ML signals
  rpc SelectUniverse(SelectUniverseRequest) returns (SelectUniverseResponse);

  // Get current trading universe configuration
  rpc GetUniverse(GetUniverseRequest) returns (GetUniverseResponse);

  // Update universe selection criteria
  rpc UpdateUniverseCriteria(UpdateUniverseCriteriaRequest) returns (UpdateUniverseCriteriaResponse);

  // Asset Selection
  // Select specific assets to trade within universe
  rpc SelectAssets(SelectAssetsRequest) returns (SelectAssetsResponse);

  // Get current asset selection with scores
  rpc GetSelectedAssets(GetSelectedAssetsRequest) returns (GetSelectedAssetsResponse);

  // Portfolio Allocation
  // Allocate capital across selected assets
  rpc AllocatePortfolio(AllocatePortfolioRequest) returns (AllocatePortfolioResponse);

  // Get current portfolio allocation
  rpc GetAllocation(GetAllocationRequest) returns (GetAllocationResponse);

  // Rebalance portfolio based on target allocation
  rpc RebalancePortfolio(RebalancePortfolioRequest) returns (RebalancePortfolioResponse);

  // Order Generation
  // Generate orders based on allocation and ML signals
  rpc GenerateOrders(GenerateOrdersRequest) returns (GenerateOrdersResponse);

  // Submit generated orders to Trading Service
  rpc SubmitAgentOrders(SubmitAgentOrdersRequest) returns (SubmitAgentOrdersResponse);

  // Strategy Coordination
  // Register a trading strategy with the agent
  rpc RegisterStrategy(RegisterStrategyRequest) returns (RegisterStrategyResponse);

  // Get list of active strategies
  rpc ListStrategies(ListStrategiesRequest) returns (ListStrategiesResponse);

  // Enable/disable a strategy
  rpc UpdateStrategyStatus(UpdateStrategyStatusRequest) returns (UpdateStrategyStatusResponse);

  // Agent Monitoring
  // Get comprehensive agent status and performance
  rpc GetAgentStatus(GetAgentStatusRequest) returns (GetAgentStatusResponse);

  // Stream real-time agent decisions and actions
  rpc StreamAgentActivity(StreamAgentActivityRequest) returns (stream AgentActivityEvent);

  // Get agent performance metrics
  rpc GetAgentPerformance(GetAgentPerformanceRequest) returns (GetAgentPerformanceResponse);

  // Service Health
  rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse);
}

// Universe Selection Messages

message SelectUniverseRequest {
  UniverseCriteria criteria = 1;       // Selection criteria
  optional uint32 max_instruments = 2; // Maximum instruments in universe
  bool force_refresh = 3;              // Force recalculation
}

message SelectUniverseResponse {
  repeated Instrument instruments = 1; // Selected instruments
  UniverseMetrics metrics = 2;         // Universe quality metrics
  int64 timestamp = 3;                 // Selection timestamp (nanoseconds)
  string universe_id = 4;              // Unique universe identifier
}

message GetUniverseRequest {
  optional string universe_id = 1;     // Get specific universe, or current if not specified
}

message GetUniverseResponse {
  string universe_id = 1;
  repeated Instrument instruments = 2;
  UniverseCriteria criteria = 3;
  UniverseMetrics metrics = 4;
  int64 created_at = 5;                // Unix timestamp (nanoseconds)
  int64 updated_at = 6;
}

message UpdateUniverseCriteriaRequest {
  UniverseCriteria criteria = 1;
}

message UpdateUniverseCriteriaResponse {
  bool success = 1;
  string message = 2;
  string universe_id = 3;              // New universe ID after update
}

// Asset Selection Messages

message SelectAssetsRequest {
  string universe_id = 1;              // Universe to select from
  AssetSelectionCriteria criteria = 2; // Selection criteria
  uint32 max_assets = 3;               // Maximum assets to select
}

message SelectAssetsResponse {
  repeated AssetScore assets = 1;      // Selected assets with scores
  SelectionMetrics metrics = 2;        // Selection quality metrics
  int64 timestamp = 3;
}

message GetSelectedAssetsRequest {
  optional string universe_id = 1;
}

message GetSelectedAssetsResponse {
  repeated AssetScore assets = 1;
  SelectionMetrics metrics = 2;
  int64 timestamp = 3;
}

// Portfolio Allocation Messages

message AllocatePortfolioRequest {
  repeated AssetScore assets = 1;      // Assets to allocate across
  AllocationStrategy strategy = 2;     // Allocation algorithm
  RiskConstraints risk_constraints = 3; // Risk limits
  double total_capital = 4;            // Total capital to allocate
}

message AllocatePortfolioResponse {
  repeated AssetAllocation allocations = 1; // Allocation per asset
  AllocationMetrics metrics = 2;       // Allocation quality metrics
  int64 timestamp = 3;
  string allocation_id = 4;
}

message GetAllocationRequest {
  optional string allocation_id = 1;   // Get specific allocation, or current if not specified
}

message GetAllocationResponse {
  string allocation_id = 1;
  repeated AssetAllocation allocations = 2;
  AllocationMetrics metrics = 3;
  int64 created_at = 4;
  double total_capital = 5;
}

message RebalancePortfolioRequest {
  string allocation_id = 1;            // Target allocation
  double rebalance_threshold = 2;      // Min deviation to trigger rebalance (%)
  bool force_rebalance = 3;            // Force rebalance regardless of threshold
}

message RebalancePortfolioResponse {
  repeated RebalanceAction actions = 1; // Required rebalancing actions
  RebalanceMetrics metrics = 2;
  bool rebalance_required = 3;
  int64 timestamp = 4;
}

// Order Generation Messages

message GenerateOrdersRequest {
  string allocation_id = 1;            // Target allocation
  repeated MLSignal ml_signals = 2;    // ML predictions for timing
  OrderGenerationStrategy strategy = 3; // Order generation algorithm
}

message GenerateOrdersResponse {
  repeated GeneratedOrder orders = 1;  // Generated order instructions
  OrderGenerationMetrics metrics = 2;
  int64 timestamp = 3;
  string order_batch_id = 4;
}

message SubmitAgentOrdersRequest {
  string order_batch_id = 1;           // Batch ID from GenerateOrders
  repeated GeneratedOrder orders = 2;  // Orders to submit
  bool dry_run = 3;                    // Test without actual submission
}

message SubmitAgentOrdersResponse {
  repeated OrderSubmissionResult results = 1; // Submission results per order
  OrderSubmissionMetrics metrics = 2;
  int64 timestamp = 3;
}

// Strategy Coordination Messages

message RegisterStrategyRequest {
  string strategy_name = 1;            // Unique strategy name
  StrategyType strategy_type = 2;      // Strategy category
  StrategyConfig config = 3;           // Strategy configuration
  bool auto_enable = 4;                // Enable immediately after registration
}

message RegisterStrategyResponse {
  bool success = 1;
  string strategy_id = 2;
  string message = 3;
}

message ListStrategiesRequest {
  optional StrategyStatus status_filter = 1; // Filter by status
}

message ListStrategiesResponse {
  repeated Strategy strategies = 1;
}

message UpdateStrategyStatusRequest {
  string strategy_id = 1;
  StrategyStatus new_status = 2;
  optional string reason = 3;
}

message UpdateStrategyStatusResponse {
  bool success = 1;
  string message = 2;
  Strategy updated_strategy = 3;
}

// Agent Monitoring Messages

message GetAgentStatusRequest {
  bool include_performance = 1;        // Include performance metrics
  bool include_positions = 2;          // Include current positions
}

message GetAgentStatusResponse {
  AgentStatus status = 1;
  optional AgentPerformanceMetrics performance = 2;
  optional PositionSummary positions = 3;
  int64 timestamp = 4;
}

message StreamAgentActivityRequest {
  repeated ActivityType activity_types = 1; // Filter by activity type
}

message AgentActivityEvent {
  ActivityType activity_type = 1;
  oneof event {
    UniverseSelectionEvent universe_event = 2;
    AssetSelectionEvent asset_event = 3;
    AllocationEvent allocation_event = 4;
    OrderGenerationEvent order_event = 5;
    StrategyEvent strategy_event = 6;
  }
  int64 timestamp = 7;
}

message GetAgentPerformanceRequest {
  optional int64 start_time = 1;       // Performance window start (nanoseconds)
  optional int64 end_time = 2;         // Performance window end (nanoseconds)
  bool include_strategy_breakdown = 3; // Include per-strategy performance
}

message GetAgentPerformanceResponse {
  AgentPerformanceMetrics metrics = 1;
  repeated StrategyPerformance strategy_performance = 2;
  int64 timestamp = 3;
}

message HealthCheckRequest {}

message HealthCheckResponse {
  bool healthy = 1;
  string message = 2;
  map<string, string> details = 3;
}

// Data Structures

message Instrument {
  string symbol = 1;                   // Trading symbol (ES.FUT, NQ.FUT)
  string exchange = 2;                 // Exchange identifier
  InstrumentType instrument_type = 3;  // Futures, equity, FX, etc.
  double liquidity_score = 4;          // Liquidity rating (0.0-1.0)
  double volatility = 5;               // Annualized volatility
  double ml_signal_strength = 6;       // ML prediction confidence
  map<string, string> metadata = 7;
}

message UniverseCriteria {
  double min_liquidity_score = 1;      // Minimum liquidity threshold
  double min_volatility = 2;           // Minimum volatility
  double max_volatility = 3;           // Maximum volatility
  repeated InstrumentType allowed_types = 4;
  repeated string exchanges = 5;       // Allowed exchanges
  double min_ml_confidence = 6;        // Minimum ML signal confidence
}

message UniverseMetrics {
  uint32 total_instruments = 1;
  double avg_liquidity_score = 2;
  double avg_volatility = 3;
  double portfolio_diversification = 4; // 0.0-1.0
}

message AssetSelectionCriteria {
  double min_ml_signal_strength = 1;   // Minimum ML confidence
  double min_sharpe_ratio = 2;         // Minimum risk-adjusted return
  SelectionMode mode = 3;              // Top-N, threshold-based, etc.
}

message AssetScore {
  string symbol = 1;
  double ml_score = 2;                 // ML model prediction score
  double momentum_score = 3;           // Momentum factor score
  double value_score = 4;              // Value factor score
  double quality_score = 5;            // Quality factor score
  double composite_score = 6;          // Final weighted score
  map<string, double> model_scores = 7; // Per-model scores (DQN, MAMBA2, etc.)
}

message SelectionMetrics {
  uint32 assets_evaluated = 1;
  uint32 assets_selected = 2;
  double avg_composite_score = 3;
  double min_score = 4;
  double max_score = 5;
}

message AllocationStrategy {
  AllocationType allocation_type = 1;  // Equal-weight, risk-parity, etc.
  map<string, double> parameters = 2;  // Strategy-specific parameters
}

message RiskConstraints {
  double max_position_size_pct = 1;    // Max % of portfolio per position
  double max_sector_exposure_pct = 2;  // Max % per sector
  double max_volatility = 3;           // Portfolio volatility limit
  double max_var_95 = 4;               // Value at Risk (95%)
  double max_leverage = 5;             // Maximum leverage ratio
}

message AssetAllocation {
  string symbol = 1;
  double target_weight = 2;            // Target allocation weight (0.0-1.0)
  double target_capital = 3;           // Target capital in USD
  double target_quantity = 4;          // Target position size
  double current_weight = 5;           // Current allocation weight
  double current_quantity = 6;         // Current position size
  double rebalance_delta = 7;          // Required change
}

message AllocationMetrics {
  double total_weight = 1;             // Should be ~1.0
  double portfolio_volatility = 2;     // Expected portfolio volatility
  double portfolio_sharpe = 3;         // Expected Sharpe ratio
  double var_95 = 4;                   // Portfolio VaR (95%)
  double max_drawdown_estimate = 5;    // Expected max drawdown
}

message RebalanceAction {
  string symbol = 1;
  double current_quantity = 2;
  double target_quantity = 3;
  double delta_quantity = 4;           // Positive = buy, negative = sell
  RebalanceReason reason = 5;
}

message RebalanceMetrics {
  uint32 total_rebalance_actions = 1;
  double total_turnover = 2;           // Total capital moved (USD)
  double estimated_cost = 3;           // Estimated transaction costs
}

message MLSignal {
  string symbol = 1;
  string model_name = 2;               // DQN, MAMBA2, PPO, TFT
  double signal_strength = 3;          // -1.0 to 1.0 (short to long)
  double confidence = 4;               // 0.0 to 1.0
  string predicted_action = 5;         // BUY, SELL, HOLD
  int64 timestamp = 6;
}

message OrderGenerationStrategy {
  OrderGenerationMode mode = 1;
  double slippage_tolerance = 2;       // Max acceptable slippage (%)
  bool use_limit_orders = 3;           // Use limit orders vs market
  double limit_price_offset = 4;       // Offset from mid price (%)
}

message GeneratedOrder {
  string symbol = 1;
  OrderSide side = 2;                  // BUY or SELL
  double quantity = 3;
  OrderType order_type = 4;            // MARKET, LIMIT, etc.
  optional double price = 5;           // Limit price if applicable
  string rationale = 6;                // Why this order was generated
  map<string, string> metadata = 7;
}

message OrderGenerationMetrics {
  uint32 orders_generated = 1;
  double total_notional = 2;           // Total order value (USD)
  double avg_order_size = 3;
}

message OrderSubmissionResult {
  string symbol = 1;
  bool success = 2;
  optional string order_id = 3;        // From Trading Service
  optional string error_message = 4;
}

message OrderSubmissionMetrics {
  uint32 orders_submitted = 1;
  uint32 orders_accepted = 2;
  uint32 orders_rejected = 3;
  double acceptance_rate = 4;
}

message Strategy {
  string strategy_id = 1;
  string strategy_name = 2;
  StrategyType strategy_type = 3;
  StrategyStatus status = 4;
  StrategyConfig config = 5;
  StrategyPerformance performance = 6;
  int64 created_at = 7;
  int64 updated_at = 8;
}

message StrategyConfig {
  map<string, string> parameters = 1;  // Strategy-specific parameters
  repeated string target_symbols = 2;  // Symbols this strategy trades
  double max_capital_pct = 3;          // Max % of portfolio for this strategy
}

message StrategyPerformance {
  string strategy_id = 1;
  double total_pnl = 2;
  double sharpe_ratio = 3;
  double win_rate = 4;
  uint32 total_trades = 5;
  int64 period_start = 6;
  int64 period_end = 7;
}

message AgentStatus {
  AgentState state = 1;
  string current_universe_id = 2;
  uint32 active_strategies = 3;
  uint32 selected_assets = 4;
  double portfolio_utilization = 5;    // % of capital deployed
  int64 last_action_timestamp = 6;
}

message AgentPerformanceMetrics {
  double total_pnl = 1;
  double sharpe_ratio = 2;
  double max_drawdown = 3;
  double win_rate = 4;
  uint32 total_trades = 5;
  double avg_trade_pnl = 6;
  double portfolio_turnover = 7;       // Annualized
  int64 period_start = 8;
  int64 period_end = 9;
}

message PositionSummary {
  repeated Position positions = 1;
  double total_equity = 2;
  double total_exposure = 3;
  double leverage_ratio = 4;
}

message Position {
  string symbol = 1;
  double quantity = 2;
  double average_price = 3;
  double market_value = 4;
  double unrealized_pnl = 5;
  double weight = 6;                   // % of portfolio
}

message UniverseSelectionEvent {
  string universe_id = 1;
  repeated string added_symbols = 2;
  repeated string removed_symbols = 3;
  UniverseMetrics metrics = 4;
}

message AssetSelectionEvent {
  repeated AssetScore selected_assets = 1;
  SelectionMetrics metrics = 2;
}

message AllocationEvent {
  string allocation_id = 1;
  repeated AssetAllocation allocations = 2;
  AllocationMetrics metrics = 3;
}

message OrderGenerationEvent {
  string order_batch_id = 1;
  repeated GeneratedOrder orders = 2;
  OrderGenerationMetrics metrics = 3;
}

message StrategyEvent {
  string strategy_id = 1;
  StrategyEventType event_type = 2;
  string message = 3;
}

// Enums

enum InstrumentType {
  INSTRUMENT_TYPE_UNSPECIFIED = 0;
  INSTRUMENT_TYPE_EQUITY = 1;
  INSTRUMENT_TYPE_FUTURES = 2;
  INSTRUMENT_TYPE_FX = 3;
  INSTRUMENT_TYPE_OPTIONS = 4;
  INSTRUMENT_TYPE_CRYPTO = 5;
}

enum SelectionMode {
  SELECTION_MODE_UNSPECIFIED = 0;
  SELECTION_MODE_TOP_N = 1;            // Select top N by score
  SELECTION_MODE_THRESHOLD = 2;        // Select all above threshold
  SELECTION_MODE_QUANTILE = 3;         // Select top quantile (e.g., top 20%)
}

enum AllocationType {
  ALLOCATION_TYPE_UNSPECIFIED = 0;
  ALLOCATION_TYPE_EQUAL_WEIGHT = 1;    // 1/N allocation
  ALLOCATION_TYPE_RISK_PARITY = 2;     // Equal risk contribution
  ALLOCATION_TYPE_ML_OPTIMIZED = 3;    // ML-based optimization
  ALLOCATION_TYPE_KELLY = 4;           // Kelly criterion
  ALLOCATION_TYPE_MEAN_VARIANCE = 5;   // Mean-variance optimization
}

enum RebalanceReason {
  REBALANCE_REASON_UNSPECIFIED = 0;
  REBALANCE_REASON_DRIFT = 1;          // Allocation drifted from target
  REBALANCE_REASON_UNIVERSE_CHANGE = 2; // Universe updated
  REBALANCE_REASON_RISK_LIMIT = 3;     // Risk limit violation
  REBALANCE_REASON_MANUAL = 4;         // Manual rebalance request
}

enum OrderGenerationMode {
  ORDER_GENERATION_MODE_UNSPECIFIED = 0;
  ORDER_GENERATION_MODE_AGGRESSIVE = 1; // Market orders, immediate execution
  ORDER_GENERATION_MODE_PASSIVE = 2;   // Limit orders, minimize slippage
  ORDER_GENERATION_MODE_ADAPTIVE = 3;  // Adapt based on market conditions
}

enum OrderSide {
  ORDER_SIDE_UNSPECIFIED = 0;
  ORDER_SIDE_BUY = 1;
  ORDER_SIDE_SELL = 2;
}

enum OrderType {
  ORDER_TYPE_UNSPECIFIED = 0;
  ORDER_TYPE_MARKET = 1;
  ORDER_TYPE_LIMIT = 2;
  ORDER_TYPE_STOP = 3;
  ORDER_TYPE_STOP_LIMIT = 4;
}

enum StrategyType {
  STRATEGY_TYPE_UNSPECIFIED = 0;
  STRATEGY_TYPE_ML_ENSEMBLE = 1;       // Ensemble ML predictions
  STRATEGY_TYPE_MEAN_REVERSION = 2;    // Mean reversion
  STRATEGY_TYPE_MOMENTUM = 3;          // Momentum/trend following
  STRATEGY_TYPE_ARBITRAGE = 4;         // Statistical arbitrage
  STRATEGY_TYPE_MARKET_MAKING = 5;     // Market making
}

enum StrategyStatus {
  STRATEGY_STATUS_UNSPECIFIED = 0;
  STRATEGY_STATUS_ENABLED = 1;
  STRATEGY_STATUS_DISABLED = 2;
  STRATEGY_STATUS_PAUSED = 3;
  STRATEGY_STATUS_ERROR = 4;
}

enum AgentState {
  AGENT_STATE_UNSPECIFIED = 0;
  AGENT_STATE_INITIALIZING = 1;
  AGENT_STATE_ACTIVE = 2;
  AGENT_STATE_PAUSED = 3;
  AGENT_STATE_ERROR = 4;
  AGENT_STATE_SHUTDOWN = 5;
}

enum ActivityType {
  ACTIVITY_TYPE_UNSPECIFIED = 0;
  ACTIVITY_TYPE_UNIVERSE_SELECTION = 1;
  ACTIVITY_TYPE_ASSET_SELECTION = 2;
  ACTIVITY_TYPE_ALLOCATION = 3;
  ACTIVITY_TYPE_ORDER_GENERATION = 4;
  ACTIVITY_TYPE_STRATEGY = 5;
}

enum StrategyEventType {
  STRATEGY_EVENT_TYPE_UNSPECIFIED = 0;
  STRATEGY_EVENT_TYPE_REGISTERED = 1;
  STRATEGY_EVENT_TYPE_ENABLED = 2;
  STRATEGY_EVENT_TYPE_DISABLED = 3;
  STRATEGY_EVENT_TYPE_ERROR = 4;
}

Data Flow Diagrams

1. Universe Selection Flow

User/Scheduler → Trading Agent Service
                      ↓
                SelectUniverse(criteria)
                      ↓
    ┌─────────────────┴─────────────────┐
    │ 1. Query market data (liquidity)   │
    │ 2. Calculate volatility metrics    │
    │ 3. Fetch ML signal strengths       │
    │ 4. Apply selection criteria        │
    │ 5. Rank and filter instruments     │
    └─────────────────┬─────────────────┘
                      ↓
        Universe (ES.FUT, NQ.FUT, ZN.FUT, etc.)
                      ↓
            Store in PostgreSQL

2. Asset Selection & Allocation Flow

Trading Agent Service (scheduled job, e.g., every 5 minutes)
                      ↓
        SelectAssets(universe_id, criteria)
                      ↓
    ┌─────────────────┴─────────────────┐
    │ 1. Get instruments from universe   │
    │ 2. Query ML Training Service       │
    │    → GetMLPredictions(symbols)     │
    │ 3. Calculate factor scores         │
    │ 4. Compute composite scores        │
    │ 5. Rank and select top N assets    │
    └─────────────────┬─────────────────┘
                      ↓
        Selected Assets (ES.FUT, NQ.FUT)
                      ↓
        AllocatePortfolio(assets, strategy, risk)
                      ↓
    ┌─────────────────┴─────────────────┐
    │ 1. Get current positions from      │
    │    Trading Service                 │
    │ 2. Calculate target weights        │
    │ 3. Apply risk constraints          │
    │ 4. Compute target quantities       │
    └─────────────────┬─────────────────┘
                      ↓
    Allocation (ES.FUT: 40%, NQ.FUT: 60%)

3. Order Generation & Submission Flow

Trading Agent Service (allocation + ML signals)
                      ↓
        GenerateOrders(allocation_id, ml_signals)
                      ↓
    ┌─────────────────┴─────────────────┐
    │ 1. Calculate delta from current    │
    │ 2. Determine order side (buy/sell) │
    │ 3. Set order type (market/limit)   │
    │ 4. Apply price offsets             │
    │ 5. Add order metadata              │
    └─────────────────┬─────────────────┘
                      ↓
        Generated Orders (BUY ES.FUT 10 @ MARKET)
                      ↓
        SubmitAgentOrders(orders)
                      ↓
    ┌─────────────────┴─────────────────┐
    │ Trading Agent → Trading Service    │
    │ SubmitMLOrder(symbol, features)    │
    └─────────────────┬─────────────────┘
                      ↓
        Trading Service executes orders
                      ↓
        Returns order IDs and status
                      ↓
    Trading Agent logs execution results

4. Strategy Coordination Flow

User → TLI → API Gateway → Trading Agent Service
                                  ↓
                RegisterStrategy(name, type, config)
                                  ↓
        Store strategy in PostgreSQL
                                  ↓
    ┌───────────────────────────┐
    │ Strategy 1: ML Ensemble   │ ← ENABLED
    │ Strategy 2: Mean Reversion│ ← DISABLED
    │ Strategy 3: Momentum      │ ← ENABLED
    └───────────────────────────┘
                                  ↓
        Periodic execution (every 5 min):
                                  ↓
    ┌─────────────────────────────────┐
    │ For each ENABLED strategy:      │
    │ 1. Run strategy logic           │
    │ 2. Generate allocation          │
    │ 3. Submit orders                │
    │ 4. Track performance            │
    └─────────────────────────────────┘

Integration Points

1. Trading Agent ↔ Trading Service

Trading Agent calls Trading Service (Client → Server):

// Get current positions for allocation decisions
let positions = trading_service_client
    .get_positions(GetPositionsRequest {
        account_id: Some(agent_account_id),
        symbol: None
    })
    .await?;

// Submit generated orders
let ml_order_result = trading_service_client
    .submit_ml_order(MLOrderRequest {
        symbol: "ES.FUT".to_string(),
        account_id: agent_account_id,
        use_ensemble: true,
        features: feature_vector,
        ..Default::default()
    })
    .await?;

Trading Service reports to Trading Agent (via callback or stream):

  • Order fill notifications
  • Position updates
  • Execution quality metrics

2. Trading Agent ↔ ML Training Service

Trading Agent queries ML predictions:

// Get ML predictions for asset selection
let predictions = ml_training_client
    .get_ml_predictions(GetMLPredictionsRequest {
        symbols: vec!["ES.FUT", "NQ.FUT", "ZN.FUT"],
        models: vec!["DQN", "MAMBA2", "PPO", "TFT"],
        timestamp: current_time,
    })
    .await?;

// Use predictions to score assets
for prediction in predictions {
    let score = calculate_composite_score(&prediction);
    asset_scores.push(AssetScore {
        symbol: prediction.symbol,
        ml_score: score,
        model_scores: prediction.model_scores,
        ..Default::default()
    });
}

3. TLI ↔ Trading Agent Service

TLI commands (via API Gateway):

# Select trading universe
tli agent universe select --min-liquidity 0.7 --max-volatility 0.5

# View current universe
tli agent universe show

# Select assets
tli agent assets select --top-n 5 --min-ml-score 0.6

# Allocate portfolio
tli agent allocate --strategy risk-parity --capital 1000000

# Generate and submit orders
tli agent orders generate --allocation-id abc123
tli agent orders submit --batch-id xyz789

# Register strategy
tli agent strategy register \
    --name "ml_ensemble_v1" \
    --type ML_ENSEMBLE \
    --config config.yaml

# Monitor agent
tli agent status
tli agent performance --window 24h
tli agent activity stream

4. Backtesting Service ↔ Trading Agent

Backtesting simulates Trading Agent:

// Backtesting Service simulates Trading Agent decisions
struct BacktestingAgent {
    agent_service_client: TradingAgentServiceClient,
    simulated_time: DateTime<Utc>,
}

impl BacktestingAgent {
    async fn run_backtest(&self, historical_data: Vec<BarData>) -> BacktestResult {
        for bar in historical_data {
            // Simulate universe selection
            let universe = self.agent_service_client
                .select_universe(SelectUniverseRequest {
                    criteria: default_criteria(),
                    ..Default::default()
                })
                .await?;

            // Simulate asset selection
            let assets = self.agent_service_client
                .select_assets(SelectAssetsRequest {
                    universe_id: universe.universe_id,
                    ..Default::default()
                })
                .await?;

            // Simulate allocation
            let allocation = self.agent_service_client
                .allocate_portfolio(AllocatePortfolioRequest {
                    assets: assets.assets,
                    ..Default::default()
                })
                .await?;

            // Simulate order generation
            let orders = self.agent_service_client
                .generate_orders(GenerateOrdersRequest {
                    allocation_id: allocation.allocation_id,
                    ..Default::default()
                })
                .await?;

            // Track simulated results
            self.apply_orders_to_simulation(orders);
        }

        Ok(self.calculate_backtest_metrics())
    }
}

Service Configuration

Port Allocation

Service gRPC Port Health Port Metrics Port
API Gateway 50051 8080 9091
Trading Service 50052 8081 9092
Backtesting Service 50053 8082 9093
ML Training Service 50054 8095 9094
Trading Agent Service 50055 8083 9095

Environment Variables

# Trading Agent Service Configuration
TRADING_AGENT_SERVICE_HOST=0.0.0.0
TRADING_AGENT_SERVICE_PORT=50055
TRADING_AGENT_HEALTH_PORT=8083
TRADING_AGENT_METRICS_PORT=9095

# Integration Configuration
TRADING_SERVICE_URL=http://trading_service:50052
ML_TRAINING_SERVICE_URL=http://ml_training_service:50054

# Agent Configuration
AGENT_UNIVERSE_REFRESH_INTERVAL=3600  # seconds (1 hour)
AGENT_ASSET_SELECTION_INTERVAL=300    # seconds (5 minutes)
AGENT_REBALANCE_THRESHOLD=0.05        # 5% drift triggers rebalance
AGENT_DEFAULT_CAPITAL=1000000         # $1M default capital

# Risk Configuration
AGENT_MAX_POSITION_SIZE_PCT=0.20      # 20% max per position
AGENT_MAX_LEVERAGE=2.0                # 2x max leverage
AGENT_MAX_PORTFOLIO_VAR_95=0.05       # 5% max VaR (95%)

# Database
DATABASE_URL=postgresql://foxhunt:foxhunt_dev_password@postgres:5432/foxhunt

# Monitoring
RUST_LOG=info
PROMETHEUS_ENABLED=true

Docker Compose Entry

trading_agent_service:
  build:
    context: .
    dockerfile: services/trading_agent_service/Dockerfile
  ports:
    - "50055:50055"  # gRPC
    - "8083:8083"    # Health
    - "9095:9095"    # Metrics
  environment:
    - TRADING_AGENT_SERVICE_PORT=50055
    - TRADING_SERVICE_URL=http://trading_service:50052
    - ML_TRAINING_SERVICE_URL=http://ml_training_service:50054
    - DATABASE_URL=postgresql://foxhunt:foxhunt_dev_password@postgres:5432/foxhunt
    - RUST_LOG=info
  depends_on:
    - postgres
    - trading_service
    - ml_training_service
  networks:
    - foxhunt_network
  healthcheck:
    test: ["CMD", "grpc_health_probe", "-addr=:50055"]
    interval: 10s
    timeout: 5s
    retries: 3

Database Schema

Tables

-- Universe history
CREATE TABLE trading_universes (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    universe_id TEXT NOT NULL UNIQUE,
    criteria JSONB NOT NULL,
    instruments JSONB NOT NULL,  -- Array of Instrument objects
    metrics JSONB NOT NULL,      -- UniverseMetrics
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_universes_created_at ON trading_universes(created_at DESC);

-- Asset selection history
CREATE TABLE asset_selections (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    universe_id TEXT REFERENCES trading_universes(universe_id),
    criteria JSONB NOT NULL,
    asset_scores JSONB NOT NULL,  -- Array of AssetScore objects
    metrics JSONB NOT NULL,
    selected_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_asset_selections_universe ON asset_selections(universe_id);
CREATE INDEX idx_asset_selections_selected_at ON asset_selections(selected_at DESC);

-- Portfolio allocations
CREATE TABLE portfolio_allocations (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    allocation_id TEXT NOT NULL UNIQUE,
    strategy JSONB NOT NULL,       -- AllocationStrategy
    risk_constraints JSONB NOT NULL,
    allocations JSONB NOT NULL,    -- Array of AssetAllocation objects
    metrics JSONB NOT NULL,
    total_capital NUMERIC(20, 2),
    created_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_allocations_created_at ON portfolio_allocations(created_at DESC);

-- Order batches
CREATE TABLE order_batches (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    order_batch_id TEXT NOT NULL UNIQUE,
    allocation_id TEXT REFERENCES portfolio_allocations(allocation_id),
    orders JSONB NOT NULL,         -- Array of GeneratedOrder objects
    metrics JSONB NOT NULL,
    submission_results JSONB,      -- Array of OrderSubmissionResult objects
    created_at TIMESTAMPTZ DEFAULT NOW(),
    submitted_at TIMESTAMPTZ
);

CREATE INDEX idx_order_batches_created_at ON order_batches(created_at DESC);
CREATE INDEX idx_order_batches_allocation ON order_batches(allocation_id);

-- Registered strategies
CREATE TABLE agent_strategies (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    strategy_id TEXT NOT NULL UNIQUE,
    strategy_name TEXT NOT NULL,
    strategy_type TEXT NOT NULL,
    status TEXT NOT NULL,          -- ENABLED, DISABLED, PAUSED, ERROR
    config JSONB NOT NULL,
    performance JSONB,             -- StrategyPerformance
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_strategies_status ON agent_strategies(status);
CREATE INDEX idx_strategies_name ON agent_strategies(strategy_name);

-- Agent activity log
CREATE TABLE agent_activity_log (
    id BIGSERIAL PRIMARY KEY,
    activity_type TEXT NOT NULL,   -- UNIVERSE_SELECTION, ASSET_SELECTION, etc.
    event_data JSONB NOT NULL,
    timestamp TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_activity_log_timestamp ON agent_activity_log(timestamp DESC);
CREATE INDEX idx_activity_log_type ON agent_activity_log(activity_type);

-- Agent performance metrics (time-series)
CREATE TABLE agent_performance_metrics (
    id BIGSERIAL PRIMARY KEY,
    metrics JSONB NOT NULL,        -- AgentPerformanceMetrics
    period_start TIMESTAMPTZ NOT NULL,
    period_end TIMESTAMPTZ NOT NULL,
    recorded_at TIMESTAMPTZ DEFAULT NOW()
);

CREATE INDEX idx_performance_metrics_period ON agent_performance_metrics(period_start, period_end);

Implementation Plan

Phase 1: Core Service Setup (Week 1)

  1. Create Service Skeleton:

    • Initialize services/trading_agent_service/ directory structure
    • Setup Cargo.toml with dependencies
    • Create proto/trading_agent.proto
    • Generate gRPC stubs
  2. Implement Basic gRPC Server:

    • main.rs with gRPC server setup
    • Health check endpoint
    • Prometheus metrics integration
  3. Database Setup:

    • Create migration for Trading Agent tables
    • Implement repository traits
    • Setup connection pooling
  4. Docker Integration:

    • Create Dockerfile
    • Add to docker-compose.yml
    • Configure networking

Phase 2: Universe & Asset Selection (Week 2)

  1. Universe Selection:

    • Implement SelectUniverse logic
    • Market data integration
    • Volatility calculation
    • Liquidity scoring
    • Store universe in database
  2. Asset Selection:

    • Implement SelectAssets logic
    • ML signal integration (call ML Training Service)
    • Factor score calculation
    • Composite scoring algorithm
  3. Testing:

    • Unit tests for selection logic
    • Integration tests with mock ML service

Phase 3: Portfolio Allocation (Week 3)

  1. Allocation Strategies:

    • Equal-weight allocation
    • Risk-parity allocation
    • ML-optimized allocation
    • Kelly criterion
  2. Risk Constraint Engine:

    • Position size limits
    • Sector exposure limits
    • VaR calculation
    • Leverage checks
  3. Rebalancing Logic:

    • Drift detection
    • Rebalance action generation
    • Cost estimation

Phase 4: Order Generation & Execution (Week 4)

  1. Order Generation:

    • Delta calculation (target - current)
    • Order type selection (market/limit)
    • Price determination
    • Order metadata tagging
  2. Trading Service Integration:

    • gRPC client for Trading Service
    • Order submission logic
    • Result handling and logging
  3. Testing:

    • End-to-end tests with Trading Service
    • Paper trading simulation

Phase 5: Strategy Coordination (Week 5)

  1. Strategy Framework:

    • Strategy registration
    • Strategy lifecycle management
    • Performance tracking per strategy
  2. Built-in Strategies:

    • ML Ensemble strategy
    • Mean reversion strategy
    • Momentum strategy
  3. Strategy Execution Engine:

    • Periodic execution scheduler
    • Strategy isolation
    • Error handling

Phase 6: Monitoring & API Gateway Integration (Week 6)

  1. Agent Monitoring:

    • Real-time status API
    • Activity streaming
    • Performance metrics calculation
  2. API Gateway Integration:

    • Add Trading Agent proxy to API Gateway
    • Update TLI with agent commands
    • Documentation
  3. Observability:

    • Grafana dashboard for agent metrics
    • Prometheus alerts for agent errors
    • Structured logging

Phase 7: Backtesting Integration (Week 7)

  1. Backtesting Simulation:

    • Backtest adapter for Trading Agent
    • Historical replay logic
    • Performance comparison
  2. Testing & Validation:

    • End-to-end tests across all services
    • Load testing
    • Chaos testing (service failures)

Phase 8: Production Hardening (Week 8)

  1. Error Handling:

    • Graceful degradation
    • Circuit breakers
    • Retry logic
  2. Performance Optimization:

    • Database query optimization
    • Caching strategies
    • Connection pooling tuning
  3. Documentation:

    • API documentation
    • Deployment guide
    • Operational runbook

Success Criteria

Functional Requirements

  • Universe selection completes in <1 second
  • Asset selection completes in <2 seconds (including ML query)
  • Portfolio allocation completes in <500ms
  • Order generation completes in <200ms
  • End-to-end (universe → orders) completes in <5 seconds
  • Strategies execute on schedule with <100ms jitter
  • All APIs return in <100ms (excluding long-running operations)

Non-Functional Requirements

  • Service uptime >99.9%
  • No data loss (all decisions logged to database)
  • Prometheus metrics exported
  • Health checks respond in <10ms
  • Graceful shutdown (drain in-flight requests)
  • Docker container restart recovery

Integration Requirements

  • Trading Service integration (order submission)
  • ML Training Service integration (prediction queries)
  • API Gateway proxy configured
  • TLI commands functional
  • Backtesting simulation working

Testing Requirements

  • Unit test coverage >80%
  • Integration tests for all gRPC methods
  • End-to-end tests across services
  • Load tests (100 req/s sustained)
  • Chaos tests (service failure recovery)

Risk Analysis

Technical Risks

Risk Impact Probability Mitigation
ML service latency High Medium Cache predictions, use stale data if needed
Trading service downtime Critical Low Queue orders, retry with exponential backoff
Database bottleneck High Medium Index optimization, read replicas, caching
Strategy logic errors Critical Medium Extensive testing, paper trading validation
Order submission failures High Medium Idempotent retry, comprehensive error handling

Operational Risks

Risk Impact Probability Mitigation
Configuration errors High Medium Schema validation, default values, dry-run mode
Resource exhaustion High Low Resource limits, monitoring alerts
Data corruption Critical Low Database transactions, audit logging
Version incompatibility Medium Low API versioning, backward compatibility

Alternatives Considered

Alternative 1: Embed Agent Logic in Trading Service

Pros: Simpler architecture, lower latency Cons: Violates SRP, harder to test, couples decision-making with execution Decision: Rejected - doesn't scale, poor separation of concerns

Alternative 2: Use Message Queue Instead of gRPC

Pros: Decoupling, buffering, retry semantics Cons: Added complexity, harder to debug, eventual consistency Decision: Rejected for MVP - can add later if needed

Alternative 3: Agent as Library, Not Service

Pros: No network overhead, simpler deployment Cons: Can't reuse across services, harder to version independently Decision: Rejected - limits reusability (backtesting needs it)


Future Enhancements

Phase 2 (Post-MVP)

  1. Advanced Allocation Strategies:

    • Black-Litterman allocation
    • Hierarchical risk parity
    • Reinforcement learning-based allocation
  2. Multi-Account Support:

    • Manage multiple trading accounts
    • Cross-account risk aggregation
  3. Regime Detection:

    • Automatic strategy switching based on market regime
    • Volatility regime detection
  4. Advanced Rebalancing:

    • Tax-aware rebalancing
    • Transaction cost optimization
  5. Strategy Marketplace:

    • User-defined strategies
    • Strategy backtesting UI
    • Strategy performance leaderboard

Appendix A: Example Workflow

Scenario: Daily portfolio rebalancing at market open

1. 08:30 AM: Universe selection job triggers
   → SelectUniverse(criteria: {min_liquidity: 0.7, max_volatility: 0.5})
   → Returns: [ES.FUT, NQ.FUT, ZN.FUT, 6E.FUT]

2. 08:31 AM: Asset selection job triggers
   → SelectAssets(universe_id: "univ-123", max_assets: 3)
   → Queries ML Training Service for predictions
   → Returns: [ES.FUT (score: 0.85), NQ.FUT (score: 0.78), ZN.FUT (score: 0.72)]

3. 08:32 AM: Portfolio allocation job triggers
   → AllocatePortfolio(assets: [...], strategy: RISK_PARITY, capital: $1M)
   → Returns: {ES.FUT: 35%, NQ.FUT: 40%, ZN.FUT: 25%}

4. 08:33 AM: Order generation job triggers
   → GenerateOrders(allocation_id: "alloc-456", ml_signals: [...])
   → Returns: [BUY ES.FUT 15 @ MARKET, BUY NQ.FUT 20 @ MARKET, SELL ZN.FUT 5 @ MARKET]

5. 08:33 AM: Order submission
   → SubmitAgentOrders(order_batch_id: "batch-789", orders: [...])
   → Calls Trading Service.SubmitMLOrder() for each order
   → Returns: {accepted: 3, rejected: 0, acceptance_rate: 1.0}

6. 08:34 AM: Monitor execution
   → StreamAgentActivity() streams order fill events
   → Logs execution results to database
   → Updates performance metrics

7. 08:35 AM: Performance tracking
   → GetAgentPerformance(window: 24h)
   → Returns: {total_pnl: $12,500, sharpe_ratio: 1.8, win_rate: 0.65}

Appendix B: Key Metrics

Trading Agent Metrics (Prometheus)

# Universe selection
trading_agent_universe_size{universe_id} gauge
trading_agent_universe_refresh_duration_seconds histogram
trading_agent_universe_liquidity_score{universe_id} gauge

# Asset selection
trading_agent_selected_assets{universe_id} gauge
trading_agent_asset_selection_duration_seconds histogram
trading_agent_asset_composite_score{symbol} gauge

# Portfolio allocation
trading_agent_portfolio_utilization gauge  # % capital deployed
trading_agent_portfolio_volatility gauge
trading_agent_portfolio_sharpe gauge
trading_agent_allocation_duration_seconds histogram

# Order generation
trading_agent_orders_generated counter
trading_agent_orders_submitted counter
trading_agent_orders_accepted counter
trading_agent_orders_rejected counter
trading_agent_order_acceptance_rate gauge

# Strategy performance
trading_agent_strategy_pnl{strategy_id} gauge
trading_agent_strategy_sharpe{strategy_id} gauge
trading_agent_strategy_trades{strategy_id} counter

# Agent health
trading_agent_active_strategies gauge
trading_agent_errors_total{error_type} counter
trading_agent_api_request_duration_seconds{method} histogram

Conclusion

The Trading Agent Service is a critical component that separates trading decision-making from execution. By following this design, we achieve:

  1. Separation of Concerns: Decision-making (Agent) vs. execution (Trading Service)
  2. Reusability: Backtesting can reuse agent logic
  3. Testability: Agent logic can be tested independently
  4. Scalability: Agent can be scaled independently of Trading Service
  5. Maintainability: Clear boundaries between components

Next Steps:

  1. Review and approve this design
  2. Create GitHub issues for each implementation phase
  3. Start with Phase 1: Core Service Setup
  4. Iterative development with weekly demos

Document Status: READY FOR REVIEW Estimated Implementation Time: 8 weeks (1 developer) Dependencies: Trading Service, ML Training Service, API Gateway Risk Level: Medium (new service, but clear interfaces)