零服务器每天 18 点自动复盘,6.6 万 Star 的 daily_stock_analysis 怎样防止 AI 乱喊单
声明:本文只讨论开源项目的工程设计,文中所有输出均为演示数据,不构成任何投资建议。股市有风险,投资需谨慎。
“让大模型帮我看盘”是很多人试过的事:把股票代码丢给聊天机器人,得到一段看似专业、实则飘忽的分析。真正难的不是让 AI 开口,而是让它每天稳定地、基于真实数据、带着约束地开口。

GitHub 上的 daily_stock_analysis(仓库 ZhuLinsen/daily_stock_analysis,以下简称 DSA)把这件事做成了一条工程化流水线:每个交易日收盘后,自动拉取自选股的行情、新闻和基本面,交给大模型生成一份“决策仪表盘”,再推送到企业微信、飞书、Telegram、邮箱等渠道。项目用 Python 编写,MIT 协议,目前已有约 6.6 万 Star,覆盖 A 股、港股、美股、日股、韩股和台股。
这篇文章不评价它“准不准”,而是拆解三个让它能长期稳定跑下去的工程设计:数据源降级链、交易日判断、交易纪律约束。这三点对任何想做“AI + 定时数据任务”的人都有参考价值。
一、它到底每天在做什么

一次完整的运行大致分为五步:
1. 交易日判断:按每只股票所属市场的交易日历,决定今天是否需要分析;
2. 拉取行情:日 K、实时行情、技术指标、筹码分布等,按数据源优先级逐个尝试;
3. 检索新闻与舆情:通过搜索服务获取公告、新闻和事件;
4. 大模型分析:把以上数据组装成提示词,由大模型输出结论、评分、买卖点位、风险警报和操作检查清单;
5. 推送决策仪表盘:汇总成一份报告,推送到配置的通知渠道。
项目结构也很清晰:
| 目录 | 职责 |
|---|---|
main.py |
主程序入口,支持单次运行、定时、Web 服务等模式 |
src/ |
核心业务:分析器、配置、消息推送 |
data_provider/ |
多数据源适配器 |
api/ 与 apps/dsa-web/ |
FastAPI 后端与 React 前端工作台 |
bot/ |
机器人交互 |
.github/workflows/ |
GitHub Actions 定时任务 |
二、5 分钟零服务器部署:GitHub Actions 方案
DSA 最受欢迎的一点是不需要自己买服务器,Fork 仓库后用 GitHub Actions 定时运行即可。
第一步:Fork 仓库。
第二步:在 Settings → Secrets and variables → Actions 中添加 Secrets,三类配置至少各填一个:
| 类别 | Secret 示例 | 说明 |
|---|---|---|
| 大模型 | GEMINI_API_KEY、ANTHROPIC_API_KEY、OPENAI_API_KEY + OPENAI_BASE_URL |
OpenAI 兼容接口可接 DeepSeek、通义千问等 |
| 通知渠道 | WECHAT_WEBHOOK_URL、FEISHU_WEBHOOK_URL、TELEGRAM_BOT_TOKEN + TELEGRAM_CHAT_ID、EMAIL_SENDER + EMAIL_PASSWORD |
可同时配置多个 |
| 自选股 | STOCK_LIST |
如 600519,hk00700,AAPL,2330.TW |
新闻搜索(如 SerpAPI、Tavily、博查、自建 SearXNG)不是必填项,但会明显影响舆情和催化因素的质量,建议至少配一个。
第三步:在 Actions 页启用工作流,然后手动运行一次“每日股票分析”验证配置。
之后它会在每个工作日北京时间 18:00 自动执行,对应的 cron 是 UTC 时间:
schedule:
- cron: '0 10 * * 1-5' # UTC 10:00 = 北京时间 18:00,周一到周五
如果更习惯本地或 Docker 运行,也只需几条命令:
git clone https://github.com/ZhuLinsen/daily_stock_analysis.git && cd daily_stock_analysis
pip install -r requirements.txt
cp .env.example .env # 填写模型、通知渠道与自选股
python main.py --dry-run # 只拉数据,不调用大模型
python main.py --stocks 600519,AAPL # 临时指定股票
python main.py --market-review # 只做大盘复盘
python main.py --schedule # 本地定时模式
python main.py --webui # 启动 Web 工作台,默认 8000 端口
三、设计一:数据源不是“一个”,而是一条降级链
免费行情接口最大的问题是不稳定:限流、改版、网络抖动是常态。DSA 的做法是把每个数据源包装成适配器,并给它们分配优先级数字,数字越小越先尝试,失败后自动尝试下一个,全部失败才算真正失败。
以普通 A 股日 K 为例,配置了 TickFlow 的 API Key 后它的默认优先级是 2,腾讯直连的默认优先级是 5,作为通用链路的最终兜底;中间还可以插入 AkShare、Tushare、Baostock 等来源。实时行情则用另一个变量单独控制顺序:
REALTIME_SOURCE_PRIORITY=tencent,akshare_sina,efinance,akshare_em
FUTU_HK_REALTIME_SOURCE_PRIORITY=futu,longbridge,akshare,yfinance

还有两个细节值得借鉴:
- 指数走独立的固定链:已登记的沪深指数不参与通用优先级排序,固定按腾讯、AkShare、TickFlow、YFinance 的顺序降级,避免个股的配置影响指数数据。
- 辅助能力一律失败放行:基本面、筹码分布、龙虎榜这类“锦上添花”的数据,出错只记录日志、标记为不支持,绝不阻断技术面和新闻这条主链路。基本面阶段默认有 8 秒的软超时预算,超时就降级继续。
这种“主链路必须成功、辅助数据尽力而为”的分层,是定时任务能长期无人值守的关键。
四、设计二:先问“今天开不开市”,再干活
一个每天定时跑的任务,如果不懂交易日历,就会在节假日白白调用大模型、推送一份基于旧数据的报告。DSA 用 exchange-calendars 为每个市场维护各自的交易日历(含节假日),规则是:
- 混合持仓时,每只股票只在其所属市场开市的日子分析,休市市场当天跳过;
- 所有相关市场都休市时,整体跳过,不启动流水线也不推送;
- 判断“最新可复用交易日”时按市场本地时区计算,A 股用上海时区、美股用纽约时区,而不是服务器的自然日;
- 若最近一个交易日的数据本地已存在,就跳过重复抓取,实现断点续传。
GitHub Actions 中还可以用两个开关控制非交易日行为:仓库变量 TRADING_DAY_CHECK_ENABLED(默认开启)和手动触发时的 force_run 参数。手动运行时还能选择 full、market-only、stocks-only 三种模式。
五、设计三:给大模型套上“交易纪律”
让 AI 直接给买卖点,最大的风险是它会追涨。DSA 在提示词之外,用规则给分析结果加了几道约束,最典型的是乖离率阈值:
- 乖离率衡量现价偏离均线(如 MA5)的程度,计算方式为
(现价 - MA5) / MA5 × 100%; - 默认阈值
BIAS_THRESHOLD=5.0,超过即提示“不追高”; - 对均线多头排列的强势股,阈值自动放宽到 1.5 倍,避免把正常的强势误判为过热;
- 盘中开启
ENABLE_REALTIME_TECHNICAL_INDICATORS时,会用实时价计算 MA5、MA10、MA20 和多头排列,否则用昨日收盘价。
决策仪表盘最终呈现的是“一句话结论 + 评分 + 买卖点位 + 风险警报 + 利好催化 + 操作检查清单”,README 中的示例大致是这样的格式:
🎯 2026-02-08 决策仪表盘
共分析3只股票 | 🟢买入:0 🟡观望:2 🔴卖出:1
📊 分析结果摘要
⚪ 中钨高新(000657): 观望 | 评分 65 | 看多
⚪ 永鼎股份(600105): 观望 | 评分 48 | 震荡
🟡 新莱应材(300260): 卖出 | 评分 35 | 看空
注意示例中“观望”远多于“买入”。规则约束的意义恰恰在于让输出更克制,而不是更刺激。
六、动手实验:用 120 行 Python 复刻这三个机制
本文配套脚本 practice/demo_dsa_pipeline.py 只用 Python 标准库,离线就能运行。它用随机游走生成模拟行情,复刻了上面三个设计:带优先级的数据源降级、按市场的交易日判断、MA5 乖离率纪律。为便于演示,三个模拟数据源对所有市场通用,真实项目中不同市场有各自的数据源链。
核心的降级逻辑只有几行:
class DataManager:
def __init__(self, sources):
self.sources = sorted(sources, key=lambda s: s.priority)
def fetch(self, code):
errors = []
for src in self.sources:
try:
data = src.daily_klines(code)
return data, src.name, errors
except DataFetchError as e:
errors.append(str(e))
raise DataFetchError("全部数据源失败: " + "; ".join(errors))
纪律校验同样直白:
def discipline(closes):
price = closes[-1]
ma5, ma10, ma20 = ma(closes, 5), ma(closes, 10), ma(closes, 20)
bias = (price - ma5) / ma5 * 100
bullish = ma5 > ma10 > ma20
threshold = BIAS_THRESHOLD * (1.5 if bullish else 1.0)
...
运行 python demo_dsa_pipeline.py 的输出(模拟日期为港股重阳节补假的 2026-10-19):
🎯 2026-10-19 决策仪表盘(演示数据,不构成投资建议)
📊 600519 数据源=AkShare(降级: TickFlow: 连接被远端关闭)
现价 105.39 | MA5 104.63 | 乖离率 +0.72% (阈值 5.0%) -> 观望
📊 000657 数据源=TickFlow
现价 125.98 | MA5 125.29 | 乖离率 +0.55% (阈值 7.5%,多头排列放宽) -> 关注(多头排列,未偏离均线)
📊 300260 数据源=TickFlow
现价 117.27 | MA5 105.28 | 乖离率 +11.39% (阈值 7.5%,多头排列放宽) -> 观望(乖离过大,不追高)
⏭ hk00700 hk 市场今日休市,跳过
📊 AAPL 数据源=TickFlow
现价 114.07 | MA5 112.98 | 乖离率 +0.96% (阈值 7.5%,多头排列放宽) -> 关注(多头排列,未偏离均线)
可以看到:第一只股票的首选数据源失败后自动降级到下一个,结果中保留了降级原因;第三只股票尾盘急拉,乖离率超过放宽后的 7.5% 阈值,被标记为“不追高”;港股当天休市被直接跳过,不浪费一次模型调用。
七、模型层:用 LiteLLM 统一各家大模型
DSA 的模型调用统一走 LiteLLM,主模型用 provider/model 的格式指定,并支持备选模型:
LITELLM_MODEL=gemini/gemini-3.1-pro-preview
LITELLM_FALLBACK_MODELS=openai/deepseek-chat # 示例值,按自己开通的模型填写
这样主模型限流或报错时可以自动切到备选模型。Agent 问股功能在 Web 的 /chat 页面提供,支持均线金叉、缠论、波浪理论、多头趋势、热点题材、事件驱动等 15 种内置策略的多轮追问,也支持上传截图让视觉模型识别股票代码加入自选。
八、落地排坑清单
1. 筹码分布接口不稳定:GitHub Actions 的工作流默认关闭筹码分析,如确有需要,在仓库变量中显式设置 ENABLE_CHIP_DISTRIBUTION=true,并接受它偶尔失败。
2. 免费数据源会限流:长期批量运行建议配置 Tushare、TickFlow、Longbridge 等需要 token 的数据源;东财接口频繁断开时可开启 ENABLE_EASTMONEY_PATCH=true。
3. cron 是 UTC 时间:改推送时间时记得减 8 小时,北京时间 9:30 对应 '30 1 * * 1-5'。
4. 节假日手动运行要加 force_run:否则交易日检查会让任务直接跳过,看起来像“没反应”。
5. 公开仓库注意隐私:Fork 后的仓库默认公开,自选股写在 Secrets 里而不是代码里;Actions 运行日志也可能包含股票代码。
6. 大模型费用要心里有数:自选股数量乘以每天一次的分析调用,加上新闻检索,月度费用需提前估算;可先用 --dry-run 验证数据链路。
7. 它是辅助,不是决策者:项目 README 明确声明不构成投资建议,作者不对使用产生的损失负责。把它当作复盘的第二视角,而不是下单的依据。
九、总结
DSA 的价值不在于“AI 会炒股”,而在于它把一件重复的事做成了可靠的工程:数据源有降级链,辅助数据失败放行,任务懂交易日历,模型输出受规则约束,部署只需一个 GitHub 账号。这套“定时任务 + 多源数据 + 大模型 + 规则护栏 + 多渠道推送”的骨架,换成舆情监控、竞品追踪、运维日报,同样适用。
如果你每天都在花时间做机械的筛选和记录,不妨 Fork 一份试试;但请记住,最后那一下判断,仍然得由你自己来做。
💡 在线实战体验:本文配套免安装的云端 Linux 交互式实验环境与终端操作,可在 边学边练平台 (https://www.skillup.host/) 直接体验运行验证。