基金持股数据统计分析:用Python追踪机构持仓变化与抱团效应
基金持股数据统计分析:用Python追踪机构持仓变化与抱团效应
基金持股数据是追踪机构动向的重要窗口。每只股票被多少基金持有、基金在增持还是减持,这些信息能帮我们判断机构对某只股票的态度。我之前写了一套基金持股分析工具,把全市场的基金持股数据系统地分析了一遍。
数据用的是基金持股接口time/f10/jjcg/{股票代码},返回该股票最近500家左右的基金持股情况,按截止日期倒序排列,每周六9点更新。字段包括基金名称、持有数量、持有市值等。
importjsonimportosimportpandasaspdimportnumpyasnpfromcollectionsimportdefaultdict data_dir="D:/stock_data"defread_jjcg(dm):file_path=os.path.join(data_dir,"time","f10","jjcg",dm)ifnotos.path.exists(file_path):returnNonewithopen(file_path,"r",encoding="utf-8")asf:data=json.load(f)returndatadefread_gplist():file_path=os.path.join(data_dir,"base","gplist")withopen(file_path,"r",encoding="utf-8")asf:data=json.load(f)returndata第一个分析:单只股票的基金持股变化。追踪某只股票被多少基金持有,基金在增持还是减持。
defanalyze_fund_holding(dm):data=read_jjcg(dm)ifnotdataorlen(data)==0:returnNoneby_date=defaultdict(list)foritemindata:jzrq=item.get("截止日期","")by_date[jzrq].append(item)dates=sorted(by_date.keys(),reverse=True)iflen(dates)<2:returnNonelatest_date=dates[0]prev_date=dates[1]latest_funds=by_date[latest_date]prev_funds=by_date[prev_date]latest_names=set(f.get("基金名称","")forfinlatest_funds)prev_names=set(f.get("基金名称","")forfinprev_funds)new_in=latest_names-prev_names exited=prev_names-latest_names latest_total_vol=sum(f.get("持有数量",0)forfinlatest_funds)prev_total_vol=sum(f.get("持有数量",0)forfinprev_funds)vol_change=(latest_total_vol-prev_total_vol)/prev_total_volifprev_total_vol>0else0result={"dm":dm,"latest_date":latest_date,"prev_date":prev_date,"latest_fund_count":len(latest_funds),"prev_fund_count":len(prev_funds),"new_funds":len(new_in),"exited_funds":len(exited),"vol_change":vol_change}iflen(new_in)>len(exited)*2andvol_change>0.1:result["signal"]="基金大幅增持"result["score"]=72eliflen(exited)>len(new_in)*2andvol_change<-0.1:result["signal"]="基金大幅减持"result["score"]=33else:result["signal"]="基金持仓稳定"result["score"]=52returnresult第二个分析:全市场基金抱团检测。找出被最多基金持有的股票,这些就是"抱团股"。
defscan_fund_clustering(top_n=30):gp_list=read_gplist()results=[]forgpingp_list:dm=gp["股票代码"]mc=gp["股票名称"]data=read_jjcg(dm)ifnotdataorlen(data)==0:continueby_date=defaultdict(list)foritemindata:jzrq=item.get("截止日期","")by_date[jzrq].append(item)ifnotby_date:continuelatest_date=max(by_date.keys())latest_funds=by_date[latest_date]total_value=sum(f.get("持有市值",0)forfinlatest_funds)results.append({"dm":dm,"mc":mc,"fund_count":len(latest_funds),"total_value":total_value,"date":latest_date})df=pd.DataFrame(results).sort_values("fund_count",ascending=False).head(top_n)print("基金持股数量TOP{}:".format(top_n))print(df.to_string(index=False))returndf被基金持有数量最多的股票就是市场公认的"核心资产"。当这些股票的基金持有数量开始下降时,说明抱团在瓦解。
第三个分析:基金净增持扫描。找出基金净增持最多的股票。
defscan_fund_net_increase(top_n=30):gp_list=read_gplist()results=[]forgpingp_list:dm=gp["股票代码"]mc=gp["股票名称"]result=analyze_fund_holding(dm)ifresultisNone:continueifresult.get("score",50)>=65:results.append({"dm":dm,"mc":mc,"fund_count":result["latest_fund_count"],"new_funds":result["new_funds"],"vol_change":result["vol_change"],"score":result["score"]})df=pd.DataFrame(results).sort_values("vol_change",ascending=False).head(top_n)print("基金净增持TOP{}:".format(top_n))print(df.to_string(index=False))returndf第四个分析:头部基金动向追踪。专门追踪几家知名公募基金的持仓变化。
deftrack_top_funds(fund_names):gp_list=read_gplist()results=defaultdict(list)forgpingp_list:dm=gp["股票代码"]mc=gp["股票名称"]data=read_jjcg(dm)ifnotdata:continuelatest_date=max(item.get("截止日期","")foritemindata)foritemindata:ifitem.get("截止日期","")!=latest_date:continuefund_name=item.get("基金名称","")fortargetinfund_names:iftargetinfund_name:results[target].append({"dm":dm,"mc":mc,"vol":item.get("持有数量",0),"value":item.get("持有市值",0)})forfund_name,holdingsinresults.items():df=pd.DataFrame(holdings).sort_values("value",ascending=False).[:10]print("{}最新重仓股TOP10:".format(fund_name))print(df.to_string(index=False))returnresults几个使用经验。第一,基金持股数据是季度披露的,有滞后性,但基金的动作往往领先股价1到2个月。第二,基金持有数量变化比持有市值变化更有参考价值,因为市值会随股价波动。第三,头部基金的动向比小基金更准,建议重点追踪易方达、中欧、景顺长城等知名公募。第四,基金抱团股瓦解前会有征兆——基金数量还在增加但股价不涨了,说明新基金在接盘但老基金在撤退。
我用的数据来源是ig50的本地数据接口,基金持股接口每周六更新,覆盖500家左右的基金,做这种机构持仓分析很方便。
接口说明:
- time/f10/jjcg/{股票代码} - 基金持股
本地路径:数据存放目录/time/f10/jjcg/{股票代码}
更新频率:每周六9点更新(耗时约9小时)
数据格式:[{}…],按截止日期倒序
主要字段:截止日期、基金名称、持有数量(股)、持有市值(元)等
数据覆盖:每只股票最近500家左右的基金持股情况
资料参考:ig50