牛市个股上涨占比统计工具(量化"大盘涨≠个股涨")|教学级量化投资原型
内容包含免责声明和风险提示,不荐股、不预测行情、不引导开户、无任何引流。
一、实际应用场景描述
在智能证券投资课程中,市场广度(Market Breadth)与个股分化是核心教学内容。
本程序适用于:
- 高校量化投资、技术分析课程实验
- 投资者教育(Investor Education)
- 市场结构认知训练
- 破除"大盘涨我就赚"的认知偏差
核心目标:
- 统计牛市期间个股上涨占比
- 量化普涨行情的实际覆盖率
- 用数据说明:大盘上涨 ≠ 所有个股上涨
- 输出历史统计报告
✅ 不做未来预测
✅ 不构成投资建议
✅ 仅作为历史数据统计示例
二、痛点引入(真实可感知)
痛点 表现
认知偏差 "大盘涨了我的股票肯定涨"
幸存者偏差 只看涨停板,忽略下跌股
缺乏数据支撑 凭感觉判断市场热度
盲目追涨 以为牛市就能躺赢
工具门槛高 专业行情软件复杂
👉 需要一个轻量、本地、可解释、可复现的统计工具
三、核心逻辑讲解(工程视角)
1️⃣ 数据模型设计
BullMarketSession
├── index_name 指数名称
├── start_date 牛市起始日
├── end_date 牛市结束日
├── index_return 指数涨幅(%)
└── stocks 个股列表(含涨跌幅)
2️⃣ 核心统计指标
指标 含义
上涨个股占比 涨幅 > 0 的个股比例
跑赢指数占比 涨幅 > 指数涨幅的比例
下跌个股占比 涨幅 < 0 的比例
分化系数 个股涨幅的标准差
3️⃣ 统计流程
输入牛市区间
遍历所有个股
计算每只涨跌幅
统计上涨 / 下跌数量
计算跑赢指数比例
输出统计报告
4️⃣ 关键公式
上涨占比 = 上涨个股数 / 总个股数 × 100%
跑赢指数占比 = 涨幅 > 指数涨幅的个股数 / 总个股数 × 100%
四、Python 模块化代码(可直接运行)
📁 项目结构
bull_market_coverage/
│
├── main.py
├── models.py
├── analyzer.py
├── reporter.py
├── storage.py
├── README.md
└── DISCLAIMER.md
✅ models.py(数据建模)
"""
models.py
牛市行情与个股数据模型
"""
class StockPerformance:
"""个股表现"""
def __init__(self, symbol, name, return_pct):
self.symbol = symbol
self.name = name
self.return_pct = return_pct
class BullMarketSession:
"""牛市区间"""
def __init__(self, index_name, start_date, end_date, index_return):
self.index_name = index_name
self.start_date = start_date
self.end_date = end_date
self.index_return = index_return
self.stocks = []
✅ analyzer.py(核心统计逻辑)
"""
analyzer.py
牛市个股上涨占比统计
"""
import numpy as np
def analyze(session):
"""
统计牛市区间个股表现
"""
total = len(session.stocks)
if total == 0:
return None
# 上涨个股
up_stocks = [s for s in session.stocks if s.return_pct > 0]
down_stocks = [s for s in session.stocks if s.return_pct < 0]
flat_stocks = [s for s in session.stocks if s.return_pct == 0]
# 跑赢指数的个股
beat_index = [s for s in session.stocks if s.return_pct > session.index_return]
returns = [s.return_pct for s in session.stocks]
return {
"total_stocks": total,
"up_count": len(up_stocks),
"down_count": len(down_stocks),
"flat_count": len(flat_stocks),
"up_pct": round(len(up_stocks) / total * 100, 2),
"down_pct": round(len(down_stocks) / total * 100, 2),
"beat_index_count": len(beat_index),
"beat_index_pct": round(len(beat_index) / total * 100, 2),
"avg_return": round(np.mean(returns), 2),
"median_return": round(np.median(returns), 2),
"std_return": round(np.std(returns), 2),
"max_return": round(max(returns), 2),
"min_return": round(min(returns), 2)
}
✅ reporter.py(统计报告输出)
"""
reporter.py
牛市覆盖率统计报告
"""
def report(session, stats):
print("\n" + "=" * 55)
print(f"【牛市个股上涨占比统计报告】")
print("=" * 55)
print(f"指数:{session.index_name}")
print(f"区间:{session.start_date} ~ {session.end_date}")
print(f"指数涨幅:{session.index_return}%")
print("-" * 55)
print(f"\n📊 总样本:{stats['total_stocks']} 只个股")
print(f"\n📈 上涨个股:{stats['up_count']} 只({stats['up_pct']}%)")
print(f"📉 下跌个股:{stats['down_count']} 只({stats['down_pct']}%)")
print(f"➡️ 平盘个股:{stats['flat_count']} 只")
print(f"\n🎯 跑赢指数:{stats['beat_index_count']} 只({stats['beat_index_pct']}%)")
print(f" (指数涨幅 {session.index_return}%)")
print(f"\n📋 收益分布:")
print(f" 平均收益:{stats['avg_return']}%")
print(f" 中位收益:{stats['median_return']}%")
print(f" 标准差:{stats['std_return']}%")
print(f" 最高收益:{stats['max_return']}%")
print(f" 最低收益:{stats['min_return']}%")
print("\n" + "=" * 55)
if stats['up_pct'] < 80:
print("⚠️ 提示:上涨个股不足 80%,市场分化明显")
if stats['beat_index_pct'] < 50:
print("⚠️ 提示:超半数个股未跑赢指数,选股至关重要")
if stats['std_return'] > 30:
print("⚠️ 提示:个股收益离散度大,风险与机遇并存")
print("=" * 55)
✅ storage.py(本地存储)
"""
storage.py
JSON 本地存储
"""
import json
FILE_PATH = "bull_market_analysis.json"
def save_result(data):
with open(FILE_PATH, "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
✅ main.py(交互入口)
"""
main.py
牛市个股上涨占比统计工具
"""
from models import StockPerformance, BullMarketSession
from analyzer import analyze
from reporter import report
from storage import save_result
def main():
print("=== 牛市个股上涨占比统计工具(教学版)===")
# 牛市基本信息
index_name = input("指数名称(如 沪深300):")
start = input("牛市起始日(YYYY-MM-DD):")
end = input("牛市结束日(YYYY-MM-DD):")
index_ret = float(input("指数涨幅(%):"))
session = BullMarketSession(index_name, start, end, index_ret)
# 个股数据录入
print("\n📌 录入个股数据(空行结束):")
while True:
symbol = input("股票代码:")
if not symbol:
break
name = input("股票名称:")
ret = float(input("区间涨幅(%):"))
session.stocks.append(StockPerformance(symbol, name, ret))
# 统计分析
stats = analyze(session)
if stats is None:
print("⚠️ 无个股数据,无法统计")
return
# 输出报告
report(session, stats)
# 保存结果
result = {
"session": {
"index": session.index_name,
"start": session.start_date,
"end": session.end_date,
"index_return": session.index_return
},
"stats": stats
}
save_result(result)
print("✅ 统计结果已保存")
if __name__ == "__main__":
main()
五、README 与使用说明
# 牛市个股上涨占比统计工具(教学版)
## 项目说明
统计牛市期间个股上涨占比与跑赢指数比例,破除"大盘涨我就赚"的认知偏差。
## 使用方式
```bash
pip install numpy
python main.py
```
## 输入示例
```
指数名称:沪深300
牛市起始日:2024-02-01
牛市结束日:2024-05-01
指数涨幅:15.8
```
## 适用范围
- 量化投资课程
- 市场结构教学
- 投资者认知训练
## 注意事项
- 仅基于历史数据
- 不构成任何投资建议
- 使用前请阅读 DISCLAIMER.md
六、DISCLAIMER.md(免责声明与风险提示)
# 免责声明与风险提示
## 免责声明
本程序仅供**教学与科研用途**,用于演示市场广度统计方法。
作者不提供任何证券交易建议,不推荐任何股票,不承诺任何收益。
## 风险提示
1. 历史统计不代表未来市场表现
2. 牛市定义存在主观性,不同标准结果不同
3. 个股表现受行业、市值、题材等多因素影响
4. "上涨占比高"不等于"随便买都能赚"
5. 统计数据可能受幸存者偏差影响(退市股未计入)
使用本工具产生的任何后果,作者概不负责。
七、核心知识点卡片(教学向)
分类 内容
Python 类、列表推导、NumPy 统计
量化金融 市场广度、个股分化、跑赢指数
投资理念 破除"大盘涨=个股涨"误区
认知训练 幸存者偏差、均值回归
工程思想 模块化、数据驱动
可扩展性 可接入历史行情 API
八、总结(工程师视角)
这是一个完全中立、去营销化、可教学的原型系统:
✅ 不鼓吹牛市
✅ 不否定指数投资
✅ 不伪装成选股神器
它真正展示的是:
如何用 Python 把"模糊的市场感觉"转化为可验证、可反思、可纠偏的数据认知
核心教学价值在于破除认知偏差:
- 大盘涨 20%,可能 30% 的个股在跌
- 牛市中仍有大量个股跑输指数
- "普涨"只是错觉,分化才是常态
本文代码仅供学习与技术交流,不构成任何投资建议,股市有风险,入市需谨慎。
利用AI解决实际问题,如果你觉得这个工具好用,欢迎关注长安牧笛!