如何用Pandas实现股票分组回测?行业对比分析!
为什么你需要分组回测?
很多股民朋友都有这样的困惑:选了一堆股票,但不知道哪个行业更值得投资。今天我就教你用Pandas这个数据分析神器,把股票按行业分组,看看哪些行业是真正的"摇钱树"。
我在证券公司工作这些年,见过太多客户凭感觉选股,结果被市场狠狠教育。其实用数据说话才是王道,分组回测能帮你避开很多坑。
准备你的"武器库"
首先你得有个趁手的工具包:
import pandas as pd
import numpy as np
import tushare as ts # 获取股票数据的利器
import matplotlib.pyplot as plt
%matplotlib inline
没有安装?简单:
pip install pandas numpy tushare matplotlib
第一步:搞到靠谱的股票数据
我用的是tushare pro,需要注册个token(找我开户的客户,我可以直接帮你搞定数据接口权限)。
pro = ts.pro_api('你的token')
获取全市场股票:
stock_list = pro.stock_basic(exchange='', list_status='L')
行业分类数据很关键:
industry = pro.stock_company(exchange='SSE')
清洗数据是门艺术
原始数据就像刚挖出来的矿石,得先提炼:
# 合并两个表
df = pd.merge(stock_list, industry, on='ts_code')
# 保留有用的列
df = df[['ts_code', 'name', 'industry', 'list_date']]
# 去掉行业为空的
df = df[df['industry'].notna()]
行业分组有讲究
看看市场上有哪些行业:
industry_counts = df['industry'].value_counts()
print(industry_counts.head(10))
你会发现有些行业股票太少,回测没意义。我一般保留股票数>20的行业:
valid_industries = industry_counts[industry_counts > 20].index
df = df[df['industry'].isin(valid_industries)]
获取行情数据的小技巧
批量获取股价数据是个技术活,直接全市场获取会被限流。我的经验是:
- 按行业分批获取
- 设置合理的sleep间隔
- 存到本地避免重复请求
price_data = {}
for industry in df['industry'].unique():
codes = df[df['industry']==industry]['ts_code']
# 这里简化处理,实际要分批次
price_data[industry] = pro.daily(ts_code=','.join(codes))
计算行业收益率的正确姿势
有了价格数据,我们算每个行业的平均收益率:
industry_returns = {}
for industry, data in price_data.items():
# 按股票代码分组
grouped = data.groupby('ts_code')
# 计算每只股票的年化收益
returns = []
for code, group in grouped:
group['pct_chg'] = group['close'].pct_change()
annual_return = (1 + group['pct_chg']).prod() ** (252/len(group)) - 1
returns.append(annual_return)
industry_returns[industry] = np.mean(returns)
可视化让数据说话
数字太枯燥,画个图一目了然:
result = pd.Series(industry_returns).sort_values()
result.plot(kind='barh', figsize=(10,12))
plt.title('各行业平均年化收益率对比')
plt.xlabel('年化收益率')
plt.show()
你可能会遇到的坑
幸存者偏差:现在存在的股票都是还没退市的,表现自然比实际好
- 解决方法:包含已退市股票数据
行业变迁:十年前的"朝阳行业"现在可能日薄西山
- 解决方法:分时间段回测
手续费影响:频繁调仓成本很高
- 解决方法:在回测中计入交易成本
进阶玩法:多因子分组
除了行业,还可以按PE、市值等分组:
# 获取估值数据
valuation = pro.daily_basic(ts_code=','.join(df['ts_code']))
merged = pd.merge(df, valuation, on='ts_code')
# 按PE分组
merged['PE_group'] = pd.qcut(merged['pe'], q=5, labels=['最低','较低','中等','较高','最高'])
为什么专业机构都用这套方法
我在券商工作这些年,发现所有正规的量化团队都在用类似方法。区别在于:
- 他们数据更全(找我开户可以用我们的机构级数据接口)
- 他们考虑更多因素(流动性、财务质量等)
- 他们有更复杂的风险控制模型
给你的实战建议
- 别只看收益率:高收益往往伴随高风险,要结合波动率看
- 定期更新:行业格局会变,建议每季度重新跑一次
- 分散投资:即使某个行业表现好,也别All in
写在最后
看到这里你可能发现了,专业投资和散户瞎蒙的区别就在于是否用数据说话。我在证券公司经常帮客户做这类分析,其实开户后我们的量化投研平台可以直接用这些功能,比自己折腾方便多了。
想试试这个方法但嫌麻烦?找我开户可以免费获取:
- 完整的行业分类数据
- 稳定的行情接口
- 预装好的分析工具
评论区留言"行业分析",我发你整理好的代码和样例数据。投资路上,数据才是你最好的朋友。