Open Paper Trading MCP
Provides AI agents with tools for paper trading stocks, options, ETFs, and bonds, including advanced options strategies and risk analysis, using real market data without financial risk.
README
Open Paper Trading MCP 📈
A comprehensive paper trading simulator with dual interfaces: REST API (FastAPI) and AI agent tools (MCP). Designed for algorithmic trading development, strategy backtesting, options trading simulation, and training AI agents in realistic market environments without financial risk.
🎯 Core Capabilities
- Multi-Asset Trading: Stocks, options, ETFs, and bonds with specialized implementations
- Advanced Options Trading: Full options chain support with Greeks calculations and 15+ spread strategies
- Professional Spread Builder: Iron Condors, Butterflies, Straddles, Strangles, and advanced multi-leg strategies
- Real-time Risk Analysis: P&L diagrams, breakeven calculations, and win probability analysis
- AI Agent Training: Native MCP interface for training trading agents and LLMs
- Production-Ready: Type-safe, async architecture with comprehensive testing and monitoring
- Dual Interface Access: Both REST API (web clients) and MCP tools (AI agents) access identical functionality
✅ Current Status (2025-01-08)
🎉 PRODUCTION READY QUALITY - Successfully implemented and deployed dual-server architecture:
- FastAPI Server (port 2080): Frontend integration + 49 REST API endpoints operational
- MCP Server (port 2081): Independent MCP server with 43 tools + auto-generated list_tools function
- Test Success Rate: 99.8% (576/581 tests passing, comprehensive journey-based testing)
- Code Quality: 100% ruff compliance, 100% mypy clean, all style violations resolved
- Database Integration: PostgreSQL async operations with proper session management
- Service Layer: TradingService fully integrated via dependency injection
- API Documentation: Auto-generated docs available at
/docs - Multi-Account Support: Complete backend implementation with account_id parameter support
- Options Trading: Complete options chain integration with live market data and professional interface
- ADK Evaluation Complete: 42/42 evaluations tested - 100% agent behavior validation with proper multi-step workflows
- MCP Tool Reliability: All 43 tools validated through live agent interaction using real market data
- AsyncIO Infrastructure: Complete resolution of event loop conflicts, 100% test stability
✅ Prerequisites
Before you begin, ensure you have the following installed:
- Docker and Docker Compose: For running the application in a containerized environment.
- Python: Version 3.11 or higher.
- uv: The project's package manager.
🚀 Quick Start
# 1. Clone the repository
git clone https://github.com/yourusername/open-paper-trading-mcp.git
cd open-paper-trading-mcp
# 2. Start everything with Docker
docker-compose up --build
# 3. Services are now available at:
# - Frontend & API: http://localhost:2080/
# - MCP Server: http://localhost:2081/
# - API Docs: http://localhost:2080/docs
🏗️ Architecture Overview
REST Client AI Agent
| |
v v
FastAPI Server MCP Server
(Port 2080) (Port 2081)
| |
+------------------+
|
v
TradingService
|
+---------+---------+
| |
v v
PostgreSQL DB Robinhood API
(Trading State) (Market Data)
Split Architecture Benefits:
- Independent Servers: FastAPI (2080) and MCP (2081) run separately, eliminating mounting conflicts
- Dual Interface Access: Web clients use REST API, AI agents use MCP tools - same underlying functionality
- Service Layer Unity: Both interfaces use identical TradingService for consistency
- Database-First: All trading state persisted in PostgreSQL with async operations
- Real-time Market Data: Direct API calls to Robinhood for current market information
- Type Safety: Full Pydantic validation on all inputs/outputs across both interfaces
🏆 Key Achievements & Lessons Learned
Major Technical Achievements
- AsyncIO Infrastructure Mastery: Resolved 164 AsyncIO event loop conflicts that were causing 49% test failure rate
- Split Architecture Success: Overcame FastMCP mounting conflicts by implementing independent server architecture
- Database Session Consistency: Established unified
get_async_session()pattern across entire codebase - Test Infrastructure Stability: Achieved 99.8% test success rate (576/581 tests passing)
- Dual Interface Implementation: Successfully created mirror functionality between REST API and MCP tools
- MCP Tool Validation Complete: 42/42 ADK evaluations completed with 100% agent behavior validation
- Live Market Data Integration: All tools successfully use real Robinhood API with proper error handling
- Production Deployment Ready: Docker containers optimized, real data policy enforced, comprehensive monitoring
Critical Lessons Learned
- Event Loop Management: Create fresh database engines per test in current event loop to prevent AsyncIO conflicts
- Service Architecture: Independent servers solve mounting conflicts better than complex integration
- Database Patterns: Always use
get_async_session()dependency injection, neverAsyncSessionLocal()directly - Testing Patterns: Standardized mocking with
side_effectfor async generators ensures reliable tests - Code Quality: Comprehensive linting (ruff), type checking (mypy), and formatting standards prevent technical debt
Development Workflow Optimizations
- Split Development: FastAPI server (frontend/API) and MCP server (AI tools) can be developed independently
- Service Layer Unity: Changes to TradingService automatically benefit both interfaces
- Test-Driven Stability: Comprehensive test coverage (70%+) with AsyncIO-safe patterns
- Live API Integration: Robinhood API tests with
@pytest.mark.robinhoodfor real-world validation
🛠️ Technology Stack
- Backend: Python, FastAPI, FastMCP
- Database: PostgreSQL
- ORM: SQLAlchemy
- Market Data: Robinhood API
- Package Management: uv
- Containerization: Docker, Docker Compose
⚙️ Development
Local Setup (without Docker)
# Install uv package manager
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uv pip sync pyproject.toml
# Set up PostgreSQL and update .env
cp .env.example .env
# Edit DATABASE_URL in .env
# Run the application
uv run python app/main.py
Configuration
The application is configured using environment variables. Copy the .env.example file to .env and update the following variables:
DATABASE_URL: The connection string for your PostgreSQL database.ROBINHOOD_USERNAME: Your Robinhood username (for live market data).ROBINHOOD_PASSWORD: Your Robinhood password.QUOTE_ADAPTER_TYPE: The quote adapter to use (testorrobinhood).
Development Commands
# Format code
python scripts/dev.py format
# Run linting
python scripts/dev.py lint
# Type checking
python scripts/dev.py typecheck
# Run all tests
python scripts/dev.py test
# Run all checks
python scripts/dev.py check
Database Development Patterns
Always use consistent database session patterns:
# ✅ CORRECT - Use get_async_session()
from app.storage.database import get_async_session
async def database_operation():
async for db in get_async_session():
result = await db.execute(select(Model))
return result.scalars().all()
# ❌ INCORRECT - Never use AsyncSessionLocal() directly
from app.storage.database import AsyncSessionLocal
async with AsyncSessionLocal() as db: # Breaks testing!
pass
Testing database code:
from unittest.mock import patch
@patch('app.storage.database.get_async_session')
async def test_function(mock_get_session, test_session):
async def mock_generator():
yield test_session
mock_get_session.return_value = mock_generator()
# Your test code here
result = await database_operation()
assert result is not None
This ensures consistent behavior between production and testing environments.
🧪 Testing Best Practices
AsyncIO Event Loop Management
Critical for async test stability:
# tests/conftest.py - Create fresh engines per test
@pytest_asyncio.fixture(scope="function")
async def db_session() -> AsyncGenerator[AsyncSession, None]:
# Create engine in current event loop (critical for AsyncIO compatibility)
test_engine = create_async_engine(
database_url,
echo=False,
future=True,
pool_pre_ping=True, # Verify connections before use
pool_recycle=300 # Recycle connections every 5 minutes
)
test_session_factory = async_sessionmaker(
bind=test_engine,
class_=AsyncSession,
expire_on_commit=False
)
try:
async with test_session_factory() as session:
yield session
finally:
await test_engine.dispose() # Critical for preventing leaks
Common Test Issues & Solutions
1. Missing Await Keywords
# ❌ WRONG - Async method without await
result = adapter.get_account_ids() # Returns coroutine!
assert len(result) == 3 # TypeError: object of type 'coroutine' has no len()
# ✅ CORRECT - Always await async methods
result = await adapter.get_account_ids()
assert len(result) == 3
2. DateTime Timezone Issues
# ❌ WRONG - Mixed timezone awareness
from datetime import datetime
created_at = datetime.now(timezone.utc) # timezone-aware
updated_at = datetime.now() # timezone-naive
# ✅ CORRECT - Consistent timezone handling
from datetime import datetime, timezone
created_at = datetime.now(timezone.utc)
updated_at = datetime.now(timezone.utc)
3. Database Session Mocking Pattern
# ✅ CORRECT - Proper async session mocking
async def test_database_operation(self, db_session: AsyncSession):
adapter = DatabaseAccountAdapter()
with patch('app.adapters.accounts.get_async_session') as mock_get_session:
async def mock_session_generator():
yield db_session
mock_get_session.side_effect = lambda: mock_session_generator()
# Test database operations with real session
result = await adapter.get_account("test-id")
assert result is not None
Test Infrastructure Achievements
- AsyncIO Event Loop Issues: ✅ RESOLVED - 164 AsyncIO errors eliminated
- Success Rate Improvement: 29% → 99.8% (576/581 tests passing)
- Database Session Consistency: ✅ Implemented across all core functions
- Test Pattern Standardization: ✅ Unified mocking patterns established
- Live API Testing: ✅ Robinhood tests integrated with
@pytest.mark.robinhoodmarker - Journey-Based Testing: ✅ User journey organization prevents timeout issues with 581 total tests
Live API Testing with Robinhood
The test suite includes integration tests that make live, read-only calls to the Robinhood API:
# Run all tests including live Robinhood calls
uv run pytest
# Exclude live Robinhood API tests (faster, no external dependencies)
uv run pytest -m "not robinhood"
# Run only Robinhood integration tests
uv run pytest -m "robinhood"
Robinhood Test Features:
- Read-only operations: Stock quotes, market data, company information, search
- Rate limiting protection: All marked as
@pytest.mark.slow - Real data validation: Verifies actual API responses and data formats
- Shared fixtures: Consistent setup via
trading_service_robinhoodfixture
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。