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

1503 lines
46 KiB
Markdown

# 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`
```protobuf
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):
```rust
// 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**:
```rust
// 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):
```bash
# 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**:
```rust
// 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
```bash
# 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
```yaml
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
```sql
-- 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)
```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)