Freqtrade 第15章:FreqAI 特征工程

特征工程是机器学习交易策略的核心环节。FreqAI 提供了完整的特征工程管道,涵盖特征构建、筛选、标准化和降维等全流程。本章详细讲解如何构建高质量的特征集。

特征构建方法

基础特征(Basic Features)

基础特征在 feature_engineering_expand_basic 方法中定义,每个特征会按 shift 参数生成对应的延时版本。

def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
    # 动量指标
    dataframe["%-rsi"] = ta.RSI(dataframe, timeperiod=14)
    dataframe["%-williams_r"] = ta.WILLR(dataframe, timeperiod=14)
    dataframe["%-cci"] = ta.CCI(dataframe, timeperiod=20)

    # 趋势指标
    dataframe["%-adx"] = ta.ADX(dataframe, timeperiod=14)
    dataframe["%-macd"] = ta.MACD(dataframe)["macd"]
    dataframe["%-macd_signal"] = ta.MACD(dataframe)["macdsignal"]

    # 波动性指标
    dataframe["%-atr"] = ta.ATR(dataframe, timeperiod=14)
    dataframe["%-natr"] = ta.NATR(dataframe, timeperiod=14)

    # 成交量指标
    dataframe["%-obv"] = ta.OBV(dataframe)
    dataframe["%-volume_sma"] = ta.SMA(dataframe["volume"], timeperiod=20)
    return dataframe

扩展特征(Expanded Features)

扩展特征在 feature_engineering_expand_all 方法中定义,通常包含多周期计算。

def feature_engineering_expand_all(self, dataframe: DataFrame, **kwargs) -> DataFrame:
    # 布林带多周期
    for period in [10, 20, 50]:
        bb = ta.BBANDS(dataframe, timeperiod=period)
        dataframe[f"%-bb_upper_{period}"] = bb["bbupper"]
        dataframe[f"%-bb_lower_{period}"] = bb["bblower"]
        dataframe[f"%-bb_width_{period}"] = bb["bbupper"] - bb["bblower"]

    # 多种移动平均线
    for period in [5, 10, 20, 30, 50, 100]:
        dataframe[f"%-sma_{period}"] = ta.SMA(dataframe, timeperiod=period)
        dataframe[f"%-ema_{period}"] = ta.EMA(dataframe, timeperiod=period)

    # 价格通道
    for period in [20, 50]:
        dataframe[f"%-hh_{period}"] = dataframe["high"].rolling(period).max()
        dataframe[f"%-ll_{period}"] = dataframe["low"].rolling(period).min()
    return dataframe

异常值检测技术

标准差方法

FreqAI 通过 DI_threshold 参数控制异常值检测的灵敏度。

{
    "freqai": {
        "feature_parameters": {
            "DI_threshold": 0.9
        }
    }
}
  • DI_threshold = 1.0:不进行异常值过滤
  • DI_threshold = 0.9:移除标准差超过 0.9 分位数的极端值
  • DI_threshold = 0.5:严格过滤,移除更多异常值

手工异常值处理

在特征工程方法中,可以手动处理异常值:

def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
    # 计算特征后,使用分位数裁剪
    for col in dataframe.columns:
        if col.startswith("%-"):
            lower = dataframe[col].quantile(0.01)
            upper = dataframe[col].quantile(0.99)
            dataframe[col] = dataframe[col].clip(lower, upper)
    return dataframe

PCA 降维

什么是 PCA

PCA(主成分分析)是一种线性降维技术,将高维特征压缩为少数"主成分"。FreqAI 支持内置的 PCA 功能。

{
    "freqai": {
        "feature_parameters": {
            "principal_component_analysis": true,
            "PCA_components": 20
        }
    }
}

何时使用 PCA

场景建议
特征数 < 50不需要 PCA
特征数 50-200可选 PCA,设 PCA_components=20-30
特征数 > 200强烈建议使用 PCA

数据管道配置

完整配置示例

{
    "freqai": {
        "enabled": true,
        "train_period_days": 60,
        "backtest_period_days": 14,
        "live_retrain_hours": 6,
        "identifier": "feature_demo",
        "feature_parameters": {
            "shift": 2,
            "include_corr_pairlist": true,
            "corr_pairlist": ["BTC/USDT", "ETH/USDT"],
            "DI_threshold": 0.95,
            "weight_factor": 0.95,
            "principal_component_analysis": true,
            "PCA_components": 30,
            "use_SVM_to_remove_outliers": true,
            "stratify_training_data": false
        },
        "data_split_parameters": {
            "test_size": 0.2,
            "random_state": 42
        }
    }
}

参数详解

参数说明建议值
shift特征的延时偏移数2-5
include_corr_pairlist是否包含相关交易对的特征true
weight_factor样本权重衰减因子0.9-0.99
use_SVM_to_remove_outliers使用 SVM 检测异常值视数据质量而定

特征标准化

FreqAI 自动对特征进行标准化处理,确保不同量纲的特征具有可比性。

标准化方法

  • Z-score 标准化:使特征均值为 0,标准差为 1
  • MinMax 标准化:将特征缩放到 [0, 1] 区间

标准化参数隐藏在 model_training_parameters 中:

{
    "freqai": {
        "model_training_parameters": {
            "standardize": true,
            "standardize_type": "zscore"
        }
    }
}

自动化数据下载

FreqAI 在训练开始前会自动下载所需的历史数据:

# 手动预下载(可选)
freqtrade download-data --exchange binance --days 90 -p BTC/USDT ETH/USDT

如果数据不足,FreqAI 会在日志中提示缺失的时间范围并自动补充下载。

常见特征模板

价量特征模板

def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
    # 价格变化率
    for period in [1, 3, 5, 10]:
        dataframe[f"%-pct_change_{period}"] = dataframe["close"].pct_change(period)

    # 价差特征
    dataframe["%-spread"] = (dataframe["high"] - dataframe["low"]) / dataframe["close"]

    # 量价关系
    dataframe["%-vwap"] = ta.VWAP(dataframe)
    dataframe["%-volume_ratio"] = dataframe["volume"] / dataframe["volume"].rolling(20).mean()

    # 收益率分布
    for period in [5, 10, 20]:
        returns = dataframe["close"].pct_change(period)
        dataframe[f"%-return_skew_{period}"] = returns.rolling(20).skew()
        dataframe[f"%-return_kurt_{period}"] = returns.rolling(20).kurt()
    return dataframe

跨交易对特征

def feature_engineering_expand_basic(self, dataframe: DataFrame, **kwargs) -> DataFrame:
    # 对于每个交易对,计算相对于 BTC 的相对强度
    if "btc" in str(kwargs.get("pair", "")).lower():
        return dataframe
    # 假设外部数据已加载为 btcd
    btcd = kwargs.get("btc_dataframe")
    if btcd is not None:
        dataframe["%-rel_strength"] = (
            dataframe["close"] / btcd["close"]
        ).pct_change(10)
    return dataframe

特征选择最佳实践

  1. 从少到多:从 10-20 个核心特征开始逐步扩展
  2. 避免未来信息:确保所有特征只用当前可用的数据
  3. 监控特征重要性:利用模型内置的特征重要性评估剔除无用特征
  4. 周期性检查:市场结构变化时及时调整特征集