ta / 批量特征工程
add_all_ta_features 一次加 86 列:能拿到什么、会丢掉什么
add_all_ta_features(df, open="open", high="high", low="low", close="close", volume="volume")
——这是 ta 最常被引用的那一行。本机实测:5 列输入进去,91 列出来,
新增 86 列,覆盖 43 个指标类中的 42 个。
但它有三个不写在 README 里的开关:窗口全部硬编码在 wrapper 里(没有 window 参数)、
vectorized=True 会静默少 18 列、
默认 fillna=False 时 400 行里没有一行是完整的。这一页把三条都量出来。
函数契约
add_all_ta_features 的参数分别起什么作用
| 参数 | 默认值 | 作用 | 注意点 |
|---|---|---|---|
df | — | 输入 DataFrame | 函数原地改传入的对象并返回它;保险做法是传 df.copy() |
open/high/low/close/volume | — | 五个列名字符串 | 必须与 DataFrame 列名完全一致(区分大小写) |
fillna | False | 传给每个指标的开关 | True 时窗口不满也算,头部数值含义不同(见预热与 NaN 页) |
colprefix | "" | 给所有新列加统一前缀 | 已有 momentum_ 这类模块前缀,再加一层可读性会下降 |
vectorized | False | 只使用「向量化」指标 | 不是加速开关,是「少算 18 列」的开关——见下节 |
没有 window | — | 无法通过这个函数调整任何窗口 | 要自定义窗口必须绕过 wrapper,直接实例化指标类 |
最容易误解的是 vectorized:README 与文档字符串只说「if True, use only vectorized functions indicators」,听起来像性能选项。实际效果是 wrapper 里 if not vectorized: 包裹的代码块被整体跳过,结果是少了 18 列。用它之前先确认你要的列还在。
输出列清单
add_all_ta_features 到底新增了哪些列:86 列清单
| 模块 | 来源 | 列数 | 新增列名(去掉模块前缀) |
|---|---|---|---|
| 成交量 | ta.volume | 10 | adi、obv、cmf、fi、em、sma_em、vpt、vwap、mfi、nvi |
| 波动率 | ta.volatility | 21 | bbm、bbh、bbl、bbw、bbp、bbhi、bbli、kcc、kch、kcl、kcw、kcp、kchi、kcli、dcl、dch、dcm、dcw、dcp、atr、ui |
| 趋势 | ta.trend | 34 | macd、macd_signal、macd_diff、sma_fast、sma_slow、ema_fast、ema_slow、vortex_ind_pos、vortex_ind_neg、vortex_ind_diff、trix、mass_index、dpo、kst、kst_sig、kst_diff、ichimoku_conv、ichimoku_base、ichimoku_a、ichimoku_b、stc、adx、adx_pos、adx_neg、cci、visual_ichimoku_a、visual_ichimoku_b、aroon_up、aroon_down、aroon_ind、psar_up、psar_down、psar_up_indicator、psar_down_indicator |
| 动量 | ta.momentum | 18 | rsi、stoch_rsi、stoch_rsi_k、stoch_rsi_d、tsi、uo、stoch、stoch_signal、wr、ao、roc、ppo、ppo_signal、ppo_hist、pvo、pvo_signal、pvo_hist、kama |
| 其他 | ta.others | 3 | dr、dlr、cr |
合计 86 列,覆盖 42 个指标类。43 个类里只有 WMAIndicator(加权移动平均)没有对应的新增列——wrapper 里根本没有引用它;另外 SMA 与 EMA 各只给了 fast(12) / slow(26) 两列,没有「单一均线」列。想用 WMA 或别的窗口,必须直接调类。完整列名清单来自本机 add_all_ta_features 的实际输出,不是从文档抄的。
vectorized 开关
vectorized=True 会静默去掉哪些列:18 列明细
| 被移除的列 | 所属区块 | 为什么 | 影响 |
|---|---|---|---|
volatility_atr、volatility_ui | add_volatility_ta 的 if not vectorized: 块 | 这两个实现在 wrapper 作者看来不是「向量化」写法 | ATR 和 Ulcer Index 直接消失 |
momentum_kama | add_momentum_ta 的同类代码块 | 同上 | KAMA 自适应均线消失 |
volume_mfi、volume_nvi | add_volume_ta 的同类代码块 | 同上 | MFI 与 NVI 消失 |
trend_adx、trend_adx_pos、trend_adx_neg | add_trend_ta 的同类代码块 | 同上 | 趋势强度三列全丢 |
trend_cci、trend_aroon_up/down/ind | 同上 | 同上 | CCI 与 Aroon 全丢 |
trend_psar_up/down/_indicator(共 4 列) | 同上 | 同上 | PSAR 全丢 |
trend_visual_ichimoku_a、_b | 同上 | 同上 | 仅失去「视觉」两条线,基础 Ichimoku 仍在 |
实测总计移除 18 列:86 → 68。值得注意的分布是:被移除的全是「非向量化实现」的那一批,其中包含 ATR、ADX、CCI 这些在实盘里用得最多的指标。如果你的特征表里少了它们,先检查是不是把 vectorized 打开过。
硬编码窗口
wrapper 里的窗口怎么设置:是写死的还是可调的
| 模块 | 指标(列名) | 窗口(源码里写死的值) |
|---|---|---|
| 成交量 | volume_fi / volume_em / volume_vwap / volume_mfi | 13 / 14 / 14 / 14 |
| 波动率 | volatility_bbm…bbp | 20,宽度 2 个标准差 |
| 波动率 | volatility_kcc…kcli | 10 |
| 波动率 | volatility_dcl…dcp | 20(offset = 0) |
| 波动率 | volatility_atr | 10(不是常见的 14) |
| 波动率 | volatility_ui | 14 |
| 趋势 | trend_macd* / trend_ppo* / trend_pvo* | 26 / 12 / 9 |
| 趋势 | trend_sma_fast / trend_sma_slow | 12 / 26 |
| 趋势 | trend_ema_fast / trend_ema_slow | 12 / 26 |
| 趋势 | trend_vortex_* / trend_trix / trend_dpo / trend_adx* / trend_cci / trend_aroon_* | 14 / 15 / 20 / 14 / 20 / 25 |
| 趋势 | trend_mass_index | fast 9 / slow 25 |
| 趋势 | trend_kst* | ROC 周期 10 / 15 / 20 / 30 |
| 趋势 | trend_ichimoku_* / trend_visual_ichimoku_* | 9 / 26 / 52 |
| 趋势 | trend_stc | slow 50 / fast 23 / cycle 10 / smooth 3 与 3 |
| 趋势 | trend_psar_* | step 0.02 / max_step 0.20 |
| 动量 | momentum_rsi / momentum_stoch_rsi* / momentum_stoch* / momentum_wr | 14(WR 用 lbp=14) |
| 动量 | momentum_tsi | slow 25 / fast 13 |
| 动量 | momentum_uo | 7 / 14 / 28 |
| 动量 | momentum_ao | 5 / 34 |
| 动量 | momentum_roc | 12(不是 RSI 那样的 14) |
| 动量 | momentum_kama | 10,pow1 = 2、pow2 = 30 |
这张表来自 ta/wrapper.py 的源码逐行扫描,不是默认参数表。重点是两件事:①add_all_ta_features 没有 window 参数,所有窗口写死在函数体里;②写死的值与类本身的默认值并不总是一样——例如 AverageTrueRange 类的默认窗口是 14,但 wrapper 里写的是 10;ROCIndicator 类默认 12,wrapper 也是 12;KAMAIndicator 类默认 10,wrapper 也是 10。所以「用类」和「用 wrapper」得到的是不同参数下的结果。
fillna 与可用行
算完 86 列之后还剩多少可用样本
| 指标 | 实测结果 | 原因 |
|---|---|---|
fillna=False(默认)下完整行数 | 0 / 400 | 86 列里最长预热 47 行,且 psar_up 一列就有 212 行 NaN——没有一行能让全部列都有值 |
fillna=True 下完整行数 | 400 / 400 | 窗口不满也算,NaN 被消除 |
fillna=True 下 NaN 单元格总数 | 0 | 同时 inf 数量也是 0(_check_fillna 会把 ±inf 替换成 NaN 再前向填充) |
fillna=False 下 NaN 最多的列 | trend_psar_up(212 行) | PSAR 的上趋势标记本身是稀疏的 |
fillna=False 下无 NaN 的列数 | 19 列 | 含 ATR、ADX、Keltner、OBV 等——但它们可能是 0 值表头 |
对输出调用 ta.utils.dropna() | 0 行 | 每一行都有 NaN,dropna 会全部删掉 |
所以「用 fillna=False 还是 True」不是风格问题,而是取哪一头:要么接受「没有一行是完整的」,自己按最长的预热裁剪;要么接受「头部数值是用不完整窗口算出来的」。官方 README 的示例用的是先把原始数据 dropna,再 add_all_ta_features——顺序不能颠倒,否则会把数据集清空。每个指标的预热长度见预热窗口页的实测表。
筛选建议
86 列太多用不完,该按什么顺序筛
拿到 86 列之后该怎么筛(推荐顺序)
- 先按模块删掉重复表达:布林带贡献 7 列、Donchian 5 列、Keltner 7 列、Aroon 3 列、Ichimoku 4 列——同族列高度相关,保留代表性的 1–2 列即可。
- 再按预热长度设起点:
psar_up(212 行 NaN)、psar_down(190 行)这类稀疏列要么单独处理,要么直接删。 - 然后处理零值表头:把
volatility_atr、trend_adx这些表头为 0 的列按窗口切片或替换成 NaN。 - 最后才谈相关性筛选:全部列都来自同一份收盘价,彼此高度共线;先用业务逻辑(量 / 价 / 波动 / 趋势)分组,再用统计方法去冗余。
- 把这次的选择写下来:列名、窗口、删掉的原因——下次升级依赖时才能判断「数值变化」是数据问题还是列变了。
如果目的是「快速看一眼」而不是「建特征表」,更省事的做法是先只算 2–3 个指标(例如 RSIIndicator + BollingerBands + AverageTrueRange),确认口径后再扩到全量。
FAQ
关于 add_all_ta_features 的常见问题
add_all_ta_features 会改我的原始 DataFrame 吗?
df.copy()。如果你还要用原始表做别的计算,务必在调用前复制一份。以官方实现为准。为什么我加出来的列数不是 86?
vectorized=True 会少 18 列(86 → 68);②colprefix 只是加前缀,不改变列数。如果列数仍然不对,确认 ta 的版本与你参考的资料一致(本站实测为 0.11.0)。能不能用 add_all_ta_features 指定窗口,比如 RSI 用 7 而不是 14?
window 参数,wrapper 里所有窗口都是写死的常量。要自定义窗口必须绕过它,直接实例化指标类,例如 RSIIndicator(close=df["close"], window=7).rsi()。为什么 ATR 列算出来和我单独调类的结果不一样?
add_volatility_ta 里写的是 window=10,而 AverageTrueRange 类自己的默认值是 14。本站实测:同一份数据下两者的前 13 行分别是 9 个 0 与 13 个 0,最大绝对差 1.26636756。要对齐就必须显式传窗口。86 列能不能直接喂给机器学习模型?
fillna=False 时没有一行是完整的(实测 0/400);②同族列高度共线;③部分列是 0/1 标记列,不是连续量。本站只说明列的产生方式与口径,不提供建模方案。add_all_ta_features 支持多标的(面板数据)吗?
为什么输出里有些列全是 0 或全是 1?
volatility_bbhi、volatility_kchi、trend_psar_up_indicator 这类以 _indicator 结尾的列,取值只有 0 和 1,表示「是否触发」。本站实测这类列在样本前 20–30 行全是 0,属于正常现象。