本文档提供 AI for Investor API 的详细使用指南、常见用例和最佳实践。
API 基础 URL: http://localhost:8000/api/v1
Swagger 文档: http://localhost:8000/docs
ReDoc 文档: http://localhost:8000/redoc
端点: POST /api/v1/auth/register
请求示例:
curl -X POST "http://localhost:8000/api/v1/auth/register" \
-H "Content-Type: application/json" \
-d '{
"username": "trader001",
"email": "trader@example.com",
"password": "SecurePass123!"
}'Python 示例:
import requests
response = requests.post(
"http://localhost:8000/api/v1/auth/register",
json={
"username": "trader001",
"email": "trader@example.com",
"password": "SecurePass123!"
}
)
print(response.json())成功响应 (200):
{
"id": 1,
"username": "trader001",
"email": "trader@example.com",
"created_at": "2026-03-07T10:00:00Z"
}错误响应:
400 Bad Request: 用户名或邮箱已存在422 Unprocessable Entity: 输入验证失败
注意事项:
- 密码至少 8 个字符
- 邮箱格式必须有效
- 速率限制:5 次/小时/IP
端点: POST /api/v1/auth/login
请求示例:
curl -X POST "http://localhost:8000/api/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{
"username": "trader001",
"password": "SecurePass123!"
}'成功响应 (200):
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "bearer"
}使用 Token:
# 在后续请求中添加 Authorization header
curl -X GET "http://localhost:8000/api/v1/strategy/" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"注意事项:
- Token 有效期:24 小时
- 速率限制:10 次/分钟/IP
- 失败登录会被记录审计日志
端点: POST /api/v1/auth/login/refresh
请求示例:
curl -X POST "http://localhost:8000/api/v1/auth/login/refresh" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "YOUR_REFRESH_TOKEN"
}'最佳实践:
- 在 Token 过期前 1 小时刷新
- 存储 refresh_token 到安全位置(如 httpOnly cookie)
端点: POST /api/v1/strategy/
请求示例:
curl -X POST "http://localhost:8000/api/v1/strategy/" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "双均线策略",
"description": "基于快慢均线交叉的趋势跟踪策略",
"code": "# Python 代码\nimport backtrader as bt\n\nclass DualMAStrategy(bt.Strategy):\n params = (\n (\"fast_period\", 10),\n (\"slow_period\", 30),\n )\n \n def __init__(self):\n self.fast_ma = bt.indicators.SMA(self.data.close, period=self.p.fast_period)\n self.slow_ma = bt.indicators.SMA(self.data.close, period=self.p.slow_period)\n self.crossover = bt.indicators.CrossOver(self.fast_ma, self.slow_ma)\n \n def next(self):\n if self.crossover > 0:\n self.buy()\n elif self.crossover < 0:\n self.sell()",
"category": "trend_following",
"parameters": {
"fast_period": {"type": "int", "default": 10, "min": 5, "max": 50},
"slow_period": {"type": "int", "default": 30, "min": 20, "max": 100}
}
}'Python 示例:
import requests
strategy_data = {
"name": "双均线策略",
"description": "基于快慢均线交叉的趋势跟踪策略",
"code": open("strategies/dual_ma_strategy.py").read(),
"category": "trend_following",
"parameters": {
"fast_period": {"type": "int", "default": 10, "min": 5, "max": 50},
"slow_period": {"type": "int", "default": 30, "min": 20, "max": 100}
}
}
response = requests.post(
"http://localhost:8000/api/v1/strategy/",
headers={"Authorization": f"Bearer {token}"},
json=strategy_data
)
print(response.json())成功响应 (200):
{
"id": "uuid-string",
"name": "双均线策略",
"description": "基于快慢均线交叉的趋势跟踪策略",
"category": "trend_following",
"created_at": "2026-03-07T10:00:00Z",
"updated_at": "2026-03-07T10:00:00Z"
}策略分类:
trend_following: 趋势跟踪mean_reversion: 均值回归momentum: 动量策略arbitrage: 套利策略custom: 自定义
端点: GET /api/v1/strategy/
请求示例:
# 获取所有策略
curl -X GET "http://localhost:8000/api/v1/strategy/" \
-H "Authorization: Bearer YOUR_TOKEN"
# 按分类过滤
curl -X GET "http://localhost:8000/api/v1/strategy/?category=trend_following&limit=10&offset=0" \
-H "Authorization: Bearer YOUR_TOKEN"查询参数:
limit: 每页数量 (1-100, 默认 20)offset: 偏移量 (默认 0)category: 分类过滤 (可选)
成功响应 (200):
{
"strategies": [
{
"id": "uuid-1",
"name": "策略1",
"description": "描述",
"category": "trend_following"
}
],
"total": 42,
"limit": 20,
"offset": 0
}端点: GET /api/v1/strategy/templates
请求示例:
curl -X GET "http://localhost:8000/api/v1/strategy/templates" \
-H "Authorization: Bearer YOUR_TOKEN"用途:
- 查看内置策略模板
- 学习策略编写模式
- 快速开始开发
端点: POST /api/v1/backtest/run
请求示例:
curl -X POST "http://localhost:8000/api/v1/backtest/run" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"strategy_id": "your-strategy-uuid",
"symbol": "000001.SZ",
"start_date": "2020-01-01",
"end_date": "2023-12-31",
"initial_cash": 100000,
"commission": 0.001,
"slippage": 0.0005,
"parameters": {
"fast_period": 10,
"slow_period": 30
}
}'Python 完整示例:
import requests
import time
# 1. 提交回测
response = requests.post(
"http://localhost:8000/api/v1/backtest/run",
headers={"Authorization": f"Bearer {token}"},
json={
"strategy_id": "your-strategy-uuid",
"symbol": "000001.SZ",
"start_date": "2020-01-01",
"end_date": "2023-12-31",
"initial_cash": 100000,
"commission": 0.001,
"slippage": 0.0005,
"parameters": {
"fast_period": 10,
"slow_period": 30
}
}
)
task_id = response.json()["task_id"]
print(f"回测任务已提交: {task_id}")
# 2. 轮询状态
while True:
status_response = requests.get(
f"http://localhost:8000/api/v1/backtest/{task_id}/status",
headers={"Authorization": f"Bearer {token}"}
)
status = status_response.json()["status"]
print(f"当前状态: {status}")
if status == "completed":
break
elif status == "failed":
print("回测失败")
break
time.sleep(5)
# 3. 获取结果
result_response = requests.get(
f"http://localhost:8000/api/v1/backtest/{task_id}",
headers={"Authorization": f"Bearer {token}"}
)
result = result_response.json()
print(f"总收益率: {result['total_return']:.2%}")
print(f"夏普比率: {result['sharpe_ratio']:.2f}")
print(f"最大回撤: {result['max_drawdown']:.2%}")成功响应 (200):
{
"task_id": "task-uuid-string",
"status": "pending",
"created_at": "2026-03-07T10:00:00Z"
}参数说明:
strategy_id: 策略 UUIDsymbol: 股票代码 (格式:代码.市场,如000001.SZ)start_date/end_date: 回测日期范围 (格式:YYYY-MM-DD)initial_cash: 初始资金 (默认: 100000)commission: 手续费率 (默认: 0.001)slippage: 滑点 (默认: 0.0005)parameters: 策略参数 (覆盖默认值)
注意事项:
- 并发限制:全局最多 10 个并发回测
- 超时:单个回测最长 30 分钟
- 数据源:目前支持 A 股历史数据
端点: GET /api/v1/backtest/{task_id}/status
请求示例:
curl -X GET "http://localhost:8000/api/v1/backtest/task-uuid/status" \
-H "Authorization: Bearer YOUR_TOKEN"成功响应 (200):
{
"task_id": "task-uuid",
"status": "running"
}状态说明:
pending: 等待执行running: 正在执行completed: 执行完成failed: 执行失败cancelled: 已取消
端点: GET /api/v1/backtest/{task_id}
成功响应 (200):
{
"task_id": "task-uuid",
"status": "completed",
"total_return": 0.256,
"sharpe_ratio": 1.85,
"max_drawdown": -0.123,
"win_rate": 0.65,
"profit_factor": 2.3,
"total_trades": 150,
"metrics_source": "fincore",
"trades": [
{
"date": "2020-01-15",
"type": "BUY",
"price": 10.5,
"shares": 1000,
"commission": 10.5
}
],
"equity_curve": [100000, 102000, 101500, ...],
"created_at": "2026-03-07T10:00:00Z",
"completed_at": "2026-03-07T10:05:00Z"
}指标说明:
total_return: 总收益率 (小数)sharpe_ratio: 夏普比率max_drawdown: 最大回撤 (负数)win_rate: 胜率 (0-1)profit_factor: 盈亏比total_trades: 总交易次数metrics_source: 指标计算来源 (fincore/manual)
连接: ws://localhost:8000/ws/backtest/{task_id}
JavaScript 示例:
const token = localStorage.getItem('token');
const ws = token
? new WebSocket('ws://localhost:8000/ws/backtest/task-uuid', ['access-token', token])
: new WebSocket('ws://localhost:8000/ws/backtest/task-uuid');
ws.onopen = () => {
console.log('WebSocket 连接已建立');
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('进度更新:', data);
if (data.type === 'completed') {
console.log('回测完成!结果:', data.result);
ws.close();
}
};
ws.onerror = (error) => {
console.error('WebSocket 错误:', error);
};消息格式:
{
"type": "progress",
"task_id": "task-uuid",
"status": "running",
"progress": 45,
"message": "正在处理 2021 年数据...",
"data": {}
}事件类型:
connected: 握手成功task_created: 任务已提交,状态为pendingprogress: 任务运行中,带progress/message/datacompleted: 任务完成,带完整resultfailed: 任务失败,带message/errorcancelled: 任务取消
权威端点: POST /api/v1/optimization/submit/backtest
请求示例:
curl -X POST "http://localhost:8000/api/v1/optimization/submit/backtest" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"strategy_id": "your-strategy-uuid",
"backtest_config": {
"strategy_id": "your-strategy-uuid",
"symbol": "000001.SZ",
"start_date": "2020-01-01T00:00:00",
"end_date": "2023-12-31T00:00:00",
"initial_cash": 100000,
"commission": 0.001,
"params": {}
},
"method": "grid",
"param_grid": {
"fast_period": [5, 10, 15, 20],
"slow_period": [20, 30, 40, 50, 60]
},
"metric": "sharpe_ratio"
}'优化方法:
grid: 网格搜索bayesian: 贝叶斯优化
目标指标:
sharpe_ratio: 夏普比率total_return: 总收益率max_drawdown: 最大回撤(最小化)
兼容入口:
POST /api/v1/backtests/optimization/gridPOST /api/v1/backtests/optimization/bayesian
兼容入口当前仅用于旧调用方迁移,服务端会代理到统一任务式主链路,并返回 deprecated 相关响应头,不建议新接入继续使用。
端点: POST /api/v1/live-trading/start
请求示例:
curl -X POST "http://localhost:8000/api/v1/live-trading/start" \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"strategy_id": "your-strategy-uuid",
"broker_config": {
"broker": "eastmoney",
"account": "your-account",
"password": "your-password"
},
"symbols": ["000001.SZ", "600000.SH"],
"initial_capital": 100000,
"risk_management": {
"max_position_pct": 0.3,
"stop_loss_pct": 0.05,
"take_profit_pct": 0.15
}
}'最佳实践:
- 先在模拟环境充分测试
- 使用小额资金开始
- 设置严格的风控参数
- 监控系统实时运行状态
| 状态码 | 含义 | 处理方式 |
|---|---|---|
| 200 | 成功 | 正常处理 |
| 201 | 创建成功 | 资源已创建 |
| 400 | 请求错误 | 检查请求参数 |
| 401 | 未认证 | 重新登录获取 token |
| 403 | 无权限 | 检查用户权限 |
| 404 | 未找到 | 检查资源 ID |
| 422 | 验证失败 | 检查输入格式 |
| 429 | 请求过多 | 降低请求频率 |
| 500 | 服务器错误 | 联系管理员 |
{
"detail": "错误描述",
"status_code": 400,
"timestamp": "2026-03-07T10:00:00Z"
}import requests
from requests.exceptions import HTTPError
try:
response = requests.post(
"http://localhost:8000/api/v1/backtest/run",
headers={"Authorization": f"Bearer {token}"},
json=backtest_data
)
response.raise_for_status()
result = response.json()
except HTTPError as e:
if e.response.status_code == 401:
print("Token 已过期,请重新登录")
# 重新登录逻辑
elif e.response.status_code == 429:
print("请求过于频繁,等待后重试")
time.sleep(60)
else:
print(f"请求失败: {e.response.json()['detail']}")
except Exception as e:
print(f"未知错误: {e}")# ✅ 好的做法:使用环境变量
import os
from datetime import datetime, timedelta
class TokenManager:
def __init__(self):
self.token = None
self.expires_at = None
def get_valid_token(self):
if self.token and datetime.now() < self.expires_at:
return self.token
# 刷新 token
response = requests.post(
"http://localhost:8000/api/v1/auth/login",
json={
"username": os.getenv("API_USERNAME"),
"password": os.getenv("API_PASSWORD")
}
)
self.token = response.json()["access_token"]
self.expires_at = datetime.now() + timedelta(hours=23)
return self.token# ✅ 好的做法:批量获取结果
def get_multiple_results(task_ids):
results = []
for task_id in task_ids:
result = requests.get(
f"http://localhost:8000/api/v1/backtest/{task_id}",
headers={"Authorization": f"Bearer {token}"}
)
results.append(result.json())
return results
# ❌ 避免:并发大量请求(会触发速率限制)import time
from functools import wraps
def retry(max_attempts=3, delay=5):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return func(*args, **kwargs)
except HTTPError as e:
if e.response.status_code == 429:
wait_time = delay * (attempt + 1)
print(f"速率限制,等待 {wait_time} 秒...")
time.sleep(wait_time)
else:
raise
raise Exception(f"重试 {max_attempts} 次后仍失败")
return wrapper
return decorator
@retry(max_attempts=3, delay=5)
def submit_backtest(data):
return requests.post(
"http://localhost:8000/api/v1/backtest/run",
headers={"Authorization": f"Bearer {token}"},
json=data
)from functools import lru_cache
import time
@lru_cache(maxsize=128)
def get_strategy(strategy_id):
"""缓存策略数据,避免重复请求"""
response = requests.get(
f"http://localhost:8000/api/v1/strategy/{strategy_id}",
headers={"Authorization": f"Bearer {token}"}
)
return response.json()
# 定期清理缓存
def clear_cache_periodically():
while True:
time.sleep(3600) # 每小时清理一次
get_strategy.cache_clear()import requests
import time
import json
def automated_backtest_workflow():
"""自动化回测工作流"""
# 1. 登录
login_response = requests.post(
"http://localhost:8000/api/v1/auth/login",
json={"username": "user", "password": "pass"}
)
token = login_response.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
# 2. 创建策略
strategy_response = requests.post(
"http://localhost:8000/api/v1/strategy/",
headers=headers,
json={
"name": "自动策略",
"code": open("strategy.py").read(),
"category": "custom"
}
)
strategy_id = strategy_response.json()["id"]
# 3. 提交回测
backtest_response = requests.post(
"http://localhost:8000/api/v1/backtest/run",
headers=headers,
json={
"strategy_id": strategy_id,
"symbol": "000001.SZ",
"start_date": "2020-01-01",
"end_date": "2023-12-31",
"initial_cash": 100000
}
)
task_id = backtest_response.json()["task_id"]
# 4. 等待完成
while True:
status_response = requests.get(
f"http://localhost:8000/api/v1/backtest/{task_id}/status",
headers=headers
)
status = status_response.json()["status"]
if status in ["completed", "failed"]:
break
time.sleep(5)
# 5. 获取结果
result_response = requests.get(
f"http://localhost:8000/api/v1/backtest/{task_id}",
headers=headers
)
result = result_response.json()
# 6. 保存结果
with open("backtest_result.json", "w") as f:
json.dump(result, f, indent=2)
return result
# 执行
result = automated_backtest_workflow()
print(f"回测完成!收益率: {result['total_return']:.2%}")def batch_parameter_optimization():
"""批量参数优化"""
# 定义参数范围
parameter_sets = [
{"fast_period": 5, "slow_period": 20},
{"fast_period": 10, "slow_period": 30},
{"fast_period": 15, "slow_period": 40},
]
results = []
for params in parameter_sets:
# 提交回测
response = requests.post(
"http://localhost:8000/api/v1/backtest/run",
headers=headers,
json={
"strategy_id": strategy_id,
"symbol": "000001.SZ",
"start_date": "2020-01-01",
"end_date": "2023-12-31",
"parameters": params
}
)
task_id = response.json()["task_id"]
# 等待完成
wait_for_completion(task_id)
# 获取结果
result = get_result(task_id)
results.append({
"parameters": params,
"sharpe_ratio": result["sharpe_ratio"],
"total_return": result["total_return"]
})
# 找到最优参数
best_result = max(results, key=lambda x: x["sharpe_ratio"])
print(f"最优参数: {best_result['parameters']}")
print(f"夏普比率: {best_result['sharpe_ratio']:.2f}")
return best_resultimport websocket
import json
class BacktestMonitor:
def __init__(self, task_id, token):
self.task_id = task_id
self.token = token
self.ws = None
def on_message(self, ws, message):
data = json.loads(message)
event_type = data.get('type')
if event_type == 'progress':
print(f"进度: {data['progress']}% - {data['message']}")
if event_type == 'completed':
print("✅ 回测完成!")
self.display_summary(data['result'])
ws.close()
def on_error(self, ws, error):
print(f"❌ 错误: {error}")
def on_open(self, ws):
print(f"🔌 已连接到回测任务: {self.task_id}")
def display_summary(self, result):
print("\n" + "="*50)
print("📊 回测结果摘要")
print("="*50)
print(f"总收益率: {result['total_return']:.2%}")
print(f"夏普比率: {result['sharpe_ratio']:.2f}")
print(f"最大回撤: {result['max_drawdown']:.2%}")
print(f"胜率: {result['win_rate']:.2%}")
print(f"总交易次数: {result['total_trades']}")
print("="*50 + "\n")
def start(self):
ws_url = f"ws://localhost:8000/ws/backtest/{self.task_id}"
self.ws = websocket.WebSocketApp(
ws_url,
on_open=self.on_open,
on_message=self.on_message,
on_error=self.on_error
)
self.ws.run_forever()
# 使用
monitor = BacktestMonitor(task_id, token)
monitor.start()| 端点 | 方法 | 描述 | 认证 |
|---|---|---|---|
/api/v1/auth/register |
POST | 用户注册 | ❌ |
/api/v1/auth/login |
POST | 用户登录 | ❌ |
/api/v1/auth/login/refresh |
POST | 刷新 token | ❌ |
/api/v1/strategy/ |
GET | 策略列表 | ✅ |
/api/v1/strategy/ |
POST | 创建策略 | ✅ |
/api/v1/strategy/{id} |
GET | 策略详情 | ✅ |
/api/v1/strategy/{id} |
PUT | 更新策略 | ✅ |
/api/v1/strategy/{id} |
DELETE | 删除策略 | ✅ |
/api/v1/strategy/templates |
GET | 策略模板 | ✅ |
/api/v1/backtest/run |
POST | 提交回测 | ✅ |
/api/v1/backtest/{task_id} |
GET | 回测结果 | ✅ |
/api/v1/backtest/{task_id}/status |
GET | 回测状态 | ✅ |
/api/v1/backtest/ |
GET | 回测列表 | ✅ |
/api/v1/optimization/submit/backtest |
POST | 参数优化(权威入口) | ✅ |
/api/v1/live-trading/start |
POST | 启动实盘 | ✅ |
/ws/backtest/{task_id} |
WebSocket | 实时进度 | ✅ |
| 端点类型 | 限制 | 窗口 |
|---|---|---|
| 认证端点 | 5-10 次 | 每分钟/IP |
| API 端点 | 100 次 | 每分钟/用户 |
| 回测提交 | 10 次 | 每小时/用户 |
- 文档:
/docs(Swagger UI) - 问题反馈: GitHub Issues
- API 状态:
/health端点
最后更新: 2026-03-07
版本: 1.0.0
作者: AI for Investor Team