stable1 14

This commit is contained in:
zhangkun9038@dingtalk.com 2025-04-28 21:07:51 +08:00
parent eceb04d22d
commit 9bb14377ed
2 changed files with 87 additions and 87 deletions

View File

@ -60,47 +60,49 @@
"method": "StaticPairList"
}
],
"freqai": {
"enabled": true,
"model_path": "/freqtrade/user_data/models",
"data_kitchen": {
"fillna": "ffill"
},
"freqaimodel": "XGBoostRegressor",
"model_training_parameters": {
"n_estimators": 300,
"learning_rate": 0.03,
"max_depth": 6,
"subsample": 0.8,
"colsample_bytree": 0.8,
"reg_lambda": 1.0,
"objective": "reg:squarederror",
"eval_metric": "rmse",
"early_stopping_rounds": 20
},
"train_period_days": 730, // 2
"backtest_period_days": 90,
"live_retrain_hours": 0,
"feature_selection": {
"method": "recursive_elimination"
},
"feature_parameters": {
"include_timeframes": ["15m", "1h", "4h"],
"include_corr_pairlist": ["BTC/USDT", "SOL/USDT", "ETH/USDT"],
"label_period_candles": 40, //
"include_shifted_candles": 2,
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": true,
"SVM_parameters": {
"nu": 0.1
{
"freqai": {
"enabled": true,
"model_path": "/freqtrade/user_data/models",
"data_kitchen": {
"fillna": "ffill"
},
"DI_threshold": 0, // DI
"indicator_periods_candles": [14, 20]
},
"data_split_parameters": {
"test_size": 0.2,
"shuffle": true
"freqaimodel": "XGBoostRegressor",
"model_training_parameters": {
"n_estimators": 300,
"learning_rate": 0.03,
"max_depth": 6,
"subsample": 0.8,
"colsample_bytree": 0.8,
"reg_lambda": 1.0,
"objective": "reg:squarederror",
"eval_metric": "rmse",
"early_stopping_rounds": 20
},
"train_period_days": 730,
"backtest_period_days": 90,
"live_retrain_hours": 0,
"feature_selection": {
"method": "recursive_elimination"
},
"feature_parameters": {
"include_timeframes": ["15m", "1h", "4h"],
"include_corr_pairlist": ["BTC/USDT", "SOL/USDT", "ETH/USDT"],
"label_period_candles": 60,
"include_shifted_candles": 2,
"weight_factor": 0.9,
"principal_component_analysis": false,
"use_SVM_to_remove_outliers": true,
"SVM_parameters": {
"nu": 0.1
},
"DI_threshold": 0,
"indicator_periods_candles": [14, 20]
},
"data_split_parameters": {
"test_size": 0.2,
"shuffle": true
}
}
},
"api_server": {

View File

@ -1,5 +1,6 @@
import logging
import numpy as np
import pandas as pd
from functools import reduce
import talib.abstract as ta
from pandas import DataFrame
@ -13,10 +14,10 @@ class FreqaiExampleStrategy(IStrategy):
FreqAI-based trading strategy using XGBoostRegressor for regression-based price movement prediction.
Optimized for short-term trading on spot markets (BTC/USDT, ETH/USDT, SOL/USDT).
Key improvements:
- Fixed KeyError in populate_entry_trend by using pd.concat for conditions
- Dynamic ATR-based stop-loss and ROI
- Relaxed entry conditions to increase trading frequency
- Enhanced feature engineering with cross-timeframe indicators
- Standardized target values to amplify prediction signals
- Standardized and transformed target values to amplify signals
- Disabled DI filtering to resolve datasieve warnings
"""
@ -45,7 +46,7 @@ class FreqaiExampleStrategy(IStrategy):
"feature_parameters": {
"include_timeframes": ["15m", "1h", "4h"],
"include_corr_pairlist": ["BTC/USDT", "SOL/USDT", "ETH/USDT"],
"label_period_candles": 40, # Extended prediction horizon
"label_period_candles": 60, # Extended prediction horizon
"include_shifted_candles": 2,
"weight_factor": 0.9,
"principal_component_analysis": False,
@ -78,9 +79,7 @@ class FreqaiExampleStrategy(IStrategy):
}
def calculate_macd(self, dataframe: DataFrame) -> DataFrame:
"""
Calculate MACD indicators and handle exceptions.
"""
"""Calculate MACD indicators and handle exceptions."""
try:
macd = ta.MACD(dataframe, fastperiod=12, slowperiod=26, signalperiod=9)
dataframe["macd"] = macd["macd"].replace([np.inf, -np.inf], np.nan).ffill().fillna(0)
@ -93,9 +92,7 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
"""
Enhanced feature engineering with cross-timeframe and momentum indicators.
"""
"""Enhanced feature engineering with cross-timeframe and momentum indicators."""
# Standard technical indicators
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
dataframe["sma20"] = ta.SMA(dataframe["close"], timeperiod=20)
@ -121,7 +118,7 @@ class FreqaiExampleStrategy(IStrategy):
bollinger_tf = qtpylib.bollinger_bands(qtpylib.typical_price(tf_data), window=20, stds=2)
dataframe[f"bb_width_{tf}"] = (bollinger_tf["upper"] - bollinger_tf["lower"]) / bollinger_tf["mid"]
# Correlated pair features (e.g., BTC influence on SOL)
# Correlated pair features
if metadata["pair"] == "SOL/USDT":
btc_data = self.dp.get_pair_dataframe(pair="BTC/USDT", timeframe=self.timeframe)
if not btc_data.empty:
@ -137,9 +134,7 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
"""
Basic feature engineering for FreqAI.
"""
"""Basic feature engineering for FreqAI."""
dataframe["%-pct-change"] = dataframe["close"].pct_change()
dataframe["%-raw_volume"] = dataframe["volume"]
dataframe["%-raw_price"] = dataframe["close"]
@ -149,9 +144,7 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
"""
Standard feature engineering for temporal features.
"""
"""Standard feature engineering for temporal features."""
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
for col in dataframe.columns:
@ -160,9 +153,7 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
"""
Set FreqAI prediction targets with standardized up_or_down values.
"""
"""Set FreqAI prediction targets with standardized and transformed values."""
logger.info(f"Setting FreqAI targets for pair: {metadata['pair']}")
if "close" not in dataframe.columns:
logger.error("DataFrame missing 'close' column")
@ -173,10 +164,12 @@ class FreqaiExampleStrategy(IStrategy):
dataframe["&-up_or_down"] = (
dataframe["close"].shift(-label_period) - dataframe["close"]
) / dataframe["close"]
# Standardize target values to amplify signal strength
# Standardize target values
dataframe["&-up_or_down"] = (
dataframe["&-up_or_down"] - dataframe["&-up_or_down"].mean()
) / dataframe["&-up_or_down"].std()
# Apply logarithmic transformation to amplify signals
dataframe["&-up_or_down"] = np.log1p(dataframe["&-up_or_down"].abs()) * np.sign(dataframe["&-up_or_down"])
dataframe["&-up_or_down"] = dataframe["&-up_or_down"].replace([np.inf, -np.inf], np.nan).ffill().fillna(0)
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
@ -191,9 +184,7 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Populate indicators and dynamic strategy parameters.
"""
"""Populate indicators and dynamic strategy parameters."""
logger.info(f"Processing pair: {metadata['pair']}")
dataframe = self.freqai.start(dataframe, metadata, self)
@ -243,35 +234,44 @@ class FreqaiExampleStrategy(IStrategy):
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Generate entry signals with relaxed conditions to increase trading frequency.
"""
"""Generate entry signals with relaxed conditions."""
# Validate required columns
required_cols = ["rsi", "buy_rsi_pred", "volume", "bb_middleband", "macd", "macdsignal", "&-up_or_down"]
if not all(col in dataframe.columns for col in required_cols):
logger.error(f"Missing required columns: {set(required_cols) - set(dataframe.columns)}")
return dataframe
dataframe = self.calculate_macd(dataframe)
enter_long_conditions = [
(dataframe["rsi"] < dataframe["buy_rsi_pred"]),
(dataframe["volume"] > dataframe["volume"].rolling(window=10).mean() * 1.0), # Relaxed volume condition
(dataframe["close"] > dataframe["bb_middleband"]),
(dataframe["macd"] > dataframe["macdsignal"]),
(dataframe["&-up_or_down"] > 0.0015) # Lowered threshold for more signals
dataframe["rsi"] < dataframe["buy_rsi_pred"],
dataframe["volume"] > dataframe["volume"].rolling(window=10).mean() * 1.0,
dataframe["close"] > dataframe["bb_middleband"],
dataframe["macd"] > dataframe["macdsignal"],
dataframe["&-up_or_down"] > (0.001 if metadata["pair"] == "BTC/USDT" else 0.0015) # Lower threshold for BTC
]
# Require at least 3 conditions to be met
dataframe.loc[dataframe[enter_long_conditions].sum(axis=1) >= 3, ["enter_long", "enter_tag"]] = (1, "long")
# Combine conditions into a DataFrame
conditions_df = pd.concat(enter_long_conditions, axis=1)
dataframe.loc[conditions_df.sum(axis=1) >= 3, ["enter_long", "enter_tag"]] = (1, "long")
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
"""
Generate exit signals with confirmation to reduce premature exits.
"""
"""Generate exit signals with confirmation."""
# Validate required columns
required_cols = ["rsi", "sell_rsi_pred", "bb_middleband", "macd", "macdsignal", "&-up_or_down"]
if not all(col in dataframe.columns for col in required_cols):
logger.error(f"Missing required columns: {set(required_cols) - set(dataframe.columns)}")
return dataframe
exit_long_conditions = [
(dataframe["rsi"] > dataframe["sell_rsi_pred"]),
(dataframe["close"] < dataframe["bb_middleband"]),
(dataframe["macd"] < dataframe["macdsignal"]),
(dataframe["&-up_or_down"] < -0.005) # Higher threshold for stronger exit signals
dataframe["rsi"] > dataframe["sell_rsi_pred"],
dataframe["close"] < dataframe["bb_middleband"],
dataframe["macd"] < dataframe["macdsignal"],
dataframe["&-up_or_down"] < -0.005
]
# Require conditions to be met for two consecutive candles
exit_signal = (dataframe[exit_long_conditions].sum(axis=1) >= 3) & (
dataframe[exit_long_conditions].shift(1).sum(axis=1) >= 3
)
# Combine conditions into a DataFrame
conditions_df = pd.concat(exit_long_conditions, axis=1)
# Require confirmation: at least 3 conditions met for two consecutive candles
exit_signal = (conditions_df.sum(axis=1) >= 3) & (conditions_df.shift(1).sum(axis=1) >= 3)
dataframe.loc[exit_signal, "exit_long"] = 1
return dataframe
@ -279,9 +279,7 @@ class FreqaiExampleStrategy(IStrategy):
self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time, entry_tag, side: str, **kwargs
) -> bool:
"""
Confirm trade entry to avoid slippage.
"""
"""Confirm trade entry to avoid slippage."""
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = df.iloc[-1].squeeze()
if side == "long":