同步文档与实际代码状态
This commit is contained in:
104
README.md
104
README.md
@@ -13,7 +13,7 @@
|
||||
### 1. 启动全栈服务
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
docker-compose -f docker-compose.trade.yml up -d
|
||||
```
|
||||
|
||||
这会同时启动 PostgreSQL、tushare API 服务(端口 8000)与 Web 浏览端(端口 8080)。
|
||||
@@ -21,7 +21,7 @@ docker-compose up -d
|
||||
### 3. 通过 CLI 跑当月主力
|
||||
|
||||
```bash
|
||||
docker-compose run --rm tushare python -m src.main
|
||||
docker-compose -f docker-compose.trade.yml run --rm tushare python -m src.main
|
||||
```
|
||||
|
||||
不传参时,按 `tushare/src/contracts.py` 的 `ROLLOVER_RULES` 自动选 FG 玻璃当月主力(例如 2026-05 -> `FG2609.ZCE`),启动后会先打印 `[AUTO] FG 当月主力 -> ...`,然后:
|
||||
@@ -35,28 +35,28 @@ docker-compose run --rm tushare python -m src.main
|
||||
|
||||
```bash
|
||||
# 触发 FG 打分
|
||||
curl -X POST http://localhost:8000/api/v1/run -H "Content-Type: application/json" \
|
||||
curl -X POST http://localhost:4001/api/v1/run -H "Content-Type: application/json" \
|
||||
-d '{"symbol":"FG"}'
|
||||
|
||||
# 查询最新打分
|
||||
curl "http://localhost:8000/api/v1/scores?limit=5"
|
||||
curl "http://localhost:4001/api/v1/scores?limit=5"
|
||||
|
||||
# 查询合约列表
|
||||
curl "http://localhost:8000/api/v1/contracts"
|
||||
curl "http://localhost:4001/api/v1/contracts"
|
||||
|
||||
# 查询 K 线数据
|
||||
curl "http://localhost:8000/api/v1/candles?ts_code=FG2609.ZCE"
|
||||
curl "http://localhost:4001/api/v1/candles?ts_code=FG2609.ZCE"
|
||||
```
|
||||
|
||||
### 5. 跑其他合约或品种
|
||||
|
||||
```bash
|
||||
# 显式指定合约
|
||||
docker-compose run --rm tushare python -m src.main RB2510.SHF
|
||||
docker-compose run --rm tushare python -m src.main I2601.DCE
|
||||
docker-compose -f docker-compose.trade.yml run --rm tushare python -m src.main RB2510.SHF
|
||||
docker-compose -f docker-compose.trade.yml run --rm tushare python -m src.main I2601.DCE
|
||||
|
||||
# 按品种代号自动选当月主力(目前只配置了 FG)
|
||||
docker-compose run --rm tushare python -m src.main --symbol FG
|
||||
docker-compose -f docker-compose.trade.yml run --rm tushare python -m src.main --symbol FG
|
||||
```
|
||||
|
||||
### 6. 玻璃 FG 主力轮换规则
|
||||
@@ -130,27 +130,27 @@ docker-compose run --rm tushare python -m src.main --symbol FG
|
||||
|
||||
```bash
|
||||
# 查看最新打分
|
||||
docker-compose exec postgres psql -U trade -d futures -c \
|
||||
docker-compose -f docker-compose.trade.yml exec postgres psql -U trade -d futures -c \
|
||||
"SELECT ts_code, trade_date, composite, signal FROM scores ORDER BY trade_date DESC LIMIT 5;"
|
||||
|
||||
# 查看合约日线
|
||||
docker-compose exec postgres psql -U trade -d futures -c \
|
||||
docker-compose -f docker-compose.trade.yml exec postgres psql -U trade -d futures -c \
|
||||
"SELECT trade_date, open, high, low, close, vol, oi FROM candles WHERE ts_code='FG2609.ZCE' ORDER BY trade_date DESC LIMIT 10;"
|
||||
|
||||
# 或通过 API 查询
|
||||
curl "http://localhost:8000/api/v1/scores?ts_code=FG2609.ZCE&limit=10"
|
||||
curl "http://localhost:8000/api/v1/candles?ts_code=FG2609.ZCE"
|
||||
curl "http://localhost:4001/api/v1/scores?ts_code=FG2609.ZCE&limit=10"
|
||||
curl "http://localhost:4001/api/v1/candles?ts_code=FG2609.ZCE"
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
trade/
|
||||
├── docker-compose.yml # Docker Compose 编排(postgres + tushare + web)
|
||||
├── 使用说明.md # 本文件
|
||||
├── docker-compose.trade.yml # Docker Compose 编排(postgres + tushare + web)
|
||||
├── README.md # 本文件
|
||||
├── CLAUDE.md # Claude Code 项目指引
|
||||
├── data/ # auth.db 目录(gitignored)
|
||||
│ └── auth.db # web 自己维护的用户表(SQLite)
|
||||
├── data/ # 数据目录(gitignored)
|
||||
│ └── (运行时生成)
|
||||
├── .gitignore # Git 忽略配置
|
||||
├── tushare/ # Python 数据服务
|
||||
│ ├── Dockerfile
|
||||
@@ -165,17 +165,17 @@ trade/
|
||||
│ └── main.py # CLI 入口
|
||||
└── web/ # Web 浏览端
|
||||
├── .dockerignore
|
||||
├── backend/ # Go 1.25 后端 (chi + lib/pq + JWT)
|
||||
├── backend/ # Go 1.25 后端 (chi + lib/pq)
|
||||
│ ├── Dockerfile # 多阶段:node 构 UI → go 构二进制 → alpine 运行
|
||||
│ ├── go.mod
|
||||
│ ├── main.go
|
||||
│ ├── embed.go # //go:embed all:dist
|
||||
│ ├── .env.example # ADMIN_USER/ADMIN_PASS/JWT_SECRET 示例
|
||||
│ ├── go.sum
|
||||
│ ├── dist/ # 占位,Docker 构建期被 vite 输出覆盖
|
||||
│ └── internal/
|
||||
│ ├── config/ # 环境变量加载
|
||||
│ ├── store/ # PostgreSQL 业务查询 + SQLite auth.db
|
||||
│ ├── auth/ # JWT + bcrypt + 首启 admin 引导
|
||||
│ ├── store/ # PostgreSQL 业务查询 + 用户管理
|
||||
│ ├── auth/ # bcrypt + 首启 admin 引导
|
||||
│ ├── middleware/ # RequireUser / RequireAdmin / 日志
|
||||
│ ├── handlers/ # 登录 / 打分 / K线 / 用户管理
|
||||
│ └── router/ # chi 路由装配
|
||||
@@ -196,10 +196,10 @@ trade/
|
||||
## 技术栈
|
||||
|
||||
- **Python 3.13** (alpine) + **tushare** + **pandas** + **FastAPI** + **psycopg3** — 数据采集、打分与 API 服务
|
||||
- **Go 1.25.8** (alpine 3.23) + **chi** + **lib/pq** + **JWT** — Web 后端
|
||||
- **Go 1.25.8** (alpine 3.23) + **chi** + **lib/pq** — Web 后端
|
||||
- **Vue 3** + **Vite** + **Element Plus** + **ECharts** — Web 前端
|
||||
- **PostgreSQL 18.3** (alpine 3.23) — 业务数据存储
|
||||
- **SQLite** — 鉴权数据存储(auth.db)
|
||||
- **PostgreSQL** — 业务数据与用户鉴权数据统一存储
|
||||
- **Docker / Docker Compose** — 容器化部署
|
||||
|
||||
## 常见问题
|
||||
@@ -214,35 +214,23 @@ A: 郑商所用 `.ZCE` 后缀(如 `FG2609.ZCE`),上期所用 `.SHF`,大
|
||||
|
||||
**Q: 如何定时自动跑?**
|
||||
|
||||
A: 通过宿主机 cron / launchd 等定时器调用 `docker-compose run --rm tushare ...`。也可直接调用 API: `curl -X POST http://localhost:8000/api/v1/run ...`。
|
||||
A: 通过宿主机 cron / launchd 等定时器调用 `docker-compose -f docker-compose.trade.yml run --rm tushare ...`。也可直接调用 API: `curl -X POST http://localhost:4001/api/v1/run ...`。
|
||||
|
||||
## Web 报表(浏览端)
|
||||
|
||||
`./web/` 提供一个图形化的浏览端,展示 tushare 流水线写入 PostgreSQL 的打分与行情数据。后端 Go(`golang:1.25.8-alpine3.23`)读取数据库,前端 Vue 3 + Element Plus + ECharts,通过 docker-compose 一起部署。
|
||||
|
||||
### 1. 配置首启凭据
|
||||
|
||||
在 `web/backend/.env` 写入(`.env` 已 gitignored,可参考 `web/backend/.env.example`):
|
||||
|
||||
```bash
|
||||
ADMIN_USER=admin
|
||||
ADMIN_PASS=请改成强密码
|
||||
JWT_SECRET=$(openssl rand -hex 32)
|
||||
```
|
||||
|
||||
`ADMIN_USER`/`ADMIN_PASS` 仅在 `auth.db` 中没有任何 admin 时生效,首次启动会以这一对凭据建立管理员;之后即使改这两个变量也不会改密。`JWT_SECRET` 必须 ≥16 字符。
|
||||
|
||||
### 2. 启动
|
||||
### 1. 启动
|
||||
|
||||
```bash
|
||||
# 构建并启动 web 服务,不影响现有 tushare
|
||||
docker-compose up -d --build web
|
||||
docker-compose -f docker-compose.trade.yml up -d --build web
|
||||
|
||||
# 查看启动日志:首启会出现 [bootstrap] admin 'xxx' created
|
||||
docker-compose logs -f web
|
||||
# 查看启动日志:首启会出现 [bootstrap] admin created
|
||||
docker-compose -f docker-compose.trade.yml logs -f web
|
||||
```
|
||||
|
||||
浏览器访问 `http://localhost:8080`,用上一步的管理员账号登录。
|
||||
浏览器访问 `http://localhost:4000`。首次启动时系统会自动创建默认管理员账号 `admin` / `admin`,首次登录后系统会强制要求修改密码。
|
||||
|
||||
### 3. 页面说明
|
||||
|
||||
@@ -258,45 +246,39 @@ docker-compose logs -f web
|
||||
|
||||
1. 用 admin 登录 → 进入 `/admin/users` → 「新建账号」,填写用户名 / 密码(≥6 位) / 角色。
|
||||
2. 把账号发给同事即可登录;无注册入口。
|
||||
3. 离职 / 风险事件:用「禁用」临时停用(token 立即失效,前端不能再请求),或「删除」彻底清除。
|
||||
3. 离职 / 风险事件:用「禁用」临时停用(被禁用的账号将无法登录),或「删除」彻底清除。
|
||||
|
||||
### 5. 数据流向与数据库分离
|
||||
### 5. 数据流向与数据库
|
||||
|
||||
```
|
||||
tushare(写) → PostgreSQL futures 数据库 ←(只读)── web 后端
|
||||
web 后端 ←(读写)→ data/auth.db (SQLite)
|
||||
tushare(写) → PostgreSQL futures 数据库 ←(读写)── web 后端
|
||||
```
|
||||
|
||||
业务数据(`candles` + `scores`)统一存储在 PostgreSQL 中,`auth.db` 表为:
|
||||
业务数据(`candles` + `scores`)与用户鉴权数据(`users`)统一存储在 PostgreSQL `futures` 数据库中。`users` 表结构:
|
||||
|
||||
```sql
|
||||
users(id, username UNIQUE, password_hash, role IN ('admin','user'),
|
||||
disabled, created_at, updated_at)
|
||||
users(id SERIAL PRIMARY KEY, username TEXT UNIQUE, password_hash TEXT,
|
||||
role TEXT CHECK(role IN ('admin','user')), disabled BOOLEAN,
|
||||
force_password_change BOOLEAN, created_at TEXT, updated_at TEXT)
|
||||
```
|
||||
|
||||
`auth.db` 在 `./data/` 目录,被 `.gitignore` 覆盖。
|
||||
|
||||
### 6. 常见问题
|
||||
|
||||
**Q: 忘记管理员密码怎么办?**
|
||||
|
||||
```bash
|
||||
docker-compose stop web
|
||||
sqlite3 data/auth.db "DELETE FROM users WHERE role='admin';"
|
||||
# 修改 web/backend/.env 里的 ADMIN_USER/ADMIN_PASS
|
||||
docker-compose up -d web
|
||||
docker-compose -f docker-compose.trade.yml stop web
|
||||
docker-compose -f docker-compose.trade.yml exec postgres psql -U trade -d futures -c \
|
||||
"DELETE FROM users WHERE role='admin';"
|
||||
docker-compose -f docker-compose.trade.yml up -d web
|
||||
```
|
||||
|
||||
启动时会重新触发 bootstrap 写入新的 admin。
|
||||
启动时会重新触发 bootstrap 写入新的默认管理员 `admin` / `admin`。
|
||||
|
||||
**Q: 改了 Go / Vue 代码但页面没变?**
|
||||
|
||||
源码不挂载,镜像内是 COPY 进去的。重建:`docker-compose build web && docker-compose up -d web`。
|
||||
|
||||
**Q: 登录提示 "JWT_SECRET 必须至少 16 个字符"?**
|
||||
|
||||
`web/backend/.env` 没设或太短,用 `openssl rand -hex 32` 生成一个 64 字符的十六进制字符串即可。
|
||||
源码不挂载,镜像内是 COPY 进去的。重建:`docker-compose -f docker-compose.trade.yml build web && docker-compose -f docker-compose.trade.yml up -d web`。
|
||||
|
||||
**Q: 为什么 tushare 容器启动后没有立即退出?**
|
||||
|
||||
因为默认命令改为 `uvicorn src.api:app` 常驻 API 服务。如需执行单次 CLI,用 `docker-compose run --rm tushare python -m src.main ...`。
|
||||
因为默认命令改为 `uvicorn src.api:app` 常驻 API 服务。如需执行单次 CLI,用 `docker-compose -f docker-compose.trade.yml run --rm tushare python -m src.main ...`。
|
||||
|
||||
Reference in New Issue
Block a user