diff --git a/docker-compose.yml b/docker-compose.yml index 5816911c..e5a14770 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,10 @@ services: - "./freqtrade/templates:/freqtrade/templates" - "./freqtrade/exchange/:/freqtrade/exchange" - "./ccxt/async_support/okx.py:/home/ftuser/.local/lib/python3.12/site-packages/ccxt/async_support/okx.py" + # FreqAI核心文件挂载 - 确保使用我们修改的版本 + - "./freqtrade/freqai/data_kitchen.py:/freqtrade/freqai/data_kitchen.py" + - "./freqtrade/freqai/data_drawer.py:/freqtrade/freqai/data_drawer.py" + - "./freqtrade/freqai/freqai_interface.py:/freqtrade/freqai/freqai_interface.py" # Expose api on port 8080 (localhost only) # Please read the https://www.freqtrade.io/en/stable/rest-api/ documentation # for more information. diff --git a/freqtrade/freqai/data_drawer.py b/freqtrade/freqai/data_drawer.py index 1080b907..94088bb2 100644 --- a/freqtrade/freqai/data_drawer.py +++ b/freqtrade/freqai/data_drawer.py @@ -301,8 +301,8 @@ class FreqaiDataDrawer: hist_preds = self.historic_predictions[pair].copy() # ensure both dataframes have the same date format so they can be merged - new_pred["date_pred"] = pd.to_datetime(new_pred["date_pred"]) - hist_preds["date_pred"] = pd.to_datetime(hist_preds["date_pred"]) + new_pred["date_pred"] = pd.to_datetime(new_pred["date_pred"], utc=True).dt.tz_localize(None) + hist_preds["date_pred"] = pd.to_datetime(hist_preds["date_pred"], utc=True).dt.tz_localize(None) # find the closest common date between new_pred and historic predictions # and cut off the new_pred dataframe at that date @@ -407,7 +407,16 @@ class FreqaiDataDrawer: """ df = self.model_return_values[pair] to_keep = [col for col in dataframe.columns if not col.startswith("&")] - dataframe = pd.concat([dataframe[to_keep], df], axis=1) + + # 确保数据框索引一致,避免时区问题 + dataframe = dataframe.copy() + df_copy = df.copy() + + # 重置索引以避免潜在的时区问题 + dataframe = dataframe.reset_index(drop=True) + df_copy = df_copy.reset_index(drop=True) + + dataframe = pd.concat([dataframe[to_keep], df_copy], axis=1) return dataframe def return_null_values_to_strategy(self, dataframe: DataFrame, dk: FreqaiDataKitchen) -> None: diff --git a/freqtrade/freqai/data_kitchen.py b/freqtrade/freqai/data_kitchen.py index 6cb52eb2..adcda0a4 100644 --- a/freqtrade/freqai/data_kitchen.py +++ b/freqtrade/freqai/data_kitchen.py @@ -471,7 +471,22 @@ class FreqaiDataKitchen: to_keep = [ col for col in dataframe.columns if not col.startswith("&") and not col.startswith("%%") ] - self.return_dataframe = pd.merge(dataframe[to_keep], self.full_df, how="left", on="date") + + # 确保日期列的时区一致性,避免时区混用错误 + df_subset = dataframe[to_keep].copy() + full_df_copy = self.full_df.copy() + + # 标准化日期列的时区 + if 'date' in df_subset.columns and 'date' in full_df_copy.columns: + # 确保两个date列都是无时区的 + if hasattr(df_subset['date'], 'dt'): + if df_subset['date'].dt.tz is not None: + df_subset['date'] = df_subset['date'].dt.tz_localize(None) + if hasattr(full_df_copy['date'], 'dt'): + if full_df_copy['date'].dt.tz is not None: + full_df_copy['date'] = full_df_copy['date'].dt.tz_localize(None) + + self.return_dataframe = pd.merge(df_subset, full_df_copy, how="left", on="date") self.return_dataframe[self.full_df.columns] = self.return_dataframe[ self.full_df.columns ].fillna(value=0) @@ -642,10 +657,22 @@ class FreqaiDataKitchen: """ pairs = self.freqai_config["feature_parameters"].get("include_corr_pairlist", []) current_pair = current_pair.replace(":", "") + + # 确保主数据框的日期列时区一致 + dataframe = dataframe.copy() + if 'date' in dataframe.columns and hasattr(dataframe['date'], 'dt'): + if dataframe['date'].dt.tz is not None: + dataframe['date'] = dataframe['date'].dt.tz_localize(None) + for pair in pairs: pair = pair.replace(":", "") # lightgbm does not work with colons - if current_pair != pair: - dataframe = dataframe.merge(corr_dataframes[pair], how="left", on="date") + if current_pair != pair and pair in corr_dataframes: + corr_df = corr_dataframes[pair].copy() + # 确保相关数据框的日期列时区一致 + if 'date' in corr_df.columns and hasattr(corr_df['date'], 'dt'): + if corr_df['date'].dt.tz is not None: + corr_df['date'] = corr_df['date'].dt.tz_localize(None) + dataframe = dataframe.merge(corr_df, how="left", on="date") return dataframe diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 30be791d..7fe1e0dc 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -1465,17 +1465,21 @@ class FreqaiPrimer(IStrategy): trend_scores.append(50) continue - # 获取时间戳 + # 获取时间戳 - 统一使用无时区的时间戳 try: last_idx = hist_df.index[-1] if isinstance(last_idx, pd.Timestamp): - timestamp = int(last_idx.timestamp()) + # 确保时间戳是无时区的 + ts = last_idx.tz_localize(None) if last_idx.tz else last_idx + timestamp = int(ts.timestamp()) elif hasattr(last_idx, 'timestamp'): timestamp = int(last_idx.timestamp()) else: - timestamp = int(pd.Timestamp.now().timestamp()) + i + # 使用UTC时间避免时区问题 + timestamp = int(pd.Timestamp.utcnow().timestamp()) + i except Exception as e: - timestamp = int(pd.Timestamp.now().timestamp()) + i + # 使用UTC时间避免时区问题 + timestamp = int(pd.Timestamp.utcnow().timestamp()) + i # 获取趋势得分 score = self.get_trend_score_with_cache(