ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

AI股票智能分析系统实战:Python源码实现行情接口到信号输出

AI股票智能分析系统实战:Python源码实现行情接口到信号输出 简介这是一套面向个人投资者与量化爱好者的 LLM 驱动股票智能分析系统源码覆盖 A 股、港股、美股及主流指数解决盯盘耗时、选股效率低、决策依据分散等问题。系统以 AI 决策仪表盘输出一句话核心结论、精确买卖点与操作清单并融合技术面、筹码分布、舆情情报与实时新闻多维分析内置 A 股三段式复盘与美股 Regime Strategy 策略引擎支持大盘复盘、AI 回测验证与 11 种策略的多轮问股 Bot还可通过图片识别截图快速添加自选股并推送到企业微信、飞书、Telegram、邮件等渠道。资源包共 356 个文件约 49.91MB以 150 个 py 源码、33 个 tsx 与 29 个 ts 前端组件、23 个 md 文档为主辅以 yml/yaml 配置、json 数据与 png/gif 演示素材结构完整便于二次开发。目前已有 197 人学习适合希望用 AI 降低盯盘压力、提升选股效率的投资者与量化入门者参考。1. AI 股票智能分析系统从行情接口到信号输出的最小闭环很多人第一次听到「AI 股票智能分析系统」这个词脑子里浮现的是那种能预测涨停、自动下单的黑箱。真动手做过就知道一套能跑起来的 Python 源码核心不是玄学预测而是把行情数据抓取、指标计算、信号生成、结果可视化这几段串成一条稳定的流水线。这套系统适合两类人一类是刚学完 Python 语法、想找个真实项目练手的入门者另一类是有交易经验、想把自己的选股逻辑代码化的从业者。它解决的不是「明天买什么」这种问题而是「如何把重复的盯盘和计算交给程序」。下面从数据源选型讲到信号输出每一步都给出可复现的代码和参数说明中间穿插我踩过的坑最后收在几个能直接用的调优技巧上。2. 数据层怎么搭行情接口选型与本地缓存策略2.1 免费行情接口的三种来源与取舍做 AI 股票分析系统第一步永远是拿到干净、稳定、可回溯的行情数据。市面上常见的数据来源分三类一是交易所或财经门户的公开接口二是券商提供的量化交易 API三是第三方数据服务商的付费接口。对于个人开发者和学习用途第一类足够起步但要注意频率限制和字段完整性。我一般会优先用akshare这类开源财经数据接口库它封装了多个公开数据源返回的是 pandas DataFrame省去大量解析工作。安装命令如下pip install akshare pandas numpy安装完成后拉取单只股票日线数据的代码如下import akshare as ak import pandas as pd # 拉取贵州茅台日线数据adjustqfq 表示前复权 df ak.stock_zh_a_hist( symbol600519, perioddaily, start_date20230101, end_date20241231, adjustqfq ) # 统一列名方便后续指标计算 df df.rename(columns{ 日期: date, 开盘: open, 收盘: close, 最高: high, 最低: low, 成交量: volume }) df[date] pd.to_datetime(df[date]) df df.sort_values(date).reset_index(dropTrue) print(df.tail())这段代码的逻辑是先按股票代码和日期区间请求数据再把中文列名映射成英文最后按日期排序。参数上adjust有三个可选值——不复权、qfq前复权、hfq后复权。做技术指标计算时一定用前复权否则除权除息那天会出现价格跳空均线和 MACD 全部失真这是血泪经验。2.2 本地缓存别每次都去请求接口直接每次分析都调接口有两个问题一是慢二是容易被限流。常见做法是在本地建一个 SQLite 缓存第一次拉全量之后只增量更新。import sqlite3 conn sqlite3.connect(stock_cache.db) df.to_sql(daily_600519, conn, if_existsreplace, indexFalse) # 增量更新只取本地最大日期之后的数据 last_date pd.read_sql( SELECT MAX(date) AS d FROM daily_600519, conn )[d].iloc[0] new_df ak.stock_zh_a_hist( symbol600519, perioddaily, start_datelast_date.replace(-, ), end_date20241231, adjustqfq )参数说明if_existsreplace适合首次建表增量场景应改成append并配合去重。SQLite 单文件足够存几千只股票的日线如果要做分钟级回测建议换 Parquet 按年分片存储读取速度会快一个量级。2.3 数据清洗的三个必做动作拿到数据后不能直接算指标至少要做三件事去重、补缺、类型转换。去重按date列 drop_duplicates补缺用前值填充ffill但停牌超过一定天数的要标记出来类型转换确保volume是数值型避免字符串参与计算报错。这三步写成一个clean_data(df)函数每次入库前调用能省掉后面大量排查时间。3. 指标与信号把交易逻辑翻译成 Python 函数3.1 均线、MACD、RSI 的标准实现技术指标是 AI 股票分析系统的中间层往上承接原始行情往下输出买卖信号。最常用的三个指标是均线、MACD 和 RSI。用 pandas 实现均线非常简单df[ma5] df[close].rolling(window5).mean() df[ma20] df[close].rolling(window20).mean() # 金叉信号短均线上穿长均线 df[golden_cross] ( (df[ma5] df[ma20]) (df[ma5].shift(1) df[ma20].shift(1)) )参数说明window5和window20是常见短中期组合做短线可以改成 5 和 10做波段改成 10 和 30。shift(1)的作用是取前一日值用来判断「上穿」这个动作漏掉它就会把持续金叉状态误判成信号。MACD 的实现稍长但逻辑固定exp12 df[close].ewm(span12, adjustFalse).mean() exp26 df[close].ewm(span26, adjustFalse).mean() df[dif] exp12 - exp26 df[dea] df[dif].ewm(span9, adjustFalse).mean() df[macd] (df[dif] - df[dea]) * 2注意adjustFalse这个参数它决定是否用递归方式计算指数移动平均。做技术分析时通常设为 False与主流软件保持一致否则数值会对不上。3.2 信号合成多指标投票比单指标靠谱单靠一个指标出信号假信号太多。我一般用「投票制」均线金叉、MACD 金叉、RSI 低于 30 三个条件里满足两个才触发买入信号。df[rsi] compute_rsi(df[close], period14) df[buy_signal] ( (df[golden_cross].astype(int) (df[dif] df[dea]).astype(int) (df[rsi] 30).astype(int)) 2 )compute_rsi需要自己写核心是计算一段时间内的平均涨幅和平均跌幅之比。参数period14是 Wilder 原始设定改成 6 会更敏感但噪音也更大。投票阈值 2可以调成 3信号更少但更准取决于你的交易频率偏好。3.3 用 AI 模型给信号打分标题里有「AI」如果只做规则信号其实算不上智能分析。常见的落地方式是在规则信号基础上用一个轻量机器学习模型做二次过滤。比如用随机森林对历史信号做分类特征包括当日涨跌幅、成交量变化率、RSI 值、MACD 柱状值等标签是「信号后 5 日是否上涨」。from sklearn.ensemble import RandomForestClassifier features [pct_change, volume_ratio, rsi, macd] X df[features].dropna() y (df[close].shift(-5) df[close]).astype(int).dropna() model RandomForestClassifier(n_estimators100, max_depth5) model.fit(X.iloc[:-5], y) df[ai_score] model.predict_proba(X)[:, 1]参数说明n_estimators100是树的数量太少欠拟合太多训练慢max_depth5控制过拟合股票数据噪音大树深了几乎必然过拟合。predict_proba返回的是概率取第二列作为「上涨概率」分数比直接输出 0/1 更有参考价值。这一步是整个系统里最容易被神化的部分实际上它只是给规则信号加了一层统计过滤不要指望它单独预测涨跌。4. 避坑与排查那些让系统跑不通的细节4.1 接口返回字段突然变了现象昨天还能跑的代码今天报 KeyError提示某个列名不存在。原因公开数据接口的字段名会随数据源调整而变化尤其是中文列名。解决在清洗函数里加一层列名映射容错用df.rename(columnscol_map, errorsignore)并在映射后检查关键列是否存在缺失时打印实际列名再手动补映射。4.2 复权方式不一致导致回测虚高现象回测收益曲线漂亮得不像话实盘完全对不上。原因指标计算用了不复权数据或者前复权和后复权混用。解决全流程统一用前复权并在数据入库时把adjust参数写进表名或元数据表避免不同来源的数据混在一起。这个坑我踩过两次回测年化 80% 的「策略」实盘三个月亏 15%就是复权没对齐。4.3 未来函数悄悄混进特征现象模型在训练集上准确率 90% 以上上线后一塌糊涂。原因特征里用了当日收盘后才能确定的数据比如用当日收盘价算的 RSI 去预测当日涨跌。解决所有特征在生成时统一shift(1)确保第 T 日用的都是 T-1 日及之前的信息。检查方法是把数据截断到某一天看信号是否只依赖截断日之前的数据。4.4 停牌股票拉低整体信号质量现象某些股票长期没有信号或者信号出现后无法成交。原因停牌期间数据缺失补值后指标失真。解决在清洗阶段标记停牌日停牌超过 10 个交易日的股票直接从分析池剔除或者在信号生成时跳过停牌区间。用volume 0可以快速识别停牌日。4.5 数据库并发写入锁死现象多进程同时更新缓存时SQLite 报database is locked。原因SQLite 默认写锁是排他的多进程同时写会冲突。解决改成单进程串行更新或者换 PostgreSQL。如果坚持用 SQLite设置timeout30并开启 WAL 模式conn.execute(PRAGMA journal_modeWAL)能缓解大部分并发问题。5. 从信号到看板可视化与批量扫描的落地技巧5.1 用一张图看清信号分布信号生成后最直观的验证方式是画图。用 matplotlib 把收盘价、均线和买卖点画在一起import matplotlib.pyplot as plt fig, ax plt.subplots(figsize(14, 6)) ax.plot(df[date], df[close], labelClose, linewidth1) ax.plot(df[date], df[ma5], labelMA5, linestyle--) ax.plot(df[date], df[ma20], labelMA20, linestyle--) buy df[df[buy_signal]] ax.scatter(buy[date], buy[close], marker^, colorred, s80, labelBuy) ax.legend() plt.tight_layout() plt.savefig(signal_chart.png, dpi150)参数说明marker^是上三角代表买入点s80控制点的大小dpi150保证导出图片清晰。这张图的作用不是给你看盘而是快速检查信号是否集中在某些异常区间比如连续暴跌后密集出信号说明阈值太宽松。5.2 批量扫描全市场的最小实现单只股票分析跑通后下一步是批量扫描。核心是把上面的流程封装成函数然后遍历股票列表def analyze(symbol): df fetch_and_clean(symbol) df add_indicators(df) df add_signals(df) latest df.iloc[-1] return { symbol: symbol, close: latest[close], buy_signal: bool(latest[buy_signal]), ai_score: round(float(latest.get(ai_score, 0)), 3) } results [analyze(s) for s in stock_list] result_df pd.DataFrame(results) result_df[result_df[buy_signal]].to_csv(today_signals.csv, indexFalse)这段代码的关键在于analyze函数要能独立处理单只股票的所有异常任何一只股票报错不能影响整体扫描。常见做法是在函数内部用 try/except 包住出错时返回 None 并记录日志。批量扫描建议放在收盘后跑避免盘中接口限流。5.3 用定时任务把系统跑成日常工具手动跑脚本不是长久之计。Linux 下用 cronWindows 下用任务计划程序每天收盘后自动执行扫描并输出 CSV。cron 表达式示例# 每个交易日 15:30 执行扫描脚本 30 15 * * 1-5 /usr/bin/python3 /home/user/stock_scan.py /home/user/scan.log 21注意1-5表示周一到周五但节假日仍会执行需要在脚本里加交易日判断。简单做法是检查当天是否有新数据入库没有就跳过。日志重定向 scan.log 21能把标准输出和错误都记下来出问题时第一时间看日志比盲目改代码高效得多。5.4 一个容易被忽略的调优点信号阈值随波动率自适应固定阈值在不同市场环境下表现差异很大。牛市里 RSI 低于 30 的机会很少熊市里频繁触发。一个实用技巧是用过去 60 日的波动率动态调整阈值vol df[close].pct_change().rolling(60).std() df[rsi_threshold] 30 vol * 100 df[buy_signal] df[rsi] df[rsi_threshold]波动率放大时阈值上移信号更宽松波动率收敛时阈值下移信号更严格。这个改动不大但能让系统在不同市场阶段的表现更均衡。我自己的习惯是每季度回看一次信号分布如果连续两个月没有信号或信号过多就检查波动率区间是否偏移然后微调系数。做这类系统没有一劳永逸的参数定期复盘比追求「最优参数」更实际。希望帮到你。本文还有配套的精品资源点击获取
返回列表