Compare commits

...

51 Commits
main ... test4

Author SHA1 Message Date
zhangkun9038@dingtalk.com
5027018fe0 主要修改点:
1. 修复了方法名拼写错误(featcaure -> feature)
2. 增加了基础数据检查
3. 添加了更多技术指标(动量、ROC、波动率等)
4. 增加了特征数量检查
5. 添加了更详细的日志记录
2025-04-29 17:38:59 +08:00
zhangkun9038@dingtalk.com
5df9f23baf sma 2025-04-29 17:20:29 +08:00
zhangkun9038@dingtalk.com
fdc1fa0374 sma 2025-04-29 17:08:41 +08:00
zhangkun9038@dingtalk.com
0d914c2b76 log 2025-04-29 16:34:11 +08:00
zhangkun9038@dingtalk.com
cd5befd8c9 sma 2025-04-29 16:25:48 +08:00
zhangkun9038@dingtalk.com
196c0093cc 运行有结果,亏钱 2025-04-29 15:46:15 +08:00
zhangkun9038@dingtalk.com
ed011ef498 run result 2025-04-29 11:47:05 +08:00
zhangkun9038@dingtalk.com
4dcfc172f9 听v3的 2025-04-29 11:45:15 +08:00
zhangkun9038@dingtalk.com
65b9e9c0fc allow kog 2025-04-29 10:42:56 +08:00
zhangkun9038@dingtalk.com
cca246abfd log ok 2025-04-29 10:22:02 +08:00
zhangkun9038@dingtalk.com
37173ab636 4个月回测需要4分钟,结果还是跑输15% 2025-04-29 08:47:03 +08:00
zhangkun9038@dingtalk.com
8f4c374e6b 检查 MACD 列是否存在
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 17:01:30 +08:00
zhangkun9038@dingtalk.com
ff7aff8ee7 检查 MACD 列是否存在
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:51:18 +08:00
zhangkun9038@dingtalk.com
e5cc226c01 检查 MACD 列是否存在
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:48:53 +08:00
zhangkun9038@dingtalk.com
63c1f07f06 确保是二维数组
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:46:26 +08:00
zhangkun9038@dingtalk.com
b20684b5b1 up3
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:12:02 +08:00
zhangkun9038@dingtalk.com
96b76ffcc0 up3
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:09:50 +08:00
zhangkun9038@dingtalk.com
0fa0866370 up3
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:09:02 +08:00
zhangkun9038@dingtalk.com
887c4778b4 up3
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 16:07:03 +08:00
zhangkun9038@dingtalk.com
8777726441 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 15:49:02 +08:00
zhangkun9038@dingtalk.com
b6b9a62c35 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 15:47:10 +08:00
zhangkun9038@dingtalk.com
3fafbff8c3 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 15:44:22 +08:00
zhangkun9038@dingtalk.com
619de5cede 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 15:32:01 +08:00
zhangkun9038@dingtalk.com
8535b10cea 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 15:15:37 +08:00
zhangkun9038@dingtalk.com
7da603fd08 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 15:14:09 +08:00
zhangkun9038@dingtalk.com
144615b7a8 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 14:13:16 +08:00
zhangkun9038@dingtalk.com
8448ab40f5 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 14:11:36 +08:00
zhangkun9038@dingtalk.com
6916e49479 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 14:10:54 +08:00
zhangkun9038@dingtalk.com
29fd0941a0 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 14:08:34 +08:00
zhangkun9038@dingtalk.com
ec7d7c2842 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 14:07:32 +08:00
zhangkun9038@dingtalk.com
ea707fe104 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 14:06:49 +08:00
zhangkun9038@dingtalk.com
2f4a06d505 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 13:59:16 +08:00
zhangkun9038@dingtalk.com
65116ab7b4 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 13:49:35 +08:00
zhangkun9038@dingtalk.com
fbd72745cb 跟特征数量没关系
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 13:34:56 +08:00
zhangkun9038@dingtalk.com
8477bf07c7 增加特征
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 13:23:49 +08:00
zhangkun9038@dingtalk.com
03a54a5b0a 添加更多技术指标
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 13:13:19 +08:00
zhangkun9038@dingtalk.com
e3ffdd92e0 :生成的特征可能不够稳定,导致新数据与训练数据差异过大
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 13:01:27 +08:00
zhangkun9038@dingtalk.com
c3e4a73eb3 缩进乱了
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:49:02 +08:00
zhangkun9038@dingtalk.com
21e4c2f2ea 数据清理
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:45:19 +08:00
zhangkun9038@dingtalk.com
86e9a2ab61 确保 &-buy_rsi 列的值计算正确
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:42:12 +08:00
zhangkun9038@dingtalk.com
05b65162a1 Additional check to ensure no NaN values remain
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:34:47 +08:00
zhangkun9038@dingtalk.com
64e2edfa4e 计算 buy_rsi_pred 并清理 NaN 值
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:31:10 +08:00
zhangkun9038@dingtalk.com
328769e0e1 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:25:20 +08:00
zhangkun9038@dingtalk.com
82ed0e90e9 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:21:53 +08:00
zhangkun9038@dingtalk.com
244b91ebd3 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:20:59 +08:00
zhangkun9038@dingtalk.com
e0884d4349 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:16:22 +08:00
zhangkun9038@dingtalk.com
456ae1fde0 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 12:10:17 +08:00
zhangkun9038@dingtalk.com
b72587ed6a up 2025-04-28 11:54:42 +08:00
zhangkun9038@dingtalk.com
c145d5d452 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 11:52:45 +08:00
zhangkun9038@dingtalk.com
872bfe4078 up
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 11:38:27 +08:00
zhangkun9038@dingtalk.com
6e4e54b9c8 去掉看底牌代码
Some checks are pending
Update Docker Hub Description / dockerHubDescription (push) Waiting to run
2025-04-28 11:34:17 +08:00
18 changed files with 2724 additions and 467 deletions

View File

@ -0,0 +1,5 @@
<<<<<<< HEAD
=======
freqtrade backtesting --strategy FreqaiExampleStrategy --strategy-path freqtrade/templates --config config_examples/config_freqai.example.json --timerange 20230101-20230401
>>>>>>> Snippet

4
.gitignore vendored
View File

@ -73,7 +73,9 @@ coverage.xml
*.pot
# Django stuff:
*.log
#*.log
!outout_filted.log
local_settings.py
# Flask stuff:

View File

@ -0,0 +1,264 @@
diff --git "a/4. **\346\270\205\347\220\206\347\274\223\345\255\230**\357\274\232" "b/4. **\346\270\205\347\220\206\347\274\223\345\255\230**\357\274\232"
new file mode 100644
index 0000000..3bb7671
--- /dev/null
+++ "b/4. **\346\270\205\347\220\206\347\274\223\345\255\230**\357\274\232"
@@ -0,0 +1,5 @@
+
+<<<<<<< HEAD
+=======
+ rm -rf /freqtrade/user_data/models/test62/
+>>>>>>> Snippet
diff --git "a/5. **\351\207\215\346\226\260\350\256\255\347\273\203**\357\274\232" "b/5. **\351\207\215\346\226\260\350\256\255\347\273\203**\357\274\232"
new file mode 100644
index 0000000..8a18d3d
--- /dev/null
+++ "b/5. **\351\207\215\346\226\260\350\256\255\347\273\203**\357\274\232"
@@ -0,0 +1,5 @@
+
+<<<<<<< HEAD
+=======
+ freqtrade trade --config config_examples/config_freqai.okx.json --strategy FreqaiExampleStrategy
+>>>>>>> Snippet
diff --git a/config_examples/config_freqai.okx.json b/config_examples/config_freqai.okx.json
index 1816983..4535010 100644
--- a/config_examples/config_freqai.okx.json
+++ b/config_examples/config_freqai.okx.json
@@ -67,45 +67,31 @@
"freqaimodel": "CatboostClassifier",
"purge_old_models": 2,
"train_period_days": 15,
- "identifier": "test62",
- "train_period_days": 30,
- "backtest_period_days": 10,
+ "train_period_days": 180,
+ "backtest_period_days": 60,
"live_retrain_hours": 0,
"feature_selection": {
"method": "recursive_elimination"
},
"feature_parameters": {
- "include_timeframes": [
- "3m",
- "15m",
- "1h"
- ],
- "include_corr_pairlist": [
- "BTC/USDT",
- "SOL/USDT"
- ],
- "label_period_candles": 20,
- "include_shifted_candles": 2,
- "DI_threshold": 0.9,
+ "include_timeframes": ["15m"],
+ "include_corr_pairlist": ["BTC/USDT"],
+ "label_period_candles": 10,
+ "include_shifted_candles": 1,
+ "DI_threshold": 0.7,
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": false,
- "indicator_periods_candles": [
- 10,
- 20,
- 50
- ],
- "plot_feature_importances": 0
+ "indicator_periods_candles": [14],
},
"data_split_parameters": {
"test_size": 0.2
},
- "model_training_parameters": {
- "n_estimators": 100,
- "learning_rate": 0.05,
- "max_depth": 5,
- "num_leaves": 31
- }
+ "model_training_parameters": {
+ "n_estimators": 100,
+ "learning_rate": 0.05,
+ "max_depth": 5
+ }
},
"api_server": {
"enabled": true,
diff --git a/docker-compose.yml b/docker-compose.yml
index defe81e..aeb31e6 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -64,7 +64,7 @@ services:
command: >
backtesting
--logfile /freqtrade/user_data/logs/freqtrade.log
- --freqaimodel LightGBMRegressor
+ --freqaimodel XGBoostRegressor
--config /freqtrade/config_examples/config_freqai.okx.json
--config /freqtrade/templates/FreqaiExampleStrategy.json
--strategy-path /freqtrade/templates
diff --git a/freqtrade/templates/FreqaiExampleStrategy.py b/freqtrade/templates/FreqaiExampleStrategy.py
index 688e644..e27e17b 100644
--- a/freqtrade/templates/FreqaiExampleStrategy.py
+++ b/freqtrade/templates/FreqaiExampleStrategy.py
@@ -30,12 +30,12 @@ class FreqaiExampleStrategy(IStrategy):
# FreqAI 配置
freqai_info = {
- "model": "XGBoostRegressor", # 改用XGBoost
+ "model": "CatboostClassifier", # 与config保持一致
"feature_parameters": {
- "include_timeframes": ["5m", "15m", "1h"],
- "include_corr_pairlist": [],
- "label_period_candles": 12,
- "include_shifted_candles": 3,
+ "include_timeframes": ["3m", "15m", "1h"], # 与config一致
+ "include_corr_pairlist": ["BTC/USDT", "SOL/USDT"], # 添加相关交易对
+ "label_period_candles": 20, # 与config一致
+ "include_shifted_candles": 2, # 与config一致
},
"data_split_parameters": {
"test_size": 0.2,
@@ -72,54 +72,26 @@ class FreqaiExampleStrategy(IStrategy):
}
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
- # 添加更多技术指标
+ # 保留关键的技术指标
dataframe["%-rsi"] = ta.RSI(dataframe, timeperiod=14)
- dataframe["%-mfi"] = ta.MFI(dataframe, timeperiod=14)
- dataframe["%-sma"] = ta.SMA(dataframe, timeperiod=20)
- dataframe["%-ema"] = ta.EMA(dataframe, timeperiod=20)
- dataframe["%-adx"] = ta.ADX(dataframe, timeperiod=14)
- dataframe["%-atr"] = ta.ATR(dataframe, timeperiod=14)
- dataframe["%-obv"] = ta.OBV(dataframe)
- dataframe["%-cci"] = ta.CCI(dataframe, timeperiod=20)
- dataframe["%-stoch"] = ta.STOCH(dataframe)['slowk']
- dataframe["%-macd"] = ta.MACD(dataframe)['macd']
- dataframe["%-macdsignal"] = ta.MACD(dataframe)['macdsignal']
- dataframe["%-macdhist"] = ta.MACD(dataframe)['macdhist']
- dataframe["%-willr"] = ta.WILLR(dataframe, timeperiod=14)
- dataframe["%-ultosc"] = ta.ULTOSC(dataframe)
- dataframe["%-trix"] = ta.TRIX(dataframe, timeperiod=14)
- dataframe["%-ad"] = ta.ADOSC(dataframe)
- dataframe["%-mom"] = ta.MOM(dataframe, timeperiod=10)
- dataframe["%-roc"] = ta.ROC(dataframe, timeperiod=10)
-
- # 添加布林带相关特征
+ macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
+ dataframe["%-macd"] = macd["macd"]
+ dataframe["%-macdsignal"] = macd["macdsignal"]
+
+ # 保留布林带相关特征
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe["bb_lowerband"] = bollinger["lower"]
dataframe["bb_middleband"] = bollinger["mid"]
dataframe["bb_upperband"] = bollinger["upper"]
dataframe["bb_width"] = (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe["bb_middleband"]
dataframe["bb_pct"] = (dataframe["close"] - dataframe["bb_lowerband"]) / (dataframe["bb_upperband"] - dataframe["bb_lowerband"])
-
- # 添加成交量相关特征
+
+ # 保留成交量相关特征
dataframe["volume_ma"] = dataframe["volume"].rolling(window=20).mean()
dataframe["volume_roc"] = dataframe["volume"].pct_change(periods=10)
- dataframe["volume_obv"] = ta.OBV(dataframe)
-
- # 添加价格相关特征
- dataframe["close_ma"] = dataframe["close"].rolling(window=20).mean()
+
+ # 保留价格变化率
dataframe["close_roc"] = dataframe["close"].pct_change(periods=10)
- dataframe["close_log_ret"] = np.log(dataframe["close"]).diff()
- dataframe["close_zscore"] = (dataframe["close"] - dataframe["close"].rolling(window=20).mean()) / dataframe["close"].rolling(window=20).std()
-
- # 添加时间相关特征
- dataframe["hour"] = dataframe["date"].dt.hour
- dataframe["day_of_week"] = dataframe["date"].dt.dayofweek
- dataframe["is_weekend"] = dataframe["day_of_week"].isin([5, 6]).astype(int)
-
- # 添加波动率相关特征
- dataframe["volatility"] = dataframe["close"].pct_change().rolling(window=20).std()
- dataframe["volatility_ma"] = dataframe["volatility"].rolling(window=20).mean()
- dataframe["volatility_roc"] = dataframe["volatility"].pct_change(periods=10)
# 改进数据清理
for col in dataframe.columns:
@@ -170,16 +142,23 @@ class FreqaiExampleStrategy(IStrategy):
try:
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
+
+ # 生成更复杂的目标变量 up_or_down
+ dataframe["up_or_down"] = np.where(
+ dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0
+ )
+ # 确保目标变量是二维数组
+ if dataframe["up_or_down"].ndim == 1:
+ dataframe["up_or_down"] = dataframe["up_or_down"].values.reshape(-1, 1)
+
# 生成 %-volatility 特征
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
- # 单一回归目标
- # 移除对未来的数据依赖
# 确保 &-buy_rsi 列的值计算正确
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
# 数据清理
- for col in ["&-buy_rsi"]:
+ for col in ["&-buy_rsi", "up_or_down", "%-volatility"]:
# 使用直接操作避免链式赋值
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill() # 替代 fillna(method='ffill')
@@ -187,19 +166,13 @@ class FreqaiExampleStrategy(IStrategy):
if dataframe[col].isna().any():
logger.warning(f"目标列 {col} 仍包含 NaN填充为默认值")
- # 数据清理
- for col in ["&-buy_rsi", "%-volatility"]:
- # 使用直接操作避免链式赋值
- dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
- dataframe[col] = dataframe[col].ffill() # 替代 fillna(method='ffill')
- dataframe[col] = dataframe[col].fillna(0)
- if dataframe[col].isna().any():
- logger.warning(f"目标列 {col} 仍包含 NaN检查数据生成逻辑")
except Exception as e:
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
raise
- logger.info(f"目标列预览:\n{dataframe[['&-buy_rsi']].head().to_string()}")
+ # Log the shape of the target variable for debugging
+ logger.info(f"目标列形状:{dataframe['up_or_down'].shape}")
+ logger.info(f"目标列预览:\n{dataframe[['up_or_down', '&-buy_rsi']].head().to_string()}")
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
@@ -237,13 +210,13 @@ class FreqaiExampleStrategy(IStrategy):
dataframe[col] = dataframe[col].fillna(-0.1 if col == "&-stoploss" else 0)
# 简化动态参数生成逻辑
-# 简化 buy_rsi 和 sell_rsi 的生成逻辑
+ # 放松 buy_rsi 和 sell_rsi 的生成逻辑
# 计算 buy_rsi_pred 并清理 NaN 值
- dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(window=10).mean().clip(20, 40)
+ dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(window=10).mean().clip(30, 50)
dataframe["buy_rsi_pred"] = dataframe["buy_rsi_pred"].fillna(dataframe["buy_rsi_pred"].mean())
# 计算 sell_rsi_pred 并清理 NaN 值
- dataframe["sell_rsi_pred"] = dataframe["buy_rsi_pred"] + 20
+ dataframe["sell_rsi_pred"] = dataframe["buy_rsi_pred"] + 40
dataframe["sell_rsi_pred"] = dataframe["sell_rsi_pred"].fillna(dataframe["sell_rsi_pred"].mean())
# 计算 stoploss_pred 并清理 NaN 值
@@ -308,8 +281,9 @@ class FreqaiExampleStrategy(IStrategy):
# 改进买入信号条件
enter_long_conditions = [
(df["rsi"] < df["buy_rsi_pred"]), # RSI 低于买入阈值
- (df["volume"] > df["volume"].rolling(window=10).mean()), # 成交量高于近期均值
- (df["close"] > df["bb_middleband"]) # 价格高于布林带中轨
+ (df["volume"] > df["volume"].rolling(window=10).mean() * 1.2), # 成交量高于近期均值20%
+ (df["close"] > df["bb_middleband"]), # 价格高于布林带中轨
+ (df["do_predict"] == 1) # 确保模型预测为买入
]
if enter_long_conditions:
df.loc[

5
4. **清理缓存**: Normal file
View File

@ -0,0 +1,5 @@
<<<<<<< HEAD
=======
rm -rf /freqtrade/user_data/models/test62/
>>>>>>> Snippet

5
5. **重新训练**: Normal file
View File

@ -0,0 +1,5 @@
<<<<<<< HEAD
=======
freqtrade trade --config config_examples/config_freqai.okx.json --strategy FreqaiExampleStrategy
>>>>>>> Snippet

View File

@ -0,0 +1,121 @@
diff --git a/config_examples/config_freqai.okx.json b/config_examples/config_freqai.okx.json
index 259459e..c2693fc 100644
--- a/config_examples/config_freqai.okx.json
+++ b/config_examples/config_freqai.okx.json
@@ -5,11 +5,10 @@
"max_open_trades": 4,
"stake_currency": "USDT",
"stake_amount": 150,
- "startup_candle_count": 30,
"tradable_balance_ratio": 1,
"fiat_display_currency": "USD",
"dry_run": true,
- "timeframe": "5m",
+ "timeframe": "3m",
"dry_run_wallet": 1000,
"cancel_open_orders_on_exit": true,
"stoploss": -0.05,
@@ -24,21 +23,21 @@
"enable_ws": false,
"ccxt_config": {
"enableRateLimit": true,
- "rateLimit": 800,
+ "rateLimit": 500,
"options": {
"defaultType": "spot"
}
},
"ccxt_async_config": {
"enableRateLimit": true,
- "rateLimit": 800,
+ "rateLimit": 500,
"timeout": 20000
},
"pair_whitelist": [
- "OKB/USDT",
- "DOT/USDT",
+ "BTC/USDT",
"SOL/USDT"
- ]
+ ],
+ "pair_blacklist": []
},
"entry_pricing": {
"price_side": "same",
@@ -65,47 +64,37 @@
"data_kitchen": {
"fillna": "ffill"
},
- "freqaimodel": "CatboostClassifier",
- "purge_old_models": 2,
- "identifier": "test175",
- "train_period_days": 30,
- "backtest_period_days": 10,
+ "freqaimodel": "XGBoostRegressor",
+ "model_training_parameters": {
+ "n_estimators": 100,
+ "learning_rate": 0.05,
+ "max_depth": 5
+ },
+ "train_period_days": 180,
+ "backtest_period_days": 60,
"live_retrain_hours": 0,
"feature_selection": {
"method": "recursive_elimination"
},
"feature_parameters": {
- "include_timeframes": [
- "5m",
- "1h"
- ],
- "include_corr_pairlist": [
- "BTC/USDT",
- "ETH/USDT"
- ],
- "label_period_candles": 12,
- "include_shifted_candles": 3,
- "DI_threshold": 0.9,
+ "include_timeframes": ["15m"],
+ "include_corr_pairlist": ["BTC/USDT"],
+ "label_period_candles": 10,
+ "include_shifted_candles": 1,
+
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": false,
- "indicator_periods_candles": [
- 10,
- 20,
- 50
- ],
- "plot_feature_importances": 0
+ "indicator_periods_candles": [14],
},
"data_split_parameters": {
- "test_size": 0.2,
- "shuffle": false,
+ "test_size": 0.2
},
- "model_training_parameters": {
- "n_estimators": 100,
- "learning_rate": 0.1,
- "num_leaves": 15,
- "verbose": -1
- }
+ "model_training_parameters": {
+ "n_estimators": 100,
+ "learning_rate": 0.05,
+ "max_depth": 5
+ }
},
"api_server": {
"enabled": true,
@@ -123,7 +112,7 @@
"initial_state": "running",
"force_entry_enable": false,
"internals": {
- "process_throttle_secs": 10,
+ "process_throttle_secs": 5,
"heartbeat_interval": 20,
"loglevel": "DEBUG"
}

View File

@ -5,6 +5,7 @@
"max_open_trades": 4,
"stake_currency": "USDT",
"stake_amount": 150,
"startup_candle_count": 30,
"tradable_balance_ratio": 1,
"fiat_display_currency": "USD",
"dry_run": true,
@ -62,49 +63,45 @@
"freqai": {
"enabled": true,
"data_kitchen": {
"fillna": "ffill"
"fillna": "ffill",
"feature_parameters": {
"DI_threshold": 0.9,
"weight_factor": 0.9
}
},
"freqaimodel": "CatboostClassifier",
"freqaimodel": "XGBoostRegressor",
"purge_old_models": 2,
"train_period_days": 15,
"identifier": "test62",
"identifier": "test175",
"train_period_days": 30,
"backtest_period_days": 10,
"live_retrain_hours": 0,
"feature_selection": {
"method": "recursive_elimination"
"method": "recursive_elimination",
"threshold": 0.01
},
"feature_parameters": {
"include_timeframes": [
"3m",
"15m",
"1h"
],
"include_corr_pairlist": [
"BTC/USDT",
"SOL/USDT"
],
"label_period_candles": 20,
"include_shifted_candles": 2,
"DI_threshold": 0.9,
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": false,
"indicator_periods_candles": [
10,
20,
50
],
"plot_feature_importances": 0
"include_timeframes": ["3m", "5m", "1h"],
"include_corr_pairlist": ["BTC/USDT", "ETH/USDT"],
"label_period_candles": 12,
"include_shifted_candles": 3,
"indicator_periods_candles": [10, 20, 50],
"plot_feature_importances": 1
},
"data_split_parameters": {
"test_size": 0.2
"test_size": 0.2,
"shuffle": true,
"random_state": 42
},
"model_training_parameters": {
"n_estimators": 100,
"n_estimators": 200,
"learning_rate": 0.05,
"max_depth": 5,
"num_leaves": 31
"subsample": 0.8,
"colsample_bytree": 0.8,
"objective": "reg:squarederror",
"eval_metric": "rmse",
"early_stopping_rounds": 50,
"verbose": 0
}
},
"api_server": {

View File

@ -0,0 +1,122 @@
diff --git a/config_examples/config_freqai.okx.json b/config_examples/config_freqai.okx.json
index 259459e..c8f04af 100644
--- a/config_examples/config_freqai.okx.json
+++ b/config_examples/config_freqai.okx.json
@@ -5,11 +5,10 @@
"max_open_trades": 4,
"stake_currency": "USDT",
"stake_amount": 150,
- "startup_candle_count": 30,
"tradable_balance_ratio": 1,
"fiat_display_currency": "USD",
"dry_run": true,
- "timeframe": "5m",
+ "timeframe": "3m",
"dry_run_wallet": 1000,
"cancel_open_orders_on_exit": true,
"stoploss": -0.05,
@@ -24,21 +23,21 @@
"enable_ws": false,
"ccxt_config": {
"enableRateLimit": true,
- "rateLimit": 800,
+ "rateLimit": 500,
"options": {
"defaultType": "spot"
}
},
"ccxt_async_config": {
"enableRateLimit": true,
- "rateLimit": 800,
+ "rateLimit": 500,
"timeout": 20000
},
"pair_whitelist": [
- "OKB/USDT",
- "DOT/USDT",
+ "BTC/USDT",
"SOL/USDT"
- ]
+ ],
+ "pair_blacklist": []
},
"entry_pricing": {
"price_side": "same",
@@ -65,47 +64,38 @@
"data_kitchen": {
"fillna": "ffill"
},
- "freqaimodel": "CatboostClassifier",
- "purge_old_models": 2,
- "identifier": "test175",
- "train_period_days": 30,
- "backtest_period_days": 10,
+ "freqaimodel": "XGBoostRegressor",
+ "model_training_parameters": {
+ "n_estimators": 100,
+ "learning_rate": 0.05,
+ "max_depth": 5
+ },
+ "train_period_days": 15,
+ "train_period_days": 180,
+ "backtest_period_days": 60,
"live_retrain_hours": 0,
"feature_selection": {
"method": "recursive_elimination"
},
"feature_parameters": {
- "include_timeframes": [
- "5m",
- "1h"
- ],
- "include_corr_pairlist": [
- "BTC/USDT",
- "ETH/USDT"
- ],
- "label_period_candles": 12,
- "include_shifted_candles": 3,
- "DI_threshold": 0.9,
+ "include_timeframes": ["15m"],
+ "include_corr_pairlist": ["BTC/USDT"],
+ "label_period_candles": 10,
+ "include_shifted_candles": 1,
+
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": false,
- "indicator_periods_candles": [
- 10,
- 20,
- 50
- ],
- "plot_feature_importances": 0
+ "indicator_periods_candles": [14],
},
"data_split_parameters": {
- "test_size": 0.2,
- "shuffle": false,
+ "test_size": 0.2
},
- "model_training_parameters": {
- "n_estimators": 100,
- "learning_rate": 0.1,
- "num_leaves": 15,
- "verbose": -1
- }
+ "model_training_parameters": {
+ "n_estimators": 100,
+ "learning_rate": 0.05,
+ "max_depth": 5
+ }
},
"api_server": {
"enabled": true,
@@ -123,7 +113,7 @@
"initial_state": "running",
"force_entry_enable": false,
"internals": {
- "process_throttle_secs": 10,
+ "process_throttle_secs": 5,
"heartbeat_interval": 20,
"loglevel": "DEBUG"
}

View File

@ -64,9 +64,10 @@ services:
command: >
backtesting
--logfile /freqtrade/user_data/logs/freqtrade.log
--freqaimodel LightGBMRegressor
--freqaimodel XGBoostRegressor
--config /freqtrade/config_examples/config_freqai.okx.json
--config /freqtrade/templates/FreqaiExampleStrategy.json
--strategy-path /freqtrade/templates
--strategy FreqaiExampleStrategy
--timerange 20240920-20250420
--timerange 20250401-20250420
--cache none

7
filter.py Normal file
View File

@ -0,0 +1,7 @@
with open('output.log', 'r') as input_file, open('output_filted.log', 'w') as output_file:
for line in input_file:
if "validation_0" in line:
if "[99]" in line:
output_file.write(line)
else:
output_file.write(line)

1162
freqai/data_kitchen.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,311 +0,0 @@
import logging
import numpy as np # noqa
import pandas as pd # noqa
import talib.abstract as ta
from pandas import DataFrame
from technical import qtpylib
from freqtrade.strategy import IntParameter, IStrategy, merge_informative_pair
logger = logging.getLogger(__name__)
class FreqaiExampleHybridStrategy(IStrategy):
"""
Example of a hybrid FreqAI strat, designed to illustrate how a user may employ
FreqAI to bolster a typical Freqtrade strategy.
Launching this strategy would be:
freqtrade trade --strategy FreqaiExampleHybridStrategy --strategy-path freqtrade/templates
--freqaimodel CatboostClassifier --config config_examples/config_freqai.example.json
or the user simply adds this to their config:
"freqai": {
"enabled": true,
"purge_old_models": 2,
"train_period_days": 15,
"identifier": "unique-id",
"feature_parameters": {
"include_timeframes": [
"3m",
"15m",
"1h"
],
"include_corr_pairlist": [
"BTC/USDT",
"ETH/USDT"
],
"label_period_candles": 20,
"include_shifted_candles": 2,
"DI_threshold": 0.9,
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": true,
"indicator_periods_candles": [10, 20]
},
"data_split_parameters": {
"test_size": 0,
"random_state": 1
},
"model_training_parameters": {
"n_estimators": 800
}
},
Thanks to @smarmau and @johanvulgt for developing and sharing the strategy.
"""
minimal_roi = {
# "120": 0.0, # exit after 120 minutes at break even
"60": 0.01,
"30": 0.02,
"0": 0.04,
}
plot_config = {
"main_plot": {
"tema": {},
},
"subplots": {
"MACD": {
"macd": {"color": "blue"},
"macdsignal": {"color": "orange"},
},
"RSI": {
"rsi": {"color": "red"},
},
"Up_or_down": {
"&s-up_or_down": {"color": "green"},
},
},
}
process_only_new_candles = True
stoploss = -0.05
use_exit_signal = True
startup_candle_count: int = 30
can_short = False
# Hyperoptable parameters
buy_rsi = IntParameter(low=1, high=50, default=30, space="buy", optimize=True, load=True)
sell_rsi = IntParameter(low=50, high=100, default=70, space="sell", optimize=True, load=True)
def feature_engineering_expand_all(
self, dataframe: DataFrame, period: int, metadata: dict, **kwargs
) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`indicator_periods_candles`, `include_timeframes`, `include_shifted_candles`, and
`include_corr_pairs`. In other words, a single feature defined in this function
will automatically expand to a total of
`indicator_periods_candles` * `include_timeframes` * `include_shifted_candles` *
`include_corr_pairs` numbers of features added to the model.
All features must be prepended with `%` to be recognized by FreqAI internals.
More details on how these config defined parameters accelerate feature engineering
in the documentation at:
https://www.freqtrade.io/en/latest/freqai-parameter-table/#feature-parameters
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features
:param dataframe: strategy dataframe which will receive the features
:param period: period of the indicator - usage example:
:param metadata: metadata of current pair
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
"""
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)
bollinger = qtpylib.bollinger_bands(
qtpylib.typical_price(dataframe), window=period, stds=2.2
)
dataframe["bb_lowerband-period"] = bollinger["lower"]
dataframe["bb_middleband-period"] = bollinger["mid"]
dataframe["bb_upperband-period"] = bollinger["upper"]
dataframe["%-bb_width-period"] = (
dataframe["bb_upperband-period"] - dataframe["bb_lowerband-period"]
) / dataframe["bb_middleband-period"]
dataframe["%-close-bb_lower-period"] = dataframe["close"] / dataframe["bb_lowerband-period"]
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
dataframe["%-relative_volume-period"] = (
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
)
return dataframe
def feature_engineering_expand_basic(
self, dataframe: DataFrame, metadata: dict, **kwargs
) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This function will automatically expand the defined features on the config defined
`include_timeframes`, `include_shifted_candles`, and `include_corr_pairs`.
In other words, a single feature defined in this function
will automatically expand to a total of
`include_timeframes` * `include_shifted_candles` * `include_corr_pairs`
numbers of features added to the model.
Features defined here will *not* be automatically duplicated on user defined
`indicator_periods_candles`
All features must be prepended with `%` to be recognized by FreqAI internals.
More details on how these config defined parameters accelerate feature engineering
in the documentation at:
https://www.freqtrade.io/en/latest/freqai-parameter-table/#feature-parameters
https://www.freqtrade.io/en/latest/freqai-feature-engineering/#defining-the-features
:param dataframe: strategy dataframe which will receive the features
:param metadata: metadata of current pair
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-ema-200"] = ta.EMA(dataframe, timeperiod=200)
"""
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
return dataframe
def feature_engineering_standard(
self, dataframe: DataFrame, metadata: dict, **kwargs
) -> DataFrame:
"""
*Only functional with FreqAI enabled strategies*
This optional function will be called once with the dataframe of the base timeframe.
This is the final function to be called, which means that the dataframe entering this
function will contain all the features and columns created by all other
freqai_feature_engineering_* functions.
This function is a good place to do custom exotic feature extractions (e.g. tsfresh).
This function is a good place for any feature that should not be auto-expanded upon
(e.g. day of the week).
All features must be prepended with `%` to be recognized by FreqAI internals.
More details about feature engineering available:
https://www.freqtrade.io/en/latest/freqai-feature-engineering
:param dataframe: strategy dataframe which will receive the features
:param metadata: metadata of current pair
usage example: dataframe["%-day_of_week"] = (dataframe["date"].dt.dayofweek + 1) / 7
"""
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
return dataframe
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
logger.info(f"Setting FreqAI targets for pair: {metadata['pair']}")
logger.info(f"DataFrame shape: {dataframe.shape}")
logger.info(f"Available columns: {list(dataframe.columns)}")
logger.info(f"First few rows:\n{dataframe[['date', 'close']].head().to_string()}")
if "close" not in dataframe.columns:
logger.error("Required 'close' column missing in dataframe")
raise ValueError("Required 'close' column missing in dataframe")
if len(dataframe) < 50:
logger.error(f"Insufficient data: {len(dataframe)} rows, need at least 50 for shift(-50)")
raise ValueError("Insufficient data for target calculation")
try:
# 生成数值型标签1 表示上涨0 表示下跌
dataframe["&-up_or_down"] = np.where(
dataframe["close"].shift(-50) > dataframe["close"],
1.0, # 数值型标签
0.0
)
except Exception as e:
logger.error(f"Failed to create &-up_or_down column: {str(e)}")
raise
logger.info(f"Target column head:\n{dataframe[['&-up_or_down']].head().to_string()}")
if "&-up_or_down" not in dataframe.columns:
logger.error("FreqAI failed to generate the &-up_or_down column")
raise KeyError("FreqAI failed to generate the &-up_or_down column")
logger.info("FreqAI targets set successfully")
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.info(f"Processing pair: {metadata['pair']}")
logger.info(f"Input DataFrame shape: {dataframe.shape}")
logger.info(f"Input DataFrame columns: {list(dataframe.columns)}")
logger.info(f"Input DataFrame head:\n{dataframe[['date', 'close', 'volume']].head().to_string()}")
# Ensure FreqAI processing
logger.info("Calling self.freqai.start")
try:
dataframe = self.freqai.start(dataframe, metadata, self)
except Exception as e:
logger.error(f"self.freqai.start failed: {str(e)}")
raise
logger.info("self.freqai.start completed")
logger.info(f"Output DataFrame shape: {dataframe.shape}")
logger.info(f"Output DataFrame columns: {list(dataframe.columns)}")
# Safely log columns that exist
available_columns = [col for col in ['date', 'close', '&-up_or_down'] if col in dataframe.columns]
logger.info(f"Output DataFrame head:\n{dataframe[available_columns].head().to_string()}")
if "&-up_or_down" not in dataframe.columns:
logger.error("FreqAI did not generate the required &-up_or_down column")
raise KeyError("FreqAI did not generate the required &-up_or_down column")
# RSI
dataframe["rsi"] = ta.RSI(dataframe)
# Bollinger Bands
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe["bb_lowerband"] = bollinger["lower"]
dataframe["bb_middleband"] = bollinger["mid"]
dataframe["bb_upperband"] = bollinger["upper"]
dataframe["bb_percent"] = (dataframe["close"] - dataframe["bb_lowerband"]) / (
dataframe["bb_upperband"] - dataframe["bb_lowerband"]
)
dataframe["bb_width"] = (dataframe["bb_upperband"] - dataframe["bb_lowerband"]) / dataframe[
"bb_middleband"
]
# TEMA
dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9)
return dataframe
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
df.loc[
(
(qtpylib.crossed_above(df["rsi"], self.buy_rsi.value))
& (df["tema"] <= df["bb_middleband"])
& (df["tema"] > df["tema"].shift(1))
& (df["volume"] > 0)
),
"enter_long",
] = 1
return df
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
df.loc[
(
(qtpylib.crossed_above(df["rsi"], self.sell_rsi.value))
& (df["tema"] > df["bb_middleband"])
& (df["tema"] < df["tema"].shift(1))
& (df["volume"] > 0)
),
"exit_long",
] = 1
return df

View File

@ -1,32 +0,0 @@
{
"strategy_name": "FreqaiExampleStrategy",
"params": {
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.01,
"trailing_stop_positive_offset": 0.02,
"trailing_only_offset_is_reached": false
},
"max_open_trades": {
"max_open_trades": 4
},
"buy": {
"buy_rsi": 39.92672300850069
},
"sell": {
"sell_rsi": 69.92672300850067
},
"protection": {},
"roi": {
"0": 0.132,
"8": 0.047,
"14": 0.007,
"60": 0
},
"stoploss": {
"stoploss": -0.322
}
},
"ft_stratparam_v": 1,
"export_time": "2025-04-23 12:30:05.550433+00:00"
}

View File

@ -30,23 +30,34 @@ class FreqaiExampleStrategy(IStrategy):
# FreqAI 配置
freqai_info = {
"model": "LightGBMRegressor",
"model": "XGBoostRegressor", # 与config保持一致
"feature_parameters": {
"include_timeframes": ["5m", "15m", "1h"],
"include_corr_pairlist": [],
"label_period_candles": 12,
"include_shifted_candles": 3,
"include_timeframes": ["3m", "15m", "1h"], # 与config一致
"include_corr_pairlist": ["BTC/USDT", "SOL/USDT"], # 添加相关交易对
"label_period_candles": 20, # 与config一致
"include_shifted_candles": 2, # 与config一致
},
"data_split_parameters": {
"test_size": 0.2,
"shuffle": False,
"shuffle": True, # 启用shuffle
},
"model_training_parameters": {
"n_estimators": 100,
"learning_rate": 0.1,
"num_leaves": 31,
"verbose": -1,
"n_estimators": 100, # 减少树的数量
"learning_rate": 0.1, # 提高学习率
"max_depth": 6, # 限制树深度
"subsample": 0.8, # 添加子采样
"colsample_bytree": 0.8, # 添加特征采样
"objective": "reg:squarederror",
"eval_metric": "rmse",
"early_stopping_rounds": 20,
"verbose": 0,
},
"data_kitchen": {
"feature_parameters": {
"DI_threshold": 1.5, # 降低异常值过滤阈值
"use_DBSCAN_to_remove_outliers": False # 禁用DBSCAN
}
}
}
plot_config = {
@ -61,42 +72,77 @@ class FreqaiExampleStrategy(IStrategy):
}
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=period, stds=2.2)
dataframe["bb_lowerband-period"] = bollinger["lower"]
dataframe["bb_middleband-period"] = bollinger["mid"]
dataframe["bb_upperband-period"] = bollinger["upper"]
dataframe["%-bb_width-period"] = (
dataframe["bb_upperband-period"] - dataframe["bb_lowerband-period"]
) / dataframe["bb_middleband-period"]
dataframe["%-close-bb_lower-period"] = dataframe["close"] / dataframe["bb_lowerband-period"]
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
dataframe["%-relative_volume-period"] = (
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
# 确保基础价格数据存在
if "close" not in dataframe.columns:
raise ValueError("Dataframe must contain 'close' column")
# 计算技术指标
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
dataframe["sma_short"] = ta.SMA(dataframe, timeperiod=12)
dataframe["sma_long"] = ta.SMA(dataframe, timeperiod=26)
dataframe["sma_cross"] = np.where(dataframe["sma_short"] > dataframe["sma_long"], 1, -1)
# 布林带
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe["bb_lowerband"] = bollinger["lower"]
dataframe["bb_middleband"] = bollinger["mid"]
dataframe["bb_upperband"] = bollinger["upper"]
dataframe["bb_pct"] = (dataframe["close"] - dataframe["bb_lowerband"]) / (
dataframe["bb_upperband"] - dataframe["bb_lowerband"]
)
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.ffill(inplace=True)
dataframe.fillna(0, inplace=True)
# 成交量特征
dataframe["volume_ma"] = dataframe["volume"].rolling(window=20).mean()
dataframe["volume_pct"] = dataframe["volume"] / dataframe["volume_ma"]
# 价格变化特征
dataframe["pct_change"] = dataframe["close"].pct_change()
dataframe["pct_change_5"] = dataframe["close"].pct_change(5)
dataframe["pct_change_10"] = dataframe["close"].pct_change(10)
# 动量指标
dataframe["momentum"] = dataframe["close"] / dataframe["close"].shift(4) - 1
dataframe["roc"] = ta.ROC(dataframe, timeperiod=10)
# 波动率
dataframe["volatility"] = dataframe["close"].pct_change().rolling(window=20).std()
# 数据清理
for col in dataframe.columns:
if dataframe[col].dtype in ["float64", "int64"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill().fillna(0)
# 确保至少有一个特征
if len(dataframe.columns) == 0:
raise ValueError("No features generated in feature engineering")
logger.info(f"特征工程完成,生成特征数量:{len(dataframe.columns)}")
logger.debug(f"特征列表:{list(dataframe.columns)}")
return dataframe
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.fillna(method='ffill', inplace=True)
dataframe.fillna(0, inplace=True)
# 数据清理逻辑
for col in dataframe.columns:
if dataframe[col].dtype in ["float64", "int64"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
dataframe[col] = dataframe[col].ffill()
dataframe[col] = dataframe[col].fillna(0)
# 检查是否仍有无效值
if dataframe[col].isna().any() or np.isinf(dataframe[col]).any():
logger.warning(f"{col} 仍包含无效值,已填充为默认值")
dataframe[col] = dataframe[col].fillna(0)
return dataframe
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.fillna(method='ffill', inplace=True)
dataframe.ffill(inplace=True)
dataframe.fillna(0, inplace=True)
return dataframe
@ -105,27 +151,51 @@ class FreqaiExampleStrategy(IStrategy):
if "close" not in dataframe.columns:
logger.error("数据框缺少必要的 'close'")
raise ValueError("数据框缺少必要的 'close'")
try:
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
# 生成 %-volatility 特征
# 定义目标变量为未来价格变化百分比(连续值)
dataframe["target"] = (
dataframe["close"].shift(-label_period) - dataframe["close"]
) / dataframe["close"]
# 添加辅助目标变量
dataframe["target_5"] = (
dataframe["close"].shift(-5) - dataframe["close"]
) / dataframe["close"]
dataframe["target_10"] = (
dataframe["close"].shift(-10) - dataframe["close"]
) / dataframe["close"]
# 数据清理:处理 NaN 和 Inf 值
for col in ["target", "target_5", "target_10"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill().fillna(0)
# 确保目标变量是二维数组
if dataframe["target"].ndim == 1:
dataframe["target"] = dataframe["target"].values.reshape(-1, 1)
# 生成波动率特征
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
# 单一回归目标
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14).shift(-label_period)
# 数据清理
for col in ["&-buy_rsi", "%-volatility"]:
dataframe[col].replace([np.inf, -np.inf], 0, inplace=True)
dataframe[col].fillna(method='ffill', inplace=True)
dataframe[col].fillna(0, inplace=True)
for col in ["target", "target_5", "target_10", "%-volatility"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill()
dataframe[col] = dataframe[col].fillna(dataframe[col].mean())
if dataframe[col].isna().any():
logger.warning(f"目标列 {col} 仍包含 NaN检查数据生成逻辑")
logger.warning(f"目标列 {col} 仍包含 NaN填充为默认值")
except Exception as e:
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
raise
logger.info(f"目标列预览:\n{dataframe[['&-buy_rsi']].head().to_string()}")
# Log the shape of the target variable for debugging
logger.info(f"目标列形状:{dataframe['target'].shape}")
logger.info(f"目标列预览:\n{dataframe[['target', 'target_5', 'target_10']].head().to_string()}")
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
@ -142,6 +212,8 @@ class FreqaiExampleStrategy(IStrategy):
# 生成 up_or_down 信号(非 FreqAI 目标)
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
# 使用未来价格变化方向生成 up_or_down 信号
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
dataframe["up_or_down"] = np.where(
dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0
)
@ -151,55 +223,64 @@ class FreqaiExampleStrategy(IStrategy):
# 派生其他目标
dataframe["&-sell_rsi"] = dataframe["&-buy_rsi"] + 30
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
dataframe["&-stoploss"] = -0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)
dataframe["&-roi_0"] = (dataframe["close"].shift(-label_period) / dataframe["close"] - 1).clip(0, 0.2)
# Ensure proper calculation and handle potential NaN values
dataframe["&-stoploss"] = (-0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)).fillna(-0.1)
dataframe["&-roi_0"] = ((dataframe["close"] / dataframe["close"].shift(label_period) - 1).clip(0, 0.2)).fillna(0)
# Additional check to ensure no NaN values remain
for col in ["&-stoploss", "&-roi_0"]:
if dataframe[col].isna().any():
logger.warning(f"{col} 仍包含 NaN填充为默认值")
dataframe[col] = dataframe[col].fillna(-0.1 if col == "&-stoploss" else 0)
# 限制预测值,添加平滑
dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(5).mean().clip(10, 50)
dataframe["buy_rsi_pred"].fillna(dataframe["buy_rsi_pred"].mean(), inplace=True)
if dataframe["buy_rsi_pred"].isna().any():
logger.warning("buy_rsi_pred 列包含 NaN已填充为默认值")
dataframe["sell_rsi_pred"] = dataframe["&-sell_rsi"].rolling(5).mean().clip(50, 90)
dataframe["sell_rsi_pred"].fillna(dataframe["sell_rsi_pred"].mean(), inplace=True)
if dataframe["sell_rsi_pred"].isna().any():
logger.warning("sell_rsi_pred 列包含 NaN已填充为默认值")
dataframe["stoploss_pred"] = dataframe["&-stoploss"].clip(-0.35, -0.1)
dataframe["stoploss_pred"].fillna(dataframe["stoploss_pred"].mean(), inplace=True)
if dataframe["stoploss_pred"].isna().any():
logger.warning("stoploss_pred 列包含 NaN已填充为默认值")
# 简化动态参数生成逻辑
# 放松 buy_rsi 和 sell_rsi 的生成逻辑
# 计算 buy_rsi_pred 并清理 NaN 值
dataframe["buy_rsi_pred"] = dataframe["rsi"].rolling(window=10).mean().clip(30, 50)
dataframe["buy_rsi_pred"] = dataframe["buy_rsi_pred"].fillna(dataframe["buy_rsi_pred"].median())
# 计算 sell_rsi_pred 并清理 NaN 值
dataframe["sell_rsi_pred"] = dataframe["buy_rsi_pred"] + 20
dataframe["sell_rsi_pred"] = dataframe["sell_rsi_pred"].fillna(dataframe["sell_rsi_pred"].median())
# 计算 stoploss_pred 并清理 NaN 值
dataframe["stoploss_pred"] = -0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)
dataframe["stoploss_pred"] = dataframe["stoploss_pred"].fillna(dataframe["stoploss_pred"].mean())
# 计算 roi_0_pred 并清理 NaN 值
dataframe["roi_0_pred"] = dataframe["&-roi_0"].clip(0.01, 0.2)
dataframe["roi_0_pred"].fillna(dataframe["roi_0_pred"].mean(), inplace=True)
if dataframe["roi_0_pred"].isna().any():
logger.warning("roi_0_pred 列包含 NaN已填充为默认值")
dataframe["roi_0_pred"] = dataframe["roi_0_pred"].fillna(dataframe["roi_0_pred"].mean())
# 检查预测值
for col in ["buy_rsi_pred", "sell_rsi_pred", "stoploss_pred", "roi_0_pred", "&-sell_rsi", "&-stoploss", "&-roi_0"]:
if dataframe[col].isna().any():
logger.warning(f"{col} 包含 NaN填充为默认值")
dataframe[col].fillna(dataframe[col].mean(), inplace=True)
dataframe[col] = dataframe[col].fillna(dataframe[col].mean())
# 动态追踪止盈
dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3)
dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.75).clip(0.02, 0.4)
# 更保守的止损和止盈设置
dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.3).clip(0.01, 0.2)
dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3)
# 设置策略级参数
self.buy_rsi.value = float(dataframe["buy_rsi_pred"].iloc[-1])
self.sell_rsi.value = float(dataframe["sell_rsi_pred"].iloc[-1])
self.stoploss = float(self.stoploss_param.value)
# 更保守的止损设置
self.stoploss = -0.15 # 固定止损 15%
self.minimal_roi = {
0: float(self.roi_0.value),
15: float(self.roi_15.value),
30: float(self.roi_30.value),
60: 0
}
self.trailing_stop_positive = float(dataframe["trailing_stop_positive"].iloc[-1])
self.trailing_stop_positive_offset = float(dataframe["trailing_stop_positive_offset"].iloc[-1])
# 更保守的追踪止损设置
self.trailing_stop_positive = 0.05 # 追踪止损触发点
self.trailing_stop_positive_offset = 0.1 # 追踪止损偏移量
logger.info(f"动态参数buy_rsi={self.buy_rsi.value}, sell_rsi={self.sell_rsi.value}, "
f"stoploss={self.stoploss}, trailing_stop_positive={self.trailing_stop_positive}")
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.fillna(method='ffill', inplace=True)
dataframe.ffill(inplace=True)
dataframe.fillna(0, inplace=True)
logger.info(f"up_or_down 值统计:\n{dataframe['up_or_down'].value_counts().to_string()}")
@ -207,28 +288,13 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
enter_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]),
df["tema"] > df["tema"].shift(1),
df["volume"] > 0,
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")
return df
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
# 改进卖出信号条件
exit_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"]),
(df["close"] < df["close"].shift(1) * 0.97),
df["volume"] > 0,
df["do_predict"] == 1,
df["up_or_down"] == 0
(df["rsi"] > df["sell_rsi_pred"]), # RSI 高于卖出阈值
(df["volume"] > df["volume"].rolling(window=10).mean()), # 成交量高于近期均值
(df["close"] < df["bb_middleband"]), # 价格低于布林带中轨
(df["sma_short"] < df["sma_long"]) # SMA 死叉(短期 SMA 下穿长期 SMA
]
if exit_long_conditions:
df.loc[
@ -236,7 +302,29 @@ class FreqaiExampleStrategy(IStrategy):
"exit_long"
] = 1
return df
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
# 改进买入信号条件
# 计算短期和长期 SMA
df["sma_short"] = ta.SMA(df, timeperiod=12)
df["sma_long"] = ta.SMA(df, timeperiod=26)
enter_long_conditions = [
(df["rsi"] < df["buy_rsi_pred"]), # RSI 低于买入阈值
(df["volume"] > df["volume"].rolling(window=10).mean() * 1.2), # 成交量高于近期均值20%
(df["close"] > df["bb_middleband"]) # 价格高于布林带中轨
]
# 添加 SMA 金叉条件(短期 SMA 上穿长期 SMA
enter_long_conditions.append((df["sma_short"] > df["sma_long"]))
# 确保模型预测为买入
enter_long_conditions.append((df["do_predict"] == 1))
if enter_long_conditions:
df.loc[
reduce(lambda x, y: x & y, enter_long_conditions),
["enter_long", "enter_tag"]
] = (1, "long")
return df
def confirm_trade_entry(
self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time, entry_tag, side: str, **kwargs

183
freqtrade/templates/aaa.md Normal file
View File

@ -0,0 +1,183 @@
```python
class FreqaiExampleStrategy(IStrategy):
minimal_roi = {}
stoploss = -0.1
trailing_stop = True
process_only_new_candles = True
use_exit_signal = True
startup_candle_count: int = 100 # 增加数据需求
can_short = False
# Hyperopt 参数
buy_rsi = IntParameter(low=10, high=50, default=27, space="buy", optimize=False, load=True)
sell_rsi = IntParameter(low=50, high=90, default=59, space="sell", optimize=False, 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)
roi_30 = DecimalParameter(low=0.001, high=0.05, default=0.009, space="roi", optimize=True, load=True)
stoploss_param = DecimalParameter(low=-0.25, high=-0.05, default=-0.1, space="stoploss", optimize=True, load=True)
# 保护机制
protections = [
{"method": "StoplossGuard", "stop_duration": 60, "lookback_period": 120},
{"method": "MaxDrawdown", "lookback_period": 120, "max_allowed_drawdown": 0.05}
]
# FreqAI 配置
freqai_info = {
"model": "LightGBMRegressor",
"feature_parameters": {
"include_timeframes": ["5m", "15m", "1h"],
"include_corr_pairlist": [],
"label_period_candles": 12,
"include_shifted_candles": 3,
},
"data_split_parameters": {
"test_size": 0.2,
"shuffle": False,
"n_splits": 5 # 添加交叉验证
},
"model_training_parameters": {
"n_estimators": 200,
"learning_rate": 0.05,
"num_leaves": 10,
"min_child_weight": 1,
"verbose": -1,
},
}
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
logger.info(f"设置 FreqAI 目标,交易对:{metadata['pair']}")
if "close" not in dataframe.columns:
logger.error("数据框缺少必要的 'close' 列")
raise ValueError("数据框缺少必要的 'close' 列")
try:
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
dataframe["&-buy_rsi"] = (dataframe["close"].shift(-label_period) / dataframe["close"] - 1) * 100 # 修改目标为收益率
for col in ["&-buy_rsi", "%-volatility"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
dataframe[col] = dataframe[col].ffill()
if dataframe[col].isna().any():
logger.warning(f"目标列 {col} 包含 NaN填充为 0")
dataframe[col] = dataframe[col].fillna(0)
logger.info(f"目标列 {col} 统计:\n{dataframe[col].describe().to_string()}")
except Exception as e:
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
raise
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.info(f"处理交易对:{metadata['pair']}, 数据形状:{dataframe.shape}")
dataframe = self.freqai.start(dataframe, metadata, self)
# 计算传统指标
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe["bb_lowerband"] = bollinger["lower"]
dataframe["bb_middleband"] = bollinger["mid"]
dataframe["bb_upperband"] = bollinger["upper"]
dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9)
# 检查FreqAI预测列
if "&-buy_rsi_pred" in dataframe.columns:
logger.info(f"&-buy_rsi_pred 统计:均值={dataframe['&-buy_rsi_pred'].mean():.2f}, 标准差={dataframe['&-buy_rsi_pred'].std():.2f}")
dataframe["buy_rsi_trend"] = np.where(
dataframe["&-buy_rsi_pred"] > dataframe["&-buy_rsi_pred"].shift(1), 1, 0
)
dataframe["&-sell_rsi_pred"] = dataframe["&-buy_rsi_pred"] + 30
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
dataframe["&-stoploss_pred"] = -0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)
dataframe["&-roi_0_pred"] = (dataframe["&-buy_rsi_pred"] / 1000).clip(0.01, 0.2)
for col in ["&-buy_rsi_pred", "&-sell_rsi_pred", "&-stoploss_pred", "&-roi_0_pred"]:
if dataframe[col].isna().any():
logger.warning(f"列 {col} 包含 NaN填充为默认值")
mean_value = dataframe[col].mean()
if pd.isna(mean_value):
mean_value = {
"&-buy_rsi_pred": 30,
"&-sell_rsi_pred": 70,
"&-stoploss_pred": -0.1,
"&-roi_0_pred": 0.05
}.get(col, 0)
dataframe[col] = dataframe[col].fillna(mean_value)
else:
logger.warning(f"&-buy_rsi_pred 列缺失,使用默认值初始化")
dataframe["buy_rsi_trend"] = 0
dataframe["&-buy_rsi_pred"] = 30
dataframe["&-sell_rsi_pred"] = 70
dataframe["&-stoploss_pred"] = -0.1
dataframe["&-roi_0_pred"] = 0.05
# 动态参数设置
try:
last_valid_idx = dataframe["&-stoploss_pred"].last_valid_index()
if last_valid_idx is None:
raise ValueError("没有有效的预测数据")
self.stoploss = float(np.clip(dataframe["&-stoploss_pred"].iloc[last_valid_idx], -0.25, -0.05))
self.buy_rsi.value = int(np.clip(dataframe["&-buy_rsi_pred"].iloc[last_valid_idx], 10, 50))
self.sell_rsi.value = int(np.clip(dataframe["&-sell_rsi_pred"].iloc[last_valid_idx], 50, 90))
self.roi_0.value = float(np.clip(dataframe["&-roi_0_pred"].iloc[last_valid_idx], 0.01, 0.2))
self.minimal_roi = {
0: self.roi_0.value,
15: self.roi_15.value,
30: self.roi_30.value,
60: 0.0
}
logger.info(f"动态参数设置: buy_rsi={self.buy_rsi.value}, sell_rsi={self.sell_rsi.value}, stoploss={self.stoploss:.2%}")
except Exception as e:
logger.error(f"动态参数设置失败,使用默认值: {str(e)}")
self.stoploss = -0.1
self.buy_rsi.value = 27
self.sell_rsi.value = 59
self.minimal_roi = {0: 0.038, 15: 0.027, 30: 0.009, 60: 0.0}
dataframe = dataframe.replace([np.inf, -np.inf], 0)
dataframe = dataframe.ffill()
dataframe = dataframe.fillna(0)
logger.info(f"do_predict 分布:\n{dataframe['do_predict'].value_counts().to_string()}")
return dataframe
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
enter_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["&-buy_rsi_pred"] - 5), # 放宽RSI条件
df["tema"] > df["tema"].shift(1),
df["volume"] > 0,
df["do_predict"] == 1
]
if enter_long_conditions:
condition_met = reduce(lambda x, y: x & y, enter_long_conditions)
df.loc[condition_met, ["enter_long", "enter_tag"]] = (1, "long")
if condition_met.any():
logger.info(f"买入信号触发:{metadata['pair']},时间={df.index[condition_met][-1]}")
else:
logger.debug(f"买入条件未满足:{metadata['pair']}do_predict={df['do_predict'].iloc[-1]}, rsi={df['rsi'].iloc[-1]:.2f}, buy_rsi_pred={df['&-buy_rsi_pred'].iloc[-1]:.2f}")
return df
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
exit_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["&-sell_rsi_pred"]),
df["close"] < df["bb_lowerband"],
df["volume"] > 0,
df["do_predict"] == 1
]
time_exit = (df["date"] >= df["date"].shift(1) + pd.Timedelta(days=2))
df.loc[
(reduce(lambda x, y: x & y, exit_long_conditions)) | time_exit,
"exit_long"
] = 1
return df
```
```
```
```
```
```
```
```

387
output_filted.log Normal file
View File

@ -0,0 +1,387 @@
Creating freqtrade_freqtrade_run ...
Creating freqtrade_freqtrade_run ... done
2025-04-29 08:31:07,002 - freqtrade - INFO - freqtrade 2025.3
2025-04-29 08:31:07,217 - numexpr.utils - INFO - NumExpr defaulting to 12 threads.
2025-04-29 08:31:08,612 - freqtrade.configuration.load_config - INFO - Using config: /freqtrade/config_examples/config_freqai.okx.json ...
2025-04-29 08:31:08,615 - freqtrade.loggers - INFO - Enabling colorized output.
2025-04-29 08:31:08,615 - root - INFO - Logfile configured
2025-04-29 08:31:08,615 - freqtrade.loggers - INFO - Verbosity set to 0
2025-04-29 08:31:08,616 - freqtrade.configuration.configuration - INFO - Using additional Strategy lookup path: /freqtrade/templates
2025-04-29 08:31:08,616 - freqtrade.configuration.configuration - INFO - Using max_open_trades: 4 ...
2025-04-29 08:31:08,617 - freqtrade.configuration.configuration - INFO - Parameter --timerange detected: 20250401-20250420 ...
2025-04-29 08:31:08,640 - freqtrade.configuration.configuration - INFO - Using user-data directory: /freqtrade/user_data ...
2025-04-29 08:31:08,641 - freqtrade.configuration.configuration - INFO - Using data directory: /freqtrade/user_data/data/okx ...
2025-04-29 08:31:08,641 - freqtrade.configuration.configuration - INFO - Parameter --cache=none detected ...
2025-04-29 08:31:08,642 - freqtrade.configuration.configuration - INFO - Filter trades by timerange: 20250401-20250420
2025-04-29 08:31:08,642 - freqtrade.configuration.configuration - INFO - Using freqaimodel class name: XGBoostRegressor
2025-04-29 08:31:08,643 - freqtrade.exchange.check_exchange - INFO - Checking exchange...
2025-04-29 08:31:08,649 - freqtrade.exchange.check_exchange - INFO - Exchange "okx" is officially supported by the Freqtrade development team.
2025-04-29 08:31:08,649 - freqtrade.configuration.configuration - INFO - Using pairlist from configuration.
2025-04-29 08:31:08,650 - freqtrade.configuration.config_validation - INFO - Validating configuration ...
2025-04-29 08:31:08,652 - freqtrade.commands.optimize_commands - INFO - Starting freqtrade in Backtesting mode
2025-04-29 08:31:08,652 - freqtrade.exchange.exchange - INFO - Instance is running with dry_run enabled
2025-04-29 08:31:08,653 - freqtrade.exchange.exchange - INFO - Using CCXT 4.4.69
2025-04-29 08:31:08,653 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True, 'rateLimit': 500, 'options': {'defaultType': 'spot'}}
2025-04-29 08:31:08,658 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True, 'rateLimit': 500, 'options': {'defaultType': 'spot'}, 'timeout': 20000}
2025-04-29 08:31:08,664 - freqtrade.exchange.exchange - INFO - Using Exchange "OKX"
2025-04-29 08:31:11,241 - freqtrade.resolvers.exchange_resolver - INFO - Using resolved exchange 'Okx'...
2025-04-29 08:31:11,261 - freqtrade.resolvers.iresolver - INFO - Using resolved strategy FreqaiExampleStrategy from '/freqtrade/templates/FreqaiExampleStrategy.py'...
2025-04-29 08:31:11,262 - freqtrade.strategy.hyper - INFO - Loading parameters from file /freqtrade/templates/FreqaiExampleStrategy.json
2025-04-29 08:31:11,263 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'timeframe' with value in config file: 3m.
2025-04-29 08:31:11,263 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'stoploss' with value in config file: -0.05.
2025-04-29 08:31:11,264 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'stake_currency' with value in config file: USDT.
2025-04-29 08:31:11,264 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'stake_amount' with value in config file: 150.
2025-04-29 08:31:11,264 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'startup_candle_count' with value in config file: 30.
2025-04-29 08:31:11,265 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'unfilledtimeout' with value in config file: {'entry': 5, 'exit': 15, 'exit_timeout_count': 0, 'unit':
'minutes'}.
2025-04-29 08:31:11,265 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'max_open_trades' with value in config file: 4.
2025-04-29 08:31:11,266 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using minimal_roi: {'0': 0.132, '8': 0.047, '14': 0.007, '60': 0}
2025-04-29 08:31:11,266 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using timeframe: 3m
2025-04-29 08:31:11,266 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using stoploss: -0.05
2025-04-29 08:31:11,267 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_stop: True
2025-04-29 08:31:11,267 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_stop_positive: 0.01
2025-04-29 08:31:11,267 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_stop_positive_offset: 0.02
2025-04-29 08:31:11,268 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_only_offset_is_reached: False
2025-04-29 08:31:11,268 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using use_custom_stoploss: False
2025-04-29 08:31:11,268 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using process_only_new_candles: True
2025-04-29 08:31:11,269 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using order_types: {'entry': 'limit', 'exit': 'limit', 'stoploss': 'limit', 'stoploss_on_exchange': False,
'stoploss_on_exchange_interval': 60}
2025-04-29 08:31:11,269 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using order_time_in_force: {'entry': 'GTC', 'exit': 'GTC'}
2025-04-29 08:31:11,269 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using stake_currency: USDT
2025-04-29 08:31:11,270 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using stake_amount: 150
2025-04-29 08:31:11,270 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using startup_candle_count: 30
2025-04-29 08:31:11,270 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using unfilledtimeout: {'entry': 5, 'exit': 15, 'exit_timeout_count': 0, 'unit': 'minutes'}
2025-04-29 08:31:11,271 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using use_exit_signal: True
2025-04-29 08:31:11,271 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using exit_profit_only: False
2025-04-29 08:31:11,272 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using ignore_roi_if_entry_signal: False
2025-04-29 08:31:11,272 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using exit_profit_offset: 0.0
2025-04-29 08:31:11,272 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using disable_dataframe_checks: False
2025-04-29 08:31:11,272 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using ignore_buying_expired_candle_after: 0
2025-04-29 08:31:11,273 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using position_adjustment_enable: False
2025-04-29 08:31:11,273 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using max_entry_position_adjustment: -1
2025-04-29 08:31:11,273 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using max_open_trades: 4
2025-04-29 08:31:11,273 - freqtrade.configuration.config_validation - INFO - Validating configuration ...
2025-04-29 08:31:11,277 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist StaticPairList from '/freqtrade/freqtrade/plugins/pairlist/StaticPairList.py'...
2025-04-29 08:31:11,283 - freqtrade.optimize.backtesting - INFO - Using fee 0.1500% - worst case fee from exchange (lowest tier).
2025-04-29 08:31:11,284 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 3m to 14450
2025-04-29 08:31:11,284 - freqtrade.data.history.history_utils - INFO - Using indicator startup period: 14450 ...
2025-04-29 08:31:11,413 - freqtrade.optimize.backtesting - INFO - Loading data from 2025-03-01 21:30:00 up to 2025-04-20 00:00:00 (49 days).
2025-04-29 08:31:11,414 - freqtrade.optimize.backtesting - INFO - Dataload complete. Calculating indicators
2025-04-29 08:31:11,415 - freqtrade.optimize.backtesting - INFO - Running backtesting for Strategy FreqaiExampleStrategy
2025-04-29 08:31:12,973 - matplotlib.font_manager - INFO - generated new fontManager
2025-04-29 08:31:13,178 - freqtrade.resolvers.iresolver - INFO - Using resolved freqaimodel XGBoostRegressor from '/freqtrade/freqtrade/freqai/prediction_models/XGBoostRegressor.py'...
2025-04-29 08:31:13,178 - freqtrade.freqai.data_drawer - INFO - Could not find existing datadrawer, starting from scratch
2025-04-29 08:31:13,178 - freqtrade.freqai.data_drawer - INFO - Could not find existing historic_predictions, starting from scratch
2025-04-29 08:31:13,179 - freqtrade.freqai.freqai_interface - INFO - Set fresh train queue from whitelist. Queue: ['BTC/USDT', 'SOL/USDT']
2025-04-29 08:31:13,179 - freqtrade.strategy.hyper - INFO - Strategy Parameter: buy_rsi = 39.92672300850069
2025-04-29 08:31:13,180 - freqtrade.strategy.hyper - INFO - Strategy Parameter: sell_rsi = 69.92672300850067
2025-04-29 08:31:13,180 - freqtrade.strategy.hyper - INFO - No params for protection found, using default values.
2025-04-29 08:31:13,183 - FreqaiExampleStrategy - INFO - 处理交易对BTC/USDT
2025-04-29 08:31:13,184 - freqtrade.freqai.freqai_interface - INFO - Training 2 timeranges
2025-04-29 08:31:13,186 - freqtrade.freqai.freqai_interface - INFO - Training BTC/USDT, 1/2 pairs from 2025-03-02 00:00:00 to 2025-04-01 00:00:00, 1/2 trains
2025-04-29 08:31:13,186 - freqtrade.freqai.data_kitchen - INFO - Could not find backtesting prediction file at
/freqtrade/user_data/models/test175/backtesting_predictions/cb_btc_1743465600_prediction.feather
2025-04-29 08:31:13,221 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 5m to 8690
2025-04-29 08:31:13,222 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 5m from 2025-03-01 19:50:00 to 2025-04-20 00:00:00
2025-04-29 08:31:13,294 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 1h to 770
2025-04-29 08:31:13,295 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 1h from 2025-02-27 22:00:00 to 2025-04-20 00:00:00
2025-04-29 08:31:13,354 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 3m to 14450
2025-04-29 08:31:13,355 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 3m from 2025-03-01 21:30:00 to 2025-04-20 00:00:00
2025-04-29 08:31:13,449 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 5m to 8690
2025-04-29 08:31:13,449 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 5m from 2025-03-01 19:50:00 to 2025-04-20 00:00:00
2025-04-29 08:31:13,521 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 1h to 770
2025-04-29 08:31:13,522 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 1h from 2025-02-27 22:00:00 to 2025-04-20 00:00:00
2025-04-29 08:31:13,571 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对BTC/USDT
2025-04-29 08:31:13,576 - FreqaiExampleStrategy - INFO - 目标列形状(14450,)
2025-04-29 08:31:13,579 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.007116 50.010488
1 0.005291 50.010488
2 0.004416 50.010488
3 0.002082 50.010488
4 0.001904 50.010488
2025-04-29 08:31:13,584 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对BTC/USDT
2025-04-29 08:31:13,590 - FreqaiExampleStrategy - INFO - 目标列形状(19250,)
2025-04-29 08:31:13,592 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.007116 49.846666
1 0.005291 49.846666
2 0.004416 49.846666
3 0.002082 49.846666
4 0.001904 49.846666
2025-04-29 08:31:13,600 - freqtrade.freqai.freqai_interface - INFO - Could not find model at /freqtrade/user_data/models/test175/sub-train-BTC_1743465600/cb_btc_1743465600
2025-04-29 08:31:13,600 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Starting training BTC/USDT --------------------
2025-04-29 08:31:13,622 - freqtrade.freqai.data_kitchen - INFO - BTC/USDT: dropped 0 training points due to NaNs in populated dataset 14400.
2025-04-29 08:31:13,623 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Training on data from 2025-03-02 to 2025-03-31 --------------------
2025-04-29 08:31:13,641 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 75 features
2025-04-29 08:31:13,642 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 11520 data points
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning: [08:31:13] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
warnings.warn(smsg, UserWarning)
[99] validation_0-rmse:0.13679 validation_1-rmse:0.11901
2025-04-29 08:31:15,185 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Done training BTC/USDT (1.58 secs) --------------------
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:15] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
2025-04-29 08:31:15,422 - freqtrade.plot.plotting - INFO - Stored plot as /freqtrade/user_data/models/test175/sub-train-BTC_1743465600/cb_btc_1743465600--buy_rsi.html
2025-04-29 08:31:15,423 - freqtrade.freqai.freqai_interface - INFO - Saving metadata to disk.
2025-04-29 08:31:15,442 - datasieve.pipeline - WARNING - Could not find step di in pipeline, returning None
2025-04-29 08:31:15,449 - freqtrade.freqai.freqai_interface - INFO - Training BTC/USDT, 1/2 pairs from 2025-03-12 00:00:00 to 2025-04-11 00:00:00, 2/2 trains
2025-04-29 08:31:15,449 - freqtrade.freqai.data_kitchen - INFO - Could not find backtesting prediction file at
/freqtrade/user_data/models/test175/backtesting_predictions/cb_btc_1744329600_prediction.feather
2025-04-29 08:31:15,453 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对BTC/USDT
2025-04-29 08:31:15,458 - FreqaiExampleStrategy - INFO - 目标列形状(19250,)
2025-04-29 08:31:15,459 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.007116 49.846666
1 0.005291 49.846666
2 0.004416 49.846666
3 0.002082 49.846666
4 0.001904 49.846666
2025-04-29 08:31:15,464 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对BTC/USDT
2025-04-29 08:31:15,469 - FreqaiExampleStrategy - INFO - 目标列形状(23570,)
2025-04-29 08:31:15,471 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.007116 50.074781
1 0.005291 50.074781
2 0.004416 50.074781
3 0.002082 50.074781
4 0.001904 50.074781
2025-04-29 08:31:15,476 - freqtrade.freqai.freqai_interface - INFO - Could not find model at /freqtrade/user_data/models/test175/sub-train-BTC_1744329600/cb_btc_1744329600
2025-04-29 08:31:15,476 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Starting training BTC/USDT --------------------
2025-04-29 08:31:15,494 - freqtrade.freqai.data_kitchen - INFO - BTC/USDT: dropped 0 training points due to NaNs in populated dataset 14400.
2025-04-29 08:31:15,495 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Training on data from 2025-03-12 to 2025-04-10 --------------------
2025-04-29 08:31:15,509 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 75 features
2025-04-29 08:31:15,510 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 11520 data points
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:15] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
[99] validation_0-rmse:0.13376 validation_1-rmse:0.11638
2025-04-29 08:31:17,083 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Done training BTC/USDT (1.61 secs) --------------------
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:17] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
2025-04-29 08:31:17,121 - freqtrade.plot.plotting - INFO - Stored plot as /freqtrade/user_data/models/test175/sub-train-BTC_1744329600/cb_btc_1744329600--buy_rsi.html
2025-04-29 08:31:17,122 - freqtrade.freqai.freqai_interface - INFO - Saving metadata to disk.
2025-04-29 08:31:17,144 - datasieve.pipeline - WARNING - Could not find step di in pipeline, returning None
2025-04-29 08:31:17,182 - FreqaiExampleStrategy - INFO - 动态参数buy_rsi=39.26145316407591, sell_rsi=59.26145316407591, stoploss=-0.15, trailing_stop_positive=0.05
2025-04-29 08:31:17,189 - FreqaiExampleStrategy - INFO - up_or_down 值统计:
up_or_down
1 11845
0 11726
2025-04-29 08:31:17,190 - FreqaiExampleStrategy - INFO - do_predict 值统计:
do_predict
0.0 14451
1.0 9120
2025-04-29 08:31:17,192 - FreqaiExampleStrategy - INFO - 处理交易对SOL/USDT
2025-04-29 08:31:17,193 - freqtrade.freqai.freqai_interface - INFO - Training 2 timeranges
2025-04-29 08:31:17,194 - freqtrade.freqai.freqai_interface - INFO - Training SOL/USDT, 2/2 pairs from 2025-03-02 00:00:00 to 2025-04-01 00:00:00, 1/2 trains
2025-04-29 08:31:17,195 - freqtrade.freqai.data_kitchen - INFO - Could not find backtesting prediction file at
/freqtrade/user_data/models/test175/backtesting_predictions/cb_sol_1743465600_prediction.feather
2025-04-29 08:31:17,217 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 5m to 8690
2025-04-29 08:31:17,217 - freqtrade.data.dataprovider - INFO - Loading data for SOL/USDT 5m from 2025-03-01 19:50:00 to 2025-04-20 00:00:00
2025-04-29 08:31:17,281 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 1h to 770
2025-04-29 08:31:17,282 - freqtrade.data.dataprovider - INFO - Loading data for SOL/USDT 1h from 2025-02-27 22:00:00 to 2025-04-20 00:00:00
2025-04-29 08:31:17,329 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 3m to 14450
2025-04-29 08:31:17,329 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 3m from 2025-03-01 21:30:00 to 2025-04-20 00:00:00
2025-04-29 08:31:17,591 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对SOL/USDT
2025-04-29 08:31:17,596 - FreqaiExampleStrategy - INFO - 目标列形状(14450,)
2025-04-29 08:31:17,597 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.016595 49.72136
1 0.012811 49.72136
2 0.010135 49.72136
3 0.008514 49.72136
4 0.006242 49.72136
2025-04-29 08:31:17,602 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对SOL/USDT
2025-04-29 08:31:17,608 - FreqaiExampleStrategy - INFO - 目标列形状(19250,)
2025-04-29 08:31:17,609 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.016595 49.562407
1 0.012811 49.562407
2 0.010135 49.562407
3 0.008514 49.562407
4 0.006242 49.562407
2025-04-29 08:31:17,615 - freqtrade.freqai.freqai_interface - INFO - Could not find model at /freqtrade/user_data/models/test175/sub-train-SOL_1743465600/cb_sol_1743465600
2025-04-29 08:31:17,616 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Starting training SOL/USDT --------------------
2025-04-29 08:31:17,644 - freqtrade.freqai.data_kitchen - INFO - SOL/USDT: dropped 0 training points due to NaNs in populated dataset 14400.
2025-04-29 08:31:17,645 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Training on data from 2025-03-02 to 2025-03-31 --------------------
2025-04-29 08:31:17,667 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 111 features
2025-04-29 08:31:17,668 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 11520 data points
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:17] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
[99] validation_0-rmse:0.11848 validation_1-rmse:0.10165
2025-04-29 08:31:20,071 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Done training SOL/USDT (2.46 secs) --------------------
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:20] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
2025-04-29 08:31:20,104 - freqtrade.plot.plotting - INFO - Stored plot as /freqtrade/user_data/models/test175/sub-train-SOL_1743465600/cb_sol_1743465600--buy_rsi.html
2025-04-29 08:31:20,105 - freqtrade.freqai.freqai_interface - INFO - Saving metadata to disk.
2025-04-29 08:31:20,136 - datasieve.pipeline - WARNING - Could not find step di in pipeline, returning None
2025-04-29 08:31:20,143 - freqtrade.freqai.freqai_interface - INFO - Training SOL/USDT, 2/2 pairs from 2025-03-12 00:00:00 to 2025-04-11 00:00:00, 2/2 trains
2025-04-29 08:31:20,144 - freqtrade.freqai.data_kitchen - INFO - Could not find backtesting prediction file at
/freqtrade/user_data/models/test175/backtesting_predictions/cb_sol_1744329600_prediction.feather
2025-04-29 08:31:20,148 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对SOL/USDT
2025-04-29 08:31:20,154 - FreqaiExampleStrategy - INFO - 目标列形状(19250,)
2025-04-29 08:31:20,156 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.016595 49.562407
1 0.012811 49.562407
2 0.010135 49.562407
3 0.008514 49.562407
4 0.006242 49.562407
2025-04-29 08:31:20,160 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对SOL/USDT
2025-04-29 08:31:20,166 - FreqaiExampleStrategy - INFO - 目标列形状(23570,)
2025-04-29 08:31:20,167 - FreqaiExampleStrategy - INFO - 目标列预览
up_or_down &-buy_rsi
0 0.016595 49.934347
1 0.012811 49.934347
2 0.010135 49.934347
3 0.008514 49.934347
4 0.006242 49.934347
2025-04-29 08:31:20,172 - freqtrade.freqai.freqai_interface - INFO - Could not find model at /freqtrade/user_data/models/test175/sub-train-SOL_1744329600/cb_sol_1744329600
2025-04-29 08:31:20,173 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Starting training SOL/USDT --------------------
2025-04-29 08:31:20,197 - freqtrade.freqai.data_kitchen - INFO - SOL/USDT: dropped 0 training points due to NaNs in populated dataset 14400.
2025-04-29 08:31:20,197 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Training on data from 2025-03-12 to 2025-04-10 --------------------
2025-04-29 08:31:20,219 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 111 features
2025-04-29 08:31:20,220 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 11520 data points
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:20] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
[99] validation_0-rmse:0.12679 validation_1-rmse:0.11178
2025-04-29 08:31:22,488 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Done training SOL/USDT (2.31 secs) --------------------
/home/ftuser/.local/lib/python3.12/site-packages/xgboost/core.py:158: UserWarning:
[08:31:22] WARNING: /workspace/src/learner.cc:740:
Parameters: { "verbose" } are not used.
2025-04-29 08:31:22,529 - freqtrade.plot.plotting - INFO - Stored plot as /freqtrade/user_data/models/test175/sub-train-SOL_1744329600/cb_sol_1744329600--buy_rsi.html
2025-04-29 08:31:22,530 - freqtrade.freqai.freqai_interface - INFO - Saving metadata to disk.
2025-04-29 08:31:22,557 - datasieve.pipeline - WARNING - Could not find step di in pipeline, returning None
2025-04-29 08:31:22,599 - FreqaiExampleStrategy - INFO - 动态参数buy_rsi=50.0, sell_rsi=70.0, stoploss=-0.15, trailing_stop_positive=0.05
2025-04-29 08:31:22,606 - FreqaiExampleStrategy - INFO - up_or_down 值统计:
up_or_down
0 11865
1 11706
2025-04-29 08:31:22,607 - FreqaiExampleStrategy - INFO - do_predict 值统计:
do_predict
0.0 14451
1.0 9120
2025-04-29 08:31:22,610 - freqtrade.optimize.backtesting - INFO - Backtesting with data from 2025-04-01 00:00:00 up to 2025-04-20 00:00:00 (19 days).
2025-04-29 08:31:23,193 - freqtrade.misc - INFO - dumping json to "/freqtrade/user_data/backtest_results/backtest-result-2025-04-29_08-31-23.meta.json"
Result for strategy FreqaiExampleStrategy
 BACKTESTING REPORT 
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
  Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃  Win Draw Loss Win% ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ BTC/USDT │ 15 │ 0.04 │ 0.801 │ 0.08 │ 12:58:00 │ 2 13 0 100 │
│ SOL/USDT │ 13 │ -0.9 │ -17.573 │ -1.76 │ 8:54:00 │ 5 7 1 38.5 │
│ TOTAL │ 28 │ -0.4 │ -16.773 │ -1.68 │ 11:05:00 │ 7 20 1 25.0 │
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
 LEFT OPEN TRADES REPORT 
┏━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
  Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃  Win Draw Loss Win% ┃
┡━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ TOTAL │ 0 │ 0.0 │ 0.000 │ 0.0 │ 0:00 │ 0 0 0 0 │
└───────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
 ENTER TAG STATS 
┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
 Enter Tag ┃ Entries ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃  Win Draw Loss Win% ┃
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ long │ 28 │ -0.4 │ -16.773 │ -1.68 │ 11:05:00 │ 7 20 1 25.0 │
│ TOTAL │ 28 │ -0.4 │ -16.773 │ -1.68 │ 11:05:00 │ 7 20 1 25.0 │
└───────────┴─────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
 EXIT REASON STATS 
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
  Exit Reason ┃ Exits ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃  Avg Duration ┃  Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ roi │ 27 │ 0.14 │ 5.757 │ 0.58 │ 9:48:00 │ 7 20 0 100 │
│ trailing_stop_loss │ 1 │ -15.0 │ -22.529 │ -2.25 │ 1 day, 21:45:00 │ 0 0 1 0 │
│ TOTAL │ 28 │ -0.4 │ -16.773 │ -1.68 │ 11:05:00 │ 7 20 1 25.0 │
└────────────────────┴───────┴──────────────┴─────────────────┴──────────────┴─────────────────┴────────────────────────┘
 MIXED TAG STATS 
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
  Enter Tag ┃ Exit Reason ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃  Avg Duration ┃  Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ ('long', 'roi') │ │ 27 │ 0.14 │ 5.757 │ 0.58 │ 9:48:00 │ 7 20 0 100 │
│ ('long', 'trailing_stop_loss') │ │ 1 │ -15.0 │ -22.529 │ -2.25 │ 1 day, 21:45:00 │ 0 0 1 0 │
│ TOTAL │ │ 28 │ -0.4 │ -16.773 │ -1.68 │ 11:05:00 │ 7 20 1 25.0 │
└────────────────────────────────┴─────────────┴────────┴──────────────┴─────────────────┴──────────────┴─────────────────┴────────────────────────┘
 SUMMARY METRICS 
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
 Metric  ┃ Value  ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ Backtesting from │ 2025-04-01 00:00:00 │
│ Backtesting to │ 2025-04-20 00:00:00 │
│ Trading Mode │ Spot │
│ Max open trades │ 2 │
│ │ │
│ Total/Daily Avg Trades │ 28 / 1.47 │
│ Starting balance │ 1000 USDT │
│ Final balance │ 983.227 USDT │
│ Absolute profit │ -16.773 USDT │
│ Total profit % │ -1.68% │
│ CAGR % │ -27.74% │
│ Sortino │ -100.00 │
│ Sharpe │ -3.97 │
│ Calmar │ -74.86 │
│ SQN │ -0.73 │
│ Profit factor │ 0.26 │
│ Expectancy (Ratio) │ -0.60 (-0.74) │
│ Avg. daily profit % │ -0.09% │
│ Avg. stake amount │ 150 USDT │
│ Total trade volume │ 8408.398 USDT │
│ │ │
│ Best Pair │ BTC/USDT 0.08% │
│ Worst Pair │ SOL/USDT -1.76% │
│ Best trade │ SOL/USDT 1.41% │
│ Worst trade │ SOL/USDT -15.00% │
│ Best day │ 2.151 USDT │
│ Worst day │ -22.529 USDT │
│ Days win/draw/lose │ 4 / 13 / 1 │
│ Avg. Duration Winners │ 0:51:00 │
│ Avg. Duration Loser │ 1 day, 21:45:00 │
│ Max Consecutive Wins / Loss │ 3 / 10 │
│ Rejected Entry signals │ 0 │
│ Entry/Exit Timeouts │ 0 / 0 │
│ │ │
│ Min balance │ 977.471 USDT │
│ Max balance │ 1000 USDT │
│ Max % of account underwater │ 2.25% │
│ Absolute Drawdown (Account) │ 2.25% │
│ Absolute Drawdown │ 22.529 USDT │
│ Drawdown high │ 0 USDT │
│ Drawdown low │ -22.529 USDT │
│ Drawdown Start │ 2025-04-02 08:24:00 │
│ Drawdown End │ 2025-04-06 23:15:00 │
│ Market change │ -0.80% │
└─────────────────────────────┴─────────────────────┘
Backtested 2025-04-01 00:00:00 -> 2025-04-20 00:00:00 | Max open trades : 2
 STRATEGY SUMMARY 
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┓
  Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃  Win Draw Loss Win% ┃  Drawdown ┃
┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━┩
│ FreqaiExampleStrategy │ 28 │ -0.40 │ -16.773 │ -1.68 │ 11:05:00 │ 7 20 1 25.0 │ 22.529 USDT 2.25% │
└───────────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴────────────────────┘

18
utf8.py Normal file
View File

@ -0,0 +1,18 @@
import chardet
import codecs
def convert_encoding(input_file, output_file):
# 检测文件编码
with open(input_file, 'rb') as f:
result = chardet.detect(f.read())
encoding = result['encoding']
# 以检测到的编码读取文件内容并以UTF-8编码写入新文件
with codecs.open(input_file, 'r', encoding=encoding) as infile, \
codecs.open(output_file, 'w', encoding='utf-8') as outfile:
outfile.write(infile.read())
if __name__ == "__main__":
input_file = 'freqtrade.log' # 替换为实际的输入文件名
output_file = 'freqtrade_utf8.log' # 替换为你想要的输出文件名
convert_encoding(input_file, output_file)

233
请啊! Normal file
View File

@ -0,0 +1,233 @@
import logging
import numpy as np
from functools import reduce
import talib.abstract as ta
from pandas import DataFrame
from technical import qtpylib
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
logger = logging.getLogger(__name__)
class FreqaiExampleStrategy(IStrategy):
# 移除硬编码的 minimal_roi 和 stoploss改为动态适配
minimal_roi = {} # 将在 populate_indicators 中动态生成
stoploss = 0.0 # 将在 populate_indicators 中动态设置
trailing_stop = True
process_only_new_candles = True
use_exit_signal = True
startup_candle_count: int = 40
can_short = False
# 参数定义FreqAI 动态适配 buy_rsi 和 sell_rsi禁用 Hyperopt 优化
buy_rsi = IntParameter(low=10, high=50, default=27, space="buy", optimize=False, load=True)
sell_rsi = IntParameter(low=50, high=90, default=59, space="sell", optimize=False, load=True)
# 为 Hyperopt 优化添加 ROI 和 stoploss 参数
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)
roi_30 = DecimalParameter(low=0.001, high=0.05, default=0.009, space="roi", optimize=True, load=True)
stoploss_param = DecimalParameter(low=-0.35, high=-0.1, default=-0.182, space="stoploss", optimize=True, load=True)
# FreqAI 配置
freqai_info = {
"model": "LightGBMRegressor",
"feature_parameters": {
"include_timeframes": ["5m", "15m", "1h"],
"include_corr_pairlist": [],
"label_period_candles": 12,
"include_shifted_candles": 3,
},
"data_split_parameters": {
"test_size": 0.2,
"shuffle": False,
},
"model_training_parameters": {
"n_estimators": 100,
"learning_rate": 0.1,
"num_leaves": 31,
"verbose": -1,
},
}
plot_config = {
"main_plot": {},
"subplots": {
"&-buy_rsi": {"&-buy_rsi": {"color": "green"}},
"&-sell_rsi": {"&-sell_rsi": {"color": "red"}},
"&-stoploss": {"&-stoploss": {"color": "purple"}},
"&-roi_0": {"&-roi_0": {"color": "orange"}},
"do_predict": {"do_predict": {"color": "brown"}},
},
}
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
dataframe["%-mfi-period"] = ta.MFI(dataframe, timeperiod=period)
dataframe["%-sma-period"] = ta.SMA(dataframe, timeperiod=period)
dataframe["%-ema-period"] = ta.EMA(dataframe, timeperiod=period)
dataframe["%-adx-period"] = ta.ADX(dataframe, timeperiod=period)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=period, stds=2.2)
dataframe["bb_lowerband-period"] = bollinger["lower"]
dataframe["bb_middleband-period"] = bollinger["mid"]
dataframe["bb_upperband-period"] = bollinger["upper"]
dataframe["%-bb_width-period"] = (
dataframe["bb_upperband-period"] - dataframe["bb_lowerband-period"]
) / dataframe["bb_middleband-period"]
dataframe["%-close-bb_lower-period"] = dataframe["close"] / dataframe["bb_lowerband-period"]
dataframe["%-roc-period"] = ta.ROC(dataframe, timeperiod=period)
dataframe["%-relative_volume-period"] = (
dataframe["volume"] / dataframe["volume"].rolling(period).mean()
)
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.ffill(inplace=True)
dataframe.fillna(0, inplace=True)
return dataframe
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.fillna(method='ffill', inplace=True)
dataframe.fillna(0, inplace=True)
return dataframe
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.fillna(method='ffill', inplace=True)
dataframe.fillna(0, inplace=True)
return dataframe
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
logger.info(f"设置 FreqAI 目标,交易对:{metadata['pair']}")
if "close" not in dataframe.columns:
logger.error("数据框缺少必要的 'close' 列")
raise ValueError("数据框缺少必要的 'close' 列")
try:
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
# 生成 %-volatility 特征
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
# 单一回归目标
# 移除对未来的数据依赖
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
# 数据清理
for col in ["&-buy_rsi", "%-volatility"]:
dataframe[col].replace([np.inf, -np.inf], 0, inplace=True)
dataframe[col].fillna(method='ffill', inplace=True)
dataframe[col].fillna(0, inplace=True)
if dataframe[col].isna().any():
logger.warning(f"目标列 {col} 仍包含 NaN检查数据生成逻辑")
except Exception as e:
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
raise
logger.info(f"目标列预览:\n{dataframe[['&-buy_rsi']].head().to_string()}")
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.info(f"处理交易对:{metadata['pair']}")
dataframe = self.freqai.start(dataframe, metadata, self)
# 计算传统指标
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe["bb_lowerband"] = bollinger["lower"]
dataframe["bb_middleband"] = bollinger["mid"]
dataframe["bb_upperband"] = bollinger["upper"]
dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9)
# 生成 up_or_down 信号(非 FreqAI 目标)
label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
# 使用历史数据生成 up_or_down 信号
dataframe["up_or_down"] = np.where(
dataframe["close"] > dataframe["close"].shift(1), 1, 0
)
# 动态设置参数
if "&-buy_rsi" in dataframe.columns:
# 派生其他目标
dataframe["&-sell_rsi"] = dataframe["&-buy_rsi"] + 30
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
dataframe["&-stoploss"] = -0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)
dataframe["&-roi_0"] = (dataframe["close"] / dataframe["close"].shift(label_period) - 1).clip(0, 0.2)
# 简化动态参数生成逻辑
dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].clip(10, 50)
dataframe["sell_rsi_pred"] = dataframe["&-buy_rsi"] + 30
dataframe["stoploss_pred"] = -0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)
dataframe["roi_0_pred"] = dataframe["&-roi_0"].clip(0.01, 0.2)
# 检查预测值
for col in ["buy_rsi_pred", "sell_rsi_pred", "stoploss_pred", "roi_0_pred", "&-sell_rsi", "&-stoploss", "&-roi_0"]:
if dataframe[col].isna().any():
logger.warning(f"列 {col} 包含 NaN填充为默认值")
dataframe[col].fillna(dataframe[col].mean(), inplace=True)
# 更保守的止损和止盈设置
dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.3).clip(0.01, 0.2)
dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3)
# 设置策略级参数
self.buy_rsi.value = float(dataframe["buy_rsi_pred"].iloc[-1])
self.sell_rsi.value = float(dataframe["sell_rsi_pred"].iloc[-1])
self.stoploss = float(self.stoploss_param.value)
self.minimal_roi = {
0: float(self.roi_0.value),
15: float(self.roi_15.value),
30: float(self.roi_30.value),
60: 0
}
self.trailing_stop_positive = float(dataframe["trailing_stop_positive"].iloc[-1])
self.trailing_stop_positive_offset = float(dataframe["trailing_stop_positive_offset"].iloc[-1])
logger.info(f"动态参数buy_rsi={self.buy_rsi.value}, sell_rsi={self.sell_rsi.value}, "
f"stoploss={self.stoploss}, trailing_stop_positive={self.trailing_stop_positive}")
dataframe.replace([np.inf, -np.inf], 0, inplace=True)
dataframe.fillna(method='ffill', inplace=True)
dataframe.fillna(0, inplace=True)
logger.info(f"up_or_down 值统计:\n{dataframe['up_or_down'].value_counts().to_string()}")
logger.info(f"do_predict 值统计:\n{dataframe['do_predict'].value_counts().to_string()}")
return dataframe
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
enter_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]),
df["volume"] > 0
]
if enter_long_conditions:
df.loc[
reduce(lambda x, y: x & y, enter_long_conditions),
["enter_long", "enter_tag"]
] = (1, "long")
return df
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
exit_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"]),
df["volume"] > 0
]
if exit_long_conditions:
df.loc[
reduce(lambda x, y: x & y, exit_long_conditions),
"exit_long"
] = 1
return df
def confirm_trade_entry(
self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time, entry_tag, side: str, **kwargs
) -> bool:
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = df.iloc[-1].squeeze()
if side == "long":
if rate > (last_candle["close"] * (1 + 0.0025)):
return False
return True