|
|
|
|
|
# 自定义数据源配置指南
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
系统支持接入自定义数据源服务,用于获取股票K线数据、标的列表和交易日历等信息。
|
|
|
|
|
|
|
|
|
|
|
|
## 支持的接口
|
|
|
|
|
|
|
|
|
|
|
|
自定义数据源需要实现以下接口:
|
|
|
|
|
|
|
|
|
|
|
|
| 接口 | 方法 | 说明 | 参数 |
|
|
|
|
|
|
|------|------|------|------|
|
|
|
|
|
|
| `/v1/stock/klines/:symbol` | GET | 查询K线数据 | `period`, `startDate`, `endDate`, `limit` |
|
|
|
|
|
|
| `/v1/stock/symbols` | GET | 查询标的列表 | `type`, `exchange`, `limit`, `offset` |
|
|
|
|
|
|
| `/v1/stock/klines/batch` | POST | 批量查询K线 | `{ symbols, period, startDate, endDate, limit }` |
|
|
|
|
|
|
| `/v1/stock/trading-dates` | GET | 获取交易日历 | `startDate`, `endDate` |
|
|
|
|
|
|
|
|
|
|
|
|
## 配置说明
|
|
|
|
|
|
|
|
|
|
|
|
### 环境变量
|
|
|
|
|
|
|
|
|
|
|
|
在 `app/backend/.env` 中添加以下配置:
|
|
|
|
|
|
|
|
|
|
|
|
```env
|
|
|
|
|
|
# 自定义数据源配置
|
|
|
|
|
|
CUSTOM_DATA_SOURCE_ENABLED=true
|
|
|
|
|
|
CUSTOM_DATA_SOURCE_URL=http://localhost:8080
|
|
|
|
|
|
CUSTOM_DATA_SOURCE_API_KEY=your-api-key
|
|
|
|
|
|
CUSTOM_DATA_SOURCE_TIMEOUT=30000
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 配置项说明
|
|
|
|
|
|
|
|
|
|
|
|
| 配置项 | 说明 | 默认值 |
|
|
|
|
|
|
|--------|------|--------|
|
|
|
|
|
|
| `CUSTOM_DATA_SOURCE_ENABLED` | 是否启用自定义数据源 | `false` |
|
|
|
|
|
|
| `CUSTOM_DATA_SOURCE_URL` | 数据源服务地址 | `http://localhost:8080` |
|
|
|
|
|
|
| `CUSTOM_DATA_SOURCE_API_KEY` | API密钥(可选) | 空 |
|
|
|
|
|
|
| `CUSTOM_DATA_SOURCE_TIMEOUT` | 请求超时时间(毫秒) | `30000` |
|
|
|
|
|
|
|
|
|
|
|
|
## API 接口文档
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 健康检查
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
GET /api/v1/datasource/health
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"enabled": true,
|
|
|
|
|
|
"status": "ok"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 查询K线数据
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
GET /api/v1/datasource/klines/:symbol?period=day&limit=60
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
- `symbol` (path) - 标的代码,如 `000001.SZ`
|
|
|
|
|
|
- `period` (query) - 周期:`day`/`week`/`month`,默认 `day`
|
|
|
|
|
|
- `startDate` (query) - 开始日期 `YYYY-MM-DD`
|
|
|
|
|
|
- `endDate` (query) - 结束日期 `YYYY-MM-DD`
|
|
|
|
|
|
- `limit` (query) - 限制条数
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"symbol": "000001.SZ",
|
|
|
|
|
|
"period": "day",
|
|
|
|
|
|
"count": 60,
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"date": "2024-01-01",
|
|
|
|
|
|
"open": 10.5,
|
|
|
|
|
|
"high": 11.2,
|
|
|
|
|
|
"low": 10.3,
|
|
|
|
|
|
"close": 10.8,
|
|
|
|
|
|
"volume": 1000000,
|
|
|
|
|
|
"amount": 10800000
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 查询标的列表
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
GET /api/v1/datasource/symbols?type=stock&limit=100
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**参数:**
|
|
|
|
|
|
- `type` (query) - 类型:`stock`/`index`/`etf`/`bond`
|
|
|
|
|
|
- `exchange` (query) - 交易所代码
|
|
|
|
|
|
- `limit` (query) - 限制条数
|
|
|
|
|
|
- `offset` (query) - 偏移量
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"count": 100,
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"symbol": "000001.SZ",
|
|
|
|
|
|
"name": "平安银行",
|
|
|
|
|
|
"type": "stock",
|
|
|
|
|
|
"exchange": "SZSE",
|
|
|
|
|
|
"industry": "银行"
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 批量查询K线
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
POST /api/v1/datasource/klines/batch
|
|
|
|
|
|
Content-Type: application/json
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
"symbols": ["000001.SZ", "000002.SZ"],
|
|
|
|
|
|
"period": "day",
|
|
|
|
|
|
"startDate": "2024-01-01",
|
|
|
|
|
|
"endDate": "2024-12-31",
|
|
|
|
|
|
"limit": 100
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"requestCount": 2,
|
|
|
|
|
|
"resultCount": 2,
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"symbol": "000001.SZ",
|
|
|
|
|
|
"data": [...]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"symbol": "000002.SZ",
|
|
|
|
|
|
"data": [...]
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 获取交易日历
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
GET /api/v1/datasource/trading-dates?startDate=2024-01-01&endDate=2024-01-31
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"startDate": "2024-01-01",
|
|
|
|
|
|
"endDate": "2024-01-31",
|
|
|
|
|
|
"totalDays": 31,
|
|
|
|
|
|
"tradingDays": 22,
|
|
|
|
|
|
"items": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"date": "2024-01-01",
|
|
|
|
|
|
"isTrading": false
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"date": "2024-01-02",
|
|
|
|
|
|
"isTrading": true
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 6. 获取最近交易日
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
GET /api/v1/datasource/nearest-trading-date?date=2024-01-01
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"requestDate": "2024-01-01",
|
|
|
|
|
|
"nearestTradingDate": "2024-01-02"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 7. 检查是否为交易日
|
|
|
|
|
|
|
|
|
|
|
|
```http
|
|
|
|
|
|
GET /api/v1/datasource/is-trading-date?date=2024-01-01
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**响应示例:**
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"code": 200,
|
|
|
|
|
|
"message": "success",
|
|
|
|
|
|
"data": {
|
|
|
|
|
|
"date": "2024-01-01",
|
|
|
|
|
|
"isTrading": false
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 在代码中使用
|
|
|
|
|
|
|
|
|
|
|
|
### 服务层调用
|
|
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
|
import { customDataSourceService } from '../services/customDataSourceService';
|
|
|
|
|
|
|
|
|
|
|
|
// 获取K线数据
|
|
|
|
|
|
const klines = await customDataSourceService.getKLines('000001.SZ', 'day', {
|
|
|
|
|
|
limit: 60,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取标的列表
|
|
|
|
|
|
const symbols = await customDataSourceService.getSymbols({
|
|
|
|
|
|
type: 'stock',
|
|
|
|
|
|
limit: 100,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 批量获取K线
|
|
|
|
|
|
const batchData = await customDataSourceService.getBatchKLines({
|
|
|
|
|
|
symbols: ['000001.SZ', '000002.SZ'],
|
|
|
|
|
|
period: 'day',
|
|
|
|
|
|
limit: 30,
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 获取交易日历
|
|
|
|
|
|
const tradingDates = await customDataSourceService.getTradingDates(
|
|
|
|
|
|
'2024-01-01',
|
|
|
|
|
|
'2024-12-31'
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
// 检查是否启用
|
|
|
|
|
|
if (customDataSourceService.isEnabled()) {
|
|
|
|
|
|
// 使用自定义数据源
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 数据源接口规范
|
|
|
|
|
|
|
|
|
|
|
|
如果你要实现自己的数据源服务,需要遵循以下规范:
|
|
|
|
|
|
|
|
|
|
|
|
### K线数据格式
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"date": "2024-01-01",
|
|
|
|
|
|
"open": 10.5,
|
|
|
|
|
|
"high": 11.2,
|
|
|
|
|
|
"low": 10.3,
|
|
|
|
|
|
"close": 10.8,
|
|
|
|
|
|
"volume": 1000000,
|
|
|
|
|
|
"amount": 10800000
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 标的信息格式
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"symbol": "000001.SZ",
|
|
|
|
|
|
"name": "平安银行",
|
|
|
|
|
|
"type": "stock",
|
|
|
|
|
|
"exchange": "SZSE",
|
|
|
|
|
|
"industry": "银行"
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 交易日历格式
|
|
|
|
|
|
|
|
|
|
|
|
```json
|
|
|
|
|
|
{
|
|
|
|
|
|
"date": "2024-01-01",
|
|
|
|
|
|
"isTrading": false
|
|
|
|
|
|
}
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 缓存策略
|
|
|
|
|
|
|
|
|
|
|
|
系统对自定义数据源接口实现了多级缓存:
|
|
|
|
|
|
|
|
|
|
|
|
| 接口 | 缓存时间 | 说明 |
|
|
|
|
|
|
|------|----------|------|
|
|
|
|
|
|
| K线数据 | 5分钟 | 频繁更新 |
|
|
|
|
|
|
| 标的列表 | 1小时 | 相对稳定 |
|
|
|
|
|
|
| 批量K线 | 5分钟 | 频繁更新 |
|
|
|
|
|
|
| 交易日历 | 24小时 | 很少变化 |
|
|
|
|
|
|
|
|
|
|
|
|
## 错误处理
|
|
|
|
|
|
|
|
|
|
|
|
当自定义数据源不可用时,系统会返回相应的错误码:
|
|
|
|
|
|
|
|
|
|
|
|
| 状态码 | 说明 |
|
|
|
|
|
|
|--------|------|
|
|
|
|
|
|
| 503 | 自定义数据源未启用 |
|
|
|
|
|
|
| 500 | 数据源请求失败 |
|
|
|
|
|
|
| 400 | 请求参数错误 |
|
|
|
|
|
|
| 404 | 数据不存在 |
|
|
|
|
|
|
|
|
|
|
|
|
## 示例:Python FastAPI 数据源服务
|
|
|
|
|
|
|
|
|
|
|
|
```python
|
|
|
|
|
|
from fastapi import FastAPI
|
|
|
|
|
|
from typing import List, Optional
|
|
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
|
|
|
|
|
|
app = FastAPI()
|
|
|
|
|
|
|
|
|
|
|
|
class KLineItem(BaseModel):
|
|
|
|
|
|
date: str
|
|
|
|
|
|
open: float
|
|
|
|
|
|
high: float
|
|
|
|
|
|
low: float
|
|
|
|
|
|
close: float
|
|
|
|
|
|
volume: int
|
|
|
|
|
|
amount: Optional[float] = None
|
|
|
|
|
|
|
|
|
|
|
|
class SymbolInfo(BaseModel):
|
|
|
|
|
|
symbol: str
|
|
|
|
|
|
name: str
|
|
|
|
|
|
type: str
|
|
|
|
|
|
exchange: Optional[str] = None
|
|
|
|
|
|
industry: Optional[str] = None
|
|
|
|
|
|
|
|
|
|
|
|
class TradingDate(BaseModel):
|
|
|
|
|
|
date: str
|
|
|
|
|
|
isTrading: bool
|
|
|
|
|
|
|
|
|
|
|
|
class BatchKLineQuery(BaseModel):
|
|
|
|
|
|
symbols: List[str]
|
|
|
|
|
|
period: str = "day"
|
|
|
|
|
|
startDate: Optional[str] = None
|
|
|
|
|
|
endDate: Optional[str] = None
|
|
|
|
|
|
limit: Optional[int] = None
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/v1/stock/klines/{symbol}", response_model=List[KLineItem])
|
|
|
|
|
|
async def get_klines(
|
|
|
|
|
|
symbol: str,
|
|
|
|
|
|
period: str = "day",
|
|
|
|
|
|
startDate: Optional[str] = None,
|
|
|
|
|
|
endDate: Optional[str] = None,
|
|
|
|
|
|
limit: Optional[int] = None
|
|
|
|
|
|
):
|
|
|
|
|
|
# 实现K线查询逻辑
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/v1/stock/symbols", response_model=List[SymbolInfo])
|
|
|
|
|
|
async def get_symbols(
|
|
|
|
|
|
type: Optional[str] = None,
|
|
|
|
|
|
exchange: Optional[str] = None,
|
|
|
|
|
|
limit: Optional[int] = None,
|
|
|
|
|
|
offset: Optional[int] = None
|
|
|
|
|
|
):
|
|
|
|
|
|
# 实现标的列表查询逻辑
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
@app.post("/v1/stock/klines/batch")
|
|
|
|
|
|
async def get_batch_klines(query: BatchKLineQuery):
|
|
|
|
|
|
# 实现批量K线查询逻辑
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
@app.get("/v1/stock/trading-dates", response_model=List[TradingDate])
|
|
|
|
|
|
async def get_trading_dates(startDate: str, endDate: str):
|
|
|
|
|
|
# 实现交易日历查询逻辑
|
|
|
|
|
|
pass
|
|
|
|
|
|
```
|