docs: add comprehensive documentation for new modules - Issue #48
Documentation updates: - CHANGELOG.md: Add entries for backtest, alerts, execution, memory, portfolio, simulation, strategy modules (1672+ tests documented) - docs/README.md: Add Module Reference section with links to new docs - docs/modules/backtest.md: Complete backtest module documentation - BacktestEngine, slippage/commission models - ResultsAnalyzer metrics and trade statistics - ReportGenerator for PDF/HTML/JSON/Markdown - docs/api/rest-api.md: FastAPI REST API reference - Authentication flow with JWT - Strategies CRUD endpoints - Error handling and configuration Also fixes pytest conftest.py plugin conflict by removing explicit pytest_plugins registration (pytest auto-discovers sub-conftest files) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3d1267a818
commit
b05cc88797
82
CHANGELOG.md
82
CHANGELOG.md
|
|
@ -8,6 +8,88 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
- Backtest module for historical strategy replay (Issues #42-44)
|
||||||
|
- BacktestEngine with historical price replay and trade execution simulation [file:tradingagents/backtest/backtest_engine.py](tradingagents/backtest/backtest_engine.py)
|
||||||
|
- Slippage models: NoSlippage, FixedSlippage, PercentageSlippage, VolumeSlippage
|
||||||
|
- Commission models: NoCommission, FixedCommission, PerShareCommission, PercentageCommission, TieredCommission
|
||||||
|
- Signal processing with OrderSide, OrderType, FillStatus enums
|
||||||
|
- OHLCV, Signal, BacktestConfig, BacktestPosition, BacktestTrade, BacktestSnapshot, BacktestResult dataclasses
|
||||||
|
- ResultsAnalyzer for post-backtest metrics calculation [file:tradingagents/backtest/results_analyzer.py](tradingagents/backtest/results_analyzer.py)
|
||||||
|
- RiskMetrics: Sharpe, Sortino, Calmar, VaR, CVaR, Ulcer index
|
||||||
|
- TradeStatistics: Win rate, profit factor, consecutive wins/losses, average trade
|
||||||
|
- BenchmarkComparison: Alpha, beta, correlation, capture ratios
|
||||||
|
- DrawdownAnalysis: Underwater periods, recovery tracking, max drawdown duration
|
||||||
|
- Monthly and yearly performance breakdown with PerformanceBreakdown dataclass
|
||||||
|
- ReportGenerator for PDF/HTML/JSON/Markdown report generation [file:tradingagents/backtest/report_generator.py](tradingagents/backtest/report_generator.py)
|
||||||
|
- SVG chart generation for equity curves, drawdown charts, monthly heatmaps
|
||||||
|
- Configurable report sections and color schemes via ReportConfig
|
||||||
|
- Factory functions: create_backtest_engine(), create_results_analyzer(), create_report_generator()
|
||||||
|
- Total: 143 tests (57 backtest engine + 42 results analyzer + 44 report generator)
|
||||||
|
|
||||||
|
- Alert notification system (Issues #38-41)
|
||||||
|
- AlertManager for orchestrating multi-channel notifications [file:tradingagents/alerts/alert_manager.py](tradingagents/alerts/alert_manager.py)
|
||||||
|
- Alert, AlertConfig, AlertResult, AlertBatch dataclasses
|
||||||
|
- AlertType enum: TRADE_SIGNAL, RISK_WARNING, POSITION_UPDATE, SYSTEM_ALERT, PRICE_ALERT
|
||||||
|
- AlertPriority enum: LOW, NORMAL, HIGH, CRITICAL
|
||||||
|
- AlertChannel enum: EMAIL, SMS, SLACK, PUSH, WEBHOOK
|
||||||
|
- Channel routing based on alert type and priority
|
||||||
|
- Rate limiting and batching support
|
||||||
|
- SlackChannel for Slack webhook integration [file:tradingagents/alerts/slack_channel.py](tradingagents/alerts/slack_channel.py)
|
||||||
|
- Block Kit message formatting with attachments
|
||||||
|
- Thread support and emoji reactions
|
||||||
|
- SMSChannel for Twilio SMS integration [file:tradingagents/alerts/sms_channel.py](tradingagents/alerts/sms_channel.py)
|
||||||
|
- Message segmentation for long texts
|
||||||
|
- Delivery status tracking
|
||||||
|
- Total: 158 tests (55 alert manager + 44 slack + 59 SMS)
|
||||||
|
|
||||||
|
- Execution module for broker integration (Issues #22-28)
|
||||||
|
- BrokerBase abstract interface for broker implementations [file:tradingagents/execution/broker_base.py](tradingagents/execution/broker_base.py)
|
||||||
|
- Order, Position, OrderStatus, OrderType, OrderSide, TimeInForce dataclasses
|
||||||
|
- BrokerRouter for routing orders by asset class [file:tradingagents/execution/broker_router.py](tradingagents/execution/broker_router.py)
|
||||||
|
- AlpacaBroker for US stocks, ETFs, and crypto [file:tradingagents/execution/alpaca_broker.py](tradingagents/execution/alpaca_broker.py)
|
||||||
|
- IBKRBroker for futures and ASX equities [file:tradingagents/execution/ibkr_broker.py](tradingagents/execution/ibkr_broker.py)
|
||||||
|
- PaperBroker for simulation mode [file:tradingagents/execution/paper_broker.py](tradingagents/execution/paper_broker.py)
|
||||||
|
- OrderManager for order lifecycle management [file:tradingagents/execution/order_manager.py](tradingagents/execution/order_manager.py)
|
||||||
|
- RiskControls for position limits and loss limits [file:tradingagents/execution/risk_controls.py](tradingagents/execution/risk_controls.py)
|
||||||
|
- Total: 358 tests across execution module
|
||||||
|
|
||||||
|
- Memory system with layered architecture (Issues #18-21)
|
||||||
|
- LayeredMemory with recency, relevancy, importance scoring [file:tradingagents/memory/layered_memory.py](tradingagents/memory/layered_memory.py)
|
||||||
|
- TradeHistoryMemory for trade outcomes and agent reasoning [file:tradingagents/memory/trade_history.py](tradingagents/memory/trade_history.py)
|
||||||
|
- RiskProfilesMemory for user preferences over time [file:tradingagents/memory/risk_profiles.py](tradingagents/memory/risk_profiles.py)
|
||||||
|
- Memory integration with agent prompts [file:tradingagents/memory/memory_integration.py](tradingagents/memory/memory_integration.py)
|
||||||
|
- Total: 207 tests across memory module
|
||||||
|
|
||||||
|
- Portfolio management (Issues #29, #31-32)
|
||||||
|
- PortfolioState for holdings, cash, mark-to-market [file:tradingagents/portfolio/portfolio_state.py](tradingagents/portfolio/portfolio_state.py)
|
||||||
|
- PerformanceMetrics for Sharpe, Sortino, drawdown, returns [file:tradingagents/portfolio/performance_metrics.py](tradingagents/portfolio/performance_metrics.py)
|
||||||
|
- AustralianCGTCalculator for 50% discount and tax reports [file:tradingagents/portfolio/cgt_calculator.py](tradingagents/portfolio/cgt_calculator.py)
|
||||||
|
- Total: 197 tests across portfolio module
|
||||||
|
|
||||||
|
- Simulation and strategy comparison (Issues #33-35)
|
||||||
|
- ScenarioRunner for parallel portfolio simulations [file:tradingagents/simulation/scenario_runner.py](tradingagents/simulation/scenario_runner.py)
|
||||||
|
- StrategyComparator for performance comparison and statistics [file:tradingagents/simulation/strategy_comparator.py](tradingagents/simulation/strategy_comparator.py)
|
||||||
|
- EconomicConditions for regime tagging and evaluation [file:tradingagents/simulation/economic_conditions.py](tradingagents/simulation/economic_conditions.py)
|
||||||
|
- Total: 141 tests across simulation module
|
||||||
|
|
||||||
|
- Strategy execution (Issues #36-37)
|
||||||
|
- SignalToOrderConverter for converting signals to orders [file:tradingagents/strategy/signal_converter.py](tradingagents/strategy/signal_converter.py)
|
||||||
|
- StrategyExecutor for end-to-end orchestration [file:tradingagents/strategy/strategy_executor.py](tradingagents/strategy/strategy_executor.py)
|
||||||
|
- Total: 93 tests across strategy module
|
||||||
|
|
||||||
|
- New analyst agents (Issues #13-17)
|
||||||
|
- MomentumAnalyst for multi-timeframe momentum, ROC, ADX [file:tradingagents/agents/analysts/momentum_analyst.py](tradingagents/agents/analysts/momentum_analyst.py)
|
||||||
|
- MacroAnalyst for FRED data interpretation, regime detection [file:tradingagents/agents/analysts/macro_analyst.py](tradingagents/agents/analysts/macro_analyst.py)
|
||||||
|
- CorrelationAnalyst for cross-asset and sector rotation [file:tradingagents/agents/analysts/correlation_analyst.py](tradingagents/agents/analysts/correlation_analyst.py)
|
||||||
|
- PositionSizingManager for Kelly criterion, risk parity, ATR sizing [file:tradingagents/agents/analysts/position_sizing.py](tradingagents/agents/analysts/position_sizing.py)
|
||||||
|
- Analyst integration with graph/setup.py workflow
|
||||||
|
- Total: 250 tests across new analyst agents
|
||||||
|
|
||||||
|
- Data vendor enhancements (Issues #11-12)
|
||||||
|
- VendorRouter for adding new data vendors [file:tradingagents/dataflows/vendor_routing.py](tradingagents/dataflows/vendor_routing.py)
|
||||||
|
- DataCacheLayer for FRED rate limit management [file:tradingagents/dataflows/data_cache.py](tradingagents/dataflows/data_cache.py)
|
||||||
|
- Total: 125 tests for vendor routing and caching
|
||||||
|
|
||||||
- Trade model for execution history with CGT tracking (Issue #6: DB-5)
|
- Trade model for execution history with CGT tracking (Issue #6: DB-5)
|
||||||
- Trade model with BUY/SELL sides and execution status tracking (PENDING, FILLED, PARTIAL, CANCELLED, REJECTED) [file:tradingagents/api/models/trade.py](tradingagents/api/models/trade.py)
|
- Trade model with BUY/SELL sides and execution status tracking (PENDING, FILLED, PARTIAL, CANCELLED, REJECTED) [file:tradingagents/api/models/trade.py](tradingagents/api/models/trade.py)
|
||||||
- TradeSide, TradeStatus, TradeOrderType enums for type-safe trade operations [file:tradingagents/api/models/trade.py:86-137](tradingagents/api/models/trade.py)
|
- TradeSide, TradeStatus, TradeOrderType enums for type-safe trade operations [file:tradingagents/api/models/trade.py:86-137](tradingagents/api/models/trade.py)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,19 @@ Detailed API documentation for developers:
|
||||||
- **[TradingGraph API](api/trading-graph.md)** - Core orchestration API
|
- **[TradingGraph API](api/trading-graph.md)** - Core orchestration API
|
||||||
- **[Agents API](api/agents.md)** - Agent interfaces and implementations
|
- **[Agents API](api/agents.md)** - Agent interfaces and implementations
|
||||||
- **[Data Flows API](api/dataflows.md)** - Data vendor integrations
|
- **[Data Flows API](api/dataflows.md)** - Data vendor integrations
|
||||||
|
- **[REST API](api/rest-api.md)** - FastAPI backend endpoints
|
||||||
|
|
||||||
|
### Module Reference
|
||||||
|
|
||||||
|
Documentation for core modules:
|
||||||
|
|
||||||
|
- **[Backtest Module](modules/backtest.md)** - Historical strategy replay, slippage/commission models, results analysis, report generation
|
||||||
|
- **[Alerts Module](modules/alerts.md)** - Multi-channel notifications (Slack, SMS, webhooks)
|
||||||
|
- **[Execution Module](modules/execution.md)** - Broker integrations (Alpaca, IBKR, Paper), order management, risk controls
|
||||||
|
- **[Memory Module](modules/memory.md)** - Layered memory system, trade history, risk profiles
|
||||||
|
- **[Portfolio Module](modules/portfolio.md)** - Portfolio state, performance metrics, CGT calculator
|
||||||
|
- **[Simulation Module](modules/simulation.md)** - Scenario runner, strategy comparator, economic conditions
|
||||||
|
- **[Strategy Module](modules/strategy.md)** - Signal conversion, strategy execution
|
||||||
|
|
||||||
### Guides
|
### Guides
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,280 @@
|
||||||
|
# REST API Reference
|
||||||
|
|
||||||
|
TradingAgents provides a FastAPI backend for programmatic access to trading functionality.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The REST API is built on FastAPI with:
|
||||||
|
- Async/await support for high performance
|
||||||
|
- JWT authentication for secure access
|
||||||
|
- SQLAlchemy 2.0 async ORM
|
||||||
|
- Pydantic validation for requests/responses
|
||||||
|
- OpenAPI documentation at `/docs`
|
||||||
|
|
||||||
|
## Running the API
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start development server
|
||||||
|
uvicorn tradingagents.api.main:app --reload --port 8000
|
||||||
|
|
||||||
|
# Production (with gunicorn)
|
||||||
|
gunicorn tradingagents.api.main:app -w 4 -k uvicorn.workers.UvicornWorker
|
||||||
|
```
|
||||||
|
|
||||||
|
## Authentication
|
||||||
|
|
||||||
|
### Login
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /api/v1/auth/login
|
||||||
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
username=user@example.com&password=SecurePassword123
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
|
||||||
|
"token_type": "bearer"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using the Token
|
||||||
|
|
||||||
|
Include the token in subsequent requests:
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/v1/strategies
|
||||||
|
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Token Expiration
|
||||||
|
|
||||||
|
Tokens expire after 30 minutes by default. Configure via `JWT_EXPIRATION_MINUTES` environment variable.
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
### Health Check
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /health
|
||||||
|
```
|
||||||
|
|
||||||
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "healthy",
|
||||||
|
"version": "1.0.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Strategies
|
||||||
|
|
||||||
|
#### List Strategies
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/v1/strategies
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
Query parameters:
|
||||||
|
- `skip` (int): Pagination offset (default: 0)
|
||||||
|
- `limit` (int): Page size (default: 100, max: 1000)
|
||||||
|
- `active_only` (bool): Filter to active strategies only
|
||||||
|
|
||||||
|
Response:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Moving Average Crossover",
|
||||||
|
"description": "Simple MA crossover strategy",
|
||||||
|
"parameters": {"fast_period": 10, "slow_period": 20},
|
||||||
|
"is_active": true,
|
||||||
|
"created_at": "2024-01-15T10:30:00Z",
|
||||||
|
"updated_at": "2024-01-15T10:30:00Z"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 1,
|
||||||
|
"skip": 0,
|
||||||
|
"limit": 100
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create Strategy
|
||||||
|
|
||||||
|
```http
|
||||||
|
POST /api/v1/strategies
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "RSI Mean Reversion",
|
||||||
|
"description": "Buy oversold, sell overbought",
|
||||||
|
"parameters": {
|
||||||
|
"rsi_period": 14,
|
||||||
|
"oversold": 30,
|
||||||
|
"overbought": 70
|
||||||
|
},
|
||||||
|
"is_active": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Response (201 Created):
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "RSI Mean Reversion",
|
||||||
|
"description": "Buy oversold, sell overbought",
|
||||||
|
"parameters": {
|
||||||
|
"rsi_period": 14,
|
||||||
|
"oversold": 30,
|
||||||
|
"overbought": 70
|
||||||
|
},
|
||||||
|
"is_active": true,
|
||||||
|
"created_at": "2024-01-15T11:00:00Z",
|
||||||
|
"updated_at": "2024-01-15T11:00:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Get Strategy
|
||||||
|
|
||||||
|
```http
|
||||||
|
GET /api/v1/strategies/{id}
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Update Strategy
|
||||||
|
|
||||||
|
```http
|
||||||
|
PUT /api/v1/strategies/{id}
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"name": "Updated Strategy Name",
|
||||||
|
"parameters": {"new_param": 42}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Delete Strategy
|
||||||
|
|
||||||
|
```http
|
||||||
|
DELETE /api/v1/strategies/{id}
|
||||||
|
Authorization: Bearer <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
Response (204 No Content)
|
||||||
|
|
||||||
|
## Error Responses
|
||||||
|
|
||||||
|
All errors return JSON with consistent structure:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"detail": "Error message here"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common Status Codes
|
||||||
|
|
||||||
|
| Code | Description |
|
||||||
|
|------|-------------|
|
||||||
|
| 400 | Bad Request - Invalid input |
|
||||||
|
| 401 | Unauthorized - Invalid or missing token |
|
||||||
|
| 403 | Forbidden - Insufficient permissions |
|
||||||
|
| 404 | Not Found - Resource doesn't exist |
|
||||||
|
| 409 | Conflict - Duplicate resource |
|
||||||
|
| 422 | Validation Error - Failed Pydantic validation |
|
||||||
|
| 500 | Internal Server Error |
|
||||||
|
|
||||||
|
### Validation Errors
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"detail": [
|
||||||
|
{
|
||||||
|
"loc": ["body", "name"],
|
||||||
|
"msg": "field required",
|
||||||
|
"type": "value_error.missing"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Environment variables:
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `DATABASE_URL` | `sqlite+aiosqlite:///./tradingagents.db` | Database connection string |
|
||||||
|
| `JWT_SECRET_KEY` | Required | Secret key for JWT signing |
|
||||||
|
| `JWT_ALGORITHM` | `HS256` | JWT signing algorithm |
|
||||||
|
| `JWT_EXPIRATION_MINUTES` | `30` | Token expiration time |
|
||||||
|
| `CORS_ORIGINS` | `["*"]` | Allowed CORS origins |
|
||||||
|
| `SQLALCHEMY_ECHO` | `false` | Log SQL queries |
|
||||||
|
|
||||||
|
## Database Migrations
|
||||||
|
|
||||||
|
The API uses Alembic for database migrations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create new migration
|
||||||
|
alembic revision --autogenerate -m "Description"
|
||||||
|
|
||||||
|
# Apply migrations
|
||||||
|
alembic upgrade head
|
||||||
|
|
||||||
|
# Rollback one migration
|
||||||
|
alembic downgrade -1
|
||||||
|
```
|
||||||
|
|
||||||
|
## OpenAPI Documentation
|
||||||
|
|
||||||
|
Interactive API documentation is available at:
|
||||||
|
- Swagger UI: `http://localhost:8000/docs`
|
||||||
|
- ReDoc: `http://localhost:8000/redoc`
|
||||||
|
- OpenAPI JSON: `http://localhost:8000/openapi.json`
|
||||||
|
|
||||||
|
## Python Client Example
|
||||||
|
|
||||||
|
```python
|
||||||
|
import httpx
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
async with httpx.AsyncClient(base_url="http://localhost:8000") as client:
|
||||||
|
# Login
|
||||||
|
response = await client.post("/api/v1/auth/login", data={
|
||||||
|
"username": "user@example.com",
|
||||||
|
"password": "password123"
|
||||||
|
})
|
||||||
|
token = response.json()["access_token"]
|
||||||
|
|
||||||
|
headers = {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
# List strategies
|
||||||
|
response = await client.get("/api/v1/strategies", headers=headers)
|
||||||
|
strategies = response.json()["items"]
|
||||||
|
|
||||||
|
# Create strategy
|
||||||
|
response = await client.post("/api/v1/strategies", headers=headers, json={
|
||||||
|
"name": "New Strategy",
|
||||||
|
"description": "Test",
|
||||||
|
"parameters": {},
|
||||||
|
})
|
||||||
|
new_strategy = response.json()
|
||||||
|
|
||||||
|
print(f"Created strategy: {new_strategy['id']}")
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
asyncio.run(main())
|
||||||
|
```
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Authentication Guide](../guides/authentication.md)
|
||||||
|
- [Database Models](../api/database-models.md)
|
||||||
|
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
|
||||||
|
|
@ -0,0 +1,322 @@
|
||||||
|
# Backtest Module
|
||||||
|
|
||||||
|
The backtest module provides comprehensive historical strategy replay with realistic slippage and commission modeling, results analysis, and report generation.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
tradingagents/backtest/
|
||||||
|
__init__.py # Public API exports
|
||||||
|
backtest_engine.py # Core backtest engine
|
||||||
|
results_analyzer.py # Metrics and trade analysis
|
||||||
|
report_generator.py # PDF/HTML/JSON/Markdown reports
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```python
|
||||||
|
from tradingagents.backtest import (
|
||||||
|
BacktestEngine,
|
||||||
|
BacktestConfig,
|
||||||
|
ResultsAnalyzer,
|
||||||
|
ReportGenerator,
|
||||||
|
OHLCV,
|
||||||
|
Signal,
|
||||||
|
OrderSide,
|
||||||
|
PercentageSlippage,
|
||||||
|
PercentageCommission,
|
||||||
|
)
|
||||||
|
from decimal import Decimal
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Configure backtest
|
||||||
|
config = BacktestConfig(
|
||||||
|
initial_capital=Decimal("100000"),
|
||||||
|
slippage_model=PercentageSlippage(Decimal("0.1")), # 0.1% slippage
|
||||||
|
commission_model=PercentageCommission(Decimal("0.1")), # 0.1% commission
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create engine
|
||||||
|
engine = BacktestEngine(config)
|
||||||
|
|
||||||
|
# Prepare price data
|
||||||
|
price_data = {
|
||||||
|
"AAPL": [
|
||||||
|
OHLCV(datetime(2023, 1, 3), 130, 132, 129, 131, 1000000),
|
||||||
|
OHLCV(datetime(2023, 1, 4), 131, 135, 130, 134, 1200000),
|
||||||
|
OHLCV(datetime(2023, 1, 5), 134, 136, 133, 135, 1100000),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define signals
|
||||||
|
signals = [
|
||||||
|
Signal(datetime(2023, 1, 3), "AAPL", OrderSide.BUY, Decimal("100")),
|
||||||
|
Signal(datetime(2023, 1, 5), "AAPL", OrderSide.SELL, Decimal("100")),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Run backtest
|
||||||
|
result = engine.run(price_data, signals)
|
||||||
|
|
||||||
|
# Analyze results
|
||||||
|
analyzer = ResultsAnalyzer()
|
||||||
|
analysis = analyzer.analyze(result)
|
||||||
|
|
||||||
|
# Generate report
|
||||||
|
generator = ReportGenerator()
|
||||||
|
report = generator.generate(result, analysis)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Backtest Engine
|
||||||
|
|
||||||
|
### BacktestConfig
|
||||||
|
|
||||||
|
Configuration for backtest execution:
|
||||||
|
|
||||||
|
| Field | Type | Default | Description |
|
||||||
|
|-------|------|---------|-------------|
|
||||||
|
| `initial_capital` | `Decimal` | Required | Starting capital |
|
||||||
|
| `slippage_model` | `SlippageModel` | `NoSlippage()` | Slippage model |
|
||||||
|
| `commission_model` | `CommissionModel` | `NoCommission()` | Commission model |
|
||||||
|
| `allow_fractional` | `bool` | `True` | Allow fractional shares |
|
||||||
|
| `margin_enabled` | `bool` | `False` | Enable margin trading |
|
||||||
|
|
||||||
|
### Slippage Models
|
||||||
|
|
||||||
|
Built-in slippage models:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from tradingagents.backtest import (
|
||||||
|
NoSlippage, # No slippage
|
||||||
|
FixedSlippage, # Fixed amount per share
|
||||||
|
PercentageSlippage, # Percentage of price
|
||||||
|
VolumeSlippage, # Volume-impact model
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fixed: $0.01 per share
|
||||||
|
slippage = FixedSlippage(Decimal("0.01"))
|
||||||
|
|
||||||
|
# Percentage: 0.1% of price
|
||||||
|
slippage = PercentageSlippage(Decimal("0.1"))
|
||||||
|
|
||||||
|
# Volume impact: 0.1% per 1% of daily volume
|
||||||
|
slippage = VolumeSlippage(
|
||||||
|
base_impact=Decimal("0.1"),
|
||||||
|
volume_factor=Decimal("0.01"),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commission Models
|
||||||
|
|
||||||
|
Built-in commission models:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from tradingagents.backtest import (
|
||||||
|
NoCommission, # No commission
|
||||||
|
FixedCommission, # Fixed per trade
|
||||||
|
PerShareCommission, # Per share
|
||||||
|
PercentageCommission, # Percentage of value
|
||||||
|
TieredCommission, # Tiered by trade value
|
||||||
|
)
|
||||||
|
|
||||||
|
# Fixed: $5 per trade
|
||||||
|
commission = FixedCommission(Decimal("5"))
|
||||||
|
|
||||||
|
# Per share: $0.005 per share, min $1, max $10
|
||||||
|
commission = PerShareCommission(
|
||||||
|
per_share=Decimal("0.005"),
|
||||||
|
minimum=Decimal("1"),
|
||||||
|
maximum=Decimal("10"),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Percentage: 0.1% of trade value
|
||||||
|
commission = PercentageCommission(Decimal("0.1"))
|
||||||
|
|
||||||
|
# Tiered: Different rates by trade size
|
||||||
|
commission = TieredCommission(tiers=[
|
||||||
|
(Decimal("10000"), Decimal("0.2")), # 0.2% for trades < $10k
|
||||||
|
(Decimal("100000"), Decimal("0.1")), # 0.1% for trades < $100k
|
||||||
|
(None, Decimal("0.05")), # 0.05% for larger trades
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
### BacktestResult
|
||||||
|
|
||||||
|
The result contains:
|
||||||
|
|
||||||
|
- `initial_capital`: Starting capital
|
||||||
|
- `final_value`: Ending portfolio value
|
||||||
|
- `total_return`: Total return percentage
|
||||||
|
- `total_trades`: Number of trades executed
|
||||||
|
- `winning_trades`: Number of profitable trades
|
||||||
|
- `losing_trades`: Number of losing trades
|
||||||
|
- `win_rate`: Win rate percentage
|
||||||
|
- `profit_factor`: Gross profit / gross loss
|
||||||
|
- `max_drawdown`: Maximum drawdown percentage
|
||||||
|
- `sharpe_ratio`: Sharpe ratio
|
||||||
|
- `sortino_ratio`: Sortino ratio
|
||||||
|
- `trades`: List of BacktestTrade records
|
||||||
|
- `snapshots`: List of BacktestSnapshot records
|
||||||
|
|
||||||
|
## Results Analyzer
|
||||||
|
|
||||||
|
### AnalysisResult
|
||||||
|
|
||||||
|
Comprehensive analysis output:
|
||||||
|
|
||||||
|
```python
|
||||||
|
analyzer = ResultsAnalyzer()
|
||||||
|
analysis = analyzer.analyze(result)
|
||||||
|
|
||||||
|
# Risk metrics
|
||||||
|
print(f"Sharpe: {analysis.risk_metrics.sharpe_ratio}")
|
||||||
|
print(f"Sortino: {analysis.risk_metrics.sortino_ratio}")
|
||||||
|
print(f"Calmar: {analysis.risk_metrics.calmar_ratio}")
|
||||||
|
print(f"VaR (95%): {analysis.risk_metrics.var_95}")
|
||||||
|
print(f"CVaR (95%): {analysis.risk_metrics.cvar_95}")
|
||||||
|
|
||||||
|
# Trade statistics
|
||||||
|
print(f"Win rate: {analysis.trade_statistics.win_rate}%")
|
||||||
|
print(f"Profit factor: {analysis.trade_statistics.profit_factor}")
|
||||||
|
print(f"Max win streak: {analysis.trade_statistics.max_win_streak}")
|
||||||
|
print(f"Average trade: {analysis.trade_statistics.avg_trade}")
|
||||||
|
|
||||||
|
# Drawdown analysis
|
||||||
|
print(f"Max drawdown: {analysis.drawdown_analysis.max_drawdown}%")
|
||||||
|
print(f"Recovery time: {analysis.drawdown_analysis.max_drawdown_duration} days")
|
||||||
|
|
||||||
|
# Monthly performance
|
||||||
|
for breakdown in analysis.monthly_performance:
|
||||||
|
print(f"{breakdown.period}: {breakdown.return_pct}%")
|
||||||
|
```
|
||||||
|
|
||||||
|
### RiskMetrics
|
||||||
|
|
||||||
|
| Metric | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `sharpe_ratio` | Risk-adjusted return (vs risk-free rate) |
|
||||||
|
| `sortino_ratio` | Downside risk-adjusted return |
|
||||||
|
| `calmar_ratio` | Return / max drawdown |
|
||||||
|
| `var_95` | 5% worst-case daily loss |
|
||||||
|
| `cvar_95` | Average of 5% worst days |
|
||||||
|
| `ulcer_index` | Depth and duration of drawdowns |
|
||||||
|
| `max_drawdown` | Maximum peak-to-trough decline |
|
||||||
|
| `max_drawdown_duration` | Longest drawdown period (days) |
|
||||||
|
| `recovery_factor` | Total return / max drawdown |
|
||||||
|
|
||||||
|
### TradeStatistics
|
||||||
|
|
||||||
|
| Metric | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `total_trades` | Total number of trades |
|
||||||
|
| `win_rate` | Percentage of winning trades |
|
||||||
|
| `profit_factor` | Gross profit / gross loss |
|
||||||
|
| `max_win` | Largest winning trade |
|
||||||
|
| `max_loss` | Largest losing trade |
|
||||||
|
| `avg_trade` | Average trade P&L |
|
||||||
|
| `median_trade` | Median trade P&L |
|
||||||
|
| `max_win_streak` | Longest winning streak |
|
||||||
|
| `max_loss_streak` | Longest losing streak |
|
||||||
|
| `avg_holding_period` | Average trade duration |
|
||||||
|
|
||||||
|
## Report Generator
|
||||||
|
|
||||||
|
### ReportConfig
|
||||||
|
|
||||||
|
Configure report output:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from tradingagents.backtest import (
|
||||||
|
ReportGenerator,
|
||||||
|
ReportConfig,
|
||||||
|
ReportFormat,
|
||||||
|
ReportSection,
|
||||||
|
)
|
||||||
|
|
||||||
|
config = ReportConfig(
|
||||||
|
format=ReportFormat.HTML,
|
||||||
|
sections=[
|
||||||
|
ReportSection.SUMMARY,
|
||||||
|
ReportSection.TRADES,
|
||||||
|
ReportSection.PERFORMANCE,
|
||||||
|
ReportSection.RISK,
|
||||||
|
ReportSection.CHARTS,
|
||||||
|
],
|
||||||
|
include_charts=True,
|
||||||
|
color_scheme={
|
||||||
|
"primary": "#2196F3",
|
||||||
|
"positive": "#4CAF50",
|
||||||
|
"negative": "#F44336",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
generator = ReportGenerator(config)
|
||||||
|
report = generator.generate(result, analysis)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Output Formats
|
||||||
|
|
||||||
|
| Format | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `HTML` | Interactive HTML with embedded CSS |
|
||||||
|
| `PDF` | PDF document (requires WeasyPrint) |
|
||||||
|
| `JSON` | Structured JSON data |
|
||||||
|
| `MARKDOWN` | Plain Markdown text |
|
||||||
|
|
||||||
|
### Report Sections
|
||||||
|
|
||||||
|
| Section | Content |
|
||||||
|
|---------|---------|
|
||||||
|
| `SUMMARY` | High-level metrics overview |
|
||||||
|
| `TRADES` | Individual trade records |
|
||||||
|
| `PERFORMANCE` | Monthly/yearly returns |
|
||||||
|
| `RISK` | Risk metrics and analysis |
|
||||||
|
| `CHARTS` | Equity curves, drawdown charts |
|
||||||
|
| `POSITIONS` | Position history |
|
||||||
|
|
||||||
|
### Charts
|
||||||
|
|
||||||
|
Built-in SVG charts:
|
||||||
|
|
||||||
|
- **Equity Curve**: Portfolio value over time
|
||||||
|
- **Drawdown Chart**: Underwater equity chart
|
||||||
|
- **Monthly Returns Heatmap**: Color-coded monthly returns
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Get chart data
|
||||||
|
charts = generator.generate_charts(result, analysis)
|
||||||
|
|
||||||
|
equity_svg = charts["equity_curve"]
|
||||||
|
drawdown_svg = charts["drawdown"]
|
||||||
|
heatmap_svg = charts["monthly_heatmap"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Factory Functions
|
||||||
|
|
||||||
|
Convenience functions for common configurations:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from tradingagents.backtest import (
|
||||||
|
create_backtest_engine,
|
||||||
|
create_results_analyzer,
|
||||||
|
create_report_generator,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create engine with common settings
|
||||||
|
engine = create_backtest_engine(
|
||||||
|
initial_capital=100000,
|
||||||
|
slippage_pct=0.1,
|
||||||
|
commission_pct=0.1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create analyzer
|
||||||
|
analyzer = create_results_analyzer()
|
||||||
|
|
||||||
|
# Create report generator
|
||||||
|
generator = create_report_generator(format="html")
|
||||||
|
```
|
||||||
|
|
||||||
|
## See Also
|
||||||
|
|
||||||
|
- [Results Analyzer API](../api/results-analyzer.md)
|
||||||
|
- [Report Generator API](../api/report-generator.md)
|
||||||
|
- [Backtesting Guide](../guides/backtesting.md)
|
||||||
|
|
@ -28,8 +28,8 @@ from typing import Dict, Any
|
||||||
|
|
||||||
from tradingagents.default_config import DEFAULT_CONFIG
|
from tradingagents.default_config import DEFAULT_CONFIG
|
||||||
|
|
||||||
# Register plugins from sub-conftest files (pytest 9.0+ requires this at root level)
|
# Note: Sub-conftest files are loaded automatically by pytest when running tests
|
||||||
pytest_plugins = ["tests.api.conftest"]
|
# in those directories. Do NOT add pytest_plugins here to avoid double-registration.
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
# ============================================================================
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue