stable1 14
This commit is contained in:
parent
eceb04d22d
commit
9bb14377ed
@ -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": {
|
||||
|
||||
@ -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":
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user