Production-grade MCP server for realistic paper trading simulation. Accurately models real-world market conditions including slippage, latency, fees, and partial fills to help validate trading strategies before live deployment.
-
Market Data Engine: Multi-provider support (Polygon, Finnhub, Alpaca, Tiingo)
- Real-time quotes and orderbook data
- WebSocket streaming for live updates
- Historical OHLCV candles
- Automatic failover and caching
-
Execution Engine: Realistic order simulation
- Volume & volatility-based slippage model
- Network latency simulation (20ms base + jitter + stress conditions)
- Maker/taker fee structure
- 7 order types: market, limit, stop, stop-limit, trailing-stop, IOC, FOK
- Partial fills based on orderbook liquidity
-
Portfolio Engine: Complete risk management
- Real-time position tracking with FIFO cost basis
- Realized & unrealized P&L calculation
- Margin requirements (initial/maintenance)
- Pre-trade risk checks (position size, allocation, daily loss, exposure)
- Configurable leverage up to 2x
getMarketData- Real-time quotes with bid/ask/lastgetOrderbook- Level-2 market depthgetHistoricalCandles- OHLCV historical datasubmitOrder- Place orders with automatic risk validationmodifyOrder- Modify price or quantitycancelOrder- Cancel pending orderssimulateExecution- Dry-run to preview slippage and feesgetPortfolio- View positions, cash, P&LgetRiskLimits- Check risk limits and usage
portfolio://current- Real-time portfolio staterisk://limits- Risk configuration and current usage
cd d:/alpha-sim
npm installCopy .env.example to .env and add your API keys:
cp .env.example .envEdit .env and add at least one market data provider:
# Polygon (Recommended)
POLYGON_API_KEY=your_key_here
# OR Alpaca
ALPACA_API_KEY=your_key_here
ALPACA_API_SECRET=your_secret_hereGet API keys:
- Polygon.io - Most comprehensive, free tier available
- Alpaca - Free paper trading API
- Finnhub - Free tier for quotes
- Tiingo - Alternative data source
# Development mode with auto-reload
npm run dev
# Production build
npm run build
npm startThe server will start on http://localhost:3001.
Add to your Claude Desktop config:
{
"mcpServers": {
"paper-trading": {
"url": "http://localhost:3001"
}
}
}All configuration is managed via environment variables in .env:
INITIAL_CASH=100000 # Starting capital
MAX_LEVERAGE=2 # Maximum leverage multiplierMAX_POSITION_SIZE=100000 # Max notional per symbol
MAX_SYMBOL_ALLOCATION=0.20 # Max 20% per symbol
MAX_DAILY_LOSS=5000 # Daily loss limit
MAX_TOTAL_EXPOSURE=200000 # Total portfolio exposureBASE_LATENCY_MS=20 # Base execution latency
JITTER_MIN_MS=5 # Random jitter range
JITTER_MAX_MS=50
STRESS_LATENCY_MIN_MS=100 # High volatility latency
STRESS_LATENCY_MAX_MS=500MAKER_FEE=0.0001 # 0.01% maker fee
TAKER_FEE=0.0003 # 0.03% taker feeUse the getMarketData tool for AAPL
Response:
{
"symbol": "AAPL",
"timestamp": 1707648000000,
"bid": 184.50,
"ask": 184.52,
"last": 184.51,
"bidSize": 100,
"askSize": 150
}Buy 100 shares of TSLA at market price
This will:
- Check risk limits automatically
- Calculate realistic slippage based on order size and volatility
- Apply maker/taker fees
- Update portfolio positions
- Return order status and fills
Simulate buying 500 shares of AAPL
Response shows expected fill price, slippage, and fees without actually placing the order.
Show me my current portfolio
Returns:
- Cash balance
- Buying power
- All open positions
- Realized & unrealized P&L
- Daily P&L
Slippage is calculated using:
slippage = (baseSlippage + volumeImpact + volatilityImpact) * orderTypeMultiplier
Where:
- Base slippage: 1 basis point default
- Volume impact:
(orderSize / avgVolume) * 0.5 - Volatility impact:
ATR * 0.3 - Order type multiplier: 1.5x for market orders, 1.0x for limit
Three components:
- Base latency: 20ms (typical network round trip)
- Random jitter: 5-50ms uniform distribution
- Stress latency: 100-500ms when volatility > 3% (simulates exchange congestion)
- Maker fees: 0.01% (providing liquidity with limit orders)
- Taker fees: 0.03% (taking liquidity with market orders)
- Fees are calculated on notional value (quantity × price)
d:/alpha-sim/
├── src/
│ ├── market-data/ # Market data providers
│ │ ├── types.ts
│ │ ├── aggregator.ts
│ │ └── providers/
│ │ ├── polygon.ts
│ │ └── alpaca.ts
│ ├── execution/ # Order execution engine
│ │ ├── types.ts
│ │ ├── slippage-model.ts
│ │ ├── latency-simulator.ts
│ │ ├── fee-calculator.ts
│ │ ├── fill-logic.ts
│ │ └── order-manager.ts
│ ├── portfolio/ # Portfolio management
│ │ ├── types.ts
│ │ ├── position-tracker.ts
│ │ ├── margin-calculator.ts
│ │ ├── risk-manager.ts
│ │ └── portfolio-service.ts
│ ├── services/ # MCP services
│ │ ├── market-data-service.ts
│ │ ├── trading-service.ts
│ │ └── portfolio-service-mcp.ts
│ ├── config.ts
│ └── index.ts # Main entry point
├── data/ # Runtime data
│ ├── portfolio.json
│ ├── risk_limits.json
│ ├── fee_model.json
│ └── latency_profile.json
└── package.json
npm testnpm run lintnpm run buildleanmcp deployFROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY dist ./dist
COPY data ./data
CMD ["node", "dist/index.js"]Make sure you've set at least one API key in .env:
POLYGON_API_KEY=your_key_hereCheck your risk limits in .env or data/risk_limits.json. You may need to:
- Increase
MAX_POSITION_SIZE - Increase
MAX_DAILY_LOSS - Reduce position sizes
Some providers may have WebSocket rate limits. The server will automatically fall back to REST API polling.
- Orderbook modeling: Most providers don't offer full Level-2 data, so orderbook is simplified
- After-hours trading: Not currently simulated
- Corporate actions: Splits, dividends not handled
- Short selling: Supported but without borrow fees
Contributions welcome! Please open an issue or PR.
MIT
For issues or questions:
- Open a GitHub issue
- Check the LeanMCP documentation