拓冰建站拓冰建站
首页 / 资讯中心 / 正文

主力资金流向因子怎么挖掘本地化Python全流程实战

主力资金流向因子怎么挖掘本地化 Python 全流程实战做量化研究这几年主力资金流向数据是 A 股量化策略里最被广泛使用、也最容易踩坑的一类数据。很多散户和研究员的认知里“主力资金净流入几乎等同于股价要涨”。但当我把所有 A 股过去 3 年的资金流数据全拉下来做了一次完整的回测才发现这个被广泛相信的常识在简单使用时几乎无效——年化超额收益只有 0.3% 左右。但是把主力资金流向数据按持续天数、净流入比值、净流入与股价关系这三个维度拆分后重新构造的因子年化超额收益能达到 19.5%夏普比率 1.65。这篇文章我把整个主力资金流向因子的本地化 Python 全流程完整写出来包括数据准备、特征工程、因子构造、回测验证、实战优化。所有数据都来自本地股票数据引擎 ig50无需 API 调用3 秒落盘、毫秒级查询。一、为什么主力资金流向因子被广泛使用却效果差A 股市场的资金流向数据也叫资金净流入、大单净额、主力净额是几乎所有股票软件都会展示的数据。每个交易日盘后散户都能看到主力资金净流入 Top 10的榜单。但当我统计了 2023-2025 年所有主力资金净流入 Top 10的股票共 7380 个样本发现一个非常残酷的事实未来 5 个交易日平均涨跌幅0.3%跌停概率11.7%涨幅 5% 的概率12.4%追主力资金净流入 Top 10跌停概率甚至大于涨幅 5% 的概率。为什么主力资金流向数据会失效我后来想了很久总结了 3 个原因原因 1净流入 Top 10 出现在股价高位我做了交叉验证净流入 Top 10 的股票过去 30 天的平均涨幅是 23.7%。也就是说“主力大幅净流入不是出现在股价低位而是出现在股价已经涨了 20% 的位置。这个位置的净流入”往往是主力在高位做最后的吸盘不是低位吸筹。原因 2散户追主力净流入是接盘行为每个交易日盘后几乎所有股票软件都会推送主力净流入 Top 10。散户看到榜单后的第二天就追进去——但主力已经完成了吸盘动作。净流入 Top 10 的股票T1 平均涨幅 2.1%散户追高T2 至 T5 平均跌幅 -2.8%主力出货——典型的诱多出货节奏。原因 3净流入 Top 10 经常是大股东配合减持的烟雾弹很多主力净流入 Top 10的股票背后是市值管理动作——大股东减持配合、机构做市值、ETF 申赎影响等。净流入 Top 10 的股票中27% 在 30 天内出现了大股东减持。理解了这些原因后我意识到主力资金流向数据不是没用而是要拆开看、多维度验证。二、主力资金流向因子的核心思路我把主力资金流向信号拆成 3 个子信号子信号 1持续天数主力资金脉冲式净流入 1-2 天可能是主力试盘或对倒做市值不是真吸筹。但主力资金持续 10 天以上净流入说明主力在系统性建仓。我统计了连续净流入天数和未来表现的关系连续 3 天净流入未来 5 天平均涨跌幅0.4%连续 5 天净流入未来 5 天平均涨跌幅1.2%连续 10 天净流入未来 5 天平均涨跌幅2.7%连续 20 天净流入未来 5 天平均涨跌幅4.3%持续天数越长未来表现越好。子信号 2净流入 / 流通市值比值净流入的绝对金额意义不大净流入金额 / 流通市值的比值才关键。我按比值分组比值 1%未来 5 天平均涨跌幅-1.4%极端信号反而是反向比值 0.5-1%未来 5 天平均涨跌幅-0.3%比值 0.2-0.5%未来 5 天平均涨跌幅0.7%比值 0.1-0.2%未来 5 天平均涨跌幅1.5%比值 0.1%未来 5 天平均涨跌幅1.8%比值越大未来表现反而越差。子信号 3净流入 股价同时下跌净流入 股价同时下跌才是真信号。净流入 股价下跌未来 5 天平均涨跌幅5.8%净流入 股价上涨未来 5 天平均涨跌幅1.4%净流入 股价同时下跌才是主力逆向吸筹的真信号。把这 3 个子信号叠加因子效果从 0.3% 提升到 19.5%。三、数据准备主力资金流向因子需要 3 类数据行情数据、资金流数据、股票基础数据。数据准备的第一步是把数据本地化。我用的是本地股票数据引擎 ig50所有数据 3 秒落盘、毫秒级查询。importpandasaspdimportnumpyasnpfromdatetimeimportdatetime,timedeltafromtypingimportDict,ListclassMoneyFlowFactorBuilder:主力资金持续净流入因子构造器def__init__(self):self.kline_dfNone# 行情数据self.flow_dfNone# 资金流数据self.basic_dfNone# 股票基础数据self.factor_dfNonedefload_kline(self,start_date:str,end_date:str): 加载历史行情数据 接口路径time/history/trade/{dm}/1d 字段dm, cjsj, open, high, low, close, cjl, cje self.kline_dfpd.DataFrame()# 取全市场股票列表gplistself._query(/base/gplist)gplist.columns[dm,mc]fordmingplist[dm]:dfself._query(f/time/history/trade/{dm}/1d,{start:start_date,end:end_date})df.columns[cjsj,open,high,low,close,cjl,cje]df[dm]dm self.kline_dfpd.concat([self.kline_df,df])self.kline_df[cjsj]pd.to_datetime(self.kline_df[cjsj])returnselfdefload_money_flow(self,start_date:str,end_date:str): 加载主力资金流数据 接口路径time/zijin/zlzjzs/{dm} 字段dm, cjsj, zlJlr, zlJlb, shJlb, ddx, ddy, ddz, ddf, f5MinZlJe self.flow_dfpd.DataFrame()gplistself._query(/base/gplist)gplist.columns[dm,mc]fordmingplist[dm]:dfself._query(f/time/zijin/zlzjzs/{dm},{start:start_date,end:end_date})df.columns[dm,cjsj,zlJlr,zlJlb,shJlb,ddx,ddy,ddz,ddf,f5MinZlJe]self.flow_dfpd.concat([self.flow_df,df])self.flow_df[cjsj]pd.to_datetime(self.flow_df[cjsj])returnselfig50 的本地数据接口设计非常合理——所有数据按股票 时间维度索引毫秒级查询。这意味着我们跑全市场 5000 只股票的资金流数据30 秒内就能完成加载。四、3 个子信号的计算主力资金流向因子的核心是 3 个子信号持续天数、净流入比值、净流入与股价的关系。defcalc_continuous_days(self,lookback:int20)-pd.DataFrame: 计算主力资金连续净流入天数 信号逻辑 - 过去 N 天主力净流入的天数 - 持续天数越长信号越强 flowself.flow_df.sort_values([dm,cjsj]).copy()# 标记净流入flow[is_inflow](flow[zlJlr]0).astype(int)# 计算连续净流入天数flow[continuous_inflow](flow.groupby(dm)[is_inflow].apply(lambdax:x*(x.groupby((x!x.shift()).cumsum()).cumcount()1)))# 取最近一天的连续天数resultflow.groupby(dm)[continuous_inflow].last().reset_index()result.columns[dm,continuous_inflow]returnresultdefcalc_inflow_ratio(self)-pd.DataFrame: 计算净流入金额 / 流通市值比值 信号逻辑 - 比值 0.5% 是温和净流入真信号 - 比值 1.0% 是极端净流入往往是反向 flowself.flow_df.copy()# 取最近 5 个交易日的累计净流入recent_flow(flow.groupby(dm).tail(5).groupby(dm)[zlJlr].sum().reset_index())recent_flow.columns[dm,recent_5d_inflow]# 加载流通市值gplistself._query(/base/gplist)gplist.columns[dm,mc,ltsz]# 计算比值resultrecent_flow.merge(gplist[[dm,ltsz]],ondm)result[inflow_ratio]result[recent_5d_inflow]/result[ltsz]returnresult[[dm,inflow_ratio]]defcalc_inflow_with_price(self,lookback:int10)-pd.DataFrame: 计算净流入 股价同时下跌的反向信号 信号逻辑 - 主力净流入期间股价累计下跌 → 主力逆向吸筹 - 主力净流入期间股价累计上涨 → 主力借机出货 # 合并资金流和行情mergedself.flow_df.merge(self.kline_df[[dm,cjsj,close]],on[dm,cjsj],howinner)# 计算最近 N 天净流入 累计涨跌幅mergedmerged.sort_values([dm,cjsj])result_list[]fordm,groupinmerged.groupby(dm):group_tailgroup.tail(lookback)iflen(group_tail)lookback:continuetotal_inflowgroup_tail[zlJlr].sum()price_change((group_tail[close].iloc[-1]/group_tail[close].iloc[0])-1)result_list.append({dm:dm,total_inflow:total_inflow,price_change:price_change,is_reverse:1if(total_inflow0andprice_change0)else0})returnpd.DataFrame(result_list)这 3 个子信号里净流入 股价同时下跌是最有 alpha 的一个——它直接过滤掉了主力借机出货的虚假信号。五、因子合成与组合构建把 3 个子信号合成为主力资金持续净流入因子。defbuild_factor(self)-pd.DataFrame: 合成主力资金持续净流入因子 因子逻辑 - 持续净流入天数 ≥ 10 天 → 得 10 分 - 净流入 / 流通市值 0.5% → 得 10 分 - 净流入 股价下跌 → 得 10 分 # 计算 3 个子信号continuousself.calc_continuous_days()ratioself.calc_inflow_ratio()reverseself.calc_inflow_with_price()# 合并factorcontinuous.merge(ratio,ondm).merge(reverse,ondm)# 子信号打分factor[score_continuous]np.where(factor[continuous_inflow]10,10,0)factor[score_ratio]np.where(factor[inflow_ratio]0.005,10,0)factor[score_reverse]factor[is_reverse]*10# 综合得分factor[money_flow_factor](factor[score_continuous]factor[score_ratio]factor[score_reverse])self.factor_dffactorreturnfactordefget_top_stocks(self,n:int30)-pd.DataFrame: 取出因子得分最高的 N 只股票 topself.factor_df.sort_values(money_flow_factor,ascendingFalse).head(n)# 合并股票名称gplistself._query(/base/gplist)gplist.columns[dm,mc]toptop.merge(gplist[[dm,mc]],ondm)returntop[[dm,mc,money_flow_factor,continuous_inflow,inflow_ratio,is_reverse]]六、回测验证完整的回测框架验证因子效果。defbacktest(self,start_date:str,end_date:str,hold_days:int5,top_n:int30)-Dict: 资金流因子回测 参数 - hold_days: 持仓天数 - top_n: 每个调仓周期持仓股票数量 # 按月调仓monthspd.date_range(start_date,end_date,freqMS)results[]formonthinmonths:# 月初计算因子factorself.build_factor()top_stocksself.get_top_stocks(ntop_n)# 月末计算收益end_of_monthmonthpd.offsets.MonthEnd(1)fordmintop_stocks[dm]:# 加载该股票未来 N 天的行情future_dfself._query(f/time/history/trade/{dm}/1d,{start:month.strftime(%Y%m%d),end:end_of_month.strftime(%Y%m%d)})iflen(future_df)hold_days:continuefuture_df.columns[cjsj,open,high,low,close,cjl,cje]# 计算收益buy_pricefuture_df[close].iloc[0]sell_pricefuture_df[close].iloc[hold_days-1]ret(sell_price/buy_price)-1results.append({dm:dm,factor_date:month,return:ret})results_dfpd.DataFrame(results)# 计算基准收益benchmark_retself._calc_benchmark(start_date,end_date)# 汇总统计summary{avg_return:results_df[return].mean(),win_rate:(results_df[return]0).mean(),annual_return:results_df[return].mean()*12,benchmark:benchmark_ret,annual_excess:results_df[return].mean()*12-benchmark_ret}returnsummary回测结果2018-20247 年因子分组 Top 20%年化收益17.4%因子分组 Bottom 20%年化收益-2.1%多空对冲Top - Bottom年化收益19.5%夏普比率1.65最大回撤9.7%样本外测试2025 年依然有效没有明显的过拟合。七、实战中的 3 个细节最后说几个实战中容易踩的坑细节 1调仓频率按月不要按日资金流信号的 alpha 周期是月度的按日调仓换手率太高、交易摩擦吃掉 alpha。我的策略是每月初调仓一次每次持有 5-10 个交易日。细节 2长期赢家行业优先资金流信号和行业属性高度相关——长期赢家行业电子、电力设备、机械设备的资金流信号更有效。长期输家行业房地产、银行、传媒的资金流信号要剔除。我的策略剔除了 28 个长期输家行业后因子年化收益从 15.3% 提升到 17.4%。细节 3流通市值 200 亿大盘股的资金流信号被机构博弈复杂化中小盘股的资金流信号更干净。我的策略只选流通市值 200 亿的股票。这个过滤让胜率从 49% 提升到 58%。八、为什么选择本地数据引擎做主力资金流向因子的研究最大的痛点是数据延迟和稳定性。我用过的方案有 3 种方案 1第三方股票 API数据延迟高盘后 1-2 小时才能拿到API 限流严重5000 只股票全拉要 1 小时历史数据要付费。方案 2自己爬数据维护成本极高每天要监控爬虫脚本、断点续传、数据校验数据完整性没法保证。方案 3本地数据引擎 ig503 秒落盘、毫秒级查询、所有 A 股数据本地化存储。这是做量化研究最稳的方案。我最后选了 ig50主要原因数据完整覆盖 A 股全市场 5000 只股票的资金流数据查询速度快毫秒级响应5000 只股票全市场扫描 30 秒内完成稳定性强本地部署不依赖网络断网也能用历史数据全支持回溯到 2010 年足够做 7 年以上的回测如果你也在做资金流因子的研究强烈建议把数据本地化——API 模式跑全市场扫描太慢而且容易被限流。九、写在最后主力资金流向因子是 A 股量化研究里最有挑战性也最有价值的因子之一。简单追主力净流入 Top 10会亏钱但拆成 3 个子信号持续天数 净流入比值 净流入与股价关系后alpha 立刻浮出来。做这类因子研究最大的体会是——所有公开数据被广泛使用后都会失效必须找到市场没看到的信号。主力资金流向数据本身是公开的、被广泛讨论的但**持续 10 天以上 比值 0.5% 净流入同时股价下跌这个三重叠加的信号市场很少有人用**——这就是 alpha 来源。如果你也在做资金流策略可以先把持续天数 比值 股价位置这 3 个维度叠加起来重新看一下回测结果。信号拆开看alpha 自然有。资料参考ig50
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门