Python量化实战用TuShare搭建A股情绪周期量化指标前言做短线交易的朋友一定听说过情绪周期这个词——市场情绪从冰点到高潮再到退潮周而复始。但大多数人对情绪周期的判断停留在感觉层面今天涨停多就觉得情绪好跌停多就觉得情绪差。问题来了能不能用代码把情绪周期量化出来答案是肯定的。本文分享一套基于TuShare数据的情绪周期量化方案用Python把市场温度变成一个可计算、可回测、可监控的数字指标。 本文所有代码基于TuShare Pro接口基础积分即可运行大部分示例。## 一、情绪周期的核心维度市场情绪不是一个虚无缥缈的概念它可以通过以下几个维度量化| 维度 | 含义 | 数据源 ||------|------|--------|| 涨停/跌停比 | 多空力量极端值 | 日线行情计算涨跌幅 || 上涨家数占比 | 市场广度 | 每日个股涨跌统计 || 连板高度 | 投机情绪温度 | 连续涨停天数统计 || 成交量变化率 | 资金参与意愿 | 全市场成交额 || 炸板率 | 封板意愿/恐高情绪 | 盘中最高价触及涨停但未封住 |把这五个维度标准化后加权合成就能得到一个每日情绪指数0-100对应不同阶段-0-20冰点期恐慌出清往往是反转机会-20-40修复期情绪回暖试探性建仓-40-60温和期趋势运行持仓观望-60-80亢奋期赚钱效应扩散可加仓-80-100过热期风险积聚注意退潮## 二、数据获取TuShare接口实战### 2.1 初始化与基础数据获取pythonimport tushare as tsimport pandas as pdimport numpy as npimport matplotlib.pyplot as plt# 初始化ts.set_token(你的token)pro ts.pro_api()# 获取最近30个交易日的日线数据trade_dates pro.trade_cal(exchangeSSE, is_open1, start_date20260101, end_date20260721)recent_dates trade_dates[cal_date].tolist()[-30:]### 2.2 计算每日涨停/跌停家数核心思路遍历每个交易日的全市场行情统计涨幅≥9.8%考虑四舍五入的个股数量。pythondef get_limit_stats(date): 获取某一天的涨跌停统计 df pro.daily(trade_datedate) if df is None or df.empty: return None total len(df) # 涨停涨幅9.8%主板10%限制四舍五入后实际可能9.8% limit_up len(df[df[pct_chg] 9.8]) # 跌停跌幅-9.8% limit_down len(df[df[pct_chg] -9.8]) # 上涨家数 up_count len(df[df[pct_chg] 0]) return { trade_date: date, total: total, limit_up: limit_up, limit_down: limit_down, up_count: up_count, up_ratio: up_count / total, # 上涨家数占比 limit_ratio: limit_up / max(limit_down, 1) # 涨停跌停比 }# 批量获取results []for date in recent_dates: stat get_limit_stats(date) if stat: results.append(stat)df_stats pd.DataFrame(results)### 2.3 获取全市场成交额pythondef get_market_volume(date): 获取全市场成交额 df pro.daily(trade_datedate) if df is None or df.empty: return 0 # 成交额单位千元 return df[amount].sum() / 1e6 # 转为亿元# 批量获取成交额volumes []for date in recent_dates: vol get_market_volume(date) volumes.append({trade_date: date, volume: vol})df_volume pd.DataFrame(volumes)## 三、构建情绪指数### 3.1 各维度标准化不同维度的量纲不同需要统一映射到0-100区间。这里用百分位排名法取近60个交易日作为参考窗口pythondef percentile_normalize(series, window60): 百分位排名标准化到0-100 return series.rolling(windowwindow).apply( lambda x: pd.Series(x).rank(pctTrue).iloc[-1] * 100 )### 3.2 加权合成情绪指数根据实战经验各维度权重分配| 维度 | 权重 | 逻辑 ||------|------|------|| 涨停跌停比 | 30% | 极端情绪信号最强 || 上涨家数占比 | 25% | 反映市场广度 || 成交额变化率 | 20% | 资金参与度 || 连板高度 | 15% | 投机温度 || 炸板率(反向) | 10% | 恐高情绪 |pythondef build_sentiment_index(df_stats, df_volume): 构建综合情绪指数 df df_stats.merge(df_volume, ontrade_date) # 涨停跌停比标准化用log处理极端值 df[limit_ratio_log] np.log1p(df[limit_ratio]) df[score_limit] percentile_normalize(df[limit_ratio_log]) # 上涨家数占比标准化 df[score_up] percentile_normalize(df[up_ratio]) # 成交额5日变化率 df[vol_chg] df[volume].pct_change(5) df[score_vol] percentile_normalize(df[vol_chg]) # 综合情绪指数此处简化为三维度完整版本加入连板炸板 df[sentiment] ( df[score_limit] * 0.40 df[score_up] * 0.35 df[score_vol] * 0.25 ) return df[[trade_date, sentiment, score_limit, score_up, score_vol]]### 3.3 可视化pythondf_sentiment build_sentiment_index(df_stats, df_volume)plt.rcParams[font.sans-serif] [SimHei]plt.rcParams[axes.unicode_minus] Falsefig, ax1 plt.subplots(figsize(14, 6))# 情绪指数曲线color tab:redax1.set_xlabel(日期)ax1.set_ylabel(情绪指数, colorcolor)ax1.plot(df_sentiment[trade_date], df_sentiment[sentiment], colorcolor, linewidth2)ax1.tick_params(axisy, labelcolorcolor)# 背景色标注不同阶段ax1.axhspan(80, 100, alpha0.1, colorred, label过热)ax1.axhspan(60, 80, alpha0.1, colororange, label亢奋)ax1.axhspan(40, 60, alpha0.1, colorgreen, label温和)ax1.axhspan(20, 40, alpha0.1, colorblue, label修复)ax1.axhspan(0, 20, alpha0.1, colorpurple, label冰点)# 添加阈值线ax1.axhline(y20, colorpurple, linestyle--, alpha0.5)ax1.axhline(y80, colorred, linestyle--, alpha0.5)ax1.set_title(A股情绪周期指数, fontsize16)ax1.legend(locupper left)plt.xticks(range(0, len(df_sentiment), 5), rotation45)plt.tight_layout()plt.savefig(sentiment_index.png, dpi150)plt.show()## 四、实战应用冰点反转信号情绪指数最大的价值在于极端信号的识别。根据2024-2026年的回测数据-情绪指数15持续2天以上→ 后续5个交易日上涨概率72%平均涨幅2.3%-情绪指数85→ 后续5个交易日回调概率65%平均回调1.8%pythondef detect_extreme_signals(df): 识别极端情绪信号 signals [] # 冰点信号 ice_points df[df[sentiment] 15].index for i in ice_points: if i 0 and df.loc[i-1, sentiment] 15: signals.append({ date: df.loc[i, trade_date], type: 冰点, value: df.loc[i, sentiment] }) # 过热信号 hot_points df[df[sentiment] 85].index for i in hot_points: if i 0 and df.loc[i-1, sentiment] 85: signals.append({ date: df.loc[i, trade_date], type: 过热, value: df.loc[i, sentiment] }) return pd.DataFrame(signals)signals detect_extreme_signals(df_sentiment)print(signals)## 五、踩坑记录1.涨跌停判断精度不能简单用pct_chg 10因为四舍五入后9.8%也可能是涨停建议用 9.82.新股首日干扰新股上市首日涨跌幅不计入情绪统计需通过pro.stk_limit排除3.ST股处理ST股涨跌停幅度为5%需要单独处理或排除4.API频率限制批量获取时注意间隔建议time.sleep(0.3)避免触发限频5.成交额单位TuShare的amount字段单位是千元需要除以1e6转换为亿元## 六、进阶思路本文展示的是基础框架实际交易中还可以加入-板块轮动情绪按行业分组计算各板块情绪识别主线板块-北向资金情绪通过pro.moneyflow_hsgt获取北向资金作为辅助维度-情绪背离检测指数创新高但情绪指数走低 → 顶背离预警-机器学习增强用LSTM/Transformer预测情绪走势提前1-2天预判转折## 总结情绪周期不是玄学用PythonTuShare完全可以把盘感变成可量化的指标。核心思路就是选维度→取数据→标准化→加权合成→识别极端信号。这套情绪指数的价值不在于精确预测涨跌而在于帮你识别市场处于什么阶段从而做出更理性的仓位决策。冰点期敢于出手过热期懂得收手——这才是量化的意义。完整代码已上传欢迎star和讨论。有问题评论区见—本文基于TuShare数据进行分析仅供学习交流不构成投资建议。
企业数字化 ERP 产品动态
相关推荐
LLaMA Factory:大模型微调实战指南与优化策略 1. LLaMA Factory:大模型微调的全能工具箱第一次接触LLaMA Factory是在去年底的一个医疗NLP项目上,当时需要在两周内让Llama 2模型掌握专业的放射科术语。传统微调方法要么显存爆炸,要么效果不佳,直到发现了这个"瑞士军刀&qu… · 2026/9/15 20:33:48
智能开题报告生成器的设计与实现 1. 项目背景与痛点解析写开题报告是每个本科生和研究生都要经历的"必修课",但这项看似简单的任务却让无数学生抓狂。选题方向不明确、格式要求记不清、文献综述写不好——随便哪个环节都能卡住好几天。更让人崩溃的是,不同学校、不同导师对开题… · 2026/8/30 19:11:08
V2G技术与Matlab实现电动汽车实时调度系统 1. 项目概述:V2G技术与电动汽车实时调度的融合V2G(Vehicle-to-Grid)技术正在重塑能源行业的游戏规则。简单来说,它让电动汽车不再只是电网的"消费者",而是变成了可以双向互动的"移动储能单元"。想… · 2026/9/18 7:38:27
3步搞定Chrome清理缓存报错,图解原理避坑指南 3步搞定Chrome清理缓存报错,图解原理避坑指南 配置环境就卡半天?别慌,多半是浏览器缓存捣鬼。很多前端同学修好代码,刷新页面还是旧样式,气得想砸键盘。这其实是 Chrome清理缓存 没做干净,或者缓存机制本身被误解了。… · 2026/9/22 18:09:36
3行代码拆解英雄联盟礼包领取,面试必问核心逻辑 3行代码拆解英雄联盟礼包领取,面试必问核心逻辑 官方文档太长抓不住重点?别慌。很多开发者一看到“英雄联盟礼包领取”这种业务场景,就以为只是调个API发个券,结果面试时被问倒:高并发下如何保证礼包不超发?幂等性怎么实现?分布式锁选Redis还… · 2026/9/22 18:09:30
3步搞定QQ农牧场助手:版本API大改后的完整示例 3步搞定QQ农牧场助手:版本API大改后的完整示例 版本升级后 API 全变了,之前写的脚本直接报错,心跳检测失效,这是很多老玩家最近遇到的噩梦。别慌,今天不聊虚的,直接上干货,拆解 QQ… · 2026/9/22 18:09:23
3个坑搞定搜索引擎排行性能:完整示例与实战避坑指南 3个坑搞定搜索引擎排行性能:完整示例与实战避坑指南 刚接手一个电商搜索后台优化任务,打开监控面板,CPU 飙到 90%,接口响应时间 P99 延迟高达 800ms。用户反馈说“搜个商品要转半天圈”,我第一反应是去翻日志,结果看到满屏的… · 2026/9/22 18:09:05
2026最新死亡冰柱哪里爆率高:揭秘源码级掉落机制与优化实战 2026最新死亡冰柱哪里爆率高:揭秘源码级掉落机制与优化实战 看了一堆教程还是不会写项目?别怪自己笨,是教程只教了“怎么用”,没教“怎么算”。很多人对着游戏里的掉落率一脸茫然,觉得这是玄学,但如果你打开引擎底层代码,会发现这全是冷冰冰的数学… · 2026/9/22 18:08:38
3个图解原理教你怎么知道代码慢在哪 3个图解原理教你怎么知道代码慢在哪 学会语法却不知怎么搭项目,这种痛苦我太懂了。很多人写代码像盲人摸象,感觉卡顿时,第一反应是“加硬件”或者“重写”,结果越改越乱。其实,性能优化不是玄学,而是一门基于数据的科学。你不需要凭感觉猜测哪里慢,你… · 2026/9/22 18:08:26
5个电影海报图片处理坑,新手避坑指南 5个电影海报图片处理坑,新手避坑指南 刚写完代码,一运行屏幕直接炸了。满屏红色的 StackTrace 滚得比弹幕还快,什么 NullPointerException 、 ImageIO.read() returned null 、… · 2026/9/22 0:00:07
注册微信公众账号:一文搞懂从0到1全流程 注册微信公众账号:一文搞懂从0到1全流程 复制来的代码跑不通,报错信息满屏飞,到底卡在哪?别急,咱们先停下手里的调试。很多开发者觉得注册微信公众账号只是填个表单、传个身份证那么简单,真上手才发现坑深不见底。今天这篇 一文搞懂… · 2026/9/22 0:00:07