1. 本地 AI 炒股工具到底解决什么问题
你是不是也刷到过各种 AI 选股神器,页面写着“精准捕捉买卖点”,点进去要么按月订阅,要么要求授权读取持仓和交易记录。对程序员来说,这种方案最大的心理障碍不是钱,而是数据流向不透明:你的自选股、成本价、仓位分布,全都经过别人的服务器。2026 年大家对数据边界越来越敏感,于是“本地 AI 炒股工具”这个方向开始被更多人认真对待。
所谓本地 AI 炒股工具,核心就三件事:本地大模型负责理解和推理,Python 负责拉取公开行情与财务数据,整个链路跑在你自己的笔记本上。它适合谁?适合想练手 LLM 应用的程序员、对隐私敏感的个人投资者、以及正在学量化想找个可解释实验框架的人。它不适合谁?不适合指望它直接给买卖信号然后全仓执行的人——这一点后面会反复强调。
我自己的做法是用 Ollama 跑本地模型,Python 拉 A 股和美股公开数据,再用一层统一 Key 通道把需要联网的模型调用收口,避免每个脚本各配一套密钥。下面从环境到验证一步步来,配置骨架可以直接复制。
2. TaoToken 前置:统一 Key 与 API 通道
本地模型能覆盖大部分分析任务,但有些场景你还是会想调用更强的云端模型,比如让大模型读一份长财报、做多轮辩论式复盘。这时候如果每个脚本都硬编码一家厂商的 Key,维护起来很痛苦。我的做法是留一个统一入口,把模型调用收敛到一处。
TaoToken 在这里的角色是统一 Key 和 API 通道:你拿到一个 Key,就可以在配置里切换不同模型,而不用改业务代码。官网地址是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end ,API 入口是 https://taotoken.net/api 。注意 API 地址不带跟踪参数,配置里填这个就行。
需要提前准备的东西:一个 TaoToken Key(在控制台创建,地址 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ),本地装好 Ollama,Python 3.10 以上。Key 只放在本地环境变量或配置文件里,不要提交到 Git。
注意:本地工具的原则是“能本地就本地”。TaoToken 通道是给需要云端强模型的环节用的,不是让你把所有请求都发出去。持仓、成本这类敏感字段永远不要拼进发往云端的 prompt。
3. 可复制配置:config.toml 与 settings.json 骨架
先建项目目录,我习惯这样分:
mkdir localstockai && cd localstockai mkdir config data agents python -m venv .venv source .venv/bin/activate # Windows 用 .venv\Scripts\activate pip install ollama akshare yfinance pandas langchain langchain-community langgraph chromadb streamlit3.1 config.toml:模型与数据源
# config/config.toml [local_llm] provider = "ollama" model = "qwen3:14b" base_url = "http://127.0.0.1:11434" temperature = 0.2 num_ctx = 8192 [cloud_llm] # 需要云端强模型时启用,Key 从环境变量读取 enabled = true base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" model = "claude-sonnet" timeout = 60 [data] a_share_source = "akshare" us_source = "yfinance" cache_dir = "./data/cache" cache_ttl_hours = 6 [risk] max_position_pct = 0.1 stop_loss_pct = 0.08 paper_trade_only = truetemperature 设 0.2 是为了让分析结论稳定一些,金融场景不需要太发散。num_ctx 给 8192,够塞下一段财报摘要加技术指标。paper_trade_only 默认 true,意思是只做纸上交易,这个开关别急着关。
3.2 settings.json:Agent 与工具注册
{ "agents": { "researcher": { "role": "拉取行情、财务、新闻,输出结构化事实", "tools": ["get_stock_price", "get_financials", "get_news_sentiment"] }, "decider": { "role": "结合事实给出倾向性建议与理由", "tools": ["analyze_stock"] }, "risk": { "role": "计算仓位上限与止损位,否决高风险建议", "tools": ["calc_position", "calc_stop_loss"] } }, "pipeline": ["researcher", "decider", "risk"], "output": { "language": "zh", "include_reasoning": true, "save_dir": "./data/reports" } }这个结构对应的是“研究员 → 决策 → 风控”三段式。风控 Agent 有一票否决权,这是整个设计里最重要的约束:模型可以看多,但仓位和止损由规则层兜底。
3.3 环境变量与 Key 注入
export TAOTOKEN_API_KEY="你的Key"Windows 用setx TAOTOKEN_API_KEY "你的Key"。代码里只读环境变量,不写死。
4. 本地推理连通性与选股回测验证
配置写完先别急着写业务,先验证两条链路:本地 Ollama 通不通,TaoToken 通道通不通。
4.1 验证 Ollama 本地推理
ollama pull qwen3:14b ollama run qwen3:14b "用一句话解释市盈率"能正常返回就说明本地模型可用。再用 Python 确认一次:
import ollama resp = ollama.chat( model="qwen3:14b", messages=[{"role": "user", "content": "返回JSON: {\"ok\": true}"}], ) print(resp["message"]["content"])4.2 验证 TaoToken 通道
import os, requests key = os.environ["TAOTOKEN_API_KEY"] r = requests.post( "https://taotoken.net/api/v1/chat/completions", headers={"Authorization": f"Bearer {key}"}, json={ "model": "claude-sonnet", "messages": [{"role": "user", "content": "只回复两个字:连通"}], }, timeout=60, ) print(r.status_code, r.json()["choices"][0]["message"]["content"])返回 200 且内容正常,说明统一 Key 通道没问题。如果 401,检查 Key 是否带上了 Bearer 前缀;如果超时,先确认本地网络能访问该域名。
4.3 拉数据并跑一次选股回测
import akshare as ak import pandas as pd df = ak.stock_zh_a_hist(symbol="000001", period="daily", adjust="qfq") df["ma20"] = df["收盘"].rolling(20).mean() df["signal"] = (df["收盘"] > df["ma20"]).astype(int) df["ret"] = df["收盘"].pct_change().shift(-1) strategy_ret = (df["signal"] * df["ret"]).dropna() print("累计收益:", (1 + strategy_ret).prod() - 1) print("交易天数:", len(strategy_ret))这段只是最朴素的均线策略,目的是验证数据管道和回测框架能跑通。真正让本地 LLM 参与时,把signal换成模型输出的倾向分即可。实测下来,先跑通数据闭环,再接入模型,排错成本低很多。
4.4 让本地模型读一次结构化输入
import ollama, json facts = { "ticker": "000001", "price": float(df["收盘"].iloc[-1]), "ma20": float(df["ma20"].iloc[-1]), "trend": "above_ma20" if df["收盘"].iloc[-1] > df["ma20"].iloc[-1] else "below_ma20", } prompt = f"根据以下事实给出倾向(看多/中性/看空)和一句理由,只输出JSON:{json.dumps(facts, ensure_ascii=False)}" resp = ollama.chat(model="qwen3:14b", messages=[{"role": "user", "content": prompt}]) print(resp["message"]["content"])到这一步,你已经有了一个最小可用的本地 AI 分析闭环:数据在本地、推理在本地、结论可解释。
5. 本篇常见错排查
Ollama 连接被拒:报Connection refused多半是服务没起。Mac/Linux 用ollama serve前台跑一次看日志,Windows 确认托盘图标在。base_url 别写成 https,本地是 http。
模型加载后内存爆掉:14B 模型在 16G 内存机器上会比较紧张。可以换qwen3:8b或llama3.2,或者把 num_ctx 降到 4096。别一边跑模型一边开一堆浏览器标签。
AkShare 拉数据报字段错:数据源接口偶尔调整列名。先print(df.columns)看实际字段,再改代码里的列引用。加个 try/except 把原始返回落盘,方便对照。
TaoToken 返回 401/403:先确认环境变量在当前 shell 生效(echo $TAOTOKEN_API_KEY),再确认请求头是Bearer加空格。Key 不要有多余换行。
回测收益看起来好得不真实:检查有没有未来函数。上面代码用shift(-1)对齐次日收益,如果你把当日收益算进去,结果会虚高。另外没扣手续费和滑点,实盘会打折。
模型输出不是 JSON:本地小模型偶尔会加解释文字。可以在 prompt 里强调“只输出JSON”,再用正则截取第一个{到最后一个},解析失败就重试一次。
持仓数据混进云端请求:这是最需要警惕的。在发往 TaoToken 通道前,加一层字段白名单过滤,只允许 ticker、价格、指标这类公开字段通过。成本价、仓位、账户余额一律不出本地。
6. 继续搭建与接入入口
把上面的骨架跑通后,你可以往几个方向扩展:给研究员 Agent 加本地 RAG,把财报 PDF 丢进 Chroma 做检索;给风控 Agent 加最大回撤约束;用 Streamlit 做个输入代码就出报告的小界面。需要长期跑编码和 Agent 编排的话,可以了解 Coding Plan( https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite );想先在线验证模型输出效果,用模型对话( https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_content=model-chat&utm_campaign=rewrite )试几轮;Key 管理和创建在 API Keys 页面( https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite );接入细节和参数说明看接入文档( https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite )。如果你用 Claude Code 这类工具做开发,Anthropic 兼容入口在 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claude-code-anthropic&utm_campaign=rewrite 。
最后提醒一句:本地 AI 炒股工具的价值在于把模型变成可解释的研究助手,而不是预测机器。先纸上交易跑几个月,确认你的回测逻辑没有漏洞,再谈其他。