1. PanWatch 项目整体设计与思路拆解
1.1 这个项目到底在解决什么问题
PanWatch 这个名字拆开看就很直白——“Pan”对应的是广域监控、全景式观察的意思,“Watch”就是盯盘、监控、值守。合在一起,它要干的事情就是给交易场景做一套全天候、自动化的智能监控与决策辅助系统。传统做法里,一个人盯几个币种、几只股票就已经手忙脚乱了,更别说同时跟踪几十个标的的价格波动、成交量异动、资金费率变化。PanWatch 的核心价值就在于把这些重复性的盯盘工作交给 AI Agent 去完成,人只需要在关键节点做决策。
我最初接触这个项目的时候,市面上已经有不少行情监控工具了,但大多数停留在“价格到了就弹个通知”的层面。PanWatch 不一样的地方在于它引入了 TradingAgents 这套多智能体协作框架,让不同的 Agent 分别扮演分析师、风控员、执行员等角色,互相校验、互相制衡。这就好比原来你只有一个哨兵,现在你有了一整支训练有素的小队,每个人负责不同的观察维度,最后汇总成一份可执行的建议。
适合谁来参考这套方案?如果你是有一定编程基础、对量化交易或自动化监控感兴趣的开发者,PanWatch 的架构思路可以直接借鉴。哪怕你暂时不碰交易领域,它里面关于 Docker 容器化部署、Agent 编排、消息推送链路的设计,放到其他监控场景里同样适用。
1.2 为什么选择 Docker 作为部署底座
PanWatch 整个项目是围绕 Docker 来构建部署体系的,这个选择不是拍脑袋决定的。交易监控系统有几个硬性要求:第一,它得 7×24 小时跑着,不能因为你本机重启就断了;第二,它依赖的组件比较多,数据库、消息队列、Agent 运行时环境,版本冲突是家常便饭;第三,你可能会在本地开发调试,然后部署到云服务器上,环境一致性必须保证。
Docker 恰好把这三点全解决了。容器化之后,PanWatch 的每个模块——数据采集、Agent 推理、信号推送——都可以拆成独立的容器,各自升级互不影响。我实测下来,用 Docker Compose 编排的话,从零到跑起来大概也就十几分钟的事情,比手动装 Python 环境、配数据库、调依赖版本要省心太多了。
注意:Windows 用户如果之前没装过 Docker Desktop,需要先确认 BIOS 里开启了虚拟化支持。很多人卡在“Virtualization support not detected”这个报错上,其实就是主板设置里 VT-x 或 AMD-V 没打开。
1.3 TradingAgents 框架的引入逻辑
TradingAgents 是 PanWatch 的智能决策核心。它不是一个单一的 AI 模型,而是一套多 Agent 协作框架。你可以把它想象成一家小型交易公司:有负责看宏观面的分析师,有盯着 K 线图的技术派,有专门算仓位的风控专员,最后还有一个拍板的组合经理。每个角色都是一个独立的 Agent,它们共享同一份市场数据,但各自用不同的提示词和推理逻辑去分析,最后投票或者加权得出一个综合判断。
这种设计的好处是显而易见的。单一模型很容易陷入“过度自信”的陷阱,给出一个方向性判断但忽略反面证据。多 Agent 互相挑刺之后,输出的信号会稳健很多。我在测试阶段对比过,单 Agent 模式下假信号率大概在四成左右,引入 TradingAgents 的三 Agent 交叉验证后,假信号率降到了两成以下。当然代价是推理时间变长了,但对中低频监控场景来说完全可以接受。
2. 核心细节解析与实操要点
2.1 Docker 环境搭建的完整流程
PanWatch 的部署第一步就是把 Docker 环境搞利索。Linux 服务器上直接用官方脚本安装是最省事的,但生产环境我建议走包管理器安装,方便后续版本管理。Ubuntu 下的操作大概是这样的:
sudo apt update sudo apt install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $VERSION_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin装完之后记得把当前用户加到 docker 组里,不然每次敲 docker 命令都要 sudo,烦得很:
sudo usermod -aG docker $USER newgrp dockerWindows 这边就简单一些,直接去官网下 Docker Desktop 安装包,一路下一步就行。但有个坑要注意:安装过程中如果提示 WSL2 需要更新,一定要先更新完再继续,否则 Docker Desktop 启动时会卡在“Docker Engine starting”界面转圈圈。
2.2 PanWatch 的容器编排结构
PanWatch 跑起来之后,至少涉及三个核心容器:数据采集器、Agent 推理服务、以及消息推送网关。数据采集器负责从交易所或行情源拉取实时数据,写入本地的 Redis 或 MySQL;Agent 推理服务订阅这些数据,跑 TradingAgents 的分析流程;推送网关则把生成的信号通过你配置的渠道发出来。
用 Docker Compose 编排的话,docker-compose.yml大概长这样:
version: '3.8' services: redis: image: redis:7-alpine ports: - "6379:6379" volumes: - redis_data:/data restart: unless-stopped mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: panwatch_root MYSQL_DATABASE: panwatch ports: - "3306:3306" volumes: - mysql_data:/var/lib/mysql restart: unless-stopped panwatch-agent: build: ./agent depends_on: - redis - mysql environment: REDIS_HOST: redis MYSQL_HOST: mysql MYSQL_PASSWORD: panwatch_root restart: unless-stopped volumes: redis_data: mysql_data:这里我把 Redis 和 MySQL 都放进来了,实际用的时候你可以根据需求裁剪。Redis 主要用来做行情数据的缓存和 Agent 之间的消息传递,MySQL 则用来持久化历史信号和交易记录。两个都设了restart: unless-stopped,保证服务器重启后容器能自动拉起来。
2.3 Agent 提示词的设计要点
TradingAgents 的效果好坏,八成取决于提示词怎么写。我踩过的最大坑就是一开始把提示词写得太“开放”,让 Agent“自由发挥”,结果它经常跑偏去分析一些跟当前监控标的无关的宏观新闻。后来我把提示词收窄成固定模板,每个 Agent 只允许在指定维度内输出结论,效果立刻稳定了。
一个典型的技术分析 Agent 提示词结构大概是:先给它当前标的的 K 线数据摘要,然后限定它只能从均线、成交量、RSI 三个指标里选两个来支撑判断,最后强制它输出“看多/看空/观望”三选一的结论,外加一句不超过五十字的理由。这种强约束下,Agent 的输出格式非常规整,后续程序解析起来也方便。
实操心得:提示词里一定要加一句“如果你不确定,就输出观望”。不加这句话的话,Agent 会倾向于强行给一个方向性判断,哪怕数据根本不支持。
3. 实操过程与核心环节实现
3.1 从零启动 PanWatch 的完整步骤
假设你已经在服务器上装好了 Docker 和 Docker Compose,接下来就是拉代码、配环境、启动。第一步先把项目克隆下来:
git clone https://github.com/your-repo/panwatch.git cd panwatch然后复制一份环境变量模板,填入你自己的配置:
cp .env.example .env.env文件里需要改的主要是这几项:行情数据源的 API Key、消息推送渠道的 Webhook 地址、以及 Agent 推理服务的模型端点。如果你用的是本地部署的大模型,模型端点就填http://host.docker.internal:11434这种;如果用云端 API,就填对应的地址和 Key。
配好之后直接一键启动:
docker compose up -d等个十几秒,用docker compose ps看一下容器状态,全是running就说明起来了。这时候你可以打开浏览器访问http://你的服务器IP:8080,应该能看到 PanWatch 的监控面板。
3.2 行情数据接入的配置细节
PanWatch 默认支持接入主流交易所的公开行情接口。配置的时候需要注意,不同交易所的接口频率限制不一样。比如某些交易所的 REST 接口每分钟只允许 1200 次请求,你如果监控了 50 个标的,每个标的每秒拉一次数据,那肯定超限。解决办法是改用 WebSocket 订阅模式,让交易所主动推数据给你,而不是你反复去问。
在 PanWatch 的配置文件里,数据采集模块有一个mode参数,可以选rest或websocket。我强烈建议选websocket,延迟更低,也不容易触发限流。配置大概是这样:
datasource: exchange: binance mode: websocket symbols: - BTCUSDT - ETHUSDT - SOLUSDT kline_interval: 1mkline_interval控制 K 线粒度,做短线监控就设1m,做趋势跟踪设1h或4h都行。设得太细的话,Agent 推理频率会很高,对算力要求也水涨船高。
3.3 Agent 推理服务的调优记录
Agent 推理是整个 PanWatch 里最吃资源的部分。我一开始在一台 2 核 4G 的轻量服务器上跑,三个 Agent 并发推理的时候 CPU 直接飙到 100%,响应延迟从正常的 2 秒涨到了 15 秒以上。后来做了两件事才把性能拉回来:一是把推理服务单独拆到一个容器里,给它限制 CPU 配额但保证内存充足;二是引入了请求队列,同一时间只允许一个标的的 Agent 推理在跑,其他的排队等。
队列机制的实现不复杂,用 Redis 的 List 结构就能做。数据采集器把需要分析的标的 push 进队列,Agent 服务用BRPOP阻塞式地从队列里取任务,取一个处理一个。这样虽然吞吐量下来了,但每个任务的响应时间稳定了,不会出现雪崩。
import redis import json r = redis.Redis(host='redis', port=6379, db=0) def worker(): while True: _, task = r.brpop('panwatch:analysis_queue') symbol = json.loads(task)['symbol'] result = run_trading_agents(symbol) publish_signal(result)这段代码就是 Agent 服务的核心循环,简单但有效。brpop在没有任务的时候会阻塞住,不消耗 CPU,有新任务进来立刻唤醒。
3.4 信号推送链路的搭建
Agent 分析出结果之后,得让人能收到。PanWatch 支持多种推送渠道,我常用的是 Telegram Bot 和钉钉机器人。Telegram 的配置最简单,找 BotFather 创建一个机器人,拿到 Token,然后在 PanWatch 里填上你的 Chat ID 就行。
钉钉稍微麻烦一点,需要在群里添加一个自定义机器人,拿到 Webhook 地址,然后设置关键词过滤。PanWatch 推送的消息里默认会带“PanWatch信号”这个关键词,你在钉钉机器人设置里把这个词加进白名单,消息才能正常发出来。
推送消息的格式我建议精简,不要一股脑把 Agent 的完整分析过程都发出来。我的做法是只推三行:标的名称、信号方向、以及一句话理由。详细的分析报告存到数据库里,需要的时候去面板上查。这样手机通知栏不会爆炸,关键信息也一眼能看清。
4. 常见问题与排查技巧实录
4.1 Docker 网络不通的排查思路
PanWatch 跑起来之后,最常见的报错就是容器之间网络不通。表现是 Agent 服务日志里一直刷“Connection refused”或者“Timeout”,连不上 Redis 或 MySQL。这个问题九成出在 Docker 网络配置上。
首先确认所有容器是不是在同一个自定义网络里。默认情况下,docker compose会创建一个以项目名命名的 bridge 网络,所有服务自动加入。但如果你手动docker run启动过某个容器,它可能跑在默认的 bridge 网络上,跟 compose 的网络隔离了。解决办法很简单,在docker-compose.yml里显式声明网络:
networks: panwatch-net: driver: bridge然后在每个服务的配置里加上networks: - panwatch-net。这样所有容器都在同一个网络里,互相用服务名就能访问,不用记 IP。
注意:容器之间通信用的是服务名,不是
localhost。在 Agent 服务的配置里,Redis 的地址要写redis://redis:6379,而不是redis://localhost:6379。这个坑我见过太多人踩了。
4.2 Agent 执行中断的常见原因
“Agent execution terminated due to error”这个报错在日志里出现的频率不低。我总结下来主要有三个原因:一是模型 API 超时,尤其是用云端大模型的时候,网络抖动导致请求失败;二是输入数据格式不对,比如行情数据里出现了null值,Agent 解析不了直接崩了;三是内存不足,Agent 推理过程中 OOM 被系统杀掉了。
针对第一种情况,加个重试机制就行。在调用模型 API 的地方包一层try-except,失败后等两秒重试,最多重试三次。第二种情况需要在数据采集端做清洗,所有null值统一替换成 0 或者上一个有效值。第三种情况就得看服务器配置了,如果内存确实紧张,要么加内存,要么把 Agent 的并发数降下来。
4.3 行情数据延迟的优化手段
做监控最怕数据延迟。我有一次发现 PanWatch 推送的信号比实际行情慢了将近一分钟,查了半天才发现是数据采集器用的 REST 轮询模式,而且轮询间隔设成了 30 秒。改成 WebSocket 之后延迟直接降到了毫秒级。
另外,如果你用的是云服务器,服务器本身跟交易所服务器的物理距离也会影响延迟。尽量选离交易所机房近的区域部署,比如交易所服务器在东京,你就选东京的云节点,延迟能从 100ms 降到 10ms 以内。
4.4 常见问题速查表
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 容器启动后立即退出 | 配置文件缺失或格式错误 | docker compose logs 服务名 | 检查.env和docker-compose.yml格式 |
| Agent 连不上 Redis | 网络隔离或地址写错 | docker exec进容器 ping 一下 | 确认在同一网络,地址用服务名 |
| 推送消息收不到 | Webhook 配置错误或关键词过滤 | 手动 curl 测试 Webhook | 检查 Token、Chat ID、关键词白名单 |
| 推理速度极慢 | CPU 不足或并发过高 | docker stats看资源占用 | 限制并发数或升级服务器配置 |
| 行情数据不更新 | WebSocket 断连 | 查看采集器日志 | 加自动重连机制,断线后指数退避重试 |
4.5 几个我踩过的坑和对应的解法
第一个坑是 MySQL 容器启动特别慢,导致 Agent 服务启动时连不上数据库直接报错退出。后来我在docker-compose.yml里加了healthcheck,让 Agent 服务等 MySQL 健康检查通过之后再启动:
mysql: healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s retries: 10 panwatch-agent: depends_on: mysql: condition: service_healthy第二个坑是 Redis 的数据没做持久化,服务器重启之后队列里的任务全丢了。虽然 PanWatch 的场景下丢几个分析任务问题不大,但如果你在做实盘信号跟踪,最好还是把 Redis 的 AOF 持久化打开,在启动命令里加--appendonly yes。
第三个坑是日志文件把磁盘写满了。Docker 容器的日志默认是无限增长的,跑几天就能吃掉几十个 G。解决办法是在docker-compose.yml里给每个服务加上日志轮转配置:
logging: driver: "json-file" options: max-size: "10m" max-file: "3"这样每个容器的日志最多占 30M,超出就自动删旧的,磁盘再也不会被撑爆。
4.6 关于 Agent 记忆机制的一点补充
TradingAgents 框架里有一个容易被忽略但很重要的设计,就是 Agent 的记忆机制。每个 Agent 在做出判断之后,会把这次的分析逻辑和结论存到记忆库里。下次遇到类似行情的时候,它会先检索记忆,看看历史上类似情况下自己的判断准不准,然后调整这次的置信度。
这个机制的好处是 Agent 会“吃一堑长一智”。我观察下来,跑了大概一周之后,Agent 对某些反复出现的假突破形态的识别率明显提高了。但记忆库也需要定期清理,不然越积越多,检索效率会下降。我的做法是每周清理一次超过三十天的旧记忆,只保留那些被后续行情验证为正确的记录。
如果你想让 Agent 的记忆更结构化,可以考虑引入向量数据库,把每次分析的特征向量存进去,检索的时候用相似度匹配而不是简单的时间排序。这样即使是很久以前的相似行情,也能被准确召回。不过这会增加一些部署复杂度,看你的实际需求权衡。
4.7 监控面板的定制化调整
PanWatch 自带一个 Web 监控面板,但默认的布局不一定适合每个人。我习惯把最重要的几个指标放在最上面:当前持仓、今日信号数、Agent 平均响应时间、以及最近一条推送的内容。面板的配置文件在frontend/config/dashboard.json,改起来就是调 JSON 数组的顺序,把对应的卡片 ID 往前排就行。
另外面板默认是每 30 秒刷新一次数据,如果你觉得不够实时,可以改成 5 秒。但要注意,刷新频率太高的话,后端接口压力会变大,尤其是同时有多个人在看面板的时候。我的建议是个人使用设 5 秒没问题,团队共用的话还是保持 30 秒比较稳妥。
4.8 关于资源占用的实测数据
最后分享一组我在不同配置服务器上跑 PanWatch 的实测数据,供你选服务器的时候参考。在 2 核 4G 的机器上,三个 Agent 并发推理时 CPU 占用率长期在 85% 以上,内存占用约 3.2G,响应延迟 8-15 秒。换到 4 核 8G 的机器后,CPU 占用降到 40% 左右,内存占用约 4.5G,响应延迟稳定在 2-3 秒。如果监控标的超过 20 个,建议直接上 8 核 16G,不然队列会积压得越来越长。
磁盘方面,MySQL 数据增长比较慢,一个月大概 500M 左右;Redis 如果开了持久化,增长会快一些,但一般 10G 的盘也够跑很久了。真正吃磁盘的是 Docker 镜像和日志,记得定期docker system prune清理一下没用的镜像和缓存。
我在实际使用中发现,PanWatch 这套东西最舒服的用法不是让它全自动交易,而是把它当成一个不知疲倦的助手。它帮你盯着盘面,有异动的时候提醒你,但最终按不按那个按钮,还是你自己决定。Agent 再聪明也有犯错的时候,把决策权完全交出去,心态上很难扛住。保持人在回路里,才是这套系统最合理的打开方式。