2026-05-04 21:36:48 +08:00
2026-05-03 22:09:46 +08:00
2026-05-04 21:36:48 +08:00
2026-05-03 22:31:19 +08:00
2026-05-03 22:31:19 +08:00

期货行情分析系统 — 使用说明

基于 Docker + Python(tushare) + PostgreSQL 的中国期货行情分析系统。当前阶段已实现数据采集、三层加权打分模型与 Web 报表浏览端。运行方式支持两种模式:① 宿主机定时器触发 docker-compose run 执行 CLI;② 通过 FastAPI HTTP API 服务触发。

环境准备

  • Docker >= 20.10
  • Docker Compose >= 2.0
  • (可选) psql 或任意 PostgreSQL 客户端用于本地查库

快速开始

1. 启动全栈服务

docker-compose -f docker-compose.trade.yml up -d

这会同时启动 PostgreSQL、tushare API 服务(端口 8000)与 Web 浏览端(端口 8080)。

3. 通过 CLI 跑当月主力

docker-compose -f docker-compose.trade.yml run --rm tushare python -m src.main

不传参时,按 tushare/src/contracts.pyROLLOVER_RULES 自动选 FG 玻璃当月主力(例如 2026-05 -> FG2609.ZCE),启动后会先打印 [AUTO] FG 当月主力 -> ...,然后:

  1. 从 tushare 拉取合约日线数据
  2. 写入 PostgreSQL futures 数据库
  3. 运行三层打分模型
  4. 保存打分结果并输出到 stdout

4. 通过 API 触发流水线

# 触发 FG 打分
curl -X POST http://localhost:4001/api/v1/run -H "Content-Type: application/json" \
  -d '{"symbol":"FG"}'

# 批量触发所有固定品种今日打分
curl -X POST http://localhost:4001/api/v1/run/batch

# 查询最新打分
curl "http://localhost:4001/api/v1/scores?limit=5"

# 查询合约列表
curl "http://localhost:4001/api/v1/contracts"

# 查询 K 线数据
curl "http://localhost:4001/api/v1/candles?ts_code=FG2609.ZCE"

5. 跑其他合约或品种

# 显式指定合约
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 -f docker-compose.trade.yml run --rm tushare python -m src.main --symbol FG

6. 玻璃 FG 主力轮换规则

当前自然月 主力合约
1、2、3 月 当年 05
4、5、6、7 月 当年 09
8、9、10、11 月 次年 01
12 月 次年 05

三层打分模型

综合分数公式

综合分数 = (短期动力 × 0.4) + (中期趋势 × 0.35) + (长期结构 × 0.25)

1. 短期动力7 日窗口,权重 0.4

逐日打分后取均值:

持仓变化 价格方向 得分
增仓 上涨 100多头主动进攻
增仓 下跌 0空头主动进攻
减仓 上涨 70空头撤退
减仓 下跌 30多头撤退
持平(|变化|<1% 上涨 60
持平(|变化|<1% 下跌 40

2. 中期趋势15 日窗口,权重 0.35

价格信号 = (今收 - 15日前收) / 15日前收
价格信号得分 = clamp(50 + 收益率×500, 0, 100)

资金意愿:
  增仓上涨天数 > 增仓下跌天数 → 80
  两者相当 → 50
  增仓下跌天数 > 增仓上涨天数 → 20

模块得分 = 价格信号 × 0.6 + 资金意愿 × 0.4

3. 长期结构30 日窗口,权重 0.25

持仓变化幅度 = (30日日均持仓 - 30日前持仓) / 30日前持仓

> 10%  → 90显著增仓
5%~10% → 70温和增仓
-5%~5% → 50基本持平
-10%~-5% → 30温和减仓
< -10% → 10显著减仓

信号解读

综合分数 信号
80-100 强烈看多 — 价格与资金共振
50-80 偏多/震荡偏强
40-50 偏空/震荡偏弱
0-40 强烈看空 — 资金主动打压

数据查询

业务数据存储在 PostgreSQL 中,可通过以下方式查询:

# 查看最新打分
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 -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:4001/api/v1/scores?ts_code=FG2609.ZCE&limit=10"
curl "http://localhost:4001/api/v1/candles?ts_code=FG2609.ZCE"

项目结构

trade/
├── docker-compose.trade.yml    # Docker Compose 编排(postgres + tushare + web)
├── README.md                    # 本文件
├── CLAUDE.md                    # Claude Code 项目指引
├── data/                        # 数据目录(gitignored)
│   └── (运行时生成)
├── .gitignore                   # Git 忽略配置
├── tushare/                     # Python 数据服务
│   ├── Dockerfile
│   ├── requirements.txt
│   └── src/                     # 数据采集 + 打分 + FastAPI
│       ├── api.py               # FastAPI 服务入口
│       ├── models.py
│       ├── fetcher.py
│       ├── scorer.py
│       ├── storage.py           # PostgreSQL 读写
│       ├── contracts.py
│       └── main.py              # CLI 入口
└── web/                         # Web 浏览端
    ├── .dockerignore
    ├── backend/                 # Go 1.25 后端 (chi + lib/pq)
    │   ├── Dockerfile           # 多阶段:node 构 UI → go 构二进制 → alpine 运行
    │   ├── go.mod
    │   ├── main.go
    │   ├── embed.go             # //go:embed all:dist
    │   ├── go.sum
    │   ├── dist/                # 占位,Docker 构建期被 vite 输出覆盖
    │   └── internal/
    │       ├── config/          # 环境变量加载
    │       ├── store/           # PostgreSQL 业务查询 + 用户管理
    │       ├── auth/            # bcrypt + 首启 admin 引导
    │       ├── middleware/      # RequireUser / RequireAdmin / 日志
    │       ├── handlers/        # 登录 / 打分 / K线 / 用户管理
    │       └── router/          # chi 路由装配
    └── frontend/                # Vue 3 + Vite + Element Plus + ECharts
        ├── package.json
        ├── vite.config.ts
        ├── tsconfig.json
        ├── index.html
        └── src/
            ├── main.ts / App.vue
            ├── router/          # 守卫(未登录/管理员路由)
            ├── stores/          # Pinia: auth.ts(持久化 token) + theme.ts(暗/浅色模式)
            ├── api/             # axios 封装 + 各端点
            ├── views/           # 登录 / 打分列表 / 图表 / 用户管理
            └── components/      # 抽屉 + ECharts K 线

技术栈

  • Python 3.13 (alpine) + tushare + pandas + FastAPI + psycopg3 — 数据采集、打分与 API 服务
  • Go 1.25.8 (alpine 3.23) + chi + lib/pq — Web 后端
  • Vue 3 + Vite + Element Plus + ECharts — Web 前端
  • PostgreSQL 18.3 (alpine 3.23) — 业务数据存储
  • PostgreSQL — 业务数据与用户鉴权数据统一存储
  • Docker / Docker Compose — 容器化部署

常见问题

Q: 为什么某些日期返回空数据?

A: tushare 数据更新有延迟,且不同接口对 token 积分等级有要求。若 fut_daily 返回空但 trade_cal 正常,通常是该日期实际行情数据尚未入库。

Q: 合约代码格式?

A: 郑商所用 .ZCE 后缀(如 FG2609.ZCE),上期所用 .SHF,大商所用 .DCE。注意不是 .CZC

Q: 如何定时自动跑?

A: 通过宿主机 cron / launchd 等定时器调用 docker-compose -f docker-compose.trade.yml run --rm tushare ...。也可直接调用 API: curl -X POST http://localhost:4001/api/v1/run ... 或批量接口 curl -X POST http://localhost:4001/api/v1/run/batch

Web 报表(浏览端)

./web/ 提供一个图形化的浏览端,展示 tushare 流水线写入 PostgreSQL 的打分与行情数据。后端 Go(golang:1.25.8-alpine3.23)读取数据库,前端 Vue 3 + Element Plus + ECharts,通过 docker-compose 一起部署。

1. 启动

# 构建并启动 web 服务,不影响现有 tushare
docker-compose -f docker-compose.trade.yml up -d --build web

# 查看启动日志:首启会出现 [bootstrap] admin created
docker-compose -f docker-compose.trade.yml logs -f web

浏览器访问 http://localhost:4000。首次启动时系统会自动创建默认管理员账号 admin / admin,首次登录后系统会强制要求修改密码。

3. 页面说明

  • 打分列表 /scores:按合约、日期、条数筛选,展示综合分/信号/三层得分;点击「明细」弹抽屉,显示短期 7 日逐日打分、中期(15d)价格收益与资金意愿、长期(30d)持仓变化。
  • K 线 / 持仓 /chart:选合约 + 日期区间,主图蜡烛(开高低收),副图持仓量曲线;鼠标拖选缩放。
  • 用户管理 /admin/users:仅管理员可见。可创建子账号(user 默认,亦可建 admin)、重置密码、禁用/启用、删除;不允许对自己执行禁用或删除。

普通用户登录后 /admin/* 路径会被前端守卫拦截并跳回 /scores,后端也会以 403 拒绝。

前端支持暗/浅色模式切换,点击顶部导航栏的「暗/亮」开关即可切换。侧边导航在暗色模式使用深色背景,浅色模式使用浅色背景。

4. 子账号维护流程

  1. 用 admin 登录 → 进入 /admin/users → 「新建账号」,填写用户名 / 密码(≥6 位) / 角色。
  2. 把账号发给同事即可登录;无注册入口。
  3. 离职 / 风险事件:用「禁用」临时停用(被禁用的账号将无法登录),或「删除」彻底清除。

5. 数据流向与数据库

tushare(写) → PostgreSQL futures 数据库 ←(读写)── web 后端

业务数据(candles + scores)与用户鉴权数据(users)统一存储在 PostgreSQL futures 数据库中。users 表结构:

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)

6. 常见问题

Q: 忘记管理员密码怎么办?

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 / admin

Q: 改了 Go / Vue 代码但页面没变?

源码不挂载,镜像内是 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 -f docker-compose.trade.yml run --rm tushare python -m src.main ...

Description
No description provided
Readme 468 KiB
Languages
Vue 37.9%
Go 33%
Python 21.1%
TypeScript 6.8%
Dockerfile 1%
Other 0.2%