第 8 章 · 02 特征工程与标签


文档摘要

第 8 章 · 02 特征工程与标签 本节摘要:特征工程是 FreqAI 策略成败的关键——模型只是学生,特征和标签才是教材。本节讲清两件事:一是怎么用 等四个函数定义基础特征,再靠配置里的 、 、 、 四个维度自动裂变成成千上万个特征;二是标签设计—— 决定模型「学什么」,回归模型要连续值标签,分类模型要离散字符串标签。还会讲特征标准化流水线(MinMaxScaler、方差过滤、PCA、离群点检测)怎么自动保护模型。 内容来源:原项目文档 、 ,汉化并套用体系化模板。 ⚠️ 风险提示:特征里只要混入「未来函数」(用了未来才能知道的数据),回测就会虚高、实盘必亏。务必检查所有特征只用到当前及历史 K 线。

第 8 章 · 02 特征工程与标签

本节摘要:特征工程是 FreqAI 策略成败的关键——模型只是学生,特征和标签才是教材。本节讲清两件事:一是怎么用 feature_engineering_expand_all 等四个函数定义基础特征,再靠配置里的 include_timeframesinclude_corr_pairlistinclude_shifted_candlesindicator_periods_candles 四个维度自动裂变成成千上万个特征;二是标签设计——set_freqai_targets 决定模型「学什么」,回归模型要连续值标签,分类模型要离散字符串标签。还会讲特征标准化流水线(MinMaxScaler、方差过滤、PCA、离群点检测)怎么自动保护模型。

内容来源:原项目文档 docs/freqai-feature-engineering.mddocs/freqai-configuration.md,汉化并套用体系化模板。

⚠️ 风险提示:特征里只要混入「未来函数」(用了未来才能知道的数据),回测就会虚高、实盘必亏。务必检查所有特征只用到当前及历史 K 线。

学习目标

阅读完本节,你应当能够:

  1. 用四个 feature_engineering_* 函数定义基础特征。
  2. 理解配置如何把基础特征裂变成大规模特征集。
  3. 区分回归标签分类标签的写法。
  4. 说明特征标准化流水线的默认行为与可选步骤。
  5. DI、SVM、DBSCAN 做离群点检测。
  6. 避免特征工程里的未来函数陷阱。

一、四个特征定义函数:各司其职

FreqAI 在策略里提供四个函数,前缀和用途各不相同:

函数 必填 裂变维度 典型用途
feature_engineering_expand_all 可选 周期×周期×位移×关联对 RSI、MFI、EMA 等带 period 参数的指标
feature_engineering_expand_basic 可选 周期×位移×关联对(无 period) pct_change、原始成交量等不带 period 的
feature_engineering_standard 可选 不裂变(只调一次) 星期几、小时等不该被扩展的特征
set_freqai_targets 必填 不裂变 定义标签

💡 命名约定:特征列必须以 % 开头(如 %-rsi-period),FreqAI 内部靠这个前缀识别。标签列必须以 & 开头(如 &-s_close)。不想传给模型但想保留的列用 %% 开头(可用于绘图)。

feature_engineering_expand_all 是主力。你在这里写一个指标,FreqAI 会自动把它套到配置里所有的时间周期、指标周期、位移 K 线数、关联币对上:

def feature_engineering_expand_all(self, dataframe, period, metadata, **kwargs): dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period) dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period) dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period) dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period) return dataframe

注意 period 参数是 FreqAI 传进来的,对应配置里的 indicator_periods_candles。你不要自己写死周期,让配置来控制。

二、配置裂变:几个指标变上千特征

基础特征定义好后,在配置的 feature_parameters 里开「裂变」:

"feature_parameters": { "include_timeframes": ["5m", "15m", "4h"], "include_corr_pairlist": ["ETH/USD", "LINK/USD", "BNB/USD"], "label_period_candles": 24, "include_shifted_candles": 2, "indicator_periods_candles": [10, 20] }

四个裂变维度的含义:

  • include_timeframes:把每个特征算在哪些时间周期上(5m、15m、4h)。
  • include_corr_pairlist:把每个特征也算在哪些关联币对上(ETH、LINK、BNB)。
  • include_shifted_candles:把每个特征往前推几根 K 线也纳入(让模型看到历史)。
  • indicator_periods_candles:把带 period 的指标算在哪些周期上(10、20)。

特征总数的计算公式:

总数 = include_timeframes数 × feature_engineering_expand_all中的特征数 × include_corr_pairlist数 × include_shifted_candles数 × indicator_periods_candles数

以上面的例子(3 个 expand_all 特征 × 3 时间周期 × 3 关联对 × 2 位移 × 2 指标周期)= 3 × 3 × 3 × 2 × 2 = 108 个特征。如果再多加几个指标和维度,轻松破万。

💡 精细控制:所有 feature_engineering_* 函数都收到一个 metadata 字典,里面有 pairtf(时间周期)、period。你可以用它做条件判断,比如只在 1h 周期上加 ROC 指标:

if metadata["tf"] == "1h": dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)

三、标签设计:决定模型学什么

set_freqai_targets唯一必填的函数。标签直接决定模型学什么——标签是「未来 N 根 K 线的收益率」,模型就学预测收益率;标签是「涨还是跌」,模型就学分类。

回归标签(配合 LightGBMRegressor 等):

def set_freqai_targets(self, dataframe, metadata, **kwargs): # 未来 label_period_candles 根 K 线的平均收益率 dataframe["&-s_close"] = ( dataframe["close"] .shift(-self.freqai_info["feature_parameters"]["label_period_candles"]) .rolling(self.freqai_info["feature_parameters"]["label_period_candles"]) .mean() / dataframe["close"] - 1 ) return dataframe

⚠️ 注意这里用了 shift(-N),是故意向未来看的——标签本来就该用未来数据,因为它是训练目标,不是特征。但特征里绝对不能这么做。

分类标签(配合 LightGBMClassifier 等):

def set_freqai_targets(self, dataframe, metadata, **kwargs): self.freqai.class_names = ["down", "up"] # 必须声明类名 dataframe['&s-up_or_down'] = np.where( dataframe["close"].shift(-100) > dataframe["close"], 'up', 'down') return dataframe

分类标签要用字符串表示类别。多分类时在同一列里叠加:

dataframe['&s-up_or_down'] = np.where( dataframe["close"].shift(-100) > dataframe["close"], 'up', 'down') dataframe['&s-up_or_down'] = np.where( dataframe["close"].shift(-100) == dataframe["close"], 'same', dataframe['&s-up_or_down'])

💡 多目标:可以定义多个 &- 标签列,但需要多输出模型(如 LightGBMClassifierMultiTarget)配合。

四、标准化流水线:自动保护模型

FreqAI 默认会构建一条数据流水线,按顺序处理特征:

默认两步是 MinMaxScaler(-1,1)VarianceThreshold(去掉方差为 0 的列)。其余步骤靠配置开关激活:

配置项 作用 适用场景
DI_threshold: 1 相异度指数,剔除远离训练集的预测 想过滤「没见过的行情」
use_SVM_to_remove_outliers: true 支持向量机检测离群点 训练数据里有异常噪声
use_DBSCAN_to_remove_outliers: true DBSCAN 聚类去噪 数据分布不规则
principal_component_analysis: true 主成分分析降维 特征太多想加速
noise_standard_deviation: 0.1 给训练特征加高斯噪声 防过拟合

相异度指数(DI) 特别重要。它衡量新预测点离训练数据有多远——离得太远说明这个预测「没把握」,FreqAI 会把 do_predict 标志减 1,策略里可以据此拒绝下单。DI_threshold 越小越严格(剔除更多),越大越宽松。

⚠️ outlier_protection_percentage:默认 30,意思是如果离群检测删掉超过 30% 的数据点,FreqAI 会报警并放弃这次离群检测,保留原始数据集。这防止过度清洗导致数据不够。

五、自定义流水线与时间加权

想更精细地控制流水线,可以在自定义模型里覆写 define_data_pipeline / define_label_pipeline:

from datasieve.transforms import SKLearnWrapper, DissimilarityIndex from datasieve.pipeline import Pipeline from sklearn.preprocessing import QuantileTransformer, StandardScaler class MyFreqaiModel(BaseRegressionModel): def define_data_pipeline(self) -> Pipeline: return Pipeline([ ('qt', SKLearnWrapper(QuantileTransformer(output_distribution='normal'))), ('di', DissimilarityIndex(di_threshold=1)) ]) def define_label_pipeline(self) -> Pipeline: return Pipeline([ ('qt', SKLearnWrapper(StandardScaler())), ])

DataSieve 流水线兼容 SKlearn API,多数 SKlearn 变换器用 SKLearnWrapper 包一层即可。

时间加权让模型更关注近期数据。设 weight_factor 后,FreqAI 按指数函数给数据点加权:

W_i = \exp(\frac{-i}{\alpha \cdot n})

其中 W_i 是第 i 个数据点的权重,n 是总点数。近期数据权重高,远期数据权重低——这对快速变化的市场尤其有用。

六、未来函数陷阱与防护

特征工程最大的雷是未来函数:特征里不小心用了未来才知道的数据。后果是回测虚高、实盘暴亏。

防护要点:

  • 特征只用当前及历史 K 线(OHLCV、指标),不要 shift(-N)(负位移是看未来)。
  • rolling().mean() 这类窗口函数时,确保窗口不延伸到未来。
  • set_freqai_targets 里的 shift(-N)允许的——那是标签,不是特征。
  • 回测时 FreqAI 按 backtest_period_days 分窗口调用 set_freqai_targets,模拟实盘无前视偏差;但 feature_engineering_* 是在整个训练区间上一次性调用的,所以特征里的前视不会被自动纠正,必须自己把关。

💡 startup_candle_count:策略里设的启动 K 线数,要≥ indicator_periods_candles 的最大值。经验法则是再乘 2,确保 TA-Lib 函数有足够数据、不在开头产生 NaN。看到日志 dropped 0 training points due to NaNs 才放心。

本节要点回顾

  1. 四个函数:feature_engineering_expand_all(主力,带 period)、_expand_basic(不带 period)、_standard(不裂变)、set_freqai_targets(必填,定义标签)。
  2. 命名约定:特征 %、标签 &、保留绘图 %%
  3. 裂变公式:时间周期 × 特征数 × 关联对 × 位移 × 指标周期,几个指标轻松破万。
  4. 标签决定学什么:回归用连续值(收益率),分类用字符串(涨/跌);多目标要多输出模型。
  5. 标准化流水线:默认 MinMaxScaler + 方差过滤,可选 DI/SVM/DBSCAN 离群检测与 PCA 降维。
  6. 未来函数:特征绝对不能 shift(-N);标签可以。startup_candle_count 建议≥最大指标周期×2。

下一节,我们看 FreqAI 的配置与运行——freqai 配置块怎么写、train_period_daysbacktest_period_days 怎么定、回测与实盘的差异在哪里。


发布者: 作者: 灏天文库 转发
评论区 (0)
U