DSAWiki
07智能 · 引擎

让大模型读懂一只股票

Prompt 不是咒语,而是一份精心准备的「分析任务书」。看看 DSA 如何把数据、规则与约束装进去。

约 9 分钟 进阶 第 07 章 · 智能

大模型不是水晶球。它不会「算出」明天涨跌,也不会替你承担风险。它真正擅长的是:把一堆结构化数据、新闻与规则,归纳成一份有结构、能执行、可解释的分析稿。理解这一点,你才能理解 DSA 为什么要在 Prompt 和守卫上花这么多功夫。

类比:一位很会写报告的分析师

你雇了一位分析师,他读过很多书、文笔极好,但没有实时行情终端。你要做的是:把行情、指标、新闻、市场背景整理好交给他,告诉他「按这个模板写,不许编数据,拿不准就写观望」。他写得漂亮不代表结论正确,但至少不会因为缺少上下文而胡说。Prompt 就是这份工作说明书。

LLM 在 DSA 里到底负责什么

它负责

  • 把技术面、基本面、新闻、市场阶段归纳成结论。
  • 按固定 JSON 契约表达,让前端、推送、回测都能复用。
  • 生成可执行的作战计划:入场区间、止损、目标、检查清单。
  • 解释「为什么」,包括风险与反方证据。

它不负责

  • 计算指标:均线、MACD、RSI 都由代码先算好。
  • 获取行情:数据来自适配器,模型看不到「实时接口」。
  • 保证收益:任何结论都可能错,且不构成投资建议。
  • 最终拍板:规则守卫与风险否决保留最后一道闸。

这种分工是刻意设计的:确定性的事交给代码,模糊的事交给模型,危险的事交给规则。三者叠加,才有可能得到「既好读又不太离谱」的输出。

接入层:像插座一样换模型

src/llm/ 定义了一个统一后端协议 GenerationBackend,核心只有一个 generate() 方法。上层只认这个协议,不关心底层是 LiteLLM、Codex CLI 还是 Claude Code CLI。

后端 ID用途工具调用适用场景
litellm统一调用 100+ 供应商支持默认,分析 + Agent 都走它
codex_cli本地 CLI 文本生成不支持实验性,本地环境
claude_code_cli本地 CLI 文本生成不支持实验性,本地环境
opencode_cli本地 CLI 文本生成不支持实验性,本地环境

Agent 的工具调用必须走 LiteLLM,因为只有它声明了 tools 能力。这个约束不是随意写的:本地 CLI 后端只负责「产出一段文本」,无法可靠地按函数名与参数返回工具调用。

每个错误都带分类(超时、空输出、非法 JSON、schema 校验失败、工具不支持、需要登录等),并标记是否可重试、是否可回退。上层据此决定「等一下再试」还是「换模型」,而不是所有错误都无脑重试。

模型与配置:三层优先级

DSA 不直接枚举所有供应商,而是交给 LiteLLM。配置按优先级从高到低是:

LITELLM_CONFIGYAML
LLM_CHANNELS渠道
单 Key 旧配置legacy
渠道协议 / 接入方式典型配置
Modelflare / AIHubMixOpenAI 兼容聚合MODELFLARE_KEY / AIHUBMIX_KEY
GeminiGoogle 原生GEMINI_API_KEY + GEMINI_MODEL
DeepSeek / 通义等OpenAI 兼容OPENAI_API_KEY + OPENAI_BASE_URL
Anthropic原生ANTHROPIC_API_KEY
Ollama本地 OpenAI 兼容本地地址 + 模型名

分析模型由 LITELLM_MODEL 指定,回退列表由 LITELLM_FALLBACK_MODELS 指定;Agent 可以用 AGENT_LITELLM_MODEL 单独指定,留空则继承全局。温度由 LLM_TEMPERATURE 给出基线,再按模型能力归一。

Prompt 解剖:五段式「任务书」

主分析 Prompt 很长,但结构清晰。可以把它拆成五段:

先定义「你是谁、对谁说话」。系统会注入市场角色(A 股 / 港股 / 美股等)、报告语言与输出风格。角色不是装饰,它决定了模型引用哪些本地概念:A 股可以谈涨跌停、北向资金;美股谈这些就会显得荒谬。

把风险纪律写进系统提示词。例如:MA5 乖离率超过 5% 不追高、优先多头排列、资金流不明时倾向观望。这些规则同时存在于代码守卫里——Prompt 让模型「知道」,守卫让系统「做到」。

喂结构化事实,而不是一堆散乱文本。行情表、均线与量能、筹码、新闻情报、市场阶段、市场结构、上下文包摘要,都会以带标题的文本块注入。缺失的块会明确标注,而不是留白让模型脑补。

定义严格的 JSON 输出。核心六大块:core_conclusion、data_perspective、intelligence、battle_plan、phase_decision、signal_attribution,约 25 个文本字段,每个字段都有枚举或格式示例。这样前端、通知、信号抽取才能稳定消费。

最后写「不许做什么」。不得因单日涨跌在买卖之间翻转;盘前不得编造当日走势;数据 stale 时置信度不得为高;不得在缺少证据时宣称龙头。这些是行为红线,不是写作建议。

下面是改写后的结构示意,不是仓库原文。读真实 Prompt 时,重点看它的分段与约束,而不是逐字背诵。

[角色]
你是一名 {market} 投资分析师,产出「决策仪表盘」。
只依据下方数据判断;数据缺失必须明确说明。

[交易纪律]
- MA5 乖离率 > 5%:严禁追高
- 优先 MA5 > MA10 > MA20 的多头排列
- 资金流不明时,倾向持有 / 观望

[输入数据]
行情表(OHLCV、量比、换手)
均线 / MACD / RSI / 乖离率
筹码分布 / 基本面 / 新闻情报
市场阶段 / 当日大盘上下文 / 市场结构

[输出契约]
{
  "core_conclusion": { "one_sentence": "...", "signal": "buy|hold|sell", ... },
  "data_perspective": { ... },
  "intelligence": { "risk_alerts": [], "catalysts": [] },
  "battle_plan": { "sniper_points": {...}, "action_checklist": [] },
  "phase_decision": { ... },
  "signal_attribution": { ... }
}

[稳定性约束]
- 不得因单日涨跌在买卖间翻转
- 盘前不得描述当天尚未发生的走势
- 数据 stale 时,置信度不得为 high

上下文包:把一只股票装进一个信封

模型的上下文窗口有限,90 天日线不可能全塞。DSA 用「上下文包」做有损压缩,至少包含:

技术面

趋势状态、均线排列、MACD/RSI、乖离率、量能、关键支撑压力。

基本面

财务快照、估值、行业归属、资金流;按市场能力标注缺失。

情报

新闻、公告、舆情、催化与风险;来自搜索服务并去重。

市场背景

市场阶段、指数涨跌、市场宽度、板块强弱。

历史对比

与上一次分析的结论、评分、关键位变化。

质量元数据

每个数据块的状态与来源,决定模型该多自信。

每个子块都有 schema 版本与质量状态。版本不匹配或标记为 not_supported 的块会被跳过,避免旧数据或错误字段污染判断。这听起来很工程化,但它直接决定了模型会不会「拿错事实说对话」。

结构化输出:从「散文」到「可消费的数据」

如果模型返回一段自由文本,下游只能展示,不能回测、告警、做信号抽取。DSA 要求 JSON,并准备了一条完整的降级链:

阶段做什么失败后
提取从响应中找出 JSON 对象,去掉前后解释尝试修复
修复json-repair 处理尾逗号、缺引号、注释判为无效
契约校验检查关键字段与类型是否存在触发完整性重试
完整性重试默认 1 次,要求补全缺失字段占位填充
文本兜底按正负关键词给保守分,标记 success=False该结果不按正常分析落库

这里的取舍很现实:宁可要一份带缺失字段的可用报告,也不要因为一个字段缺失就整轮失败。但兜底结果必须被标记,不能被当成正常结论继续传播。

后置守卫:LLM 出稿,规则定稿

模型最容易犯的错不是「不会写」,而是「写得太顺」。它会把一根阳线描述成趋势反转,把接近压力位的追高说成突破确认。守卫的职责就是把这些漂亮话拉回价格事实。

规则阈值 / 条件动作
破位现价 / 支撑 < 0.985提高风险等级,压制买入
贴近支撑现价 / 支撑 ≤ 1.03卖出建议需有重大风险证据,否则降为持有
突破现价 / 压力 > 1.01才算有效突破,结合量能与资金流
贴近压力现价 / 压力 ≥ 0.97买入若缺资金流入,降为持有/观望
评分校准hold / watch分数夹到 45–59,避免「观望 85 分」
阶段约束盘前 / 数据 stale不得描述未发生的走势,置信度不得为高

这些阈值不是「市场真理」,而是项目选择的风险偏好。它们可以被讨论、被调整,但必须被显式写出来,而不是藏在模型的即兴判断里。

一句话总结

LLM 负责「写得像分析师」,守卫负责「别像疯了的分析师」。两者缺一不可。

多模型回退:把「模型挂了」变成可恢复事件

分析侧会按「主模型 + 回退列表」依次尝试。失败原因不同,处理也不同:

  • 超时 / 限流:同一 provider 内可以退避重试;跨 provider 直接切换,因为限流桶互不相干。
  • JSON 不合法:判定该模型本次失败,切下一个;不会拿坏 JSON 硬解析。
  • 流式失败:可退回非流式再试一次。
  • 参数不支持:部分模型只接受默认温度,系统能识别报错并自动修复参数,只重试一次。

多 key 场景下,LiteLLM 的 Router 可以做简单负载均衡,并对失败请求重试;但最终能否成功,仍取决于你配置的模型质量与额度。

参数:温度、窗口与「别乱发挥」

参数建议原因
温度低(如 0.1–0.3)分析任务要稳定、可复现;高温适合创意写作,不适合风控
上下文窗口按模型能力控制输入长度太长会增加成本与「中间遗忘」,太短会丢关键证据
超时分析 300 秒级别可配长 Prompt 的首 token 延迟较高,过短会误杀
最大输出按 JSON 契约估算过小会截断 JSON,直接触发解析失败

有些模型固定温度、不支持某些参数。系统会从报错文本识别并缓存修复结果,避免每次调用都踩同一个坑。

Token 与成本:钱花在哪

一次单股分析的输入通常包含行情表、指标、新闻、市场背景与很长的系统提示词;输出是一份结构化 JSON。总体量级通常在几千到数万 token,取决于股票数量、新闻长度、上下文包与模型。Agent 多轮问股会更高,因为每一轮都要带历史与工具结果。

降低成本的三件事

  • Prompt 缓存:系统提示词与稳定前缀可被供应商缓存,按更低价计费。
  • 控制上下文:上下文包做有损压缩,避免把整篇新闻塞进去。
  • 选对模型:分析任务不一定需要最贵的旗舰模型;回退模型可以用更便宜的。

用量与隐私

  • 每次调用记录 prompt/completion/total 与缓存命中,按 provider 归一。
  • 消息内容只保留 HMAC 指纹,不把完整 Prompt 明文写进遥测。
  • Web「Token 用量」页可按模型/时间查看消耗。

风险清单:LLM 分析最容易翻车的五件事

① 幻觉

编造不存在的新闻、财务数字或「机构观点」。缓解:只喂结构化证据、要求引用、后置校验。

② 数据过期

拿旧价格当现价。缓解:质量状态、stale 标记、禁止高置信度。

③ 提示注入

新闻正文里可能藏着「忽略上述指令」之类的文本。缓解:把新闻当数据、限定证据范围、规则守卫;但没有系统能 100% 免疫。

④ 过度自信

语言流畅让读者误以为结论可靠。缓解:统一评分刻度、风险提示、置信度约束。

⑤ 单日翻转

昨天买、今天卖、明天又买。缓解:稳定性约束与守卫。

⑥ 成本失控

批量分析 + 多轮回退把额度烧光。缓解:用量统计、回退模型、预算护栏。

自测一下

模型返回了一段看起来合理、但 JSON 少了关键字段的响应。系统最可能怎么处理?

原因:结构化输出是下游所有功能的基础。系统会先提取 JSON、用 json-repair 修复、校验最小契约;失败则触发完整性重试或切换模型,最后才用占位字段兜底。关键是「兜底要留痕」——不能把一段无法验证的散文当成正常分析继续传播。

源码与文档锚点