|
|
# AmazingData 金融数据服务平台 - 完整实现方案
|
|
|
|
|
|
## 一、项目概述
|
|
|
|
|
|
基于AmazingData SDK构建的金融数据服务平台,提供历史数据缓存、实时数据订阅、批量数据管理等功能。
|
|
|
|
|
|
---
|
|
|
|
|
|
## 二、技术架构
|
|
|
|
|
|
```
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
|
│ 前端层 (Frontend) │
|
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
|
│ │ 登录页面 │ │ 配置管理页面 │ │ 数据查询页面 │ │ 测试中心页面 │ │
|
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
|
│
|
|
|
▼
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
|
│ API网关层 (API Gateway) │
|
|
|
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
|
|
|
│ │ FastAPI + Uvicorn │ JWT认证 │ 限流/熔断 │ 日志/监控 │ CORS │ │
|
|
|
│ └─────────────────────────────────────────────────────────────────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
|
│
|
|
|
▼
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
|
│ 业务服务层 (Services) │
|
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
|
│ │ 认证服务 │ │ 配置服务 │ │ 历史数据服务 │ │ 实时数据服务 │ │
|
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
|
│ │ 缓存管理服务 │ │ 财务数据服务 │ │ 基础数据服务 │ │ 测试服务 │ │
|
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
|
│
|
|
|
▼
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
|
│ 数据访问层 (Data Access) │
|
|
|
│ ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │
|
|
|
│ │ SQLAlchemy ORM │ │ Redis Cache │ │ AmazingData SDK │ │
|
|
|
│ └────────────────────┘ └────────────────────┘ └────────────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
|
│
|
|
|
▼
|
|
|
┌─────────────────────────────────────────────────────────────────────────────────┐
|
|
|
│ 数据存储层 (Storage) │
|
|
|
│ ┌────────────────────┐ ┌────────────────────┐ ┌────────────────────┐ │
|
|
|
│ │ PostgreSQL │ │ Redis │ │ File System │ │
|
|
|
│ │ (主数据库) │ │ (缓存/消息队列) │ │ (日志/导出) │ │
|
|
|
│ └────────────────────┘ └────────────────────┘ └────────────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 三、技术栈选型
|
|
|
|
|
|
| 层级 | 技术 | 版本 | 说明 |
|
|
|
|------|------|------|------|
|
|
|
| 后端框架 | FastAPI | ^0.104.0 | 高性能异步Web框架 |
|
|
|
| ORM | SQLAlchemy | ^2.0.0 | 数据库ORM |
|
|
|
| 数据库 | PostgreSQL | 15+ | 主数据库 |
|
|
|
| 缓存 | Redis | 7+ | 缓存与消息队列 |
|
|
|
| 前端 | Vue3 + TypeScript | ^3.3.0 | 前端框架 |
|
|
|
| UI组件 | Element Plus | ^2.4.0 | UI组件库 |
|
|
|
| 图表 | ECharts | ^5.4.0 | K线图展示 |
|
|
|
| 认证 | JWT + bcrypt | - | 用户认证 |
|
|
|
| 任务调度 | APScheduler | ^3.10.0 | 定时任务 |
|
|
|
| SDK | AmazingData | 1.0.24 | 数据源SDK |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 四、数据库设计
|
|
|
|
|
|
### 4.1 实体关系图 (ER Diagram)
|
|
|
|
|
|
```
|
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
|
│ users │ │ sdk_configs │ │ system_configs │
|
|
|
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
|
|
|
│ id (PK) │ │ id (PK) │ │ id (PK) │
|
|
|
│ username │ │ name │ │ key │
|
|
|
│ password_hash │ │ username │ │ value │
|
|
|
│ is_active │ │ password │ │ description │
|
|
|
│ created_at │ │ host │ │ created_at │
|
|
|
│ updated_at │ │ port │ │ updated_at │
|
|
|
└──────────────────┘ │ is_active │ └──────────────────┘
|
|
|
│ created_at │
|
|
|
└──────────────────┘
|
|
|
│
|
|
|
▼
|
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
|
│stock_kline_daily │ │ stock_kline_min │ │stock_kline_other │
|
|
|
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
|
|
|
│ id (PK) │ │ id (PK) │ │ id (PK) │
|
|
|
│ code │ │ code │ │ code │
|
|
|
│ trade_date │ │ trade_datetime │ │ period_type │
|
|
|
│ open │ │ open │ │ trade_date │
|
|
|
│ high │ │ high │ │ open │
|
|
|
│ low │ │ low │ │ high │
|
|
|
│ close │ │ close │ │ low │
|
|
|
│ volume │ │ volume │ │ close │
|
|
|
│ amount │ │ amount │ │ volume │
|
|
|
│ created_at │ │ created_at │ │ amount │
|
|
|
└──────────────────┘ └──────────────────┘ │ created_at │
|
|
|
└──────────────────┘
|
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
|
│future_kline_daily│ │ future_kline_min │ │realtime_snapshot │
|
|
|
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
|
|
|
│ id (PK) │ │ id (PK) │ │ id (PK) │
|
|
|
│ code │ │ code │ │ code │
|
|
|
│ trade_date │ │ trade_datetime │ │ trade_time │
|
|
|
│ open │ │ open │ │ pre_close │
|
|
|
│ high │ │ high │ │ last │
|
|
|
│ low │ │ low │ │ open │
|
|
|
│ close │ │ close │ │ high │
|
|
|
│ volume │ │ volume │ │ low │
|
|
|
│ amount │ │ amount │ │ volume │
|
|
|
│ settle │ │ settle │ │ amount │
|
|
|
│ open_interest │ │ open_interest │ │ ...其他字段 │
|
|
|
│ created_at │ │ created_at │ │ created_at │
|
|
|
└──────────────────┘ └──────────────────┘ │ expires_at │
|
|
|
└──────────────────┘
|
|
|
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
|
|
|
│ cache_tasks │ │ cache_records │ │ api_test_logs │
|
|
|
├──────────────────┤ ├──────────────────┤ ├──────────────────┤
|
|
|
│ id (PK) │ │ id (PK) │ │ id (PK) │
|
|
|
│ task_name │ │ task_id (FK) │ │ test_name │
|
|
|
│ task_type │ │ code │ │ api_endpoint │
|
|
|
│ security_type │ │ trade_date │ │ request_params │
|
|
|
│ start_date │ │ status │ │ response_data │
|
|
|
│ end_date │ │ record_count │ │ status_code │
|
|
|
│ status │ │ created_at │ │ execution_time │
|
|
|
│ progress │ └──────────────────┘ │ error_message │
|
|
|
│ total_count │ │ created_at │
|
|
|
│ success_count │ └──────────────────┘
|
|
|
│ error_count │
|
|
|
│ created_at │
|
|
|
│ completed_at │
|
|
|
└──────────────────┘
|
|
|
```
|
|
|
|
|
|
### 4.2 表结构详细定义
|
|
|
|
|
|
#### 4.2.1 用户表 (users)
|
|
|
```sql
|
|
|
CREATE TABLE users (
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
username VARCHAR(50) UNIQUE NOT NULL,
|
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
);
|
|
|
```
|
|
|
|
|
|
#### 4.2.2 SDK配置表 (sdk_configs)
|
|
|
```sql
|
|
|
CREATE TABLE sdk_configs (
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
name VARCHAR(100) NOT NULL,
|
|
|
username VARCHAR(100) NOT NULL,
|
|
|
password VARCHAR(255) NOT NULL,
|
|
|
host VARCHAR(100) NOT NULL,
|
|
|
port INTEGER NOT NULL,
|
|
|
local_path VARCHAR(255) DEFAULT './amazing_data_cache/',
|
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
|
is_default BOOLEAN DEFAULT FALSE,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
);
|
|
|
```
|
|
|
|
|
|
#### 4.2.3 股票日线数据表 (stock_kline_daily)
|
|
|
```sql
|
|
|
CREATE TABLE stock_kline_daily (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
trade_date DATE NOT NULL,
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
volume BIGINT NOT NULL,
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
UNIQUE(code, trade_date)
|
|
|
);
|
|
|
|
|
|
CREATE INDEX idx_stock_daily_code_date ON stock_kline_daily(code, trade_date);
|
|
|
CREATE INDEX idx_stock_daily_trade_date ON stock_kline_daily(trade_date);
|
|
|
```
|
|
|
|
|
|
#### 4.2.4 股票分钟数据表 (stock_kline_min)
|
|
|
```sql
|
|
|
CREATE TABLE stock_kline_min (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
period_type VARCHAR(10) NOT NULL, -- min1, min5, min15, min30, min60
|
|
|
trade_datetime TIMESTAMP NOT NULL,
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
volume BIGINT NOT NULL,
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
UNIQUE(code, period_type, trade_datetime)
|
|
|
);
|
|
|
|
|
|
CREATE INDEX idx_stock_min_code_period_datetime ON stock_kline_min(code, period_type, trade_datetime);
|
|
|
CREATE INDEX idx_stock_min_trade_datetime ON stock_kline_min(trade_datetime);
|
|
|
```
|
|
|
|
|
|
#### 4.2.5 期货日线数据表 (future_kline_daily)
|
|
|
```sql
|
|
|
CREATE TABLE future_kline_daily (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
trade_date DATE NOT NULL,
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
volume BIGINT NOT NULL,
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
settle DECIMAL(12, 4),
|
|
|
open_interest BIGINT,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
UNIQUE(code, trade_date)
|
|
|
);
|
|
|
|
|
|
CREATE INDEX idx_future_daily_code_date ON future_kline_daily(code, trade_date);
|
|
|
CREATE INDEX idx_future_daily_trade_date ON future_kline_daily(trade_date);
|
|
|
```
|
|
|
|
|
|
#### 4.2.6 期货分钟数据表 (future_kline_min)
|
|
|
```sql
|
|
|
CREATE TABLE future_kline_min (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
period_type VARCHAR(10) NOT NULL,
|
|
|
trade_datetime TIMESTAMP NOT NULL,
|
|
|
open DECIMAL(12, 4) NOT NULL,
|
|
|
high DECIMAL(12, 4) NOT NULL,
|
|
|
low DECIMAL(12, 4) NOT NULL,
|
|
|
close DECIMAL(12, 4) NOT NULL,
|
|
|
volume BIGINT NOT NULL,
|
|
|
amount DECIMAL(18, 4) NOT NULL,
|
|
|
settle DECIMAL(12, 4),
|
|
|
open_interest BIGINT,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
UNIQUE(code, period_type, trade_datetime)
|
|
|
);
|
|
|
|
|
|
CREATE INDEX idx_future_min_code_period_datetime ON future_kline_min(code, period_type, trade_datetime);
|
|
|
```
|
|
|
|
|
|
#### 4.2.7 实时快照数据表 (realtime_snapshot)
|
|
|
```sql
|
|
|
CREATE TABLE realtime_snapshot (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
security_type VARCHAR(20) NOT NULL, -- stock, future, index, etc.
|
|
|
trade_time TIMESTAMP NOT NULL,
|
|
|
pre_close DECIMAL(12, 4),
|
|
|
last DECIMAL(12, 4),
|
|
|
open DECIMAL(12, 4),
|
|
|
high DECIMAL(12, 4),
|
|
|
low DECIMAL(12, 4),
|
|
|
close DECIMAL(12, 4),
|
|
|
volume BIGINT,
|
|
|
amount DECIMAL(18, 4),
|
|
|
ask_price1 DECIMAL(12, 4),
|
|
|
ask_volume1 INTEGER,
|
|
|
bid_price1 DECIMAL(12, 4),
|
|
|
bid_volume1 INTEGER,
|
|
|
-- ... 其他快照字段
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
expires_at TIMESTAMP WITH TIME ZONE NOT NULL -- 7天后过期
|
|
|
);
|
|
|
|
|
|
CREATE INDEX idx_snapshot_code_time ON realtime_snapshot(code, trade_time);
|
|
|
CREATE INDEX idx_snapshot_expires ON realtime_snapshot(expires_at);
|
|
|
```
|
|
|
|
|
|
#### 4.2.8 缓存任务表 (cache_tasks)
|
|
|
```sql
|
|
|
CREATE TABLE cache_tasks (
|
|
|
id SERIAL PRIMARY KEY,
|
|
|
task_name VARCHAR(200) NOT NULL,
|
|
|
task_type VARCHAR(50) NOT NULL, -- 'detect_missing', 'cache_data'
|
|
|
security_type VARCHAR(20) NOT NULL, -- 'stock', 'future'
|
|
|
period_type VARCHAR(10), -- daily, min1, etc.
|
|
|
start_date DATE NOT NULL,
|
|
|
end_date DATE NOT NULL,
|
|
|
status VARCHAR(20) DEFAULT 'pending', -- pending, running, completed, failed
|
|
|
progress DECIMAL(5, 2) DEFAULT 0,
|
|
|
total_count INTEGER DEFAULT 0,
|
|
|
success_count INTEGER DEFAULT 0,
|
|
|
error_count INTEGER DEFAULT 0,
|
|
|
error_message TEXT,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
|
|
started_at TIMESTAMP WITH TIME ZONE,
|
|
|
completed_at TIMESTAMP WITH TIME ZONE
|
|
|
);
|
|
|
```
|
|
|
|
|
|
#### 4.2.9 缓存记录表 (cache_records)
|
|
|
```sql
|
|
|
CREATE TABLE cache_records (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
task_id INTEGER REFERENCES cache_tasks(id),
|
|
|
code VARCHAR(20) NOT NULL,
|
|
|
trade_date DATE NOT NULL,
|
|
|
record_count INTEGER NOT NULL,
|
|
|
status VARCHAR(20) DEFAULT 'success',
|
|
|
error_message TEXT,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
);
|
|
|
```
|
|
|
|
|
|
#### 4.2.10 API测试日志表 (api_test_logs)
|
|
|
```sql
|
|
|
CREATE TABLE api_test_logs (
|
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
test_name VARCHAR(200) NOT NULL,
|
|
|
api_category VARCHAR(50) NOT NULL,
|
|
|
api_endpoint VARCHAR(200) NOT NULL,
|
|
|
request_method VARCHAR(10) NOT NULL,
|
|
|
request_params JSONB,
|
|
|
response_data JSONB,
|
|
|
status_code INTEGER,
|
|
|
execution_time_ms INTEGER,
|
|
|
is_success BOOLEAN DEFAULT FALSE,
|
|
|
error_message TEXT,
|
|
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
|
);
|
|
|
|
|
|
CREATE INDEX idx_test_logs_category ON api_test_logs(api_category);
|
|
|
CREATE INDEX idx_test_logs_created ON api_test_logs(created_at);
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 五、API接口设计
|
|
|
|
|
|
### 5.1 认证相关接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| POST | /api/v1/auth/login | 用户登录 |
|
|
|
| POST | /api/v1/auth/logout | 用户登出 |
|
|
|
| GET | /api/v1/auth/me | 获取当前用户信息 |
|
|
|
| POST | /api/v1/auth/refresh | 刷新Token |
|
|
|
|
|
|
### 5.2 配置管理接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/configs/sdk | 获取SDK配置列表 |
|
|
|
| GET | /api/v1/configs/sdk/{id} | 获取指定SDK配置 |
|
|
|
| POST | /api/v1/configs/sdk | 创建SDK配置 |
|
|
|
| PUT | /api/v1/configs/sdk/{id} | 更新SDK配置 |
|
|
|
| DELETE | /api/v1/configs/sdk/{id} | 删除SDK配置 |
|
|
|
| POST | /api/v1/configs/sdk/{id}/test | 测试SDK连接 |
|
|
|
| POST | /api/v1/configs/sdk/{id}/set-default | 设为默认配置 |
|
|
|
|
|
|
### 5.3 基础数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/base/codes | 获取代码列表 |
|
|
|
| GET | /api/v1/base/codes/{code}/info | 获取证券信息 |
|
|
|
| GET | /api/v1/base/calendar | 获取交易日历 |
|
|
|
| GET | /api/v1/base/calendar/trading-days | 获取指定区间交易日 |
|
|
|
|
|
|
### 5.4 历史行情数据接口
|
|
|
|
|
|
#### 股票历史数据
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/stock/kline | 获取股票K线数据(单个/批量) |
|
|
|
| GET | /api/v1/stock/kline/{code}/chart | 获取股票K线图数据 |
|
|
|
| GET | /api/v1/stock/snapshot | 获取股票历史快照数据 |
|
|
|
|
|
|
#### 期货历史数据
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/future/kline | 获取期货K线数据(单个/批量) |
|
|
|
| GET | /api/v1/future/kline/{code}/chart | 获取期货K线图数据 |
|
|
|
| GET | /api/v1/future/snapshot | 获取期货历史快照数据 |
|
|
|
|
|
|
### 5.5 实时数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/realtime/snapshot | 获取最新快照数据 |
|
|
|
| POST | /api/v1/realtime/subscribe | 开始实时数据订阅 |
|
|
|
| DELETE | /api/v1/realtime/subscribe | 停止实时数据订阅 |
|
|
|
| GET | /api/v1/realtime/subscribe/status | 获取订阅状态 |
|
|
|
| GET | /api/v1/realtime/snapshot/stream | WebSocket实时数据流 |
|
|
|
|
|
|
### 5.6 财务数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/finance/balance-sheet | 获取资产负债表 |
|
|
|
| GET | /api/v1/finance/cash-flow | 获取现金流量表 |
|
|
|
| GET | /api/v1/finance/income | 获取利润表 |
|
|
|
| GET | /api/v1/finance/profit-express | 获取业绩快报 |
|
|
|
| GET | /api/v1/finance/profit-notice | 获取业绩预告 |
|
|
|
|
|
|
### 5.7 股东股本数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/shareholder/top10 | 获取十大股东数据 |
|
|
|
| GET | /api/v1/shareholder/count | 获取股东户数 |
|
|
|
| GET | /api/v1/shareholder/equity | 获取股本结构 |
|
|
|
|
|
|
### 5.8 融资融券数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/margin/summary | 获取融资融券汇总 |
|
|
|
| GET | /api/v1/margin/detail | 获取融资融券明细 |
|
|
|
|
|
|
### 5.9 指数数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/index/constituents | 获取指数成分股 |
|
|
|
| GET | /api/v1/index/weights | 获取指数权重 |
|
|
|
|
|
|
### 5.10 ETF数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/etf/pcf | 获取ETF申赎数据 |
|
|
|
| GET | /api/v1/etf/share | 获取ETF份额数据 |
|
|
|
|
|
|
### 5.11 可转债数据接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/kzz/issuance | 获取可转债发行数据 |
|
|
|
|
|
|
### 5.12 数据缓存管理接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| POST | /api/v1/cache/detect-missing | 检测缺失数据 |
|
|
|
| POST | /api/v1/cache/batch-cache | 批量缓存数据 |
|
|
|
| GET | /api/v1/cache/tasks | 获取缓存任务列表 |
|
|
|
| GET | /api/v1/cache/tasks/{id} | 获取任务详情 |
|
|
|
| DELETE | /api/v1/cache/tasks/{id} | 取消任务 |
|
|
|
| GET | /api/v1/cache/status/{code} | 获取代码缓存状态 |
|
|
|
|
|
|
### 5.13 测试中心接口
|
|
|
|
|
|
| 方法 | 路径 | 说明 |
|
|
|
|------|------|------|
|
|
|
| GET | /api/v1/test/categories | 获取测试分类 |
|
|
|
| GET | /api/v1/test/endpoints | 获取所有接口列表 |
|
|
|
| POST | /api/v1/test/run | 执行单个接口测试 |
|
|
|
| POST | /api/v1/test/run-all | 执行全部接口测试 |
|
|
|
| GET | /api/v1/test/history | 获取测试历史记录 |
|
|
|
| GET | /api/v1/test/history/{id} | 获取单次测试详情 |
|
|
|
|
|
|
---
|
|
|
|
|
|
## 六、核心业务逻辑
|
|
|
|
|
|
### 6.1 数据获取流程 (缓存优先)
|
|
|
|
|
|
```
|
|
|
用户请求 → 检查本地缓存 → 有数据 → 直接返回
|
|
|
↓
|
|
|
无数据/不完整
|
|
|
↓
|
|
|
调用AmazingData SDK → 获取数据 → 写入缓存 → 返回数据
|
|
|
```
|
|
|
|
|
|
### 6.2 缺失数据检测算法
|
|
|
|
|
|
```python
|
|
|
# 伪代码
|
|
|
def detect_missing_data(code, start_date, end_date, period='daily'):
|
|
|
# 1. 获取指定区间的交易日列表
|
|
|
trading_days = get_trading_days(start_date, end_date)
|
|
|
|
|
|
# 2. 查询数据库中已有数据的日期
|
|
|
existing_data = query_db_for_existing_dates(code, start_date, end_date, period)
|
|
|
|
|
|
# 3. 计算每个交易日的数据条数
|
|
|
missing_dates = []
|
|
|
for date in trading_days:
|
|
|
expected_count = get_expected_count_for_date(code, date, period)
|
|
|
actual_count = existing_data.get(date, 0)
|
|
|
|
|
|
# 4. 偏差超过10%认为缺失
|
|
|
if actual_count < expected_count * 0.9:
|
|
|
missing_dates.append({
|
|
|
'date': date,
|
|
|
'expected': expected_count,
|
|
|
'actual': actual_count,
|
|
|
'missing_ratio': 1 - actual_count / expected_count
|
|
|
})
|
|
|
|
|
|
return missing_dates
|
|
|
```
|
|
|
|
|
|
### 6.3 数据去重插入逻辑
|
|
|
|
|
|
```python
|
|
|
# 伪代码
|
|
|
def cache_data_with_dedup(code, data_df, period='daily'):
|
|
|
# 1. 构建唯一键
|
|
|
if period == 'daily':
|
|
|
existing = query_existing_data(code, data_df.index.min(), data_df.index.max())
|
|
|
else:
|
|
|
existing = query_existing_data(code, data_df.index.min(), data_df.index.max(), period)
|
|
|
|
|
|
# 2. 比较核心数据字段 (open, high, low, close, volume)
|
|
|
core_columns = ['open', 'high', 'low', 'close', 'volume']
|
|
|
|
|
|
to_insert = []
|
|
|
for idx, row in data_df.iterrows():
|
|
|
key = (code, idx) if period == 'daily' else (code, period, idx)
|
|
|
|
|
|
if key in existing:
|
|
|
# 3. 数据已存在,比较核心字段
|
|
|
existing_row = existing[key]
|
|
|
is_same = all(
|
|
|
abs(row[col] - existing_row[col]) < 0.0001
|
|
|
for col in core_columns
|
|
|
)
|
|
|
if is_same:
|
|
|
continue # 数据相同,跳过
|
|
|
|
|
|
to_insert.append(row)
|
|
|
|
|
|
# 4. 批量插入新数据
|
|
|
if to_insert:
|
|
|
batch_insert(to_insert)
|
|
|
```
|
|
|
|
|
|
### 6.4 实时数据订阅流程
|
|
|
|
|
|
```
|
|
|
前端请求订阅 → 后端建立WebSocket连接 → 初始化AmazingData订阅
|
|
|
↓
|
|
|
前端 ← WebSocket推送 ← 回调函数接收数据 ← SDK实时推送
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 七、前端页面设计
|
|
|
|
|
|
### 7.1 页面结构
|
|
|
|
|
|
```
|
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
|
│ [Logo] AmazingData金融数据服务平台 [用户] [退出] │
|
|
|
├─────────────────────────────────────────────────────────────┤
|
|
|
│ ┌──────┐ │
|
|
|
│ │ 首页 │ ┌──────────────────────────────────────────┐ │
|
|
|
│ ├──────┤ │ │ │
|
|
|
│ │数据查询│ │ 页面内容区域 │ │
|
|
|
│ ├──────┤ │ │ │
|
|
|
│ │配置管理│ │ │ │
|
|
|
│ ├──────┤ │ │ │
|
|
|
│ │缓存管理│ │ │ │
|
|
|
│ ├──────┤ │ │ │
|
|
|
│ │测试中心│ │ │ │
|
|
|
│ └──────┘ └──────────────────────────────────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
### 7.2 登录页面
|
|
|
- 用户名/密码输入框
|
|
|
- 记住我选项
|
|
|
- 登录按钮
|
|
|
|
|
|
### 7.3 配置管理页面
|
|
|
- SDK配置列表(卡片形式)
|
|
|
- 添加/编辑配置表单(弹窗)
|
|
|
- 测试连接按钮
|
|
|
- 设为默认按钮
|
|
|
|
|
|
### 7.4 数据查询页面
|
|
|
- **K线图查询**
|
|
|
- 代码输入(支持股票/期货)
|
|
|
- 时间区间选择(默认1年)
|
|
|
- 周期选择(日线/分钟线)
|
|
|
- K线图展示(ECharts)
|
|
|
- 数据表格展示
|
|
|
|
|
|
- **批量数据查询**
|
|
|
- 多代码输入(支持批量粘贴)
|
|
|
- 时间区间选择
|
|
|
- 数据列表展示(分页)
|
|
|
- 导出功能
|
|
|
|
|
|
### 7.5 缓存管理页面
|
|
|
- **缺失数据检测**
|
|
|
- 品种选择(股票/期货)
|
|
|
- 时间区间选择
|
|
|
- 检测结果列表
|
|
|
- 一键缓存按钮
|
|
|
|
|
|
- **缓存任务管理**
|
|
|
- 任务列表(进度条展示)
|
|
|
- 任务详情(成功/失败统计)
|
|
|
- 取消任务按钮
|
|
|
|
|
|
### 7.6 测试中心页面
|
|
|
- 接口分类树(基础数据/历史数据/实时数据/财务数据/...)
|
|
|
- 接口列表(表格)
|
|
|
- 单个接口测试(参数表单 + 结果展示)
|
|
|
- 一键全部测试按钮
|
|
|
- 测试历史记录
|
|
|
|
|
|
---
|
|
|
|
|
|
## 八、项目目录结构
|
|
|
|
|
|
```
|
|
|
amazing-data-service/
|
|
|
├── backend/
|
|
|
│ ├── app/
|
|
|
│ │ ├── __init__.py
|
|
|
│ │ ├── main.py # FastAPI入口
|
|
|
│ │ ├── config.py # 配置管理
|
|
|
│ │ ├── dependencies.py # 依赖注入
|
|
|
│ │ ├── core/
|
|
|
│ │ │ ├── __init__.py
|
|
|
│ │ │ ├── security.py # JWT认证
|
|
|
│ │ │ ├── exceptions.py # 异常处理
|
|
|
│ │ │ └── middleware.py # 中间件
|
|
|
│ │ ├── api/
|
|
|
│ │ │ ├── __init__.py
|
|
|
│ │ │ ├── v1/
|
|
|
│ │ │ │ ├── __init__.py
|
|
|
│ │ │ │ ├── auth.py # 认证接口
|
|
|
│ │ │ │ ├── configs.py # 配置接口
|
|
|
│ │ │ │ ├── base_data.py # 基础数据接口
|
|
|
│ │ │ │ ├── stock.py # 股票数据接口
|
|
|
│ │ │ │ ├── future.py # 期货数据接口
|
|
|
│ │ │ │ ├── realtime.py # 实时数据接口
|
|
|
│ │ │ │ ├── finance.py # 财务数据接口
|
|
|
│ │ │ │ ├── shareholder.py # 股东数据接口
|
|
|
│ │ │ │ ├── margin.py # 融资融券接口
|
|
|
│ │ │ │ ├── index.py # 指数数据接口
|
|
|
│ │ │ │ ├── etf.py # ETF数据接口
|
|
|
│ │ │ │ ├── kzz.py # 可转债数据接口
|
|
|
│ │ │ │ ├── cache.py # 缓存管理接口
|
|
|
│ │ │ │ └── test.py # 测试中心接口
|
|
|
│ │ ├── models/
|
|
|
│ │ │ ├── __init__.py
|
|
|
│ │ │ ├── user.py # 用户模型
|
|
|
│ │ │ ├── config.py # 配置模型
|
|
|
│ │ │ ├── stock.py # 股票数据模型
|
|
|
│ │ │ ├── future.py # 期货数据模型
|
|
|
│ │ │ ├── realtime.py # 实时数据模型
|
|
|
│ │ │ ├── finance.py # 财务数据模型
|
|
|
│ │ │ ├── cache.py # 缓存任务模型
|
|
|
│ │ │ └── test.py # 测试日志模型
|
|
|
│ │ ├── schemas/
|
|
|
│ │ │ ├── __init__.py
|
|
|
│ │ │ ├── auth.py # 认证Schema
|
|
|
│ │ │ ├── base.py # 基础Schema
|
|
|
│ │ │ ├── config.py # 配置Schema
|
|
|
│ │ │ ├── kline.py # K线Schema
|
|
|
│ │ │ ├── finance.py # 财务Schema
|
|
|
│ │ │ ├── cache.py # 缓存Schema
|
|
|
│ │ │ └── test.py # 测试Schema
|
|
|
│ │ ├── services/
|
|
|
│ │ │ ├── __init__.py
|
|
|
│ │ │ ├── auth_service.py # 认证服务
|
|
|
│ │ │ ├── config_service.py # 配置服务
|
|
|
│ │ │ ├── amazing_data_service.py # SDK封装服务
|
|
|
│ │ │ ├── cache_service.py # 缓存服务
|
|
|
│ │ │ ├── stock_service.py # 股票数据服务
|
|
|
│ │ │ ├── future_service.py # 期货数据服务
|
|
|
│ │ │ ├── realtime_service.py # 实时数据服务
|
|
|
│ │ │ ├── finance_service.py # 财务数据服务
|
|
|
│ │ │ ├── base_data_service.py # 基础数据服务
|
|
|
│ │ │ └── test_service.py # 测试服务
|
|
|
│ │ ├── db/
|
|
|
│ │ │ ├── __init__.py
|
|
|
│ │ │ ├── base.py # 数据库基础
|
|
|
│ │ │ └── session.py # 会话管理
|
|
|
│ │ └── utils/
|
|
|
│ │ ├── __init__.py
|
|
|
│ │ ├── date_utils.py # 日期工具
|
|
|
│ │ ├── data_utils.py # 数据处理工具
|
|
|
│ │ └── validators.py # 验证器
|
|
|
│ ├── alembic/ # 数据库迁移
|
|
|
│ ├── tests/
|
|
|
│ ├── requirements.txt
|
|
|
│ └── Dockerfile
|
|
|
├── frontend/
|
|
|
│ ├── src/
|
|
|
│ │ ├── api/ # API接口封装
|
|
|
│ │ ├── components/ # 公共组件
|
|
|
│ │ ├── views/ # 页面视图
|
|
|
│ │ │ ├── Login.vue
|
|
|
│ │ │ ├── Dashboard.vue
|
|
|
│ │ │ ├── ConfigManager.vue
|
|
|
│ │ │ ├── DataQuery/
|
|
|
│ │ │ │ ├── KlineChart.vue
|
|
|
│ │ │ │ └── BatchQuery.vue
|
|
|
│ │ │ ├── CacheManager/
|
|
|
│ │ │ │ ├── DetectMissing.vue
|
|
|
│ │ │ │ └── TaskManager.vue
|
|
|
│ │ │ └── TestCenter/
|
|
|
│ │ │ ├── ApiTest.vue
|
|
|
│ │ │ └── TestHistory.vue
|
|
|
│ │ ├── router/
|
|
|
│ │ ├── store/
|
|
|
│ │ ├── utils/
|
|
|
│ │ └── App.vue
|
|
|
│ ├── public/
|
|
|
│ ├── package.json
|
|
|
│ └── vite.config.ts
|
|
|
├── database/
|
|
|
│ ├── init.sql # 数据库初始化脚本
|
|
|
│ └── migrations/
|
|
|
├── docker/
|
|
|
│ ├── docker-compose.yml
|
|
|
│ └── nginx.conf
|
|
|
├── docs/
|
|
|
│ ├── api.md
|
|
|
│ └── deploy.md
|
|
|
├── scripts/
|
|
|
│ ├── init_db.py
|
|
|
│ └── create_admin.py
|
|
|
└── README.md
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 九、部署架构
|
|
|
|
|
|
```
|
|
|
┌─────────────────────────────────────────────────────────────────────┐
|
|
|
│ Docker Compose │
|
|
|
│ │
|
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
|
│ │ Nginx │ │ Frontend │ │ Backend │ │
|
|
|
│ │ (反向代理) │ │ (Vue3) │ │ (FastAPI) │ │
|
|
|
│ └──────┬───────┘ └──────────────┘ └──────┬───────┘ │
|
|
|
│ │ │ │
|
|
|
│ └────────────────────────────────────┘ │
|
|
|
│ │ │
|
|
|
│ ┌────────────┼────────────┐ │
|
|
|
│ ▼ ▼ ▼ │
|
|
|
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
|
|
│ │ PostgreSQL │ │ Redis │ │ (AmazingData │ │
|
|
|
│ │ (主数据库) │ │ (缓存) │ │ SDK连接) │ │
|
|
|
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
|
|
└─────────────────────────────────────────────────────────────────────┘
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 十、关键功能实现要点
|
|
|
|
|
|
### 10.1 AmazingData SDK适配器
|
|
|
|
|
|
```python
|
|
|
class AmazingDataAdapter:
|
|
|
"""SDK适配器,封装AmazingData所有接口"""
|
|
|
|
|
|
def __init__(self, config: SDKConfig):
|
|
|
self.config = config
|
|
|
self._ad = None
|
|
|
self._base_data = None
|
|
|
self._market_data = None
|
|
|
self._info_data = None
|
|
|
self._calendar = None
|
|
|
|
|
|
def connect(self) -> bool:
|
|
|
"""建立连接"""
|
|
|
import AmazingData as ad
|
|
|
ad.login(**self.config.to_dict())
|
|
|
self._ad = ad
|
|
|
self._base_data = ad.BaseData()
|
|
|
self._info_data = ad.InfoData()
|
|
|
self._calendar = self._base_data.get_calendar()
|
|
|
self._market_data = ad.MarketData(self._calendar)
|
|
|
return True
|
|
|
|
|
|
# 基础数据接口
|
|
|
def get_code_list(self, security_type: str) -> List[str]: ...
|
|
|
def get_code_info(self, security_type: str) -> pd.DataFrame: ...
|
|
|
def get_trading_calendar(self, market: str) -> List[int]: ...
|
|
|
|
|
|
# 历史行情接口
|
|
|
def get_kline(self, codes, start_date, end_date, period) -> Dict[str, pd.DataFrame]: ...
|
|
|
def get_snapshot(self, codes, start_date, end_date) -> Dict[str, pd.DataFrame]: ...
|
|
|
|
|
|
# 财务数据接口
|
|
|
def get_balance_sheet(self, codes, start_date, end_date) -> Dict[str, pd.DataFrame]: ...
|
|
|
def get_cash_flow(self, codes, start_date, end_date) -> Dict[str, pd.DataFrame]: ...
|
|
|
def get_income_statement(self, codes, start_date, end_date) -> Dict[str, pd.DataFrame]: ...
|
|
|
|
|
|
# 其他所有接口...
|
|
|
```
|
|
|
|
|
|
### 10.2 缓存服务
|
|
|
|
|
|
```python
|
|
|
class CacheService:
|
|
|
"""数据缓存服务"""
|
|
|
|
|
|
def get_kline_with_cache(self, code: str, start_date: date,
|
|
|
end_date: date, period: str) -> pd.DataFrame:
|
|
|
"""优先从缓存获取,否则从SDK获取并缓存"""
|
|
|
|
|
|
# 1. 查询本地数据库
|
|
|
cached_data = self.db.query_kline(code, start_date, end_date, period)
|
|
|
|
|
|
# 2. 检查数据完整性
|
|
|
if self._is_data_complete(cached_data, start_date, end_date):
|
|
|
return cached_data
|
|
|
|
|
|
# 3. 从SDK获取缺失数据
|
|
|
missing_ranges = self._find_missing_ranges(cached_data, start_date, end_date)
|
|
|
for range_start, range_end in missing_ranges:
|
|
|
sdk_data = self.sdk.get_kline(code, range_start, range_end, period)
|
|
|
self.db.save_kline(code, sdk_data, period)
|
|
|
|
|
|
# 4. 重新查询完整数据
|
|
|
return self.db.query_kline(code, start_date, end_date, period)
|
|
|
```
|
|
|
|
|
|
### 10.3 实时数据WebSocket
|
|
|
|
|
|
```python
|
|
|
class RealtimeManager:
|
|
|
"""实时数据管理器"""
|
|
|
|
|
|
def __init__(self):
|
|
|
self.subscribers: Dict[str, Set[WebSocket]] = {}
|
|
|
self.sdk_subscriber = None
|
|
|
|
|
|
async def subscribe(self, websocket: WebSocket, codes: List[str]):
|
|
|
"""客户端订阅"""
|
|
|
await websocket.accept()
|
|
|
for code in codes:
|
|
|
if code not in self.subscribers:
|
|
|
self.subscribers[code] = set()
|
|
|
# 启动SDK订阅
|
|
|
self._start_sdk_subscription(code)
|
|
|
self.subscribers[code].add(websocket)
|
|
|
|
|
|
def _on_sdk_data(self, code: str, data: dict):
|
|
|
"""SDK数据回调"""
|
|
|
# 1. 保存到数据库(带过期时间)
|
|
|
self.db.save_realtime(data)
|
|
|
|
|
|
# 2. 推送给所有订阅者
|
|
|
for ws in self.subscribers.get(code, []):
|
|
|
asyncio.create_task(ws.send_json(data))
|
|
|
```
|
|
|
|
|
|
---
|
|
|
|
|
|
## 十一、开发计划
|
|
|
|
|
|
| 阶段 | 任务 | 预计时间 |
|
|
|
|------|------|----------|
|
|
|
| 第一阶段 | 项目初始化、数据库设计、基础框架搭建 | 2天 |
|
|
|
| 第二阶段 | 认证模块、配置管理模块开发 | 2天 |
|
|
|
| 第三阶段 | SDK适配器、基础数据接口开发 | 3天 |
|
|
|
| 第四阶段 | 历史数据接口(股票/期货)、缓存逻辑 | 4天 |
|
|
|
| 第五阶段 | 实时数据订阅功能 | 3天 |
|
|
|
| 第六阶段 | 财务/股东/融资融券等数据接口 | 3天 |
|
|
|
| 第七阶段 | 批量缓存管理功能 | 3天 |
|
|
|
| 第八阶段 | 测试中心功能 | 2天 |
|
|
|
| 第九阶段 | 前端页面开发 | 5天 |
|
|
|
| 第十阶段 | 集成测试、部署文档 | 2天 |
|
|
|
|
|
|
**总计:约29天**
|
|
|
|
|
|
---
|
|
|
|
|
|
## 十二、风险与注意事项
|
|
|
|
|
|
1. **数据准确性**:AmazingData SDK返回的数据需要验证,建议增加数据校验逻辑
|
|
|
2. **并发性能**:大量数据查询时需要控制并发,避免SDK连接超时
|
|
|
3. **存储空间**:历史数据量巨大,需要定期归档或清理
|
|
|
4. **SDK连接**:AmazingData SDK需要保持连接,建议使用连接池
|
|
|
5. **实时数据延迟**:网络延迟可能导致实时数据推送不及时
|
|
|
|
|
|
---
|
|
|
|
|
|
*文档版本: 1.0*
|
|
|
*创建日期: 2025年*
|