Files
Hermes-Skills/okx-auto-position/references/trading-db-architecture-2026-08-25.md
T

103 lines
5.7 KiB
Markdown

# 交易信号三库架构 — DB Topology (2026-08-25)
> User asked "币圈持仓有平仓信号吗?" → 暴露 schema 错位:我先查了不存在的 `recent_signals` 表,才意识到三个 DB 各司其职。
## 三个 DB 各管一段
```
┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ TelegramForwarder │ │ signal_queue.db │ │ signal_history.db │
│ db/forward.db │───→│ .hermes/trading/ │───→│ .hermes/trading/ │
│ │ │ │ │ │
│ Tables: │ │ Tables: │ │ Tables: │
│ • chats │ │ • queue │ │ • signals │
│ • users │ │ • sqlite_sequence │ │ • confirmed_signals │
│ • forward_rules ⚠️ │ │ │ │ • position_history │
│ • replace_rules │ │ Cols: id, raw_text, │ │ • position_locks ⚠️ │
│ • media_types │ │ status, created_at, │ │ • sqlite_sequence │
│ • keywords │ │ processed_at, │ │ │
│ • push_configs │ │ result, error, │ │ │
│ • rss_* │ │ retries │ │ │
│ • rule_syncs │ │ │ │ │
└──────────────────────┘ └──────────────────────┘ └──────────────────────┘
转发规则 实时队列 历史 + 持仓锁
```
## 各表职责
### 1. `forward.db::forward_rules` — 转发规则
- `enable_rule` 字段(0/1)是 silent killer:8h+ 无信号先查这条(v4.5.43,2026-08-06 session)
- 管 TG channel → 内部 queue 的路由
- 与本 skill 无直接关系,但 `enable_rule=0` 会让 queue 不进数据
### 2. `signal_queue.db::queue` — **实时信号流**(source of truth for "现在有没有信号")
- `status='done'` + `result` 字段 = 最新处理结果
- `result` 内容:`✅ 已推送 | X long 5x | 28.0张 | 性价比高` / `⏭️ 跳过: 性价比低` / `⏭️ 跳过: trader [未知] 不在白名单`
- **问"现在有没有平仓信号"先查这里**
- 看 `raw_text` 是否含 `🚨 已平仓提醒` / `已平仓`
### 3. `signal_history.db::signals` — 历史信号落库
- 只追加,反映"曾经来过什么信号"(无论 execute 是否成功)
- 有 `outcome` + `outcome_time` 字段记录执行结果
- **不是实时信号源**(等 queue 处理完才写)
### 4. `signal_history.db::position_locks` — **持仓归属**(source of truth for "现在持仓是谁的")
- 唯一字段:`symbol, trader, side, locked_at, reason, auto_locked`
- 当前持仓要查这张表(不是 `signals`)
- `locked_at` 是 ISO 字符串(不是 timestamp!),parse 时 `datetime.fromisoformat()`
- 用户问"持仓谁的" → 先看这张
### 5. `signal_history.db::confirmed_signals` — execute 记录
- 哪条信号真正触发了下单
- v4.5.51 lock 追溯方法的核心表
## 常见错位与正解
| 用户问题 | ❌ 错查 | ✅ 正查 |
|---|---|---|
| "现在持仓多少?" | `signals` 表(只有历史) | `position_locks` |
| "持仓是谁的?" | `signals.trader`(可能 stale) | `position_locks.trader` |
| "现在有没有平仓信号?" | `signals` 表(等落库有延迟) | `signal_queue.db::queue` (status='done') |
| "X 信号 execute 成功了吗?" | `signals.outcome` | `confirmed_signals` |
| "TG 转发还活着吗?" | `signals` 表 | `forward.db::forward_rules.enable_rule` |
## 实战速查 (一键脚本)
```python
# 当前持仓 (5 个字段)
sqlite3 /home/openclaw/.hermes/trading/signal_history.db \
"SELECT symbol, trader, side, locked_at, reason FROM position_locks;"
# 最近 24h 平仓信号 (从 queue 实时拿)
python3 -c "
import sqlite3
conn = sqlite3.connect('/home/openclaw/.hermes/trading/signal_queue.db')
rows = conn.execute('''
SELECT created_at, raw_text, result FROM queue
WHERE status='done' AND raw_text LIKE '%已平仓%'
ORDER BY id DESC LIMIT 5
''').fetchall()
for ts, txt, res in rows: print(ts, res, txt[:80])
"
# forwarder 规则是否启用
sqlite3 /home/openclaw/TelegramForwarder/db/forward.db \
"SELECT id, source_chat, dest_chat, enable_rule FROM forward_rules;"
```
## 教训 (本次 session 2026-08-25)
1. **`recent_signals` 表在 `signal_dedup.db`** — `signal_history.db` 里没有它(我第一查就报 "no such table: recent_signals")
2. **`position_locks.locked_at` 是 ISO 字符串不是 timestamp** — 不要 `int(timestamp/1000)`,用 `datetime.fromisoformat()`
3. **`signals` 表的 `timestamp` 字段是 ISO 字符串** — 同样不能用 `/1000` 转 unix
4. **`signal_queue.db::queue.created_at` 是 ISO 字符串** — 用 `datetime.fromisoformat()` parse
## 跟 v4.5.51 / v4.5.56 的关系
v4.5.51 锁追溯三步 (`position_locks` → `confirmed_signals` → `recent_signals`) 已覆盖,但**没说明为什么用三张表**。本 reference 补充了 DB 拓扑(为什么三表 + 各表职责),让"三步追溯"不再像 magic incantation。
## 维护建议
- 任何新增"信号处理流程"的代码 → 必须先说明写入哪张表(queue / signals / confirmed_signals / position_locks)
- 任何"实时状态"查询 → 必须说明用的是 queue 还是 signals
- 新加 DB 必然更新本 reference + 顶部架构图