diff --git a/config_examples/config_freqai.okx.json b/config_examples/config_freqai.okx.json index 9452c08..ab345b7 100644 --- a/config_examples/config_freqai.okx.json +++ b/config_examples/config_freqai.okx.json @@ -35,7 +35,7 @@ "timeout": 20000 }, "pair_whitelist": [ - "OKB/USDT", + "BTC/USDT", "SOL/USDT" ] }, @@ -66,7 +66,7 @@ }, "freqaimodel": "CatboostClassifier", "purge_old_models": 2, - "identifier": "test176", + "identifier": "test178", "train_period_days": 30, "backtest_period_days": 10, "live_retrain_hours": 0, @@ -80,7 +80,7 @@ ], "include_corr_pairlist": [ "BTC/USDT", - "ETH/USDT" + "SOL/USDT" ], "label_period_candles": 12, "include_shifted_candles": 3, diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py index 2d5472f..d046692 100644 --- a/freqtrade/templates/FreqaiExampleStrategy.py +++ b/freqtrade/templates/FreqaiExampleStrategy.py @@ -24,7 +24,7 @@ class FreqaiExampleStrategy(IStrategy): startup_candle_count: int = 40 can_short = False - buy_rsi = IntParameter(low=10, high=50, default=27, space="buy", optimize=True, load=True) + buy_rsi = IntParameter(low=10, high=40, default=20, space="buy", optimize=True, load=True) sell_rsi = IntParameter(low=50, high=90, default=59, space="sell", optimize=True, load=True) roi_0 = DecimalParameter(low=0.01, high=0.2, default=0.038, space="roi", optimize=True, load=True) roi_15 = DecimalParameter(low=0.005, high=0.1, default=0.027, space="roi", optimize=True, load=True) @@ -38,11 +38,11 @@ class FreqaiExampleStrategy(IStrategy): "model": "LightGBMRegressor", "feature_parameters": { "include_timeframes": ["5m"], - "include_corr_pairlist": ["SOL/USDT"], + "include_corr_pairlist": ["OKB/USDT", "SOL/USDT"], # 与白名单一致 "label_period_candles": 12, "include_shifted_candles": 0, "include_periods": [20], - "DI_threshold": 5.0 + "DI_threshold": 1.5 # 提高以减少丢弃预测 }, "data_split_parameters": { "test_size": 0.2, @@ -128,9 +128,9 @@ class FreqaiExampleStrategy(IStrategy): return dataframe def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: - logger.info(f"Processing pair: {metadata['pair']}") - logger.info(f"DataFrame rows: {len(dataframe)}") - logger.info(f"Columns before freqai.start: {list(dataframe.columns)}") + logger.info(f"populate_indicators Processing pair: {metadata['pair']}") + logger.info(f"populate_indicators DataFrame rows: {len(dataframe)}") + logger.info(f"populate_indicators Columns before freqai.start: {list(dataframe.columns)}") if "close" not in dataframe.columns or dataframe["close"].isna().all(): logger.error(f"DataFrame missing 'close' column or all NaN for pair: {metadata['pair']}") @@ -173,19 +173,6 @@ class FreqaiExampleStrategy(IStrategy): logger.warning("bb_lowerband contains NaN, filling with close") dataframe["bb_lowerband"] = dataframe["bb_lowerband"].fillna(dataframe["close"]) logger.info(f"bb_lowerband stats: {dataframe['bb_lowerband'].describe().to_string()}") - # 生成 up_or_down - label_period = self.freqai_info["feature_parameters"]["label_period_candles"] - if len(dataframe) < label_period + 1: - logger.warning(f"DataFrame too short ({len(dataframe)} rows), cannot compute up_or_down") - dataframe["up_or_down"] = 0 - else: - dataframe["up_or_down"] = np.where( - dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0 - ) - if dataframe["up_or_down"].isna().any(): - logger.warning("up_or_down contains NaN, filling with 0") - dataframe["up_or_down"] = dataframe["up_or_down"].fillna(0) - logger.info(f"up_or_down stats: {dataframe['up_or_down'].describe().to_string()}") if "date" in dataframe.columns: dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek @@ -211,17 +198,23 @@ class FreqaiExampleStrategy(IStrategy): logger.info(f"{col} stats: {dataframe[col].describe().to_string()}") # 调试特征分布 + if "%-bb_width-period_10_OKB/USDT_5m" in dataframe.columns: + if dataframe["%-bb_width-period_10_OKB/USDT_5m"].std() > 0: + dataframe["%-bb_width-period_10_OKB/USDT_5m"] = ( + dataframe["%-bb_width-period_10_OKB/USDT_5m"] - dataframe["%-bb_width-period_10_OKB/USDT_5m"].mean() + ) / dataframe["%-bb_width-period_10_OKB/USDT_5m"].std() + logger.info(f"%-bb_width-period_10_OKB stats: {dataframe['%-bb_width-period_10_OKB/USDT_5m'].describe().to_string()}") if "%-bb_width-period_10_SOL/USDT_5m" in dataframe.columns: if dataframe["%-bb_width-period_10_SOL/USDT_5m"].std() > 0: dataframe["%-bb_width-period_10_SOL/USDT_5m"] = ( dataframe["%-bb_width-period_10_SOL/USDT_5m"] - dataframe["%-bb_width-period_10_SOL/USDT_5m"].mean() ) / dataframe["%-bb_width-period_10_SOL/USDT_5m"].std() - logger.info(f"%-bb_width-period_10 stats: {dataframe['%-bb_width-period_10_SOL/USDT_5m'].describe().to_string()}") + logger.info(f"%-bb_width-period_10_SOL stats: {dataframe['%-bb_width-period_10_SOL/USDT_5m'].describe().to_string()}") def get_expected_columns(freqai_config: dict) -> list: indicators = ["rsi", "bb_width", "pct-change"] periods = freqai_config.get("feature_parameters", {}).get("include_periods", [10, 20]) - pairs = freqai_config.get("include_corr_pairlist", ["SOL/USDT", "BTC/USDT"]) + pairs = freqai_config.get("include_corr_pairlist", ["OKB/USDT", "SOL/USDT"]) timeframes = freqai_config.get("include_timeframes", ["5m"]) shifts = [0] expected_columns = ["%-volatility", "%-day_of_week", "%-hour_of_day"] @@ -256,11 +249,10 @@ class FreqaiExampleStrategy(IStrategy): def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: enter_long_conditions = [ - qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"] + (5 if metadata["pair"] == "BTC/USDT" else 0)), - df["tema"] > df["tema"].shift(1), + qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]), + df["close"] > df["tema"], df["volume"] > 0, - df["do_predict"] == 1, - df["up_or_down"] == 1 + df["do_predict"] == 1 ] if enter_long_conditions: df.loc[ @@ -274,7 +266,9 @@ class FreqaiExampleStrategy(IStrategy): ["enter_long", "enter_tag"] ] = (1, "long") if df["entry_signal"].iloc[-1]: - logger.info(f"Entry signal triggered for {metadata['pair']}: rsi={df['rsi'].iloc[-1]}, buy_rsi_pred={df['buy_rsi_pred'].iloc[-1]}, do_predict={df['do_predict'].iloc[-1]}") + logger.info(f"Entry signal triggered for {metadata['pair']}: rsi={df['rsi'].iloc[-1]}, buy_rsi_pred={df['buy_rsi_pred'].iloc[-1]}, do_predict={df['do_predict'].iloc[-1]}, close={df['close'].iloc[-1]}, tema={df['tema'].iloc[-1]}") + logger.info(f"Entry conditions: RSI_cross={qtpylib.crossed_above(df['rsi'], df['buy_rsi_pred']).iloc[-1]}, Close_above_tema={df['close'].iloc[-1] > df['tema'].iloc[-1]}, Volume={df['volume'].iloc[-1] > 0}, Do_predict={df['do_predict'].iloc[-1] == 1}") + logger.info(f"Last candle: rsi={df['rsi'].iloc[-1]}, buy_rsi_pred={df['buy_rsi_pred'].iloc[-1]}, close={df['close'].iloc[-1]}, tema={df['tema'].iloc[-1]}, do_predict={df['do_predict'].iloc[-1]}") return df def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame: @@ -283,8 +277,7 @@ class FreqaiExampleStrategy(IStrategy): (df["close"] < df["close"].shift(1) * 0.98) | (df["close"] < df["bb_lowerband"]), df["volume"] > 0, - df["do_predict"] == 1, - df["up_or_down"] == 0 + df["do_predict"] == 1 ] time_exit = (df["date"] >= df["date"].shift(1) + pd.Timedelta(days=1)) df.loc[ diff --git a/freqtrade/templates/celuo.diff b/freqtrade/templates/celuo.diff new file mode 100644 index 0000000..adee292 --- /dev/null +++ b/freqtrade/templates/celuo.diff @@ -0,0 +1,104 @@ +diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py +index 1d7ed33..245f771 100644 +--- a/freqtrade/templates/FreqaiExampleStrategy.py ++++ b/freqtrade/templates/FreqaiExampleStrategy.py +@@ -128,9 +128,9 @@ class FreqaiExampleStrategy(IStrategy): + return dataframe + + def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: +- logger.info(f"Processing pair: {metadata['pair']}") +- logger.info(f"DataFrame rows: {len(dataframe)}") +- logger.info(f"Columns before freqai.start: {list(dataframe.columns)}") ++ logger.info(f"populate_indicators Processing pair: {metadata['pair']}") ++ logger.info(f"populate_indicators DataFrame rows: {len(dataframe)}") ++ logger.info(f"populate_indicators Columns before freqai.start: {list(dataframe.columns)}") + + if "close" not in dataframe.columns or dataframe["close"].isna().all(): + logger.error(f"DataFrame missing 'close' column or all NaN for pair: {metadata['pair']}") +@@ -173,6 +173,19 @@ class FreqaiExampleStrategy(IStrategy): + logger.warning("bb_lowerband contains NaN, filling with close") + dataframe["bb_lowerband"] = dataframe["bb_lowerband"].fillna(dataframe["close"]) + logger.info(f"bb_lowerband stats: {dataframe['bb_lowerband'].describe().to_string()}") ++ # 生成 up_or_down ++ label_period = self.freqai_info["feature_parameters"]["label_period_candles"] ++ if len(dataframe) < label_period + 1: ++ logger.warning(f"DataFrame too short ({len(dataframe)} rows), cannot compute up_or_down") ++ dataframe["up_or_down"] = 0 ++ else: ++ dataframe["up_or_down"] = np.where( ++ dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0 ++ ) ++ if dataframe["up_or_down"].isna().any(): ++ logger.warning("up_or_down contains NaN, filling with 0") ++ dataframe["up_or_down"] = dataframe["up_or_down"].fillna(0) ++ logger.info(f"up_or_down stats: {dataframe['up_or_down'].describe().to_string()}") + + if "date" in dataframe.columns: + dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek +@@ -197,17 +210,18 @@ class FreqaiExampleStrategy(IStrategy): + dataframe[col] = 50 if col == "buy_rsi_pred" else 80 + logger.info(f"{col} stats: {dataframe[col].describe().to_string()}") + +- if "%-bb_width-period_20_SOL/USDT_5m" in dataframe.columns: +- if dataframe["%-bb_width-period_20_SOL/USDT_5m"].std() > 0: +- dataframe["%-bb_width-period_20_SOL/USDT_5m"] = ( +- dataframe["%-bb_width-period_20_SOL/USDT_5m"] - dataframe["%-bb_width-period_20_SOL/USDT_5m"].mean() +- ) / dataframe["%-bb_width-period_20_SOL/USDT_5m"].std() +- logger.info(f"%-bb_width-period_20 stats: {dataframe['%-bb_width-period_20_SOL/USDT_5m'].describe().to_string()}") ++ # 调试特征分布 ++ if "%-bb_width-period_10_SOL/USDT_5m" in dataframe.columns: ++ if dataframe["%-bb_width-period_10_SOL/USDT_5m"].std() > 0: ++ dataframe["%-bb_width-period_10_SOL/USDT_5m"] = ( ++ dataframe["%-bb_width-period_10_SOL/USDT_5m"] - dataframe["%-bb_width-period_10_SOL/USDT_5m"].mean() ++ ) / dataframe["%-bb_width-period_10_SOL/USDT_5m"].std() ++ logger.info(f"%-bb_width-period_10 stats: {dataframe['%-bb_width-period_10_SOL/USDT_5m'].describe().to_string()}") + + def get_expected_columns(freqai_config: dict) -> list: + indicators = ["rsi", "bb_width", "pct-change"] +- periods = freqai_config.get("feature_parameters", {}).get("include_periods", [20]) +- pairs = freqai_config.get("include_corr_pairlist", ["SOL/USDT"]) ++ periods = freqai_config.get("feature_parameters", {}).get("include_periods", [10, 20]) ++ pairs = freqai_config.get("include_corr_pairlist", ["SOL/USDT", "BTC/USDT"]) + timeframes = freqai_config.get("include_timeframes", ["5m"]) + shifts = [0] + expected_columns = ["%-volatility", "%-day_of_week", "%-hour_of_day"] +@@ -242,11 +256,17 @@ class FreqaiExampleStrategy(IStrategy): + + def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: + enter_long_conditions = [ +- qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]), ++ qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"] + (5 if metadata["pair"] == "BTC/USDT" else 0)), + df["tema"] > df["tema"].shift(1), + df["volume"] > 0, +- df["do_predict"] == 1 ++ df["do_predict"] == 1, ++ df["up_or_down"] == 1 + ] ++ if enter_long_conditions: ++ df.loc[ ++ reduce(lambda x, y: x & y, enter_long_conditions), ++ ["enter_long", "enter_tag"] ++ ] = (1, "long") + df["entry_signal"] = reduce(lambda x, y: x & y, enter_long_conditions) + df["entry_signal"] = df["entry_signal"].rolling(window=2, min_periods=1).max().astype(bool) + df.loc[ +@@ -259,14 +279,16 @@ class FreqaiExampleStrategy(IStrategy): + + def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame: + exit_long_conditions = [ +- (qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"] - 5)) | ++ (qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"])) | + (df["close"] < df["close"].shift(1) * 0.98) | + (df["close"] < df["bb_lowerband"]), + df["volume"] > 0, +- df["do_predict"] == 1 ++ df["do_predict"] == 1, ++ df["up_or_down"] == 0 + ] ++ time_exit = (df["date"] >= df["date"].shift(1) + pd.Timedelta(days=1)) + df.loc[ +- reduce(lambda x, y: x & y, exit_long_conditions), ++ (reduce(lambda x, y: x & y, exit_long_conditions)) | time_exit, + "exit_long" + ] = 1 + return df diff --git a/nohup.out b/nohup.out index 0ec5701..254a264 100644 --- a/nohup.out +++ b/nohup.out @@ -2,3 +2,4 @@ 实时监控 freqtrade_freqtrade_run_ef258891294d 的日志,过滤 'but got Index'... 开始过滤日志,输出到 freqtrade_error_logs.txt ... 实时监控 freqtrade_freqtrade_run_ef258891294d 的日志,过滤 'but got Index'... +未捕获到包含 'but got Index' 的日志,文件 freqtrade_error_logs.txt 为空