ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用大模型搭建AI股票分析系统:FDE流程驱动工程实战

用大模型搭建AI股票分析系统:FDE流程驱动工程实战 先分享一套近期在做的 AI 编程落地思路借助大模型从零搭建一个属于自己的股票分析系统。整个项目包含数据获取、技术指标计算、大模型深度分析、交互页面展示和 Docker 部署五个环节核心方法可以概括为 FDEFlow-Driven Engineering流程驱动工程——先把业务链路拆成清晰的数据流再让大模型在每一个关键节点辅助完成代码生成、参数调优和问题排查。这篇文章会把完整流程、可运行代码和踩坑点都整理出来适合正在学习大模型应用开发、AI 编程以及想快速搭建量化分析工具的开发者。1. 背景与核心概念1.1 什么是 FDEFDE 的全称是 Flow-Driven Engineering即“流程驱动工程”。它不是某一个具体的框架或软件而是一套基于大模型 AI 编程的工程组织方式。传统开发流程里我们习惯把系统拆成模块、类、函数再逐个实现。FDE 的切入角度不同它强调先画清一条完整的业务数据流数据输入 - 数据清洗 - 指标计算 - 分析判断 - 结果输出 - 部署运维这条链路中的每一环都有自己的输入、处理和输出。当我们把链路界定清楚之后大模型就能更好地理解上下文生成的代码也不容易跑偏。比如要做一个股票分析系统先梳理链路输入股票代码、时间范围、行情源清洗去除停牌日、空值、异常跳空数据计算移动平均线、RSI、MACD 等技术指标分析把行情摘要和指标结果交给大模型生成投资观点和风险提示输出以网页形式展示图表、指标表和 AI 结论部署通过 Docker 打包运行在服务器或本地。FDE 的核心价值在于把 AI 编程从一个“写代码”的动作升级为“设计一条可执行、可验证的数据流”。对开发者来说这种思维方式也能大幅减少大模型生成的代码与业务需求不一致的问题。1.2 为什么用大模型来做股票分析系统传统股票分析系统通常包括行情数据、技术指标和图表展示这类系统本身不难做。但用户真正需要的往往不只是“金叉死叉”这种机械信号而是能结合当前行情特征、指标变化和市场环境生成一段有逻辑、有风险意识的解读。这时候大模型的价值就体现出来了。它可以完成三类典型任务自然语言转查询用户输入“帮我分析最近 60 天的走势和成交量变化”大模型理解意图后调用对应函数获取数据并生成分析结构化数据总结把最近 N 天的 K 线数据、均线排列、RSI 数值整理成摘要让大模型输出通俗易懂的结论智能问答与复盘把历史行情、指标、新闻摘要组合成上下文让大模型回答用户提出的具体问题比如“当前是否处于超卖区间”。所以本文实现的不是一个大而全的商业炒股软件而是一个“数据 指标 大模型”的轻量级分析工作台。它足够灵活方便你后续接入更多数据源、更换不同大模型甚至扩展成定时任务。1.3 系统整体设计系统架构可以简化为三层层级主要职责对应技术数据层获取股票行情、缓存数据、数据清洗yfinance / akshare、pandas智能层计算指标、调用大模型、生成分析结论pandas、OpenAI 兼容接口展示层图表展示、指标表格、AI 对话页面Streamlit、Plotly这三层是分离的。数据层只负责“把数据送到内存里”智能层专注“计算和推理”展示层负责“让用户看得见”。FDE 思路下每一层都可以独立测试也方便后续替换。2. 环境准备与版本说明2.1 运行环境本文示例以 Python 项目为主建议使用 Python 3.10 或更高版本。操作系统方面Windows、macOS、Linux 均可需要注意的地方是部分数据源对系统网络环境有要求如果拉取行情失败可以换成 akshare 或本地 CSV 数据。推荐使用虚拟环境python -m venv stock_env source stock_env/bin/activate # Windows 下使用 stock_env\Scripts\activate2.2 技术栈清单组件作用说明streamlitWeb 交互页面轻量、适合快速搭建数据应用pandas数据处理与指标计算核心依赖plotly交互式图表展示 K 线、均线yfinance获取美股行情也可换 akshare 获取 A 股openai调用大模型 API支持 DeepSeek、Ollama 等 OpenAI 兼容服务docker容器化部署统一运行环境版本建议streamlit1.30 pandas2.0 plotly5.18 yfinance0.2.40 openai1.30.0 akshare1.13.0具体版本需要根据你的项目实际情况调整本文示例以常见环境为例重点演示配置思路。如果你的 Python 版本较旧先升级 Python再安装依赖会更省心。2.3 安装依赖pip install streamlit pandas plotly yfinance openai akshare安装完成后可以快速验证python -c import pandas; print(pandas.__version__) python -c import streamlit; print(streamlit.__version__)如果输出正常说明环境准备完成。3. 核心模块实现3.1 股票数据获取模块数据层是所有分析的前提。这里以 yfinance 为例它可以通过接口直接获取历史行情适合快速实现。同时兼容 akshare 的思路也会在注释里给出。创建stock_data.pyimport pandas as pd import yfinance as yf def fetch_stock_data(symbol: str, period: str 6mo, interval: str 1d) - pd.DataFrame: 获取股票历史行情。 :param symbol: 股票代码例如 600519.SS 代表贵州茅台 :param period: 1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, max :param interval: 1m, 2m, 15m, 1h, 1d, 1wk, 1mo :return: DataFrame包含 Open High Low Close Volume 等字段 ticker yf.Ticker(symbol) df ticker.history(periodperiod, intervalinterval, auto_adjustTrue) if df.empty: raise ValueError(f未获取到 {symbol} 的数据请检查代码或网络环境) # 统一列名为大写便于后续使用 df df.reset_index() df.columns [col.title() for col in df.columns] return df def clean_stock_data(df: pd.DataFrame) - pd.DataFrame: 数据清洗去空值、去除成交量异常为 0 的行。 df df.dropna(subset[Open, High, Low, Close]) df df[df[Volume] 0] return df.reset_index(dropTrue)这里需要注意auto_adjustTrue表示使用复权价格更贴近真实收益A 股代码在 yfinance 中需要带后缀例如600519.SS如果网络请求失败建议在项目里增加重试逻辑或切换数据源。3.2 技术指标计算模块技术指标我们不依赖 TA-Lib因为它在 Windows 上安装比较麻烦。用 pandas 手写几个常用指标代码可控性更高也方便后续扩展。创建indicators.pyimport pandas as pd def add_moving_average(df: pd.DataFrame, windows: list [5, 10, 20, 60]) - pd.DataFrame: 增加多条移动平均线例如 MA5、MA10、MA20。 df df.copy() for w in windows: df[fMA{w}] df[Close].rolling(windoww).mean() return df def add_rsi(df: pd.DataFrame, period: int 14) - pd.DataFrame: 计算 RSI 相对强弱指标。 RSI 70 表示超买RSI 30 表示超卖。 df df.copy() delta df[Close].diff() gain delta.clip(lower0) loss -delta.clip(upper0) avg_gain gain.rolling(windowperiod).mean() avg_loss loss.rolling(windowperiod).mean() rs avg_gain / avg_loss df[RSI] 100 - (100 / (1 rs)) return df def add_macd(df: pd.DataFrame, fast: int 12, slow: int 26, signal: int 9) - pd.DataFrame: 计算 MACD 指标。 df df.copy() ema_fast df[Close].ewm(spanfast, adjustFalse).mean() ema_slow df[Close].ewm(spanslow, adjustFalse).mean() df[DIF] ema_fast - ema_slow df[DEA] df[DIF].ewm(spansignal, adjustFalse).mean() df[MACD] (df[DIF] - df[DEA]) * 2 return df def compute_all_indicators(df: pd.DataFrame) - pd.DataFrame: 一键计算 MA、RSI、MACD 指标。 df add_moving_average(df) df add_rsi(df) df add_macd(df) return df移动平均线能反映趋势方向RSI 能提示超买超卖MACD 能捕捉短期动能变化。实际使用中不需要所有指标同时出现你可以根据分析需求按需选择。3.3 大模型接口封装大模型是这个系统的“分析大脑”。为了兼容不同服务商我建议按 OpenAI 兼容接口来封装这样无论是 DeepSeek、Qwen、通义还是本地部署的 Ollama、vLLM只要提供base_url和api_key就能直接切换。创建llm_client.pyfrom openai import OpenAI class LLMClient: 大模型客户端使用 OpenAI 兼容协议。 可通过环境变量配置 base_url 和 api_key。 def __init__(self, model_name: str None): self.api_key os.getenv(LLM_API_KEY, EMPTY) self.base_url os.getenv(LLM_BASE_URL, https://api.openai.com/v1) self.model_name model_name or os.getenv(LLM_MODEL, gpt-3.5-turbo) self.client OpenAI(api_keyself.api_key, base_urlself.base_url) def chat(self, messages: list, temperature: float 0.3, max_tokens: int 2000): 发送对话消息。 :param messages: 形如 [{role: system, content: ...}, {role: user, content: ...}] response self.client.chat.completions.create( modelself.model_name, messagesmessages, temperaturetemperature, max_tokensmax_tokens, ) return response.choices[0].message.content使用时的环境变量示例export LLM_API_KEY你的 API Key export LLM_BASE_URLhttps://api.deepseek.com/v1 export LLM_MODELdeepseek-chat如果你希望完全本地化运行也可以将base_url指向本机 Ollamaexport LLM_BASE_URLhttp://localhost:11434/v1 export LLM_MODELqwen2.5:14b这样设计的好处是代码不绑定具体厂商换模型只改环境变量不影响业务逻辑。3.4 提示词工程大模型能否输出高质量分析取决于提示词设计。在股票分析场景中我通常使用“角色设定 任务描述 数据上下文 输出要求”四段式结构。创建prompts.pydef build_stock_analysis_prompt(symbol: str, recent_data_desc: str, indicator_desc: str) - list: system_prompt ( 你是一名专业的股票分析师擅长技术面分析。 你给出的分析必须基于用户提供的行情数据和指标数据 不能编造不存在的价格信息。 回答要结构化包含趋势判断、支撑压力位、风险提示三个部分。 ) user_prompt f 请分析 {symbol} 的最新走势。 【最近行情摘要】 {recent_data_desc} 【核心指标】 {indicator_desc} 【输出要求】 1. 用 200 字以内概括当前趋势 2. 指出关键支撑位和压力位 3. 给出风险提示说明指标局限性 4. 不构成投资建议。 return [ {role: system, content: system_prompt}, {role: user, content: user_prompt.strip()} ]这里的亮点是“不编造价格”和“不构成投资建议”。大模型很容易一本正经地补充细节因此我们要在提示词里明确约束数据边界降低幻觉风险。4. 实战从零搭建股票分析系统4.1 创建项目结构建议按下面的目录结构组织代码stock-ai/ ├── stock_data.py ├── indicators.py ├── llm_client.py ├── prompts.py ├── app.py ├── requirements.txt ├── .env.example └── Dockerfile4.2 编写数据摘要生成模块大模型无法直接处理几千行 K 线数据所以我们需要把原始数据变成“摘要”。合理的做法是取最近若干条数据再加上统计特征。在indicators.py中新增函数def generate_data_summary(df: pd.DataFrame, tail: int 10) - str: 将最近 tail 行数据转换为适合大模型阅读的文本摘要。 recent df.tail(tail) lines [] for _, row in recent.iterrows(): lines.append( f{row[Date].strftime(%Y-%m-%d)} f开 {row[Open]:.2f} 高 {row[High]:.2f} f低 {row[Low]:.2f} 收 {row[Close]:.2f} f量 {row[Volume]:.0f} ) return \n.join(lines) def generate_indicator_desc(df: pd.DataFrame) - str: 生成指标汇总文本。 latest df.iloc[-1] desc [] for col in [MA5, MA10, MA20, MA60, RSI]: if col in df.columns: desc.append(f{col}: {latest[col]:.2f}) if DIF in df.columns and DEA in df.columns: desc.append(fDIF: {latest[DIF]:.2f}) desc.append(fDEA: {latest[DEA]:.2f}) desc.append(fMACD: {latest[MACD]:.2f}) return .join(desc)这一步非常关键。把连续数据压缩成“最近 10 天 指标快照”既保留趋势细节又控制 token 数量能明显降低 API 费用。4.3 搭建 Streamlit 页面创建app.pyimport os import pandas as pd import plotly.graph_objects as go import streamlit as st from stock_data import fetch_stock_data, clean_stock_data from indicators import compute_all_indicators, generate_data_summary, generate_indicator_desc from llm_client import LLMClient from prompts import build_stock_analysis_prompt st.set_page_config(page_titleAI 股票分析系统, layoutwide) st.title( 用大模型打造你的专属股票分析系统) with st.sidebar: symbol st.text_input(股票代码, valueAAPL) period st.selectbox(周期, [3mo, 6mo, 1y, 2y], index1) use_ai st.checkbox(启用大模型分析, valueTrue) if use_ai: st.info(大模型将从行情与指标中生成分析结论仅供参考。) st.cache_data(ttl600) def load_data(symbol, period): df fetch_stock_data(symbol, period) df clean_stock_data(df) df compute_all_indicators(df) return df try: df load_data(symbol, period) except Exception as e: st.error(f数据获取失败{e}) st.stop() st.subheader(f{symbol} 最新行情) latest df.iloc[-1] col1, col2, col3, col4 st.columns(4) col1.metric(收盘价, f{latest[Close]:.2f}, f{latest[Close] - df.iloc[-2][Close]:.2f}) col2.metric(成交量, f{latest[Volume]:.0f}) col3.metric(RSI, f{latest[RSI]:.2f}) col4.metric(MACD, f{latest[MACD]:.2f}) st.subheader(K 线与均线) fig go.Figure() fig.add_trace(go.Candlestick( xdf[Date], opendf[Open], highdf[High], lowdf[Low], closedf[Close], nameK线 )) for ma in [MA5, MA10, MA20, MA60]: if ma in df.columns: fig.add_trace(go.Scatter(xdf[Date], ydf[ma], namema, modelines)) fig.update_layout(xaxis_rangeslider_visibleFalse, height500) st.plotly_chart(fig, use_container_widthTrue) st.subheader(最近行情数据) st.dataframe(df.tail(20)) if use_ai: with st.spinner(大模型正在分析行情请稍候...): try: client LLMClient() data_summary generate_data_summary(df) indicator_desc generate_indicator_desc(df) messages build_stock_analysis_prompt( symbolsymbol, recent_data_descdata_summary, indicator_descindicator_desc ) result client.chat(messages) st.subheader( AI 分析结论) st.write(result) except Exception as e: st.error(f大模型分析失败{e}请检查 API 配置是否填写正确。)运行方式streamlit run app.py浏览器访问http://localhost:8501就能看到系统界面。4.4 运行与验证在本地运行后你会看到左侧可以输入股票代码、选择周期中间区域展示 K 线图和均线下方可以查看最近 20 条行情数据勾选“启用大模型分析”后页面会输出结构化的 AI 解读。预期输出的大模型分析大致如下【趋势判断】 近 20 日股价维持在 MA20 上方整体处于上升通道但短期 RSI 接近 65动能有所减弱。 【支撑与压力】 短期支撑位在 178.5 附近压力位在 185.2 附近。 【风险提示】 技术指标存在滞后性若成交量不能持续放大需警惕高位回调风险。以上内容不构成投资建议。这里的数值只是示例实际输出会随行情变化。4.5 如果是 A 股数据怎么做如果你更关注 A 股可以把数据层换成 akshare核心代码改动很小。示例import akshare as ak def fetch_stock_data_akshare(symbol: str, period_days: int 120): 使用 akshare 获取 A 股日线数据。 :param symbol: 例如 600519 df ak.stock_zh_a_hist( symbolsymbol, perioddaily, start_date20240101, end_date20241231, adjustqfq ) df.rename(columns{ 日期: Date, 开盘: Open, 最高: High, 最低: Low, 收盘: Close, 成交量: Volume }, inplaceTrue) return df注意 akshare 接口有时会随数据源页面结构变化而变化如果遇到字段对不上需要根据实际返回调整列名。5. 部署实战Docker 容器化5.1 编写 Dockerfile为了让系统能部署到任意服务器我们使用 Docker 打包。Streamlit 应用本身很轻量镜像我通常会基于 Python 3.10-slim。创建DockerfileFROM python:3.10-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8501 CMD [streamlit, run, app.py, --server.port8501, --server.address0.0.0.0]5.2 构建镜像并运行docker build -t stock-ai:latest . docker run -d --name stock-ai \ -p 8501:8501 \ -e LLM_API_KEY你的 API Key \ -e LLM_BASE_URLhttps://api.deepseek.com/v1 \ -e LLM_MODELdeepseek-chat \ stock-ai:latest运行后访问服务器 IP 的 8501 端口即可。如果是在云服务器上部署还需要在安全组放行 8501 端口。生产环境建议用 Nginx 反向代理并配置 HTTPS避免 API Key 和页面被明文传输。5.3 环境变量说明环境变量是否必填默认值说明LLM_API_KEY使用大模型时必填EMPTY大模型服务商提供的 API KeyLLM_BASE_URL可选OpenAI 官方可切换为 DeepSeek、Ollama 等LLM_MODEL可选gpt-3.5-turbo按照服务商支持的模型名称填写在本地开发时可以把变量写入.env文件但建议不要提交到 Git 仓库。示例.env.exampleLLM_API_KEYyour-api-key LLM_BASE_URLhttps://api.deepseek.com/v1 LLM_MODELdeepseek-chat6. 常见问题与排查思路问题现象常见原因解决思路yfinance 获取数据为空网络受限、股票代码格式错误检查代码后缀例如 A 股使用 600519.SS切换 akshare 数据源Streamlit 页面白屏依赖版本冲突重建虚拟环境按 requirements.txt 重新安装大模型返回结果不相关提示词未约束数据范围在 system prompt 中强调“只能基于给定数据”大模型分析超时请求数据量过多缩短 recent_data_desc 的长度只保留最近 10 条左右Docker 容器启动后无法访问端口未映射或安全组未放行检查 docker run 的 -p 参数确认服务器防火墙规则RSI 出现 NaN数据量不足加大周期参数例如从 6mo 改为 1yAPI Key 泄露风险硬编码在代码里改用环境变量管理生产环境使用密钥管理工具排查思路可以总结成三步先看数据层是否拿到数据再看指标层是否为 NaN最后看大模型层是否成功调用。只要数据链路通畅系统基本就能正常运行。7. 最佳实践与工程建议7.1 大模型输出需要增加校验大模型生成的内容不适合直接作为事实。建议在展示前做两个校验是否包含明确的“不构成投资建议”表述是否包含数据和风险提示等关键结构。如果输出缺失可以增加重试机制或提示词后处理。更严谨的做法是让大模型输出 JSON 格式再进行结构化解析。7.2 数据缓存与成本控制股票行情一天内变化不大不需要每次访问页面都重新拉取。利用 Streamlit 的st.cache_data(ttl600)可以缓存 10 分钟减少请求次数。大模型调用也是成本来源。建议增加以下控制指标摘要只传最近 10 条数据用户点击“生成分析”按钮时才调用而不是每次刷新都调用对话历史限制上下文长度使用temperature0.3等较低参数提高回答稳定性。7.3 安全边界整个系统最需要注意的是 API Key 安全。不要把 Key 写入前端页面也不要提交到公开仓库。生产环境建议使用 Docker 环境变量或者云厂商的密钥管理服务。如果系统部署到公网建议在 Nginx 或网关层增加基础认证避免任何人都能访问你的分析页面防止被刷接口产生费用。7.4 模型选择建议场景推荐方案说明快速体验云端 API免去本地 GPU 成本适合原型数据敏感本地部署 Ollama数据不出内网满足合规要求高并发生产私有化部署 vLLM吞吐量高适合团队使用FDE 方法在这里体现得很明显模型选择不应该是写死代码而是作为流程中的一个节点通过环境变量随时切换。8. 总结与下一步学习路线本文从 FDE 流程驱动工程的角度完整实现了一个基于大模型的股票分析系统包含数据获取、指标计算、大模型分析、Streamlit 展示和 Docker 部署。你可以基于这套代码继续扩展接入更多数据源例如 tushare、Wind、本地数据库增加基本面分析能力把财报数据导入大模型上下文加入定时任务每天收盘后自动生成分析报告并推送到钉钉或飞书引入向量数据库构建历史复盘问答机器人使用多模型投票机制让多个大模型分别分析并汇总观点。如果本文对你有帮助可以收藏备用也欢迎在实际项目里验证 FDE 这套方法。下一步建议你先跑通本地版再尝试 Docker 部署最后逐步把数据源换成自己常用市场的真实数据。
返回列表