






















最近在 AI 的帮助下,写了一个全市场 ETF 动量分析脚本。其实这个脚本很早就已经写好了,但最近比较忙,一直没时间整理发推文。
在 ETF 轮动策略中,常见的做法是使用固定的 ETF 候选池。但这种方式存在一个明显的问题:行情是不断变化的,固定的候选池很难覆盖不同时段的市场机会。
如果从长周期来看,固定候选池确实可以抓住大趋势。但另一方面,我们能不能做一个“动态 ETF 候选池”? 从理论上讲,动态候选池应该更有机会捕捉阶段性行情。
手动分析全市场ETF来构建动态ETF候选池,几乎不太可能:
所以,我们需要一个自动化工具,来帮助我们在某个交易日快速完成全市场 ETF 的分析和筛选。

该自动化分析工具的大致思路是:从全市场 ETF 出发,做动量分析,并筛选出动量分散、相关性较低的一组 ETF。
以下是基于Tushare数据来实现这个思路的主要步骤:
使用 Tushare 的 fund_basic() 接口获取 ETF 列表:
pro.fund_basic(market="E")
然后筛选出满足以下条件的基金:
list_date <= trading_datedelist_date 为空或 ≥ trading_date)使用 fund_daily() 接口获取行情数据,包括:open, high, low, close, pre_close, vol, amount 等字段。
虽然接口本身不支持复权,但返回的数据提供了 pre_close字段,因此我们可以自行实现前复权或后复权逻辑。
这里采用的是对数价格的线性回归方法来计算动量:
最终得分定义为:
score = annualized_returns × r_squared
核心代码如下:
y = np.log(prices)
x = np.arange(len(y), dtype=float)
# 等权线形回归
slope, intercept = np.polyfit(x, y, 1)
annualized_returns = math.pow(math.exp(slope), 250) - 1
r_squared = 1 - (sum((y - (slope * x + intercept))**2) / ((len(y) - 1) * np.var(y, ddof=1)))
score = annualized_returns * r_squared
这种方式可以同时考虑:
相比单纯涨幅,更稳健。
当然也可以用其他的一些动量指标,比如非等权平均、动态回溯窗口进行回归等。
全市场 ETF 中,很多高动量标的其实属于同一类资产(例如同一行业或同一指数),如果不做处理,最终选出来的组合可能高度集中。
因此,我们可以通过相关性分析来进行筛选。筛选逻辑如下:
这本质上是在做一个“去相关”的动量组合构建。

为了直观地感受最终筛选的ETF的动量变化,我新增了热力图功能,用于可视化最终入选 ETF 的历史动量得分变化。
这样,我们就可以很直观地看到:

另外我单独写了一个相关性分析脚本,用于分析给定 ETF 列表中,两两之间的相关性。以帮助更细致地理解:

在实际实现中,还做了一些比较重要的过滤和风控处理:
整体来看,这个脚本的核心目标是:
从“全市场”中,自动构建一个“高动量 + 低相关 + 可交易”的 ETF 组合候选池
相比传统固定池策略,更加灵活,也更贴近真实市场结构。
不过,其具体效果如何,还是得测试测试才知道,目前完全靠这个来实现整套ETF轮动策略的自动化还是不太安全,更多的是进行辅助分析,最终还是需要人来分析把关。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。