# ๐ AI-Trader: Can AI Beat the Market?
[](https://python.org)
[](LICENSE)
[](https://docker.com)
[](https://fastapi.tiangolo.com)
**REST API service for autonomous AI trading competitions. Run multiple AI models in NASDAQ 100 trading simulations with zero human intervention.**
[๐ Quick Start](#-quick-start) โข [๐ API Documentation](#-api-documentation) โข [๐ณ Docker Deployment](#-docker-deployment) โข [ไธญๆๆๆกฃ](README_CN.md)
---
## โจ Latest Updates (v0.3.0)
**Major Architecture Upgrade - REST API Service**
- ๐ **REST API Server** - Complete FastAPI implementation
- `POST /simulate/trigger` - Start simulation jobs with date ranges
- `GET /simulate/status/{job_id}` - Monitor progress in real-time
- `GET /results` - Query results with filtering
- `GET /health` - Service health checks
- ๐พ **SQLite Database** - Complete persistence layer
- Price data storage with on-demand downloads
- Job tracking and lifecycle management
- Position records with P&L tracking
- AI reasoning logs and tool usage analytics
- ๐ **On-Demand Price Data** - Automatic gap filling
- Priority-based download strategy
- Graceful rate limit handling
- Coverage tracking per symbol
- ๐ณ **Production-Ready Docker** - Single-command deployment
- Health checks and automatic restarts
- Volume persistence for data and logs
- Simplified configuration
- ๐งช **Comprehensive Testing** - 175 tests with high coverage
- ๐ **Complete Documentation** - API guides and validation procedures
See [CHANGELOG.md](CHANGELOG.md) for full release notes and [ROADMAP.md](ROADMAP.md) for planned features.
---
## ๐ What is AI-Trader?
> **AI-Trader enables multiple AI models to compete autonomously in NASDAQ 100 trading, making 100% independent decisions through a standardized tool-based architecture.**
### ๐ฏ Core Features
- ๐ค **Fully Autonomous Trading** - AI agents analyze, decide, and execute without human intervention
- ๐ **REST API Architecture** - Trigger simulations and monitor results via HTTP
- ๐ ๏ธ **MCP Toolchain** - Standardized tools for market research, price queries, and trade execution
- ๐ **Multi-Model Competition** - Deploy GPT, Claude, Qwen, DeepSeek, or custom models
- ๐ **Real-Time Analytics** - Track positions, P&L, and AI decision reasoning
- โฐ **Historical Replay** - Backtest with anti-look-ahead controls
- ๐พ **Persistent Storage** - SQLite database for all results and analytics
- ๐ **External Orchestration** - Integrate with Windmill.dev or any HTTP client
---
## ๐๏ธ Architecture
```
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ REST API (Port 8080) โ
โ POST /simulate/trigger โ GET /status โ GET /results โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Simulation Worker โ
โ โข Job Manager (concurrent job prevention) โ
โ โข Date-sequential, model-parallel execution โ
โ โข Isolated runtime configs per model-day โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโดโโโโโโโโโโโโโโ
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AI Agent (Model-Day) โ โ SQLite Database โ
โ โข GPT-4, Claude, etc. โ โ โข Jobs & Details โ
โ โข MCP Tool Access โ โ โข Positions & Holdings โ
โ โข Decision Logging โ โ โข Reasoning Logs โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MCP Services (Internal) โ
โ โข Math (8000) โข Search (8001) โข Trade (8002) โ
โ โข Price (8003) - All localhost-only โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
```
### Key Components
- **FastAPI Server** - RESTful interface for job management and results
- **Job Manager** - Coordinates simulation execution, prevents concurrent jobs
- **Simulation Worker** - Orchestrates date-sequential, model-parallel execution
- **Model-Day Executor** - Runs single model for single date with isolated config
- **SQLite Database** - Persistent storage with 6 relational tables
- **MCP Services** - Internal tool ecosystem (math, search, trade, price)
---
## ๐ Quick Start
### ๐ณ Docker Deployment (Recommended)
**1. Prerequisites**
- Docker and Docker Compose installed
- API keys: OpenAI, Alpha Vantage, Jina AI
**2. Setup**
```bash
# Clone repository
git clone https://github.com/Xe138/AI-Trader.git
cd AI-Trader
# Configure environment
cp .env.example .env
# Edit .env and add your API keys:
# OPENAI_API_KEY=your_key_here
# ALPHAADVANTAGE_API_KEY=your_key_here
# JINA_API_KEY=your_key_here
```
**3. Start API Server**
```bash
# Start in background
docker-compose up -d
# View logs
docker logs -f ai-trader
# Verify health
curl http://localhost:8080/health
```
**4. Trigger Simulation**
```bash
curl -X POST http://localhost:8080/simulate/trigger \
-H "Content-Type: application/json" \
-d '{
"config_path": "/app/configs/default_config.json",
"start_date": "2025-01-16",
"end_date": "2025-01-17",
"models": ["gpt-4"]
}'
```
**5. Monitor Progress**
```bash
# Get job status (use job_id from trigger response)
curl http://localhost:8080/simulate/status/{job_id}
# View results
curl http://localhost:8080/results?job_id={job_id}
```
---
## ๐ API Documentation
### Endpoints
#### `POST /simulate/trigger`
Start a new simulation job.
**Request:**
```json
{
"config_path": "/app/configs/default_config.json",
"start_date": "2025-01-16",
"end_date": "2025-01-17",
"models": ["gpt-4", "claude-3.7-sonnet"]
}
```
**Parameters:**
- `config_path` (required) - Path to configuration file in container
- `start_date` (required) - Start date in YYYY-MM-DD format
- `end_date` (optional) - End date in YYYY-MM-DD format. If omitted, defaults to `start_date` (single day)
- `models` (optional) - Array of model signatures to run. If omitted, runs all enabled models from config
- `detail` (optional) - Detail level: "summary" (default) or "full" (includes AI reasoning logs)
**Response:**
```json
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "pending",
"total_model_days": 4,
"message": "Simulation job created and started"
}
```
#### `GET /simulate/status/{job_id}`
Query job execution status and progress.
**Response:**
```json
{
"job_id": "550e8400-...",
"status": "running",
"progress": {
"completed": 2,
"failed": 0,
"pending": 2,
"total": 4
},
"details": [
{
"model_signature": "gpt-4",
"trading_date": "2025-01-16",
"status": "completed",
"start_time": "2025-01-16T10:00:00",
"end_time": "2025-01-16T10:05:00"
}
]
}
```
#### `GET /results`
Retrieve simulation results with optional filtering.
**Query Parameters:**
- `job_id` - Filter by job UUID
- `date` - Filter by trading date (YYYY-MM-DD)
- `model` - Filter by model signature
**Response:**
```json
{
"count": 2,
"results": [
{
"job_id": "550e8400-...",
"model_signature": "gpt-4",
"trading_date": "2025-01-16",
"final_cash": 9850.50,
"total_value": 10250.75,
"profit_loss": 250.75,
"positions": {...},
"holdings": [...]
}
]
}
```
#### `GET /health`
Service health check.
**Response:**
```json
{
"status": "healthy",
"database": "connected",
"timestamp": "2025-01-16T10:00:00Z"
}
```
### Complete API Reference
#### Request Validation Rules
**Date Format:**
- Must be YYYY-MM-DD format
- Must be valid calendar date
- Cannot be in the future
- `start_date` must be <= `end_date`
- Maximum date range: 30 days (configurable via `MAX_SIMULATION_DAYS`)
**Model Selection:**
- Must match signatures defined in config file
- Only enabled models will run
- If `models` array omitted, all enabled models from config run
**Configuration Path:**
- Must exist in container filesystem
- Must be valid JSON with required fields
- Typically stored in `/app/configs/`
#### Error Responses
All API endpoints return consistent error responses:
```json
{
"detail": "Error message describing what went wrong"
}
```
**Common HTTP Status Codes:**
- `200 OK` - Successful request
- `400 Bad Request` - Invalid parameters or validation failure
- `404 Not Found` - Job ID not found
- `409 Conflict` - Job already running (concurrent job prevention)
- `500 Internal Server Error` - Unexpected server error
**Example Validation Errors:**
Invalid date format:
```json
{
"detail": "Invalid date format: 2025-1-16. Use YYYY-MM-DD"
}
```
Date range too large:
```json
{
"detail": "Date range too large: 45 days. Maximum allowed: 30 days"
}
```
Future date:
```json
{
"detail": "Dates cannot be in the future: 2026-01-16"
}
```
Concurrent job:
```json
{
"detail": "Another simulation job is already running: "
}
```
#### Job Status Values
- `pending` - Job created, waiting to start
- `running` - Job currently executing
- `completed` - All model-days completed successfully
- `partial` - Some model-days completed, some failed
- `failed` - All model-days failed
#### Model-Day Status Values
- `pending` - Not started yet
- `running` - Currently executing
- `completed` - Finished successfully
- `failed` - Execution failed with error
### Advanced API Usage
#### On-Demand Price Data Downloads
AI-Trader automatically downloads missing price data when needed:
1. **Automatic Gap Detection** - System checks database for missing date ranges
2. **Priority-Based Downloads** - Downloads symbols that complete the most dates first
3. **Rate Limit Handling** - Gracefully handles Alpha Vantage API limits
4. **Coverage Tracking** - Records downloaded date ranges per symbol
**Configuration:**
```bash
# Enable/disable automatic downloads (default: true)
AUTO_DOWNLOAD_PRICE_DATA=true
# Alpha Vantage API key (required for downloads)
ALPHAADVANTAGE_API_KEY=your_key_here
```
**Download Behavior:**
- If price data exists in database, uses cached data (no API call)
- If data missing, downloads from Alpha Vantage during simulation
- Rate limit hit: Pauses downloads, continues simulation with available data
- Next simulation resumes downloads where it left off
**Example Workflow:**
```bash
# First run: Downloads data for requested dates
curl -X POST http://localhost:8080/simulate/trigger \
-d '{"start_date": "2025-01-16", "end_date": "2025-01-20", ...}'
# Downloads AAPL, MSFT, GOOGL for 2025-01-16 to 2025-01-20
# Second run: Reuses cached data, no downloads
curl -X POST http://localhost:8080/simulate/trigger \
-d '{"start_date": "2025-01-18", "end_date": "2025-01-19", ...}'
# Uses cached data, zero API calls
# Third run: Only downloads new dates
curl -X POST http://localhost:8080/simulate/trigger \
-d '{"start_date": "2025-01-20", "end_date": "2025-01-22", ...}'
# Reuses 2025-01-20 data, downloads 2025-01-21 and 2025-01-22
```
#### Detail Levels
Control how much data is logged during simulation:
**Summary Mode (default):**
```bash
curl -X POST http://localhost:8080/simulate/trigger \
-d '{"start_date": "2025-01-16", "detail": "summary", ...}'
```
- Logs positions, P&L, and tool usage
- Does NOT log AI reasoning steps
- Minimal database storage
- Faster execution
**Full Mode:**
```bash
curl -X POST http://localhost:8080/simulate/trigger \
-d '{"start_date": "2025-01-16", "detail": "full", ...}'
```
- Logs positions, P&L, tool usage, AND AI reasoning
- Stores complete conversation history in `reasoning_logs` table
- Larger database footprint
- Useful for debugging AI decision-making
**Querying Reasoning Logs:**
```bash
docker exec -it ai-trader sqlite3 /app/data/jobs.db
sqlite> SELECT * FROM reasoning_logs WHERE job_id='...' AND date='2025-01-16';
```
#### Concurrent Job Prevention
Only one simulation can run at a time:
```bash
# Start first job
curl -X POST http://localhost:8080/simulate/trigger -d '{...}'
# Response: {"job_id": "abc123", "status": "running"}
# Try to start second job
curl -X POST http://localhost:8080/simulate/trigger -d '{...}'
# Response: 409 Conflict
# {"detail": "Another simulation job is already running: abc123"}
# Wait for first job to complete
curl http://localhost:8080/simulate/status/abc123
# {"status": "completed", ...}
# Now second job can start
curl -X POST http://localhost:8080/simulate/trigger -d '{...}'
# Response: {"job_id": "def456", "status": "running"}
```
---
## ๐ ๏ธ Configuration
### Environment Variables
```bash
# AI Model API Configuration
OPENAI_API_BASE= # Optional: custom OpenAI proxy
OPENAI_API_KEY=your_key_here # Required: OpenAI API key
# Data Source Configuration
ALPHAADVANTAGE_API_KEY=your_key_here # Required: Alpha Vantage
JINA_API_KEY=your_key_here # Required: Jina AI search
# API Server Port (host-side mapping)
API_PORT=8080 # Change if port 8080 is occupied
# Agent Configuration
AGENT_MAX_STEP=30 # Maximum reasoning steps per day
# Data Volume Configuration
VOLUME_PATH=. # Base directory for persistent data
```
### Configuration File
Create custom configs in `configs/` directory:
```json
{
"agent_type": "BaseAgent",
"date_range": {
"init_date": "2025-01-01",
"end_date": "2025-01-31"
},
"models": [
{
"name": "GPT-4",
"basemodel": "openai/gpt-4",
"signature": "gpt-4",
"enabled": true
}
],
"agent_config": {
"max_steps": 30,
"max_retries": 3,
"initial_cash": 10000.0
},
"log_config": {
"log_path": "./data/agent_data"
}
}
```
---
## ๐งช Testing & Validation
### Automated Validation
```bash
# Make scripts executable
chmod +x scripts/*.sh
# Validate Docker build and startup
bash scripts/validate_docker_build.sh
# Test all API endpoints
bash scripts/test_api_endpoints.sh
```
### Manual Testing
```bash
# 1. Start API server
docker-compose up -d
# 2. Health check
curl http://localhost:8080/health
# 3. Trigger small test job (single day)
curl -X POST http://localhost:8080/simulate/trigger \
-H "Content-Type: application/json" \
-d '{
"config_path": "/app/configs/default_config.json",
"start_date": "2025-01-16",
"models": ["gpt-4"]
}'
# 4. Monitor until complete
curl http://localhost:8080/simulate/status/{job_id}
# 5. View results
curl http://localhost:8080/results?job_id={job_id}
```
See [TESTING_GUIDE.md](TESTING_GUIDE.md) for comprehensive testing procedures and troubleshooting.
---
## ๐ฏ Trading Environment
- ๐ฐ **Initial Capital**: $10,000 per AI model
- ๐ **Trading Universe**: NASDAQ 100 stocks
- โฐ **Trading Schedule**: Weekdays only (historical simulation)
- ๐ **Data Sources**: Alpha Vantage (prices) + Jina AI (market intelligence)
- ๐ **Anti-Look-Ahead**: Data access limited to current date and earlier
---
## ๐ง AI Agent Capabilities
Through the MCP (Model Context Protocol) toolchain, AI agents can:
- ๐ฐ **Research Markets** - Search news, analyst reports, financial data (Jina AI)
- ๐ **Query Prices** - Get real-time and historical OHLCV data
- ๐ฐ **Execute Trades** - Buy/sell stocks, manage positions
- ๐งฎ **Perform Calculations** - Mathematical analysis and computations
- ๐ **Log Reasoning** - Document decision-making process
**All operations are 100% autonomous - zero human intervention or pre-programmed strategies.**
---
## ๐ Project Structure
```
AI-Trader/
โโโ api/ # FastAPI application
โ โโโ main.py # API server entry point
โ โโโ database.py # SQLite schema and operations
โ โโโ job_manager.py # Job lifecycle management
โ โโโ simulation_worker.py # Job orchestration
โ โโโ model_day_executor.py # Single model-day execution
โ โโโ runtime_manager.py # Isolated runtime configs
โ โโโ models.py # Pydantic request/response models
โ
โโโ agent/ # AI agent core
โ โโโ base_agent/
โ โโโ base_agent.py # BaseAgent implementation
โ
โโโ agent_tools/ # MCP service implementations
โ โโโ tool_math.py # Mathematical calculations
โ โโโ tool_jina_search.py # Market intelligence search
โ โโโ tool_trade.py # Trading execution
โ โโโ tool_get_price_local.py # Price queries
โ โโโ start_mcp_services.py # Service orchestration
โ
โโโ tests/ # Test suite (102 tests, 85% coverage)
โ โโโ unit/ # Unit tests
โ โโโ integration/ # Integration tests
โ
โโโ configs/ # Configuration files
โ โโโ default_config.json # Default simulation config
โ
โโโ scripts/ # Validation scripts
โ โโโ validate_docker_build.sh # Docker build validation
โ โโโ test_api_endpoints.sh # API endpoint testing
โ
โโโ data/ # Persistent data (volume mount)
โ โโโ jobs.db # SQLite database
โ โโโ agent_data/ # Agent execution data
โ
โโโ docker-compose.yml # Docker orchestration
โโโ Dockerfile # Container image definition
โโโ entrypoint.sh # Container startup script
โโโ requirements.txt # Python dependencies
โโโ README.md # This file
```
---
## ๐ Integration Examples
### Windmill.dev Workflow
```typescript
// Trigger simulation
export async function triggerSimulation(
api_url: string,
config_path: string,
start_date: string,
end_date: string | null,
models: string[]
) {
const body = { config_path, start_date, models };
if (end_date) body['end_date'] = end_date;
const response = await fetch(`${api_url}/simulate/trigger`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
return response.json();
}
// Poll for completion
export async function waitForCompletion(api_url: string, job_id: string) {
while (true) {
const status = await fetch(`${api_url}/simulate/status/${job_id}`)
.then(r => r.json());
if (['completed', 'failed', 'partial'].includes(status.status)) {
return status;
}
await new Promise(resolve => setTimeout(resolve, 10000)); // 10s poll
}
}
// Get results
export async function getResults(api_url: string, job_id: string) {
return fetch(`${api_url}/results?job_id=${job_id}`)
.then(r => r.json());
}
```
### Python Client
```python
import requests
import time
# Trigger simulation (date range)
response = requests.post('http://localhost:8080/simulate/trigger', json={
'config_path': '/app/configs/default_config.json',
'start_date': '2025-01-16',
'end_date': '2025-01-17',
'models': ['gpt-4', 'claude-3.7-sonnet']
})
job_id = response.json()['job_id']
# Or trigger single day (omit end_date)
response = requests.post('http://localhost:8080/simulate/trigger', json={
'config_path': '/app/configs/default_config.json',
'start_date': '2025-01-16',
'models': ['gpt-4']
})
# Poll for completion
while True:
status = requests.get(f'http://localhost:8080/simulate/status/{job_id}').json()
if status['status'] in ['completed', 'failed', 'partial']:
break
time.sleep(10)
# Get results
results = requests.get(f'http://localhost:8080/results?job_id={job_id}').json()
print(f"Completed with {results['count']} results")
```
---
## ๐ Database Schema
The SQLite database (`data/jobs.db`) contains:
### Tables
- **jobs** - Job metadata (id, status, created_at, etc.)
- **job_details** - Per model-day execution details
- **positions** - Trading position records with P&L
- **holdings** - Portfolio holdings breakdown
- **reasoning_logs** - AI decision reasoning history
- **tool_usage** - MCP tool usage statistics
### Querying Data
```bash
# Direct database access
docker exec -it ai-trader sqlite3 /app/data/jobs.db
# Example queries
sqlite> SELECT * FROM jobs ORDER BY created_at DESC LIMIT 5;
sqlite> SELECT model_signature, AVG(profit_loss) FROM positions GROUP BY model_signature;
sqlite> SELECT * FROM reasoning_logs WHERE job_id='...';
```
---
## ๐ ๏ธ Development
### Running Tests
```bash
# Install dependencies
pip install -r requirements.txt
# Run test suite
pytest tests/ -v --cov=api --cov-report=term-missing
# Run specific test
pytest tests/unit/test_job_manager.py -v
```
### Adding Custom Models
Edit `configs/default_config.json`:
```json
{
"models": [
{
"name": "Custom Model",
"basemodel": "provider/model-name",
"signature": "custom-model",
"enabled": true,
"openai_base_url": "https://api.custom.com/v1",
"openai_api_key": "custom_key_here"
}
]
}
```
---
## ๐ Documentation
- [CHANGELOG.md](CHANGELOG.md) - Release notes and version history
- [DOCKER_API.md](DOCKER_API.md) - Detailed API deployment guide
- [TESTING_GUIDE.md](TESTING_GUIDE.md) - Comprehensive testing procedures
- [CLAUDE.md](CLAUDE.md) - Development guide for contributors
---
## ๐ค Contributing
Contributions welcome! Please read [CLAUDE.md](CLAUDE.md) for development guidelines.
---
## ๐ License
MIT License - see [LICENSE](LICENSE) for details
---
## ๐ Links
- **GitHub**: https://github.com/Xe138/AI-Trader
- **Docker Hub**: `ghcr.io/xe138/ai-trader:latest`
- **Issues**: https://github.com/Xe138/AI-Trader/issues
---
**Built with FastAPI, SQLite, Docker, and the MCP Protocol**