- Generate full AI-consumable docs (docs/ai/): system overview, architecture, module cheatsheet, API contracts, data model, build guide, decision log, glossary, and open questions (deep tier coverage) - Add PROBLEM_REPORT.md: categorized bug/risk summary - Add DETAILED_CODE_REVIEW.md: full line-by-line review of all 15 backend files, documenting 4 fatal issues, 5 critical deployment bugs, 4 security vulnerabilities, and 6 architecture defects with prioritized fix plan
5.5 KiB
项目问题报告
生成时间:2026-03-03 基于 commit
0d9dffa的代码分析
🔴 高危问题(可能导致实盘出错)
P1:数据库从未真正迁移到云端
现象:你以为整个系统已经跑在 Cloud SQL 上,实际上只有 agg_trades 原始成交数据在双写。其他核心数据全在本地 PG(127.0.0.1)。
| 数据表 | 本地 PG | Cloud SQL |
|---|---|---|
agg_trades(原始成交) |
✅ | ✅ 双写 |
signal_indicators(信号输出) |
✅ | ❌ 没有 |
paper_trades(模拟盘) |
✅ | ❌ 没有 |
rate_snapshots(费率快照) |
✅ | ❌ 没有 |
market_indicators(市场数据) |
✅ | ❌ 没有 |
live_trades(实盘交易) |
❌ | ✅ 只在云端 |
live_config / live_events |
❌ | ✅ 只在云端 |
最致命的问题:live_executor.py 和 risk_guard.py 默认连 Cloud SQL(DB_HOST=10.106.0.3),但 signal_engine.py 只把信号写到本地 PG。这意味着:
- 实盘执行器读取的
signal_indicators表在 Cloud SQL 里可能是空的 - 风控模块监控的
live_trades和信号引擎写的数据完全在两个不同的数据库里
影响:实盘交易链路存在断裂风险,需立即核查服务器上各进程实际连接的数据库地址。
修复方向:统一所有进程连接到 Cloud SQL,或统一连接到本地 PG(通过 Cloud SQL Auth Proxy)。
P2:users 表双定义字段不一致
db.py 和 auth.py 各自定义了一个 users 表,字段不同:
| 字段 | db.py 版本 | auth.py 版本 |
|---|---|---|
email |
✅ | ✅ |
password_hash |
✅ | ✅ |
role |
✅ | ✅ |
created_at |
✅ | ✅ |
discord_id |
❌ | ✅ |
banned |
❌ | ✅ |
FastAPI 启动时先跑 init_schema()(db.py 版),再跑 ensure_auth_tables()(auth.py 版),因为 CREATE TABLE IF NOT EXISTS 第一次成功后就不再执行,实际创建的是缺少 discord_id 和 banned 字段的旧版本。
影响:封禁用户功能(banned 字段)在新装环境下可能失效。
P3:signal_indicators 表 INSERT 包含 strategy 字段但 schema 没有
save_indicator() 函数向 signal_indicators 插入数据时包含 strategy 字段(signal_engine.py:697),但 SCHEMA_SQL 里的建表语句没有这个字段(db.py:205-224)。
影响:在全新环境初始化后,信号引擎写入会报列不存在的错误。
🟡 中危问题(影响稳定性和维护)
P4:requirements.txt 严重不完整
文件只列了 5 个包,实际运行还需要:
| 缺失依赖 | 用于 |
|---|---|
asyncpg |
FastAPI 异步数据库 |
psycopg2-binary |
同步数据库(signal_engine 等) |
aiohttp |
live_executor、risk_guard |
websockets 或 httpx |
agg_trades_collector WS 连接 |
psutil |
已在文件里,但版本未锁定 |
影响:新机器部署直接失败。
P5:market_indicators 和 liquidations 表不在主 schema 中
这两张表由各自的 collector 进程单独创建,不在 init_schema() 里。如果 collector 没跑过,signal_engine 查这两张表时会报错(会降级为默认中间分,不会崩溃,但数据不准)。
P6:没有 CI/CD,没有自动化测试
- 代码变更完全靠人工验证
- 策略逻辑(
evaluate_signal)没有任何单元测试,重构风险极高 - 部署流程:手动 ssh + git pull + pm2 restart
🟠 安全风险
P7:测试网密码硬编码在源代码里
三个文件里都有:
os.getenv("PG_PASS", "arb_engine_2026") # db.py:19
os.getenv("DB_PASSWORD", "arb_engine_2026") # live_executor.py:44
os.getenv("DB_PASSWORD", "arb_engine_2026") # risk_guard.py:42
代码一旦泄露(GitHub public、截图等),测试网数据库直接裸奔。
P8:JWT Secret 有测试网默认值
_jwt_default = "arb-engine-jwt-secret-v2-2026" if _TRADE_ENV == "testnet" else None
如果生产环境 TRADE_ENV 没有正确设置,会静默使用这个已知 secret,所有 JWT 都可伪造。
🔵 架构债务(长期)
P9:三套数据库连接配置并存,极易混淆
| 配置方式 | 使用的进程 | 默认连哪 |
|---|---|---|
db.py 的 PG_HOST |
main.py、signal_engine、collectors | 127.0.0.1(本地) |
进程内 DB_HOST |
live_executor、risk_guard、position_sync | 10.106.0.3(Cloud SQL) |
market_data_collector.py 内 PG_HOST |
market_data_collector | 127.0.0.1(本地) |
没有统一的连接配置入口,每个进程各自读各自的环境变量,迁移时极容易漏改。
P10:前端轮询压力
/api/rates 每 2 秒轮询一次,用户多了服务器压力线性增长。目前 3 秒缓存有一定缓冲,但没有限流保护。
📋 建议优先级
| 优先级 | 任务 |
|---|---|
| 🔴 立即 | 登服务器确认各进程实际连的数据库地址,核查实盘链路是否完整 |
| 🔴 立即 | 补全 signal_indicators 表的 strategy 字段 |
| 🔴 本周 | 统一数据库连接配置,所有进程用同一套环境变量 |
| 🟡 本周 | 修复 users 表双定义问题,合并到 auth.py 版本 |
| 🟡 本周 | 补全 requirements.txt |
| 🟠 本月 | 把硬编码密码移到 .env 文件,不进代码仓库 |
| 🔵 长期 | 添加 signal_engine 核心逻辑的单元测试 |
| 🔵 长期 | 配置 GitHub Actions 做基础 lint 和安全扫描 |