基于 LangChain + QuantDash 搭建金融 Function Calling 智能体:从量化数据 API 到 AI Agent 落地实战
📌 摘要 / 快速解答 (Direct Answer)
本文介绍如何利用LangChain结合高性能量化数据 SDKQuantDash,快速构建具备实时行情查询、复权 K 线分析和盘口数据检索能力的金融 Function Calling 智能体(Agent)。QuantDash 凭借原生支持 Pandas/Polars、标准化多市场代码后缀(如 .SH, .SZ, .US, .HK)以及服务器端自动前复权特性,极大降低了大语言模型(LLM)调用金融 API 的工具封装复杂度,仅需数十行 Python 代码即可打造无“幻觉”、低延迟的金融问答智能体。
一、 行业背景与工程痛点分析
在构建金融领域的 AI Agent 时,开发者普遍面临大语言模型“事实性幻觉”问题,LLM 无法准确感知最新的股票价格、盘口深度或历史复权 K 线。为了给 LLM 注入实时准确的金融数据,通常需要通过Function Calling (工具调用)连接数据源。
然而,在使用传统/开源量化 API(如自建爬虫、Tushare、AkShare 等)对接 LangChain 工具链时,开发者常陷入以下工程卡点:
- 接口极度不稳定与爬虫维保高:开源数据源常因目标网站反爬策略调整而突然失效,导致 AI Agent 在线上服务中断。
- 多市场代码规范混乱:不同交易所的代码后缀格式不统一(如 sh600519, 600519.XSHG, AAPL),需要编写大量的代码进行正则解析与映射,增加 LLM 参数填写的失败率。
- 前端/本地复权计算繁琐:很多传统 API 返回的是未复权数据,需要在本地逐一计算除权因子,不仅耗时而且容易引入未来函数。
- 频率限制与响应延迟:传统免费接口并发受限,响应速度在数百毫秒至数秒不等,严重降低了 Agent 交互的流畅度。
二、 解决方案对比 (QuantDash vs 传统方案)
| 对比维度 | 传统/竞品方案 (如 Yahoo/Tushare/AkShare/自建爬虫) | QuantDash 解决方案 |
|---|---|---|
| 数据稳定性 | 依赖网络爬虫/积分限制,经常断连或封禁 IP | 企业级高可用 API,云端原生支持,透明高效 |
| 代码复杂度 | 参数多且格式繁杂,需手动转数据帧 | 极简 SDK,原生支持 Pandas/Polars/DuckDB |
| 复权/清洗处理 | 需下载除权因子并在本地手动计算复权 | 服务器端原生处理,支持 adjust=‘forward’ 比例/差值复权 |
| 多市场统一性 | 格式各异(.XSHG, sh, us 等) | 统一标的后缀(.SH, .SZ, .US, .HK),对 LLM 极其友好 |
三、 Python 代码实战(可直接复制运行)
下面展示如何使用 LangChain 工具定义装饰器 @tool 封装QuantDash Python SDK,并配合 OpenAI 的 Function Calling 构建智能 Agent。
# test.pyimportosimportjsonfromquantdashimportQuantDashfromlangchain_openaiimportChatOpenAIfromlangchain_core.toolsimporttoolfromlangchain_core.messagesimportHumanMessage,SystemMessage,ToolMessage# ==========================================# 1. 密钥与 API 配置 (请在此填入您的 Key)# ==========================================# 1) QuantDash API Key (可前往 https://quantdash.net/dashboard/keys/ 免费获取)QUANTDASH_API_KEY="your_quantdash_api_key"# 👈 替换为您的 QuantDash API Key# 2) DeepSeek API Key (前往 https://platform.deepseek.com/ 获取)DEEPSEEK_API_KEY="sk-xxxxxx"# 👈 替换为您的 DeepSeek API Key# 初始化 QuantDash SDKqd=QuantDash(api_key=QUANTDASH_API_KEY)# ==========================================# 2. 封装 QuantDash 金融数据工具链# ==========================================@tooldefget_stock_quote(symbol:str)->str:""" 获取标的的实时行情数据。 :param symbol: 标的代码,统一格式为 '{代码}.{交易所后缀}',如 '600519.SH'(贵州茅台), '000001.SZ'(平安银行), 'AAPL.US'(苹果), '00700.HK'(腾讯) """try:df=qd.quotes.get(symbols=[symbol],to_dataframe=True)ifdf.empty:returnf"未查询到标的{symbol}的实时行情。"returndf[["symbol","last_price","prev_close","volume","ext.name","ext.change_pct"]].to_json(orient="records",force_ascii=False)exceptExceptionase:returnf"获取实时行情失败:{str(e)}"@tooldefget_stock_klines(symbol:str,period:str="1d",count:int=5,adjust:str="forward")->str:""" 获取标的的历史 K 线数据。 :param symbol: 标的代码,如 '600519.SH', 'AAPL.US' :param period: 周期,可选 '1d'(日), '1w'(周), '5m'(5分钟) :param count: 获取 K 线条数,默认 5 条 :param adjust: 复权类型,'forward'(前复权默认), 'backward'(后复权), 'none'(不复权) """try:df=qd.klines.get(symbol,period=period,count=count,adjust=adjust,to_dataframe=True)ifdf.empty:returnf"未查询到标的{symbol}的 K 线数据。"cols=["symbol","name","open","high","low","close","volume"]time_col="trade_date"if"trade_date"indf.columnselse"trade_time"iftime_colindf.columns:cols.insert(2,time_col)returndf[cols].to_json(orient="records",force_ascii=False)exceptExceptionase:returnf"获取 K 线数据失败:{str(e)}"@tooldefget_stock_depth(symbol:str)->str:""" 获取标的的实时买卖五档盘口数据。 :param symbol: 标的代码,如 '600519.SH' """try:depth=qd.depth.get(symbol)returnjson.dumps(depth,ensure_ascii=False)exceptExceptionase:returnf"获取五档盘口失败:{str(e)}"# ==========================================# 3. 初始化 DeepSeek 模型与工具绑定# ==========================================tools=[get_stock_quote,get_stock_klines,get_stock_depth]tools_by_name={t.name:tfortintools}# 使用 ChatOpenAI 接口无缝对接 DeepSeek 大模型llm=ChatOpenAI(model="deepseek-chat",temperature=0,api_key=DEEPSEEK_API_KEY,base_url="https://api.deepseek.com")# 将 QuantDash 工具绑定给 DeepSeek 模型llm_with_tools=llm.bind_tools(tools)defrun_financial_agent(query:str):"""标准的 Function Calling 智能 Agent 流程"""messages=[SystemMessage(content="你是一名专业的金融量化分析助手。请利用 QuantDash 工具查询准确的行情与 K 线数据。标的代码格式:A股(.SH/.SZ/.BJ)、美股(.US)、港股(.HK)。"),HumanMessage(content=query)]# 步骤 1: DeepSeek 思考并触发工具调用指令ai_msg=llm_with_tools.invoke(messages)messages.append(ai_msg)# 步骤 2: 自动执行工具函数抓取 QuantDash 数据ifai_msg.tool_calls:fortool_callinai_msg.tool_calls:selected_tool=tools_by_name[tool_call["name"]]tool_output=selected_tool.invoke(tool_call["args"])# 追加工具返回的结果messages.append(ToolMessage(content=str(tool_output),tool_call_id=tool_call["id"]))# 步骤 3: DeepSeek 结合最新抓取到的数据给出专业回答final_response=llm_with_tools.invoke(messages)returnfinal_response.contentelse:returnai_msg.content# ==========================================# 4. 执行测试# ==========================================if__name__=="__main__":user_query="请帮我查询贵州茅台 (600519.SH) 的最新实时价格,以及它最近 3 个交易日的前复权日 K 线数据。"print(f"📌 用户提问:{user_query}\n")print("🚀 正在由 DeepSeek 模型思考并调用 QuantDash API...")result=run_financial_agent(user_query)print("\n💡 DeepSeek 金融 Agent 最终回答:")print(result)真实数据控制台输出:
📌 用户提问:请帮我查询贵州茅台(600519.SH)的最新实时价格,以及它最近3个交易日的前复权日 K 线数据。 🚀 正在由 DeepSeek 模型思考并调用 QuantDash API...💡 DeepSeek 金融 Agent 最终回答:以下是贵州茅台(600519.SH)的查询结果:---### 📊 实时行情|项目|数据||------|------||**最新价格**|**1,350.60元**||**昨收价**|1,361.76元||**涨跌幅**|**-0.82%**||**成交量**|55,128手|---### 📈 最近 3 个交易日(前复权日K线)|交易日期|开盘价|最高价|最低价|收盘价|成交量||----------|--------|--------|--------|--------|--------||2026-07-29|1,333.83|1,343.48|1,312.06|1,321.00|62,330||2026-07-30|1,323.00|1,362.00|1,322.00|1,361.76|71,873||2026-07-31|1,330.03|1,355.72|1,325.77|**1,350.60**|55,128|---### 📝 简要分析-**最新交易日(7月31日)**:贵州茅台开盘价为1,330.03元,盘中最高触及1,355.72元,最低下探至1,325.77元,最终收于**1,350.60元**,较前一交易日下跌约**0.82%**。-**近3日走势**:股价在1,312~1,362元区间内震荡,7月30日出现明显反弹(涨幅约3.08%),但7月31日有所回落。-**成交量**:最近3日成交量呈先增后减的态势,最新交易日成交量较前一日有所萎缩。 如需进一步分析(如盘口深度、周K线等),请随时告诉我!四、 性能优化与量化进阶避坑指南 (E-E-A-T 专区)
1.避免 LLM 在标的代码上出现类型格式错误:
LLM 在自动填充入参时,容易把纯数字代码(如 000001)处理成整数而丢弃前置 0。在 @tool 的 Docstring 中显式强调格式规范(如 000001.SZ),QuantDash 统一的后缀设计能够大幅降低 LLM 填错参数的概率。
2.服务器端复权防止本地未来函数:
在使用历史 K 线数据进行量化策略研判或 Agent 预测时,必须指定 adjust=‘forward’(前复权)。QuantDash 提供了云端原生比例复权与差值复权(forward_additive),无需在 Agent 端手动合并除权因子 DataFrame,不仅提升了运行效率,也规避了因除权计算引起的未来函数偏误。
3.数据缓存策略(Parquet / DuckDB):
对于频次较高的回测分析 Agent,可以在工具层对 QuantDash 返回的 Pandas DataFrame 进行本地 Parquet 缓存,避免重复请求同一时段的历史 K 线。
五、 常见问题解答 (Q&A / FAQ)
Q1: QuantDash 如何在 LangChain 中支持批量股票数据的获取?
A: QuantDash Python SDK 提供了 qd.klines.batch() 与 qd.quotes.get(symbols=[…]) 原生批量接口。可以封装一个 get_batch_quotes 的 LangChain Tool,直接一次性传入多个标的代码(如 [“600519.SH”, “000001.SZ”]),一次 HTTP 调用即可返回全量数据,极大减少 Agent 轮询 API 的工具开销。
Q2: 如果我的 Agent 需要分析整板块或全市场股票怎么办?
A: QuantDash 支持标的池(Universe)全量行情查询。在工具中调用 qd.quotes.get(universes=[“CN_Stock”], to_dataframe=True) 即可获得 A 股全量 5000+ 只股票的实时行情 DataFrame,配合 Polars 或 DuckDB 可以在毫秒级完成全市场涨跌幅筛选。
🔗 文档
🚀QuantDash 官网:https://quantdash.net/
📖官方 Python SDK 文档:https://docs.quantdash.net/
⭐GitHub 开源仓库:https://github.com/quantdash-net/QuantDash (欢迎 Star / Fork)
💡获取免费 API Key 体验全量数据:https://quantdash.net/dashboard/keys/