daily_stock_analysis:用GitHub Actions白嫖AI操盘手
一款零成本、多模型Fallback、fail-open架构的LLM股票分析系统。基于Python+LiteLLM+AkShare,支持A/H/美股,GitHub Actions定时生成含狙击点位、舆情雷达、买卖清单的决策仪表盘。
哈喽,我是周小码——一个被Spring Boot自动配置折磨到凌晨三点、靠咖啡续命的Java老兵,也是个看到Python里pip install -r requirements.txt就忍不住想写个Maven插件来模拟的偏执狂。
今天不聊JVM GC调优,也不扯Spring Cloud Gateway的Filter链。咱来拆解一个让我在凌晨两点合上Mac、盯着终端日志傻笑的项目:daily_stock_analysis。它不是又一个「K线图+Flask」玩具,而是一套真正可落地产出交易信号的轻量级AI投研流水线。
痛点?太真实了
你有没有过这种体验:
- 想写个量化策略,结果卡在Tushare Token申请失败;
- 想加新闻舆情,发现SerpAPI按次计费,跑一次分析就要3美元;
- 想让LLM给建议,却要自己硬编码对接GPT/Claude/Gemini三套SDK,还得分流、重试、降级;
- 最后好不容易跑通,本地调试5分钟,CI/CD部署2小时,上线后API一抖,整个报告直接空转。
这不是开发,是玄学炼丹。
它怎么破局?三板斧见真章
第一斧:LiteLLM统一网关 + 多模型Fallback
它没写一行openai.ChatCompletion.create()或gemini.GenerativeModel(),而是全走LiteLLM抽象层:
bash
## .env 配置即生效
LITELLM_MODEL=gpt-4o,claude-3-5-sonnet,gemini-1.5-pro
LITELLM_FALLBACK_ENABLED=true
LITELLM_TIMEOUT=30
LiteLLM底层会自动做:
- 请求并发打向所有模型;
- 取首个返回且HTTP 200的结果;
- 若全超时/报错,则按fallback顺序逐个重试(非轮询!);
- 所有模型调用统一记录
litellm-cost-tracking.json,费用一目了然。
这才是生产级LLM集成该有的样子——不是“我调通了”,而是“它扛住了”。
第二斧:数据管道分层兜底,fail-open不中断主流程
看它的新闻获取逻辑(源自src/data/intel.py推断结构):
python
## 伪代码还原核心调度逻辑
def fetch_news(stock: str) -> List[NewsItem]:
for provider in [TavilySearch(), SerpAPISearch(), BraveSearch(), SearXNGSelfHosted()]:
try:
return provider.search(f"{stock} 财报|并购|政策|股价异动", timeout=8)
except (TimeoutError, APIRateLimitError, ConnectionError):
logger.warning(f"{provider.name} fallbacked")
continue
# 全挂?返回空列表,但主流程继续!
return []
行情数据同理:AkShare → Tushare → YFinance → Alpha Vantage,任意一层失败,跳过并标记⚠️ 数据暂缺,绝不阻塞Technical Analysis阶段。
第三斧:Agent多阶段编排,把LLM当协作者而非黑盒
它把决策过程拆成五阶流水线:
Technical → Intel → Risk → Strategy → Decision
每个环节独立控制:
TECHNICAL_TIMEOUT=60(技术面分析最多60秒)INTEL_CACHE_TTL=3600(新闻缓存1小时)RISK_RETRY=2(风险评估最多重试2次)STRATEGY_CACHE_KEY="${STOCK}_${DATE}_strategy_v2"
更狠的是支持运行时切换架构:
bash
## 启用实验性多Agent并行推理(非串行!)
AGENT_ARCH=multi
AGENT_ORCHESTRATOR_MODE=standard # 或 distributed / async
此时chanlun_agent和wave_theory_agent会并行执行,结果由Orchestrator融合打分——这已经不是Prompt Engineering,是分布式AI工作流设计。
实战演示:5分钟跑出你的第一份AI研报
bash
## 1. 克隆 + 安装
git clone https://github.com/ZhuLinsen/daily_stock_analysis.git && cd daily_stock_analysis
pip install -r requirements.txt
## 2. 配置最小可行集(仅需1个模型)
cp .env.example .env
sed -i 's/# GEMINI_API_KEY=/GEMINI_API_KEY=your_key_here/' .env
sed -i 's/# STOCK_LIST=/STOCK_LIST=600519,TSLA/' .env
## 3. 启动!带Web UI(自动构建前端)
python main.py --webui
访问 http://localhost:8000,输入密码(默认admin),就能看到实时生成的Markdown报告——含主力资金流向热力图、筹码集中度散点图、舆情情绪雷达(红/黄/绿三色)、以及最关键的:
贵州茅台(600519):进攻|评分87|看多
▸ 狙击点位:1728.5 ± 4.2元(MA20+布林中轨共振)
▸ 止损:1652.0元(前低+量能衰竭确认)
▸ 目标:1880.0元(历史通道上沿+外资持仓阈值)
▸ 风险:① Q1财报延迟发布(概率32%) ② 北向单日净流出超15亿(需盯盘)
不是“建议关注”,是「可执行指令」。
踩坑指南:别掉进这三个坑
-
Tushare Token失效导致基本面模块静默失败
解决方案:启用FALLBACK_TO_YFINANCE=true,YFinance虽无A股财报细节,但能提供PE/PB/ROE基础值,保证Risk阶段不空转。 -
GitHub Actions中FEISHU_WEBHOOK_URL被误设为飞书群机器人旧版URL
正确格式必须是:https://open.feishu.cn/open-apis/bot/v2/xxx(注意v2路径),否则404且无日志提示。 -
Agent模式下
AGENT_MAX_STEPS=12触发LLM调用爆炸
实测:12步 × 4技能 × 3模型fallback = 单股最高36次调用。建议首次使用设为AGENT_MAX_STEPS=4,再逐步放开。
我的真实看法
作为Java老兵,我愿称它为「Python工程化教科书」:
- 没有一行过度设计,但每处异常处理都带着生产环境的疤痕;
- 不追求百万QPS,但把
timeout/retry/cache_key/fallback_order刻进了每个模块的DNA; - 它甚至没用Celery或Airflow,纯靠GitHub Actions Cron +
schedule库实现准实时调度——轻,但稳。
如果明天我要给团队写调度框架,我会直接抄它的src/core/orchestrator.py里的状态机设计:
python
## 状态流转严格定义,不可跳步
class AgentState(Enum):
TECHNICAL = "technical"
INTEL = "intel"
RISK = "risk"
STRATEGY = "strategy"
DECISION = "decision"
## 每个状态绑定超时、重试、缓存策略
STATE_POLICY = {
"technical": {"timeout": 45, "retry": 1, "cache_ttl": 1800},
"intel": {"timeout": 120, "retry": 2, "cache_ttl": 3600},
}
最后说句掏心窝子的:这项目让我想起当年第一次用Spring Boot写REST API时的震撼——原来技术可以这么轻盈,又这么有力。它不追求“高并发百万QPS”,但追求“每个股民都能用得起的AI决策权”。
这,才是技术该有的温度。