A股「早选晚打」双引擎:用 Ollama 本地推理 + DeepSeek 云端精筛搭建零成本量化流水线

A股「早选晚打」双引擎:用 Ollama 本地推理 + DeepSeek 云端精筛搭建零成本量化流水线
国内做 AI + 量化的都知道:东方财富 API 被 DPI 拦截、AKShare 函数名随版本漂移、策略从设计到落地中间隔着无数坑。本文分享一套真实跑通的「早选晚打」双引擎交易系统——Ollama 本地粗筛 + DeepSeek 精筛 + 腾讯财经零成本数据源,每天 2.5 分钟出候选池,14:30 尾盘出触发信号。
一、问题:策略再好,调不通等于零
上一篇文章解决了数据源的问题(绕过 DPI、零成本获取全 A 股行情)。但如果只是把数据喂给 LLM 问「哪只股票值得买」,结果就是:
# ❌ 天真方案
prompt = f"分析这 4300 只股票,推荐 3 只"
response = deepseek.chat(prompt)
# 返回:context length exceeded(4300 行的 JSON 远超上下文窗口)
# 或者:推荐了 ST 股、强周期股当价值股、代码和名称对不上
量化交易和 AI 的结合不是「把行情数据丢给 GPT」,而是一个多阶段的工程问题。
二、架构:「早选晚打」双引擎
为什么是双引擎?
去年试过「狙击埋伏」策略——预设精确买点,等市场自己送上门。效果很差:小资金绑在「等待」上,两三天没信号,心态容易崩。
反思后确定了两个原则:
- 主动出击优于被动等待——不等击球点,看到止跌信号就入场
- 两道防线互补——激进突破 + 稳健回调,覆盖不同市况
最终架构如下:
09:20 策略一·量价突破 → vp_breakout_scanner.py → 3 只短线突破候选
09:25 策略二·回调强买 → a_share_scanner.py → 5 只回调候选池
[用户白天做功课、盯盘]
14:30 尾盘综合分析 → closing_analysis.py → 入场触发信号
14:30 - 15:00 用户决策 + 下单
策略定位于 14:30 尾盘——价格全天博弈后更诚实、T+1 友好、趋势已走完。
策略二:回调强买(主线)
核心逻辑:不等股价跌到预设狙击区,看到「止跌信号」就主动入场。
三个入场触发器(满足任一即可进入候选):
| 触发器 | 条件 | 实现 |
|---|---|---|
| 🔫 缩量止跌 | 当日量 < 前日量×0.7 且收阳 | 盘口观察 |
| 🔫 V反信号 | 盘中低点距 MA20 ≤ 1% 且反弹 ≥ 1% | closing_analysis.py 自动检测 |
| 🔫 均线企稳 | 盘中触及 MA20 后反弹企稳 | 自动检测 |
止损/止盈:
- 止损 = MA20 × 0.98(以均线为锚,非固定百分比)
- 止盈 = min(入场价 × 1.08, 前期高点)
- 持有 3-5 天
策略一:量价突破(辅线)
不猜顶底,只在资金已经动手时跟进:
- 昨日成交额 > 20日均量 × 1.5
- 收盘价 > 20日最高价的 95%
- MA20 向上
- PE 5-40,市值 > 50亿
止损/止盈:-3% / +5%,持有 1-3 天。
三、数据管道:用腾讯财经 API 零成本获取全 A 股行情
东方财富 API 被 DPI 拦截(TCP 通但 HTTP 层 RST),新浪财经同理。但 qt.gtimg.cn 不受拦截,50只/批,全量 4300+ 只约 80 秒,返回 GBK 编码。
import requests
def fetch_batch(codes: list[str]) -> list[dict]:
"""腾讯财经批量查询"""
url = "http://qt.gtimg.cn/q=" + ",".join(codes)
resp = requests.get(url, timeout=10)
resp.encoding = "gbk" # ⚠️ 必须设 GBK
results = []
for line in resp.text.strip().split("\n"):
if '="' not in line:
continue
parts = line.split("~")
results.append({
"code": parts[2],
"name": parts[1],
"price": float(parts[3]),
"pe": float(parts[39]) if parts[39] else 0,
"amount": float(parts[36]) * 10000 if parts[36] else 0,
"ret_5d": float(parts[62]) if parts[62] else 0,
"ret_10d": float(parts[63]) if parts[63] else 0,
"ret_20d": float(parts[64]) if parts[64] else 0,
})
return results
关键字段映射(腾讯 API 零文档,全靠逆向):
| parts 索引 | 含义 | 用途 |
|---|---|---|
parts[62] |
5日涨跌% | 计算 MA5 / 短期动量 |
parts[63] |
10日涨跌% | 计算 MA10,趋势健康度核心输入 |
parts[64] |
20日涨跌% | 计算 MA20 / 狙击区 / 止损 |
parts[35] |
价/量/额 | 一字拆三字段 |
parts[47-48] |
52周高低 | 判断当前位置 |
用 ret_10d 反推 MA10:
ma10 = price / (1 + ret_10d / 100)
四、五层筛选流水线
策略二的扫描器 a_share_scanner.py 包含完整的 L0-L5 流水线:
全市场 4,300+ (腾讯 API, ~80s)
│
├─ L1: 狙击初筛
│ ST 过滤 / 京交所排除 / 价格≤3 / PE≤0 或 >50 / 市值<50亿
│ 距 MA20 距离排序 → Top 50
│
├─ L2: 趋势健康度(4分制,≥3 才进候选)
│ ① MA5 > MA10 > MA20 (多头排列)
│ ② 股价 > MA20 (中期趋势)
│ ③ 20日涨幅 > -10% (非急速下跌)
│ ④ 股价 > 52周低 × 1.05 (有安全垫)
│
├─ L3: PSS 五维加权评分
│ 入场精度 30% + 风报比 25% + 趋势 20% + 基本面 15% + 催化剂 10%
│
├─ L4: Ollama 本地粗筛 (deepseek-r1:14b, ~22s)
│ Top 15 → 金子 vs 石块判断
│
└─ L5: DeepSeek 云端精筛 (deepseek-chat, ~19s)
逐条检查 6 条铁律 → Top 3-5 推荐
总耗时:约 150 秒(2.5 分钟)。
L4: Ollama 本地粗筛
用 RTX 5080 (16GB) 跑 deepseek-r1:14b,推理速度 ~88.7 tok/s。
import requests
OLLAMA_URL = "http://localhost:11434/api/generate"
json_schema = {
"type": "object",
"properties": {
"verified": {
"type": "array",
"items": {
"type": "object",
"properties": {
"code": {"type": "string"},
"name": {"type": "string"},
"verdict": {"type": "string", "enum": ["gold", "rock"]},
"pss_ok": {"type": "boolean"},
"fatal_flaw": {"type": "string"},
},
"required": ["code", "name", "verdict"],
}
}
},
"required": ["verified"],
}
resp = requests.post(OLLAMA_URL, json={
"model": "deepseek-r1:14b",
"prompt": prompt,
"format": json_schema, # Schema 约束输出
"stream": False,
"options": {"num_ctx": 4096, "temperature": 0.05}
})
关键参数:temperature=0.05(不是 0.3 也不是 0.15)。经过实测对比,0.05 覆盖面更广(13 vs 9 只),且输出稳定可复现——同一天同一输入两次跑出来的 Top 5 重叠率 100%。
L5: DeepSeek 云端精筛
Prompt 内嵌 6 条交易铁律:
❶ 公告排雷: 搜索「代码 减持 质押 监管函」→ 一票否决
❷ 强周期判断: 铝/钢/煤/化工等 PE 低 ≠ 低估
❸ 下跌加速: 等止跌信号,别接飞刀
❹ 仓位 ≤ 10%(小资金测试阶段)
❺ 目标价 > 成本价
❻ 止损必须同步给出
五、风控体系:三层否决 + 6 条铁律
年初踩过两次坑后(联创光电大股东减持+82%质押、宏桥控股强周期+下跌加速),重建了三层否决:
L1 量化否决
├─ 强周期行业 (22个关键词) + trend<2 → 一票否决
└─ 下跌加速 (5日跌幅 > 20日跌幅×0.5) + trend≤1 → 一票否决
L2 公告排雷
└─ AnySearch 批量扫描 Top 15
命中「减持/质押/监管函/立案」→ 一票否决
L3 AI 铁律兜底
└─ DeepSeek 精筛逐条检查 6 条铁律
强周期行业关键词表:
CYCLICAL_KEYWORDS = [
"铝", "钢", "铁", "煤", "炭", "化工", "有色", "水泥", "玻璃",
"铜", "锌", "镍", "锂", "钴", "稀土", "石化", "原油", "天然气",
"航运", "港口", "造船", "造纸", "化纤", "化肥", "农药",
]
六、部署:4 条 Cron 实现全自动
cronjob create --name "策略二·回调强买" --script "sniper_scan.sh" --schedule "25 9 * * 1-5"
cronjob create --name "策略一·量价突破" --script "vp_breakout_scanner.py" --no-agent --schedule "20 9 * * 1-5"
cronjob create --name "尾盘综合分析" --script "closing_analysis.py" --no-agent --schedule "30 14 * * 1-5"
cronjob create --name "P3情报融合日报" --script "p3_fusion_briefing.py" --no-agent --schedule "0 17 * * 1-5"
Cron 踩坑记:
python必须加-u强制无缓冲,否则 cron 环境下 stdout 全被吞- 脚本路径必须物理位于
~/.hermes/scripts/,软链接也不行 .env加载必须用load_dotenv(override=True),否则 cron 进程已有的环境变量会遮蔽.env里的新 key
七、实战踩坑:那些让你怀疑人生的 bug
1. ak.stock_info_a_code_name() 超时 7 分钟
AKShare 的 stock_info_a_code_name() 会连 www.bse.cn(北京证券交易所),在本机网络下频繁超时(7 分钟+),导致整个扫描流水线不可用。
# ❌ 错误:连 BSE 超时 7 分钟
df = ak.stock_info_a_code_name()
# ✅ 正确:分别获取沪深代码,完全避开 BSE
sh = ak.stock_info_sh_name_code()
sz = ak.stock_info_sz_name_code()
# 列名归一化
sh = sh.rename(columns={"证券代码": "code", "证券简称": "name"})
sz = sz.rename(columns={"A股代码": "code", "A股简称": "name"})
2. Ollama 名称幻觉
Ollama 在排名股票时经常把代码和名称搞混——输出 "600030 招商银行",但 600030 是中信证券。
修复:解析 Ollama 输出的 JSON 后,用源数据逐条校正名称。
for stock in results:
code_clean = "".join(filter(str.isdigit, str(stock["code"])))
match = df[df["symbol_clean"] == code_clean]
if not match.empty:
stock["name"] = match.iloc[0]["name"] # 强制覆盖
3. DeepSeek API 模型名陷阱
deepseek-v4-flash 返回空内容(HTTP 200 但 content 为空字符串)。改用 deepseek-chat 正常——虽然后端映射到同一模型,但响应处理不同。
4. 腾讯 API GBK 编码
qt.gtimg.cn 返回 GBK 编码,不设 resp.encoding = "gbk" 直接中文乱码——Python requests 默认猜编码会猜错。
八、总结:本地算力 + 云端精筛 = 零成本量化流水线
这条流水线的核心思想是 用本地 Ollama 做粗活,用 DeepSeek API 做细活:
| 阶段 | 工具 | 耗时 | 成本 |
|---|---|---|---|
| 数据获取 | 腾讯 API (qt.gtimg.cn) |
80s | 免费 |
| 量化初筛 | pandas 多因子 | <1s | 本地 |
| 公告排雷 | AnySearch API | 30s | 免费 |
| AI 粗筛 | Ollama deepseek-r1:14b |
22s | 本地 GPU |
| AI 精筛 | DeepSeek deepseek-chat |
19s | ~¥0.01/次 |
| 总计 | ~150s | ≈ 免费 |
每天早晨 09:25 产出候选池,下午 14:30 产出触发信号,全程无需盯盘。
下一步:接入东方财富财富号社区情绪数据(已经找到 API)、加入商品期货→A股映射(螺纹钢→钢铁股、碳酸锂→锂电股),构建信息领先优势。
全套代码开源:
a_share_scanner.py+closing_analysis.py+fetch_a_shares.py
GitHub: jipin-ai/ji_pin(a-stock-intel 工具包)
本文是 CSDN 技术阵地第二篇,前一篇:绕过 DPI、零成本搭建 A 股智能 Agent 工具9)
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)