提交
This commit is contained in:
70
README.md
70
README.md
@@ -9,21 +9,24 @@
|
||||
|
||||
## 快速启动
|
||||
|
||||
两个终端分别启动后端与前端:
|
||||
两个终端分别启动后端与前端(命令均从仓库根 `stock/` 执行):
|
||||
|
||||
```bash
|
||||
# 终端 1 —— 后端 API(http://localhost:8000)
|
||||
cd backend
|
||||
env -u SSLKEYLOGFILE uv run uvicorn app.main:app --reload --port 8000
|
||||
bash backend/restart_backend.sh
|
||||
|
||||
# 终端 2 —— 前端开发服务器(http://localhost:5173)
|
||||
cd frontend
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
> `env -u SSLKEYLOGFILE` 是本机(Windows)必需的:用户环境变量 `SSLKEYLOGFILE` 值开头混有不可见控制符,asyncpg 建连即崩。详见下文「快速开始(开发模式)」与「常见问题」。
|
||||
> 后端统一走 `backend/restart_backend.sh`:自动杀旧进程树 + 剔除会崩 asyncpg 的 `SSLKEYLOGFILE` + 带热重载重启 + 日志写 `backend_run.log`。Windows cmd 下等价命令:`backend\restart_backend.cmd`。详见下文「快速开始(开发模式)」。
|
||||
|
||||
**首次运行前**:
|
||||
1. 装依赖:后端 `cd backend && uv sync`、前端 `cd frontend && pnpm install`。
|
||||
2. 后端依赖 **PostgreSQL(16/17)+ Redis 已启动**,并配好 `backend/.env`(复制 `.env.example`)。
|
||||
3. 建库表:`cd backend && uv run alembic upgrade head`。
|
||||
|
||||
首次运行前先安装依赖:后端 `uv sync`(backend 下)、前端 `pnpm install`(frontend 下)。
|
||||
浏览器打开 http://localhost:5173 即可使用。详细说明见下文「快速开始(开发模式)」。
|
||||
|
||||
---
|
||||
@@ -67,28 +70,36 @@ stock/
|
||||
├── TECH_STACK.md # 技术选型与架构决策(必读)
|
||||
├── README.md # 本文件
|
||||
├── backend/ # FastAPI + 回测引擎
|
||||
│ ├── pyproject.toml # uv 依赖声明
|
||||
│ ├── pyproject.toml # uv 依赖声明(pytest 在 dev 组)
|
||||
│ ├── .env.example # 配置示例(数据库 / 费率)
|
||||
│ ├── smoke_test.py # 后端全链路自检脚本
|
||||
│ ├── smoke_test.py # 后端全链路自检脚本(线上库鉴权+核心 API)
|
||||
│ ├── conftest.py # pytest 根(使 tests/ 可直接 import app.*)
|
||||
│ ├── tests/ # pytest 单元测试(交割单解析/复权换算/缓存/限速/事件回测纯函数)
|
||||
│ ├── scripts/ # 一次性运维脚本(TDX 导入 / 复权因子回补…)
|
||||
│ └── app/
|
||||
│ ├── main.py # FastAPI 入口(启动建表)
|
||||
│ ├── main.py # FastAPI 入口(lifespan 拉起夜间调度)
|
||||
│ ├── config.py # 配置(pydantic-settings)
|
||||
│ ├── db.py # async SQLAlchemy 引擎/会话
|
||||
│ ├── domain.py # 领域契约(Bar/Signal/Fill/Position…)
|
||||
│ ├── models.py # ORM(Candle / BacktestRun)
|
||||
│ ├── models.py # ORM(Candle / StockBasic / 用户数据表…)
|
||||
│ ├── schemas.py # Pydantic DTO(= OpenAPI 契约)
|
||||
│ ├── commission.py # A 股交易成本(已修正、可配置)
|
||||
│ ├── auth.py # Argon2 密码 + 会话(SHA-256 摘要)
|
||||
│ ├── auth_api.py # 登录/登出(含按 IP 限速)
|
||||
│ ├── scheduler.py # 夜间定时任务(收盘后自动同步 + 会话清理)
|
||||
│ ├── cache.py # Redis 读缓存(本地层 + 版本号失效 + 熔断冷却恢复)
|
||||
│ ├── indicators.py # 指标:MACD/RSI/KDJ/布林/均线(单一事实源)
|
||||
│ ├── api.py # 路由:/health /candles /backtest
|
||||
│ ├── data/ # DataProvider 适配器(Tushare/AKShare)+ 周期聚合
|
||||
│ └── backtest/ # engine / broker(PaperBroker) / metrics / strategies
|
||||
│ ├── api/ # 路由包:stocks / etfs / market / backtest / screener / user + _deps 共享件
|
||||
│ ├── data/ # 数据管道(tushare 适配 + 同步 + 懒加载缓存)
|
||||
│ ├── screener/ # 智能选股(LLM 解析 + 全市场引擎 + 夜间同步)
|
||||
│ └── backtest/ # engine / events(全市场事件回测) / strategies
|
||||
└── frontend/ # Vue SPA
|
||||
├── src/
|
||||
│ ├── main.ts # PrimeVue(Aura 深色) + Pinia
|
||||
│ ├── main.ts # Vue + Pinia
|
||||
│ ├── api/ # 类型化客户端 + DTO 镜像
|
||||
│ ├── stores/ # Pinia 回测状态
|
||||
│ ├── components/ # KLineChart / EquityChart / MetricsPanel / BacktestForm
|
||||
│ └── views/ # BacktestView
|
||||
│ ├── stores/ # Pinia(鉴权/设置/同步状态)
|
||||
│ ├── composables/ # 组合式工具(防抖 ref / 路由 query 同步)
|
||||
│ ├── components/ # StockDetailOverlay / DetailKLine / LimitBoard / MarketOverview…
|
||||
│ └── views/ # Home / Stocks / ETF / Concepts / Indexes / Screener / Backtest
|
||||
└── vite.config.ts # /api 代理到 :8000
|
||||
```
|
||||
|
||||
@@ -117,17 +128,16 @@ pip install uv
|
||||
|
||||
### 1) 后端
|
||||
|
||||
实际启动命令(venv 解释器直启,日志重定向到仓库根 `backend_run.log`,改代码自动热重载):
|
||||
实际启动命令(一键脚本,自动杀旧进程树 + 剔除 SSLKEYLOGFILE + 热重载 + 日志写仓库根 `backend_run.log`):
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
uv sync # 创建 .venv 并安装依赖(仅首次)
|
||||
env -u SSLKEYLOGFILE .venv/Scripts/python.exe -m uvicorn app.main:app --reload --port 8000 > ../backend_run.log 2>&1
|
||||
uv sync # 创建 .venv 并安装依赖(仅首次)
|
||||
bash backend/restart_backend.sh # 从仓库根执行(Git Bash);Windows cmd 下等价:backend\restart_backend.cmd
|
||||
```
|
||||
|
||||
看日志:`tail -f backend_run.log`;确认起没起:`curl http://localhost:8000/api/health`。
|
||||
|
||||
等价的 `uv run` 写法(不带日志重定向,直接打到当前终端):
|
||||
等价的 `uv run` 写法(不杀旧进程、日志直接打到当前终端):
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
@@ -135,13 +145,15 @@ env -u SSLKEYLOGFILE uv run uvicorn app.main:app --reload --port 8000
|
||||
```
|
||||
|
||||
- **`env -u SSLKEYLOGFILE`(本机 Windows 必需)**:用户环境变量 `SSLKEYLOGFILE` 的值开头混有 U+202A 不可见控制符,asyncpg 建连时执行 `ssl.keylog_filename` 直接抛 `OSError: [Errno 22]`,uvicorn 启动即崩。Git Bash 下用 `env -u` 剔除即可;根治可 `setx SSLKEYLOGFILE "C:\Users\cirry\Desktop\fhzg.log"`(重开终端后不再需要前缀)。验证:`python -c "import os; print(repr(os.environ.get('SSLKEYLOGFILE')))"`。
|
||||
- **Windows `--reload` 僵死**:watcher 偶尔改文件不重载且日志无 Reloading 行,此时只能杀进程树重启——`netstat -ano | grep :8000` 找 PID,`taskkill //PID <pid> //T //F`。
|
||||
- **Windows `--reload` 僵死**:watcher 偶尔改文件不重载且日志无 Reloading 行,此时只能杀进程树重启——一键脚本 `bash backend/restart_backend.sh`(Git Bash)或 `backend\restart_backend.cmd`(cmd):自动杀旧进程树(`--reload` 起 launcher→reloader→worker 三层进程)+ 带 reload 重启 + 日志写 `backend_run.log`。手动:`netstat -ano | grep :8000` 找 PID,`taskkill //PID <pid> //T //F`。
|
||||
- 数据库结构由 Alembic 管理:首次部署/更新代码后先执行 `uv run alembic upgrade head`(见「初始化登录系统」)。
|
||||
- 交互式 API 文档:http://localhost:8000/docs
|
||||
- **夜间自动同步**:后端启动即拉起调度(`app/scheduler.py`),每日 18:05 本地时间自动跑全市场 A 股 + ETF 同步并清理过期会话;进程启动时若已过点且当日数据未落库会补跑。关闭:`.env` 设 `NIGHTLY_SYNC_ENABLED=false`,时间改 `NIGHTLY_SYNC_HOUR`。
|
||||
|
||||
**自检**(无需起服务器,验证全链路):
|
||||
**测试**:
|
||||
```bash
|
||||
uv run --with httpx --directory backend python smoke_test.py
|
||||
uv run --directory backend pytest -q # 单元测试(交割单解析/复权换算/缓存/限速等纯函数,不碰库)
|
||||
uv run --with httpx --directory backend python smoke_test.py # 全链路自检(线上库鉴权+核心 API)
|
||||
```
|
||||
|
||||
### 2) 前端
|
||||
@@ -152,7 +164,8 @@ pnpm install # 首次
|
||||
pnpm dev # http://localhost:5173
|
||||
```
|
||||
|
||||
前端 `/api` 请求由 Vite 代理到后端 `:8000`(见 `vite.config.ts`),无需处理跨域。
|
||||
- **必须用 pnpm,不要用 npm/yarn**:项目锁定 `pnpm-lock.yaml`,`node_modules` 是 pnpm 的硬链接结构,`npm install` 会写坏依赖,导致装包/构建崩溃。以后装包一律 `pnpm add <pkg>`(不要 `npm install <pkg>`)。
|
||||
- 前端 `/api` 请求由 Vite 代理到后端 `:8000`(见 `vite.config.ts`),无需处理跨域。
|
||||
|
||||
打开 http://localhost:5173 → 选周期、改参数 → 点「开始回测」。
|
||||
鼠标悬停 K 线可看当日详情弹框;切日线/周线/月线/年线;勾「fast 模式」可对比关闭费用/T+1 的差异。
|
||||
@@ -229,9 +242,10 @@ EXPOSE_API_DOCS=false
|
||||
| 方法 | 路径 | 说明 |
|
||||
|---|---|---|
|
||||
| GET | `/api/health` | 健康检查 |
|
||||
| GET | `/api/candles/{symbol}?timeframe=1d&limit=1000` | 取 K 线(`timeframe`: `1d`/`1w`/`1M`/`1y`) |
|
||||
| POST | `/api/data/sync` | 拉取并缓存某标的日线(Tushare 主 → AKShare 兜底)。body: `{symbol, source?, force?}` |
|
||||
| POST | `/api/backtest` | 跑回测(真实标的首次自动拉取并缓存) |
|
||||
| POST | `/api/backtest` | 跑回测(真实标的首次自动拉取并缓存;前端已改用 `/api/backtest/event` 事件回测,此为旧策略回测 API) |
|
||||
|
||||
个股 K 线统一走 `GET /api/screener/preview/{ts_code}`(含复权/指标预热/翻页,两级缓存)。
|
||||
|
||||
**回测请求示例**:
|
||||
```json
|
||||
|
||||
Reference in New Issue
Block a user