diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 3ec45912..fe0b001a 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -125,8 +125,8 @@ class FreqaiPrimer(IStrategy): } freqai_info = { - "identifier": "test58", - "model": "LightGBMRegressor", + "identifier": "freqai_primer_mixed", + "model": "LightGBMRegressor", # 默认回归模型 "feature_parameters": { "include_timeframes": ["3m", "15m", "1h"], "label_period_candles": 12, @@ -137,10 +137,27 @@ class FreqaiPrimer(IStrategy): "shuffle": False, }, "model_training_parameters": { - "n_estimators": 200, - "learning_rate": 0.05, - "num_leaves": 31, - "verbose": -1, + "price_value_divergence": { # 回归模型配置 + "model": "LightGBMRegressor", + "model_params": { + "n_estimators": 200, + "learning_rate": 0.05, + "num_leaves": 31, + "verbose": -1, + } + }, + "optimal_first_length": { # 分类模型配置 + "model": "LightGBMClassifier", + "model_params": { + "n_estimators": 150, + "learning_rate": 0.1, + "num_leaves": 15, + "max_depth": 8, + "min_child_samples": 10, + "class_weight": "balanced", + "verbose": -1, + } + } }, "fit_live_predictions_candles": 100, "live_retrain_candles": 100, @@ -227,7 +244,29 @@ class FreqaiPrimer(IStrategy): dataframe["volume_z_score"] = dataframe["volume_z_score"].replace([np.inf, -np.inf], 0).ffill().fillna(0) dataframe["&-price_value_divergence"] = dataframe["&-price_value_divergence"].replace([np.inf, -np.inf], 0).ffill().fillna(0) - + + # 新增:分类模型优化 first_length + # 基于市场状态预测最优的 first_length 分类(2, 4, 6, 8, 10) + # 使用技术指标和市场波动率作为特征 + atr = ta.ATR(dataframe, timeperiod=14) + volatility_ratio = atr / dataframe['close'] + + # 定义市场状态特征 + trend_strength = abs(dataframe['close'] - dataframe['ema200']) / dataframe['ema200'] + volume_anomaly = abs(dataframe['volume_z_score']) > 2 + + # 基于市场状态确定最优 first_length 类别 + # 0: 激进(2) 1: 中性(4) 2: 稳健(6) 3: 保守(8) 4: 极保守(10) + conditions = [ + (volatility_ratio > 0.02) & (trend_strength > 0.05), # 高波动+强趋势 -> 激进 + (volatility_ratio > 0.015) & (trend_strength > 0.03), # 中高波动+中强趋势 -> 中性 + (volatility_ratio > 0.01) | (volume_anomaly), # 中等波动或成交量异常 -> 稳健 + (volatility_ratio < 0.008) & (trend_strength < 0.02), # 低波动+弱趋势 -> 保守 + ] + choices = [0, 1, 2, 3] + + dataframe["&*-optimal_first_length"] = np.select(conditions, choices, default=4) + return dataframe def is_stochrsi_overbought(self, dataframe: DataFrame, period=10, threshold=85) -> bool: """ @@ -1292,21 +1331,28 @@ class FreqaiPrimer(IStrategy): def detect_trend_status(self, dataframe: DataFrame, metadata: dict) -> str: """ - 基于加权分段的trend_score判断趋势状态 + 基于分类模型优化 first_length 的趋势检测 规则: - - 将最近N个trend_score分为3段:first, second, third - - 长度比例为:first:second:third = 1:3:5 - - 例如:2,6,10(固定使用段长2) - - 权重:first(权重10),second(权重7),third(权重3) - - 使用静态段长:first段长度固定为2 + - 使用 LightGBMClassifier 预测最优 first_length 类别 + - 类别映射:0:激进(2), 1:中性(4), 2:稳健(6), 3:保守(8), 4:极保守(10) + - 根据预测的类别动态调整段长,而非固定使用2 """ pair = metadata.get('pair', 'Unknown') try: - # 直接使用静态值2作为第一段长度 - first_length = 2 + # 使用分类模型预测最优 first_length + if "&*-optimal_first_length" in dataframe.columns: + # 获取最新预测值 + optimal_length_class = int(dataframe["&*-optimal_first_length"].iloc[-1]) + length_mapping = {0: 2, 1: 4, 2: 6, 3: 8, 4: 10} + first_length = length_mapping.get(optimal_length_class, 2) + logger.info(f"[{pair}] 使用分类模型优化 first_length: {first_length} (类别: {optimal_length_class})") + else: + # 回退到默认值 + first_length = 2 + logger.warning(f"[{pair}] 分类模型未预测,使用默认 first_length: {first_length}") - # 根据比例计算第二段和第三段长度 + # 根据 first_length 动态调整其他段长 second_length = first_length * 3 third_length = first_length * 5