1. 从一条热搜说起:为什么要给 A 股装一个“会辩论的 AI”
“他给 A 股装了个会辩论的 AI”这个标题第一次出现在我时间线上的时候,我正蹲在电脑前调一个多因子回测脚本,屏幕上全是 backtrader 的日志。说实话,第一反应是“又一个蹭 AI 热度的标题党”,但点进去看完思路之后,我改主意了——这个方向确实踩到了当前 A 股量化圈一个很真实的痛点:单一大模型做投资判断,太容易一本正经地胡说八道。
我自己从 2021 年开始折腾 A 股量化,从最原始的 OBV 抓妖股、一线抓牛妖股指标公式,到后来用 backtrader 做多股回测,再到这两年把 AI 大模型接进选股流程,踩过的坑能写一本书。最典型的一个坑就是:你问大模型“这只票能不能买”,它永远能给你一套听起来很有道理的逻辑,涨了它说符合预期,跌了它说风险释放,反正怎么都对。这种“事后诸葛亮”式的输出,对实盘毫无价值。
“会辩论的 AI”这个思路,本质上是把单一模型的独断,变成了多个角色之间的对抗性推理。你可以理解成:以前是一个分析师拍脑袋给结论,现在是三个分析师坐在会议室里吵,一个看多、一个看空、一个专门挑逻辑漏洞,最后综合出一个相对靠谱的判断。这个思路在 AI 圈叫Multi-Agent Debate,在 A 股这个场景下,它解决的核心问题不是“预测涨跌”,而是过滤掉那些经不起推敲的伪逻辑。
这篇文章适合谁看?如果你是对 AI 应用开发感兴趣的程序员,想找一个真实落地的 AI Agent 项目练手;如果你是做量化的散户或者小团队,手里有 A 股分钟数据下载的需求,想用 AI 辅助选股但被“幻觉”坑过;或者你只是单纯好奇“AI 炒股”到底靠不靠谱——这篇都会给你一套可以直接抄作业的思路和代码骨架。我会把整个系统的设计逻辑、核心模块、实操步骤、以及我踩过的坑全部摊开讲,不藏私。
需要先说明一点:这套系统不预测股价,它做的是逻辑审查和风险提示。任何声称能精准预测 A 股涨跌的 AI,要么是骗子,要么是还没被市场毒打过。我们要的是“帮我把明显有问题的逻辑筛掉”,而不是“告诉我明天买哪只”。
2. 整体架构设计:三个 AI 角色怎么吵起来
2.1 为什么是“辩论”而不是“投票”
很多人第一反应是:多搞几个模型,让它们各自给个结论,然后投票取多数,不就完了?我一开始也是这么想的,实测下来效果很差。原因很简单:如果三个模型用的是同一套训练数据、同一个知识截止日期、同一种思维模式,它们的错误是高度相关的。三个模型一起错,投票只会让你更自信地错。
辩论机制不一样的地方在于,它引入了对抗性。看多的 Agent 必须给出买入理由,看空的 Agent 必须找出反驳点,裁判 Agent 负责判断谁的论据更扎实。这个过程会逼着每个 Agent 去挖掘对方逻辑里的漏洞,而不是各自输出一段四平八稳的废话。我实测下来,辩论机制最大的价值是暴露不确定性——当看多和看空双方吵得不可开交时,系统会明确告诉你“这只票的逻辑存在重大分歧”,这本身就是极有价值的信号。
从工程角度看,辩论机制还有一个隐性好处:它天然适合做可解释性输出。你不需要去猜模型为什么给这个结论,因为整个辩论过程就是推理链条。这对 A 股这种特别讲究“逻辑”的市场来说,比一个冷冰冰的分数有用得多。
2.2 三个核心 Agent 的角色定义
我最终定下来的架构是三个 Agent,每个角色都有明确的职责边界,避免它们互相“串味”:
看多 Agent(Bull):它的唯一任务是从给定数据中找出支持买入的证据。注意,是“从给定数据中”,不是让它自由发挥。我会把 A 股分钟数据、OBV 指标、成交量变化、近期公告摘要等喂给它,让它基于这些事实构建看多逻辑。这个角色的提示词里我会明确写“你是一个乐观但严谨的分析师,你的论据必须来自提供的数据,不允许编造”。
看空 Agent(Bear):职责相反,专门找风险点。它的提示词会强调“你是一个风险控制官,你的任务是找出所有可能导致亏损的因素,包括但不限于技术面背离、资金面异常、基本面恶化”。这个角色特别重要,因为大模型天生有“讨好用户”的倾向,你问它能不能买,它倾向于说能。给它一个明确的“找茬”任务,能有效对冲这种偏见。
裁判 Agent(Judge):它不参与辩论,只负责听双方陈述,然后给出裁决。裁决内容包括:哪一方的论据更充分、哪些论据存在逻辑漏洞、最终的综合判断是什么、置信度如何。裁判的提示词里我会要求它“必须指出至少一个双方都没考虑到的问题”,逼它做深度思考而不是简单站队。
这三个角色的提示词是整个系统的灵魂,我后面会给出具体的模板。这里先记住一个原则:角色定义越具体,输出质量越高。不要写“你是一个分析师”,要写“你是一个专注于 A 股短线交易、有 10 年经验、特别看重成交量配合的分析师”。
2.3 数据层:A 股分钟数据怎么搞
辩论要有素材,素材就是数据。A 股分钟数据下载这件事,说简单也简单,说麻烦也麻烦。免费的路子主要是几个财经数据接口,但都有各自的限制:有的只给最近几天,有的频率限制严格,有的字段不全。我自己的做法是本地化存储 + 增量更新。
具体来说,我会用 Python 写一个定时任务,每天收盘后拉取当天所有关注股票的分钟级数据,存到本地的 SQLite 或者 Parquet 文件里。为什么用 Parquet?因为 A 股分钟数据量其实不小,一只票一天 240 根 K 线,500 只票一年就是几千万行,用 CSV 存查询起来会想死。Parquet 列式存储配合 pandas 或者 polars,查询速度能快一个数量级。
这里有个坑要提醒:不同数据源的分钟数据对齐方式不一样。有的把 9:30 那根 K 线算作第一根,有的把 9:25 集合竞价单独算。你在做回测或者喂给 AI 之前,一定要先统一时间戳格式,否则后面指标计算全是错的。我当初就因为这个问题,回测结果和实盘差了十万八千里,排查了两天才发现是时间对齐的问题。
另外,关于“东方股吧反爬”这个热词,我多说一句:股吧的情绪数据确实有价值,但反爬机制也越来越严。我的建议是不要硬爬,一方面法律风险,另一方面维护成本太高。真要用情绪数据,可以考虑用公开的财经新闻摘要替代,或者用大模型对新闻标题做情绪打分,效果不一定差。
2.4 技术栈选型:为什么不用现成的 Agent 框架
现在 AI Agent 框架很多,LangChain、AutoGen、CrewAI 都能做多 Agent 协作。我一开始也试过 AutoGen,但最后选择了自己手写编排逻辑。原因有三个:
第一,可控性。辩论流程需要精确控制发言顺序、上下文传递、终止条件,现成框架的抽象层反而增加了调试难度。当裁判 Agent 输出格式不对时,我需要能直接定位到是哪一步的 prompt 出了问题,而不是在一堆框架代码里绕。
第二,成本。多 Agent 辩论意味着多次 API 调用,token 消耗是单次调用的好几倍。自己写编排可以精确控制每次调用的上下文长度,该截断的截断,该缓存的缓存。用框架的话,很容易在不知不觉中把上下文撑爆。
第三,可替换性。A 股这个场景对模型的中文理解能力要求很高,我可能会在不同模型之间切换测试。自己写的编排层,换模型只需要改一个配置项;用框架的话,可能要改一堆适配代码。
当然,如果你只是想快速验证想法,用现成框架也没问题。但如果你打算长期维护这套系统,我建议还是自己写编排层,代码量其实不大,核心逻辑也就几百行。
3. 核心模块拆解:从数据到辩论的完整链路
3.1 数据预处理:把原始 K 线变成 AI 能理解的“事实”
大模型不是万能的,你直接把 240 根 K 线的原始数据丢给它,它根本处理不了。我的做法是先做特征工程,把原始数据压缩成结构化的“事实卡片”,再喂给 Agent。
具体来说,每只股票我会生成这样一张事实卡片:
- 价格维度:当前价、5 日涨跌幅、20 日涨跌幅、距离近期高点和低点的百分比
- 成交量维度:当日成交量、5 日均量、量比、OBV 指标当前值和趋势
- 技术指标维度:MACD 金叉死叉状态、RSI 数值、布林带位置
- 资金维度:如果有龙虎榜数据就加上,没有就标注“数据缺失”
- 公告维度:最近 3 天的公告标题摘要
这张卡片用 JSON 格式组织,大概 500 到 800 字。为什么控制在这个长度?因为太短信息不够,太长会稀释关键信息,而且增加 token 成本。我实测下来,800 字左右的事实卡片,配合好的提示词,Agent 的输出质量最高。
这里有个关键技巧:所有数值都要带上“相对含义”。比如不要只写“RSI = 72”,要写“RSI = 72,处于超买区间”。大模型对绝对数值不敏感,但对“超买”“超卖”“放量”“缩量”这类定性描述反应很好。这一步相当于帮模型做了一次预判断,能显著提升输出质量。
3.2 提示词工程:让每个 Agent 各司其职
提示词是这套系统的核心资产,我调了大概两周才稳定下来。下面给出我实际在用的模板骨架,你可以直接拿去改。
看多 Agent 的提示词:
你是一位专注 A 股短线交易的资深分析师,有 10 年实盘经验,特别擅长从技术面和资金面挖掘机会。 你的任务:基于以下事实卡片,构建一个尽可能有力的看多逻辑。 规则: 1. 所有论据必须来自事实卡片,不允许编造数据 2. 至少给出 3 条独立的看多理由 3. 每条理由要说明“为什么这个信号意味着上涨概率增加” 4. 如果事实卡片中存在明显利空,你必须正面回应,不能回避 5. 最后给出一个 0-100 的看多信心分 事实卡片: {fact_card}看空 Agent 的提示词结构类似,但任务换成“找出所有风险点”,规则里加一条“你必须假设这只票即将下跌,然后找出支持这个假设的证据”。这个“假设下跌”的设定很关键,它能激活模型的对抗性思维。
裁判 Agent 的提示词最复杂:
你是一位独立的风险控制官,不参与多空辩论,只负责裁决。 你的任务: 1. 分别总结看多和看空双方的核心论据 2. 指出双方论据中存在的逻辑漏洞或数据误读 3. 指出至少一个双方都忽略的风险因素 4. 给出综合判断:偏多、偏空、还是观望 5. 给出置信度(0-100),并说明什么情况下这个判断会失效 规则: - 你不允许简单地说“双方都有道理”,必须给出明确倾向 - 如果双方论据质量都很差,你可以直接说“数据不足,建议观望” - 你的判断必须基于事实卡片,不允许引入外部信息 看多陈述: {bull_output} 看空陈述: {bear_output} 事实卡片: {fact_card}这套提示词我迭代了十几个版本,最大的心得是:规则要具体到可执行。“给出 3 条理由”比“充分论证”有用得多,“指出至少一个被忽略的风险”比“全面考虑”有用得多。大模型需要明确的指令,模糊的要求只会得到模糊的输出。
3.3 辩论流程编排:顺序、上下文与终止条件
辩论流程我设计成两轮,不是一轮也不是三轮。一轮太浅,双方还没来得及深入就结束了;三轮以上边际收益递减,而且 token 成本线性增长。两轮的具体流程是:
第一轮:看多 Agent 先发言,输出看多逻辑。然后看空 Agent 拿到看多逻辑 + 事实卡片,针对性反驳。注意,看空 Agent 的输入里要包含看多的输出,这样它才能“接招”而不是自说自话。
第二轮:看多 Agent 拿到看空的反驳,做最后一次回应。然后裁判 Agent 综合所有内容做裁决。
这个流程的关键在于上下文传递。看空 Agent 的输入 = 事实卡片 + 看多第一轮输出;看多第二轮输入 = 事实卡片 + 看空输出;裁判输入 = 事实卡片 + 所有轮次输出。每一轮的上下文都在增长,所以我在事实卡片阶段就控制了长度,给后续轮次留出空间。
终止条件我设了三个:正常走完两轮、任何一方输出格式严重错误、或者 token 超限。实际跑下来,95% 以上的情况都能正常走完。格式错误主要出现在模型输出 JSON 解析失败,我的处理方式是重试一次,再失败就跳过这只票,记录到日志里人工检查。
3.4 输出结构化:把辩论结果变成可操作的信号
辩论结束后,裁判的输出是一段自然语言。但我要的是能进回测系统的结构化信号。所以我在裁判提示词里要求它最后输出一个 JSON 块,格式固定:
{ "verdict": "bullish|bearish|neutral", "confidence": 75, "key_bull_points": ["理由1", "理由2"], "key_bear_points": ["风险1", "风险2"], "ignored_risk": "双方都忽略的风险", "invalidation_condition": "什么情况下判断失效" }这个 JSON 块我用正则表达式从裁判输出里提取,解析成功后存入数据库。回测的时候,我就可以按 verdict 和 confidence 做分组统计,看看“高置信度看多”的信号后续表现到底如何。
这里有个实操心得:不要完全信任模型输出的 JSON。我遇到过模型在 JSON 里加注释、用单引号、或者漏掉逗号的情况。所以解析代码一定要做容错,解析失败时保留原始文本,不要直接丢弃。我现在的做法是先用json.loads试一次,失败就用正则提取关键字段,再失败就标记为“解析异常”存原始文本。
4. 实操全流程:从零跑通一个辩论实例
4.1 环境准备与依赖安装
先把环境搭起来。我用的是 Python 3.11,主要依赖就几个:
pip install pandas polars pyarrow openai tushare akshare简单说明一下每个包的用途:pandas 和 polars 做数据处理,pyarrow 是 Parquet 的底层依赖,openai 是调用大模型 API 的 SDK(如果你用其他模型,换成对应的 SDK 就行),tushare 和 akshare 是获取 A 股数据的常用库。
关于数据源,我建议两个都装。tushare 的分钟数据需要积分,akshare 免费但稳定性一般。我的做法是平时用 akshare 拉数据,遇到字段缺失或者接口异常时用 tushare 补。两个数据源交叉验证,还能发现一些数据质量问题。
注意:数据接口的调用频率都有限制,不要写死循环去拉。我的做法是加一个 0.5 秒的 sleep,并且把拉取任务放在收盘后执行,避免影响盘中操作。
4.2 数据拉取与本地存储
数据拉取的核心逻辑是增量更新。第一次跑的时候全量拉,之后每天只拉当天的新数据。下面是我在用的核心代码骨架:
import akshare as ak import pandas as pd from pathlib import Path from datetime import datetime, timedelta DATA_DIR = Path("./data/minute") DATA_DIR.mkdir(parents=True, exist_ok=True) def fetch_minute_data(symbol: str, start_date: str, end_date: str): """拉取单只股票的分钟数据""" df = ak.stock_zh_a_hist_min_em( symbol=symbol, period="5", start_date=start_date, end_date=end_date, adjust="qfq" ) return df def save_to_parquet(df: pd.DataFrame, symbol: str): """按股票代码分文件存储""" file_path = DATA_DIR / f"{symbol}.parquet" if file_path.exists(): old_df = pd.read_parquet(file_path) df = pd.concat([old_df, df]).drop_duplicates( subset=["时间"], keep="last" ) df.to_parquet(file_path, index=False)这段代码有几个细节值得说。第一,period="5"表示 5 分钟 K 线,你也可以用 1 分钟,但数据量会大 5 倍,我实测下来 5 分钟对于短线判断已经够用。第二,adjust="qfq"是前复权,做技术指标必须用复权数据,否则除权那天会出现巨大的假跳空。第三,去重的时候用keep="last",保证最新拉取的数据覆盖旧数据。
4.3 事实卡片生成:把数据翻译成 AI 语言
有了原始数据,下一步是生成事实卡片。这是整个流程里最需要“手工调优”的环节,因为什么信息放进去、怎么表述,直接决定辩论质量。
def build_fact_card(symbol: str, df: pd.DataFrame) -> dict: """从分钟数据生成事实卡片""" latest = df.iloc[-1] close = latest["收盘"] # 计算涨跌幅 close_5d_ago = df.iloc[-240*5]["收盘"] if len(df) > 240*5 else df.iloc[0]["收盘"] change_5d = (close - close_5d_ago) / close_5d_ago * 100 # 计算量比 vol_today = df.tail(48)["成交量"].sum() # 当天 4 小时 vol_5d_avg = df.tail(48*5)["成交量"].sum() / 5 volume_ratio = vol_today / vol_5d_avg if vol_5d_avg > 0 else 1 # OBV 计算 obv = compute_obv(df) obv_trend = "上升" if obv[-1] > obv[-48] else "下降" card = { "symbol": symbol, "current_price": round(close, 2), "change_5d": f"{change_5d:.2f}%", "volume_ratio": f"{volume_ratio:.2f}", "obv_trend": obv_trend, "rsi": round(compute_rsi(df), 1), "macd_status": get_macd_status(df), "bollinger_position": get_bollinger_position(df), } return cardOBV 的计算逻辑很简单:收盘价涨就加成交量,跌就减成交量,然后累加。这个指标在“OBV 抓妖股”这个热词里被频繁提到,确实有它的道理——OBV 能反映资金是在流入还是流出,而且比单纯看成交量更稳定。我实测下来,OBV 趋势和价格趋势背离的时候,往往是比较强的反转信号。
RSI 和 MACD 的计算我就不展开写了,网上标准实现很多。关键是把数值翻译成定性描述。比如 RSI 大于 70 就标注“超买”,小于 30 标注“超卖”,中间标注“中性”。这个翻译步骤看起来简单,但对模型理解帮助很大。
4.4 辩论执行:一次完整的调用记录
下面是我实际跑一次辩论的完整记录,股票代码我隐去了,只看逻辑。
事实卡片(简化版):
{ "symbol": "XXXXXX", "current_price": 15.32, "change_5d": "+8.5%", "volume_ratio": "2.3", "obv_trend": "上升", "rsi": 68.5, "macd_status": "金叉后第 3 天", "bollinger_position": "中轨上方,接近上轨" }看多 Agent 输出(节选):
理由一:5 日涨幅 8.5% 配合量比 2.3,属于典型的放量上涨,说明有增量资金进场,不是缩量反弹的假突破。 理由二:OBV 趋势上升,与价格趋势同向,资金流入信号明确,没有出现量价背离。 理由三:MACD 金叉后第 3 天,处于金叉初期,历史上这个阶段往往还有延续空间。 信心分:72
看空 Agent 输出(节选):
反驳一:RSI 已经到 68.5,接近超买区间,短线追高风险较大。看多说的“放量上涨”在 RSI 高位时反而可能是出货信号。 反驳二:布林带接近上轨,统计上触及上轨后短期回调概率超过 60%。 反驳三:看多忽略了 5 日涨幅 8.5% 本身已经透支了部分上涨空间,如果没有新的催化剂,继续上攻动力不足。 信心分:65(看空信心)
裁判 Agent 输出(节选):
综合判断:偏多,但置信度中等(58)。 双方论据质量:看多的量价配合论据较扎实,看空的 RSI 超买论据也成立。核心分歧在于“放量上涨是启动还是出货”,这取决于后续是否有持续资金流入。 被忽略的风险:双方都没有考虑大盘整体环境。如果大盘处于下跌趋势,个股的独立行情很难持续。 失效条件:如果次日成交量萎缩到 5 日均量以下,看多逻辑失效。
这个案例很典型:看多和看空都有道理,裁判没有和稀泥,而是指出了关键分歧点和被忽略的风险。这种输出对实盘的参考价值,比单纯一个“买入”或“卖出”信号高得多。
4.5 结果入库与回测对接
辩论结果解析成 JSON 后,我存到一张专门的表里,字段包括:股票代码、日期、verdict、confidence、看多理由、看空理由、被忽略风险、失效条件、原始输出。这张表就是回测的输入。
回测的时候,我用 backtrader 做多股回测。核心逻辑是:每天收盘后跑一遍辩论,第二天开盘按信号操作。比如 verdict 是 bullish 且 confidence 大于 70,就买入;verdict 是 bearish 就卖出或观望。回测周期我一般跑一年以上,太短了统计意义不足。
这里有个重要的回测陷阱要提醒:不要用未来数据。事实卡片里所有指标都必须基于当天收盘前的数据计算,不能包含当天收盘后的信息。我当初就犯过这个错,把当天收盘价算进了 RSI,结果回测收益虚高得离谱,实盘一跑就露馅。
5. 常见问题与排查技巧实录
5.1 模型输出格式不稳定怎么办
这是最高频的问题。大模型有时候不按你要求的 JSON 格式输出,有时候在 JSON 外面包一层解释文字,有时候字段名拼错。我的处理策略是三层容错:
第一层,提示词里明确要求“只输出 JSON,不要有任何其他文字”,并且给出格式示例。这一层能解决 80% 的问题。
第二层,解析时先用正则提取 JSON 块(匹配{...}的最长内容),再尝试json.loads。这一层能解决 15% 的问题。
第三层,如果还是失败,用大模型做一次“格式修复”,把原始输出丢回去让它重新整理成 JSON。这一层解决剩下的 5%。
如果三层都失败,就记录原始输出,标记为异常,人工检查。我跑了几千次,真正需要人工介入的不到 1%。
5.2 辩论变成“互相吹捧”怎么破
有时候看多和看空会达成诡异的共识,比如看空说“虽然我看空,但看多的逻辑也有道理”,然后裁判说“双方都有道理,建议观望”。这种输出毫无价值。
我的解法是在提示词里加强制对抗规则:看空 Agent 必须找出至少 3 条反对理由,如果找不到,必须明确说“数据不足以支持看空,但我对看多逻辑存疑,因为……”。裁判 Agent 必须给出明确倾向,不允许“双方都有道理”这种和稀泥的结论。
另外,我会在事实卡片里故意加入一些模糊信息,比如“近期有机构调研但未披露细节”,这种信息天然容易引发分歧,能激活辩论。
5.3 数据缺失或异常怎么处理
A 股数据经常有缺失,比如停牌、涨跌停导致分钟数据不连续、接口临时故障等。我的原则是宁可跳过,不要瞎补。
如果某只票当天数据缺失超过 20%,直接跳过,不生成事实卡片。如果缺失较少,用前值填充,但在事实卡片里标注“数据存在缺失,判断置信度应下调”。这个标注很重要,裁判 Agent 看到这个提示会自动降低置信度。
涨跌停的情况要特别处理。一字涨停的票,分钟数据几乎没有波动,所有技术指标都失真。我的做法是检测到一字板就跳过辩论,直接标记为“无法分析”。
5.4 成本控制:怎么让 token 消耗降下来
多 Agent 辩论的 token 消耗是单次调用的 3 到 5 倍。如果每天跑 500 只票,成本会很可观。我用了几个策略来控制:
策略一:预筛选。先用简单的规则筛掉明显不值得分析的票,比如日均成交额低于 5000 万的、ST 的、上市不满 3 个月的。这一步能筛掉 60% 以上的票。
策略二:缓存。事实卡片生成后缓存起来,如果同一天多次调用,直接读缓存。裁判的裁决结果也缓存,避免重复分析。
策略三:分级调用。先用便宜的小模型做初筛,只有小模型认为“值得深入分析”的票,才用大模型跑完整辩论。这个策略能再省 50% 以上的成本。
策略四:控制上下文。事实卡片控制在 800 字以内,辩论轮次控制在两轮,历史对话不重复传入。这些细节加起来能省不少 token。
5.5 常见问题速查表
| 问题现象 | 可能原因 | 排查方向 | 解决方法 |
|---|---|---|---|
| 输出不是 JSON | 提示词不够明确 | 检查提示词是否有格式示例 | 加“只输出 JSON”约束,加三层容错 |
| 辩论无对抗性 | 角色定义太模糊 | 检查看空提示词 | 加“必须找出 3 条反对理由” |
| 置信度总是很高 | 模型过度自信 | 检查裁判提示词 | 要求裁判说明失效条件 |
| 数据指标异常 | 复权或时间对齐问题 | 检查数据预处理 | 统一用前复权,统一时间戳 |
| token 消耗过大 | 上下文太长 | 检查事实卡片长度 | 压缩到 800 字,加预筛选 |
| 回测收益虚高 | 用了未来数据 | 检查指标计算时点 | 确保只用当天收盘前数据 |
| 接口频繁失败 | 调用频率超限 | 检查请求间隔 | 加 sleep,收盘后执行 |
| 解析异常率高 | 模型不稳定 | 检查模型版本 | 换更稳定的模型或加格式修复 |
6. 我踩过的坑和几条实在建议
6.1 不要指望 AI 告诉你买什么
这是我最大的体会。这套系统跑了大半年,我最大的收获不是“AI 帮我选到了牛股”,而是“AI 帮我避开了一些逻辑有问题的票”。它的价值在于风险过滤,不在于收益增强。
你如果抱着“让 AI 告诉我明天买什么”的心态来做这个项目,大概率会失望。但如果你把它当成一个“逻辑审查员”,帮你检查自己的判断有没有漏洞,它的价值就出来了。我现在的工作流是:自己先看中几只票,然后用辩论系统跑一遍,看看看空 Agent 能不能找出我没想到的风险。很多时候它确实能找出我忽略的点。
6.2 提示词要当代码一样维护
我一开始把提示词写在代码里,改一次要重新部署。后来我把提示词抽出来放到单独的配置文件,用 YAML 管理,改提示词不用动代码。再后来我加了版本号,每次改提示词都记录版本和改动原因,方便回溯。
这个习惯救了我好几次。有一次我改了一版看空提示词,结果那周的看空信号特别多,我以为是市场变差了,后来查版本记录才发现是新提示词太激进。回滚到旧版本就正常了。提示词是这套系统的核心资产,值得像代码一样认真管理。
6.3 回测和实盘的差距要有心理准备
回测收益和实盘收益的差距,在 AI 辅助选股这个场景下会特别明显。原因有几个:一是回测用的是历史数据,模型可能“见过”这些数据;二是回测不考虑滑点和流动性;三是市场风格会变,模型在某个阶段有效的逻辑,换个阶段就失效了。
我的做法是回测只用来验证逻辑,不用来预测收益。如果回测显示某个信号有正向收益,我会去看它的逻辑是否合理,而不是直接相信这个收益数字。逻辑合理 + 回测正向,才值得小仓位试水。
6.4 关于“AI 无禁词聊天”这类热词的冷思考
热搜里有一堆“无禁词 AI 聊天”“无限制 AI 对话”之类的词,我理解大家想要的是“不被限制的 AI 能力”。但在 A 股这个场景下,限制反而是好事。如果 AI 可以随意编造数据、随意给出激进建议,那才是灾难。
我反而会主动给 Agent 加限制:不允许编造数据、不允许给出具体买卖点位、不允许预测具体涨幅。这些限制让输出更保守,但更可靠。在投资这件事上,保守一点没坏处。
6.5 后续可以扩展的方向
这套系统目前只做了技术面和资金面的辩论,后续可以扩展的方向不少。比如加入基本面 Agent,专门分析财报数据;加入新闻情绪 Agent,分析近期新闻的情感倾向;加入大盘环境 Agent,判断整体市场处于什么阶段。
另一个方向是辩论过程的可视化。现在输出是文本,如果能做成一个时间线,展示每个 Agent 的发言和裁判的裁决,会更直观。这个用简单的 Web 前端就能做,我打算下一步试试。
还有一个方向是多模型辩论。现在三个 Agent 用的是同一个模型,如果换成不同厂商的模型,比如一个用国产模型、一个用海外模型,辩论的多样性会更高。不过成本也会上去,需要权衡。
最后说一句实在的:这套系统不是印钞机,它是一个帮你想得更全面的工具。A 股市场里,少犯错比多赚钱更重要。能帮你少踩一个坑,这套系统就值了。