This commit is contained in:
zhangkun9038@dingtalk.com 2025-05-10 16:24:09 +00:00
parent 4df3623b96
commit e558c1b0bd
13 changed files with 22545 additions and 1549 deletions

95
config_examples/nb.json Normal file
View File

@ -0,0 +1,95 @@
{
"strategy": "TheForceFreqaiStrategy",
"timeframe": "5m",
"timerange": "20240701-20250115",
"exchange": {
"name": "okx",
"ccxt_config": {
"enableRateLimit": true,
"rateLimit": 500,
"options": {"defaultType": "spot"},
"timeout": 20000
},
"pair_whitelist": [
"OKB/USDT"
],
"fee": 0.0008
},
"pair_whitelist": ["OKB/USDT"],
"dataformat_ohlcv": "feather",
"download_data": {
"timeframes": ["5m"],
"timerange": "20240701-20250115"
},
"stake_currency": "USDT",
"stake_amount": 150,
"stoploss": -0.15,
"minimal_roi": {
"0": 0.05,
"60": 0.03,
"120": 0.01
},
"startup_candle_count": 200,
"max_open_trades": 4,
"use_exit_signal": true,
"unfilledtimeout": {
"entry": 5,
"exit": 15,
"unit": "minutes"
},
"export": "trades",
"cache": "none",
"loglevel": "DEBUG",
"verbosity": 2,
"entry_pricing": {
"price_side": "same",
"use_order_book": true,
"order_book_top": 1,
"price_last_balance": 0.0,
"check_depth_of_market": {
"enabled": false,
"bids_to_ask_delta": 1
}
},
"exit_pricing": {
"price_side": "other",
"use_order_book": true,
"order_book_top": 1
},
"pairlists": [
{
"method": "StaticPairList"
}
],
"freqai": {
"enabled": true,
"identifier": "theforce_model",
"save_backtest_models": true,
"live_retrain": true,
"purge_old_models": true,
"fit_live_predictions_candles": 50,
"force_train": true,
"verbose": 2,
"train_period_days": 7,
"backtest_period_days": 2,
"feature_parameters": {
"include_timeframes": ["5m"],
"include_corr_pairlist": [],
"label_period_candles": 5,
"include_shifted_candles": 2,
"DI_threshold": 1.5,
"indicator_periods_candles": [10, 20, 50],
"include_default_features": ["open", "high", "low", "close", "volume"],
"use_SVM_to_remove_outliers": false
},
"data_split_parameters": {
"test_size": 0.2,
"random_state": 42
},
"model_training_parameters": {
"n_estimators": 100,
"max_depth": 7,
"verbose": -1
}
}
}

View File

@ -67,10 +67,10 @@ services:
backtesting
--logfile /freqtrade/user_data/logs/freqtrade.log
--freqaimodel XGBoostRegressor
--config /freqtrade/config_examples/config_my_hyperopt.json
--config /freqtrade/config_examples/nb.json
--strategy-path /freqtrade/templates
--strategy FreqaiExampleStrategy
--timerange 20250405-20250415
--strategy TheForceV7
--timerange 20240901-20250315
--export trades
--fee 0.0008
--cache none

View File

@ -0,0 +1,192 @@
from freqtrade.strategy import IStrategy, DecimalParameter, IntParameter
from pandas import DataFrame
import pandas as pd
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np
from typing import Dict, List, Optional
import logging
logger = logging.getLogger(__name__)
class TheForceFreqaiStrategy(IStrategy):
timeframe = '5m'
minimal_roi = {"0": 0.05, "60": 0.03, "120": 0.01}
stoploss = -0.15
process_only_new_candles = True
use_exit_signal = True
startup_candle_count = 200
max_open_trades = 4
buy_macd_diff = DecimalParameter(-10.0, 10.0, default=0.0, space="buy")
sell_stoch_overbought = IntParameter(70, 90, default=80, space="sell")
freqai = {
"enabled": True,
"model": "LightGBMRegressor",
"train_period_days": 7,
"backtest_period_days": 2,
"identifier": "theforce_model",
"feature_params": {
"include_timeframes": ["5m"],
"include_corr_pairlist": [],
"label_period_candles": 5,
"include_shifted_candles": 2,
"DI_threshold": 1.5,
"include_default_features": ["open", "high", "low", "close", "volume"],
"use_SVM_to_remove_outliers": False
},
"data_split_parameters": {
"test_size": 0.2,
"random_state": 42
},
"model_training_parameters": {
"n_estimators": 100,
"max_depth": 7,
"verbose": -1
},
"live_retrain": True,
"purge_old_models": True,
"fit_live_predictions_candles": 50,
"data_kitchen_thread_count": 2,
"force_train": True,
"verbose": 2,
"save_backtest_models": True
}
def __init__(self, config: Dict):
super().__init__(config)
self.feature_cache = {}
self.freqai_config = self.freqai
logging.getLogger('').setLevel(logging.DEBUG)
logger.setLevel(logging.DEBUG)
for log in ['freqtrade.freqai', 'freqtrade.freqai.data_kitchen',
'freqtrade.freqai.data_drawer', 'freqtrade.freqai.prediction_models']:
logging.getLogger(log).setLevel(logging.DEBUG)
logger.info("Initialized TheForceFreqaiStrategy with DEBUG logging")
def _normalize_column(self, series: pd.Series) -> pd.Series:
if series.nunique() <= 1:
return pd.Series(np.zeros_like(series), index=series.index)
min_val = series.min()
max_val = series.max()
normalized = (series - min_val) / (max_val - min_val)
return normalized.fillna(0)
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.debug(f"Populating indicators for pair {metadata['pair']}")
logger.debug(f"Input dataframe shape: {dataframe.shape}, columns: {list(dataframe.columns)}")
logger.debug(f"First 5 rows:\n{dataframe.head().to_string()}")
dataframe = self.freqai.start(dataframe, metadata, self)
logger.info("FreqAI start called, checking dataframe columns: %s", list(dataframe.columns))
required_columns = ['open', 'high', 'low', 'close', 'volume']
missing_columns = [col for col in required_columns if col not in dataframe.columns]
if missing_columns:
logger.error(f"Missing columns in dataframe: {missing_columns}")
return dataframe
if dataframe.empty or len(dataframe) < self.startup_candle_count:
logger.error(f"Insufficient data: {len(dataframe)} candles, required {self.startup_candle_count}")
return dataframe
macd = ta.MACD(dataframe)
dataframe['macd'] = macd['macd'].fillna(0)
dataframe['macdsignal'] = macd['macdsignal'].fillna(0)
dataframe['macd_diff'] = macd['macd'] - macd['macdsignal']
stoch = ta.STOCH(dataframe)
dataframe['slowk'] = stoch['slowk'].fillna(0)
dataframe['slowd'] = stoch['slowd'].fillna(0)
dataframe['ema_short'] = ta.EMA(dataframe, timeperiod=12).fillna(dataframe['close'])
dataframe['ema_long'] = ta.EMA(dataframe, timeperiod=26).fillna(dataframe['close'])
logger.debug(f"Indicators generated: {list(dataframe.columns)}")
logger.debug(f"Indicator sample:\n{dataframe[['macd', 'slowk', 'ema_short']].tail().to_string()}")
return dataframe
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.debug(f"Setting FreqAI targets for pair {metadata['pair']}")
label_candles = self.freqai_config['feature_params']['label_period_candles']
dataframe['&-target'] = (
dataframe['close'].shift(-label_candles) / dataframe['close'] - 1
).fillna(0)
valid_targets = len(dataframe['&-target'].dropna())
logger.debug(f"Target '&-target' generated with {valid_targets} valid values")
logger.debug(f"Target stats: min={dataframe['&-target'].min()}, max={dataframe['&-target'].max()}, mean={dataframe['&-target'].mean()}")
logger.debug(f"Target sample:\n{dataframe['&-target'].tail().to_string()}")
return dataframe
def feature_engineering_expand(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.debug(f"Expanding features for pair {metadata['pair']}")
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['%-pct_change'] = dataframe['close'].pct_change()
dataframe['%-volume_change'] = dataframe['volume'].pct_change(periods=5)
for col in dataframe.columns:
if col.startswith('%-'):
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill().fillna(0)
if dataframe[col].nunique() > 1:
dataframe[f"{col}_norm"] = self._normalize_column(dataframe[col])
else:
dataframe[f"{col}_norm"] = 0
logger.debug(f"Features generated: {list(dataframe.columns)}")
logger.debug(f"Feature sample:\n{dataframe[[c for c in dataframe.columns if c.startswith('%-')]].tail().to_string()}")
return dataframe
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.debug(f"Standard feature engineering for pair {metadata['pair']}")
dataframe['%-rsi'] = ta.RSI(dataframe, timeperiod=14)
dataframe['%-day_of_week'] = dataframe['date'].dt.dayofweek
dataframe['%-hour_of_day'] = dataframe['date'].dt.hour
for col in dataframe.columns:
if col.startswith('%-'):
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill().fillna(0)
logger.debug(f"Standard features generated: {list(dataframe.columns)}")
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.debug(f"Populating entry trend for pair {metadata['pair']}")
logger.debug(f"Columns available: {list(dataframe.columns)}")
logger.debug(f"&-target stats: {dataframe['&-target'].describe()}")
logger.debug(f"slowk stats: {dataframe['slowk'].describe()}")
logger.debug(f"macd_diff stats: {dataframe['macd_diff'].describe()}")
if '&-target' not in dataframe.columns:
logger.warning(f"'&-target' column missing for pair {metadata['pair']}, using indicators only")
dataframe.loc[
(dataframe['macd'] > dataframe['macdsignal']) &
(dataframe['macd_diff'] > self.buy_macd_diff.value) &
(dataframe['slowk'] < 30) &
(dataframe['ema_short'] > dataframe['ema_long']),
'enter_long'] = 1
logger.debug(f"Fallback entry signals: {dataframe['enter_long'].sum()} buys")
return dataframe
dataframe.loc[
(dataframe['macd'] > dataframe['macdsignal']) &
(dataframe['macd_diff'] > self.buy_macd_diff.value) &
(dataframe['slowk'] < 30) &
(dataframe['ema_short'] > dataframe['ema_long']) &
(dataframe['&-target'] > 0.005),
'enter_long'] = 1
logger.debug(f"FreqAI entry signals: {dataframe['enter_long'].sum()} buys")
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.debug(f"Populating exit trend for pair {metadata['pair']}")
dataframe.loc[
(dataframe['macd'] < dataframe['macdsignal']) &
(dataframe['slowk'] > self.sell_stoch_overbought.value),
'exit_long'] = 1
return dataframe

View File

@ -0,0 +1,206 @@
1,4d0
< import numpy as np # noqa
< import pandas as pd # noqa
< from pandas import DataFrame
<
6c2,3
<
---
> import pandas as pd
> import numpy as np
12,13c9
<
< INTERFACE_VERSION = 2
---
> INTERFACE_VERSION = 3
14a11
> # 基础参数
16c13
< "0": 10
---
> "0": 10
36d32
< plot_config = {
37a34,35
> # 绘图配置
> plot_config = {
51a50
>
65c64
< def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
---
> def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
77,78d75
<
<
85c82
< macd = ta.MACD(dataframe,12,26,1)
---
> macd = ta.MACD(dataframe, 12, 26, 1)
102,103c99
<
<
---
>
106c102
< def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
---
> def populate_buy_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
116,130c112,113
< (
< ( #Original buy condition
< (dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
< &
< (dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
< )
< |
< ( #V3 added based on SmoothScalp
< (dataframe['slowk'] < 30) & (dataframe['slowd'] < 30) &
< (qtpylib.crossed_above(dataframe['slowk'], dataframe['slowd']))
< )
< )
< &
< ( #Original buy condition #Might need improvement to have better signals
< (dataframe['macd'] > dataframe['macd'].shift(1))
---
> (
> (dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
132c115
< (dataframe['macdsignal'] > dataframe['macdsignal'].shift(1))
---
> (dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
134,149c117,120
< &
< ( #Original buy condition
< (dataframe['close'] > dataframe['close'].shift(1))
< & #V6 added condition to improve buy's
< (dataframe['open'] > dataframe['open'].shift(1))
< )
< &
< ( #Original buy condition
< (dataframe['ema5c'] >= dataframe['ema5o'])
< |
< (dataframe['open'] < dataframe['ema5l'])
< )
< &
< (
<
< (dataframe['volume'] > dataframe['volvar'])
---
> |
> (
> (dataframe['slowk'] < 30) & (dataframe['slowd'] < 30) &
> (qtpylib.crossed_above(dataframe['slowk'], dataframe['slowd']))
152,154c123,125
< |
< ( # V2 Added buy condition w/ Bollingers bands
< (dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
---
> &
> (
> (dataframe['macd'] > dataframe['macd'].shift(1))
156c127,131
< (dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
---
> (dataframe['macdsignal'] > dataframe['macdsignal'].shift(1))
> )
> &
> (
> (dataframe['close'] > dataframe['close'].shift(1))
158,162c133
< (
< (dataframe['close'] <= dataframe['bb_lowerband'])
< |
< (dataframe['open'] <= dataframe['bb_lowerband'])
< )
---
> (dataframe['open'] > dataframe['open'].shift(1))
164,168c135,143
< |
< ( # V5 added Pullback RSI thanks to simoelmou
< (dataframe['close'] > dataframe['ema200c'])
< &
< (dataframe['rsi7'] < 35)
---
> &
> (
> (dataframe['ema5c'] >= dataframe['ema5o'])
> |
> (dataframe['open'] < dataframe['ema5l'])
> )
> &
> (
> (dataframe['volume'] > dataframe['volvar'])
175c150
< def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
---
> def populate_sell_trend(self, dataframe: pd.DataFrame, metadata: dict) -> pd.DataFrame:
185,200c160,161
< (
< ( #Original sell condition
< (dataframe['slowk'] <= 80) & (dataframe['slowd'] <= 80)
< )
< |
< ( #V3 added based on SmoothScalp
< (qtpylib.crossed_above(dataframe['slowk'], 70))
< |
< (qtpylib.crossed_above(dataframe['slowd'], 70))
< )
< )
< &
< ( #Original sell condition
< (dataframe['macd'] < dataframe['macd'].shift(1))
< &
< (dataframe['macdsignal'] < dataframe['macdsignal'].shift(1))
---
> (
> (dataframe['slowk'] <= 80) & (dataframe['slowd'] <= 80)
202,204c163,165
< &
< ( #Original sell condition
< (dataframe['ema5c'] < dataframe['ema5o'])
---
> |
> (
> (qtpylib.crossed_above(dataframe['slowk'], 70))
206c167
< (dataframe['open'] >= dataframe['ema5h']) # V3 added based on SmoothScalp
---
> (qtpylib.crossed_above(dataframe['slowd'], 70))
209,213c170,172
< |
< ( # V2 Added sell condition w/ Bollingers bands
< (dataframe['slowk'] <= 80)
< &
< (dataframe['slowd'] <= 80)
---
> &
> (
> (dataframe['macd'] < dataframe['macd'].shift(1))
215,219c174
< (
< (dataframe['close'] >= dataframe['bb_upperband'])
< |
< (dataframe['open'] >= dataframe['bb_upperband'])
< )
---
> (dataframe['macdsignal'] < dataframe['macdsignal'].shift(1))
221,225c176,180
< |
< (# V6 Added sell condition for extra high values
< (dataframe['high'] > dataframe['bb_upperband'])
< &
< (((dataframe['high'] - dataframe['bb_upperband']) * 100 / dataframe['bb_upperband']) > 1)
---
> &
> (
> (dataframe['ema5c'] < dataframe['ema5o'])
> |
> (dataframe['open'] >= dataframe['ema5h'])
227d181
<
230,231c184
< return dataframe
<
---
>

187
freqtrade/templates/v7.py Normal file
View File

@ -0,0 +1,187 @@
from freqtrade.strategy import IStrategy
from pandas import DataFrame
import numpy as np # noqa
import pandas as pd # noqa
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
class TheForceV7(IStrategy):
INTERFACE_VERSION = 3 # 升级到 V3 接口
minimal_roi = {
"0": 10
}
stoploss = -0.1
trailing_stop = False
timeframe = '5m'
process_only_new_candles = False
use_exit_signal = True # 替换 use_sell_signal
ignore_roi_if_entry_signal = True # 替换 ignore_roi_if_buy_signal
startup_candle_count: int = 30
order_types = {
'entry': 'limit', # 替换 buy
'exit': 'limit', # 替换 sell
'stoploss': 'market',
'stoploss_on_exchange': False
}
order_time_in_force = {
'entry': 'gtc',
'exit': 'gtc'
}
plot_config = {
'main_plot': {
'tema': {},
'sar': {'color': 'white'},
},
'subplots': {
"MACD": {
'macd': {'color': 'blue'},
'macdsignal': {'color': 'orange'},
},
"RSI": {
'rsi': {'color': 'red'},
}
}
}
def informative_pairs(self):
return []
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
stoch = ta.STOCH(dataframe)
dataframe['slowd'] = stoch['slowd']
dataframe['slowk'] = stoch['slowk']
dataframe['rsi7'] = ta.RSI(dataframe, timeperiod=7)
macd = ta.MACD(dataframe, 12, 26, 1)
dataframe['macd'] = macd['macd']
dataframe['macdsignal'] = macd['macdsignal']
dataframe['macdhist'] = macd['macdhist']
dataframe['ema5h'] = ta.EMA(dataframe['high'], timeperiod=5)
dataframe['ema5l'] = ta.EMA(dataframe['low'], timeperiod=5)
dataframe['ema5c'] = ta.EMA(dataframe['close'], timeperiod=5)
dataframe['ema5o'] = ta.EMA(dataframe['open'], timeperiod=5)
dataframe['ema200c'] = ta.MA(dataframe['close'], 200)
dataframe['volvar'] = (dataframe['volume'].rolling(100).mean() * 1.5)
bollinger = qtpylib.bollinger_bands(dataframe['close'], window=21, stds=2)
dataframe['bb_lowerband'] = bollinger['lower']
dataframe['bb_upperband'] = bollinger['upper']
dataframe['bb_middleband'] = bollinger['mid']
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(
(
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
&
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
)
|
(
(dataframe['slowk'] < 30) & (dataframe['slowd'] < 30) &
(qtpylib.crossed_above(dataframe['slowk'], dataframe['slowd']))
)
)
&
(
(dataframe['macd'] > dataframe['macd'].shift(1))
&
(dataframe['macdsignal'] > dataframe['macdsignal'].shift(1))
)
&
(
(dataframe['close'] > dataframe['close'].shift(1))
&
(dataframe['open'] > dataframe['open'].shift(1))
)
&
(
(dataframe['ema5c'] >= dataframe['ema5o'])
|
(dataframe['open'] < dataframe['ema5l'])
)
&
(
(dataframe['volume'] > dataframe['volvar'])
)
|
(
(dataframe['slowk'] >= 20) & (dataframe['slowk'] <= 80)
&
(dataframe['slowd'] >= 20) & (dataframe['slowd'] <= 80)
&
(
(dataframe['close'] <= dataframe['bb_lowerband'])
|
(dataframe['open'] <= dataframe['bb_lowerband'])
)
)
|
(
(dataframe['close'] > dataframe['ema200c'])
&
(dataframe['rsi7'] < 35)
)
),
'enter_long'] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
(
(
(dataframe['slowk'] <= 80) & (dataframe['slowd'] <= 80)
)
|
(
(qtpylib.crossed_above(dataframe['slowk'], 70))
|
(qtpylib.crossed_above(dataframe['slowd'], 70))
)
)
&
(
(dataframe['macd'] < dataframe['macd'].shift(1))
&
(dataframe['macdsignal'] < dataframe['macdsignal'].shift(1))
)
&
(
(dataframe['ema5c'] < dataframe['ema5o'])
|
(dataframe['open'] >= dataframe['ema5h'])
)
|
(
(dataframe['slowk'] <= 80)
&
(dataframe['slowd'] <= 80)
&
(
(dataframe['close'] >= dataframe['bb_upperband'])
|
(dataframe['open'] >= dataframe['bb_upperband'])
)
)
|
(
(dataframe['high'] > dataframe['bb_upperband'])
&
(((dataframe['high'] - dataframe['bb_upperband']) * 100 / dataframe['bb_upperband']) > 1)
)
),
'exit_long'] = 1
return dataframe

11423
output.log

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
{"FreqaiExampleStrategy":{"run_id":"508f04f53e3b629d04b7cc23f20ff499670e9ae4","backtest_start_time":1746632368,"timeframe":"3m","timeframe_detail":null,"backtest_start_ts":1743811200,"backtest_end_ts":1744675200}}

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

@ -1,395 +0,0 @@
import logging
import numpy as np
import pandas as pd # 添加 pandas 导入
from functools import reduce
import talib.abstract as ta
from pandas import DataFrame
from typing import Dict, List, Optional
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": "XGBoostRegressor", # 与config保持一致
"save_backtest_models": True,
"feature_parameters": {
"include_timeframes": ["3m", "15m", "1h"], # 与config一致:w
"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": True, # 启用shuffle
},
"model_training_parameters": {
"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 = {
"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 __init__(self, config: Dict):
super().__init__(config)
# 初始化特征缓存
self.feature_cache = {}
# 设置日志级别
logger.setLevel(logging.DEBUG)
# 输出模型路径用于调试
freqai_model_path = self.config.get("freqai", {}).get("model_path", "/freqtrade/user_data/models")
logger.info(f"FreqAI 模型路径:{freqai_model_path}")
def _normalize_column(self, series: pd.Series) -> pd.Series:
"""对单个列进行最小最大归一化"""
if series.nunique() <= 1:
# 如果列中所有值都相同或为空直接返回全0
return pd.Series(np.zeros_like(series), index=series.index)
min_val = series.min()
max_val = series.max()
normalized = (series - min_val) / (max_val - min_val)
return normalized.fillna(0)
def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
# 基础指标
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
dataframe["macd"], dataframe["macdsignal"], dataframe["macdhist"] = ta.MACD(
dataframe, fastperiod=12, slowperiod=26, signalperiod=9
)
# 布林带及其宽度
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"]
# ATR (Average True Range)
dataframe["atr"] = ta.ATR(dataframe, timeperiod=14)
# RSI 变化率
dataframe["rsi_gradient"] = dataframe["rsi"].diff().fillna(0)
# 数据清理与归一化
for col in dataframe.select_dtypes(include=[np.number]).columns:
# Ensure column is valid and contains more than one unique value to avoid division by zero
if dataframe[col].nunique() > 1:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], np.nan)
dataframe[col] = dataframe[col].ffill().fillna(0)
dataframe[f"{col}_norm"] = self._normalize_column(dataframe[col])
else:
dataframe[f"{col}_norm"] = 0 # Default if normalization not possible
logger.info(f"特征工程完成,特征数量:{len(dataframe.columns)}")
return dataframe
def _add_noise(self, dataframe: DataFrame, noise_level: float = 0.02) -> DataFrame:
"""为数值型特征添加随机噪声以增强模型泛化能力"""
df = dataframe.copy()
numeric_cols = df.select_dtypes(include=[np.number]).columns.tolist()
for col in numeric_cols:
noise = np.random.normal(loc=0.0, scale=noise_level * df[col].std(), size=df.shape[0])
df[col] += noise
logger.info(f"已向 {len(numeric_cols)} 个数值型特征添加 {noise_level * 100:.0f}% 噪声")
return df
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["%-volume_change"] = dataframe["volume"].pct_change(periods=5)
dataframe["%-price_momentum"] = dataframe["close"] / dataframe["close"].shift(20) - 1
# 数据清理逻辑
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)
# 添加 2% 噪声以增强模型鲁棒性
dataframe = self._add_noise(dataframe, noise_level=0.02)
logger.info(f"特征工程完成,特征数量:{len(dataframe.columns)}")
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.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"]
# 定义目标变量为未来价格变化百分比(连续值)
dataframe["up_or_down"] = (
dataframe["close"].shift(-label_period) - dataframe["close"]
) / dataframe["close"]
# 数据清理:处理 NaN 和 Inf 值
dataframe["up_or_down"] = dataframe["up_or_down"].replace([np.inf, -np.inf], np.nan)
dataframe["up_or_down"] = dataframe["up_or_down"].ffill().fillna(0)
# 确保目标变量是二维数组
if dataframe["up_or_down"].ndim == 1:
dataframe["up_or_down"] = dataframe["up_or_down"].values.reshape(-1, 1)
# 检查并处理 NaN 或无限值
dataframe["up_or_down"] = dataframe["up_or_down"].replace([np.inf, -np.inf], np.nan)
dataframe["up_or_down"] = dataframe["up_or_down"].ffill().fillna(0)
# 生成 %-volatility 特征
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
# 确保 &-buy_rsi_pred 列的值计算正确
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
if "&-buy_rsi_pred" not in dataframe.columns:
logger.warning("&-buy_rsi_pred 列不存在,正在使用 &-buy_rsi 模拟替代")
dataframe["&-buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(window=10).mean().clip(20, 40)
dataframe["&-buy_rsi_pred"] = dataframe["&-buy_rsi_pred"].fillna(dataframe["&-buy_rsi_pred"].median())
# 确保 &-sell_rsi_pred 存在(基于 buy_rsi_pred + 偏移量)
if "&-sell_rsi_pred" not in dataframe.columns:
logger.warning("&-sell_rsi_pred 列不存在,正在使用 &-buy_rsi_pred + 20 模拟替代")
dataframe["&-sell_rsi_pred"] = dataframe["&-buy_rsi_pred"] + 20
dataframe["&-sell_rsi_pred"] = dataframe["&-sell_rsi_pred"].clip(50, 90)
dataframe["&-sell_rsi_pred"] = dataframe["&-sell_rsi_pred"].fillna(dataframe["&-sell_rsi_pred"].median())
# 数据清理
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')
dataframe[col] = dataframe[col].fillna(dataframe[col].mean()) # 使用均值填充 NaN 值
if dataframe[col].isna().any():
logger.warning(f"目标列 {col} 仍包含 NaN填充为默认值")
except Exception as e:
logger.error(f"创建 FreqAI 目标失败:{str(e)}")
raise
# 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:
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"]
dataframe["up_or_down"] = np.where(
dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0
)
# 确保 do_predict 列存在并填充默认值
if "do_predict" not in dataframe.columns:
dataframe["do_predict"] = 0
logger.warning("do_predict 列不存在,已创建并填充为 0。")
# 添加详细日志以验证 do_predict 的值
if "do_predict" in dataframe.columns:
logger.debug(f"do_predict 列存在前5行预览\n{dataframe[['do_predict']].head().to_string()}")
else:
logger.warning("do_predict 列不存在,可能未正确加载模型或进行预测。")
# 确保 &-buy_rsi_pred 存在(如果模型未提供则模拟生成)
if "&-buy_rsi" in dataframe.columns:
dataframe["&-buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(window=10).mean().clip(20, 40)
dataframe["&-buy_rsi_pred"] = dataframe["&-buy_rsi_pred"].fillna(dataframe["&-buy_rsi_pred"].median())
else:
logger.warning("&-buy_rsi 列不存在,无法生成 &-buy_rsi_pred将使用默认值")
dataframe["&-buy_rsi_pred"] = 27 # 默认 RSI 买入阈值
# 生成 &-sell_rsi_pred基于 buy_rsi_pred + 偏移量)
if "&-buy_rsi_pred" in dataframe.columns:
dataframe["&-sell_rsi_pred"] = dataframe["&-buy_rsi_pred"] + 20
dataframe["&-sell_rsi_pred"] = dataframe["&-sell_rsi_pred"].clip(50, 90)
dataframe["&-sell_rsi_pred"] = dataframe["&-sell_rsi_pred"].fillna(dataframe["&-sell_rsi_pred"].median())
else:
logger.warning("&-buy_rsi_pred 列不存在,无法生成 &-sell_rsi_pred将使用默认值")
dataframe["&-sell_rsi_pred"] = 59 # 默认 RSI 卖出阈值
# 确保 &-sell_rsi_pred 最终存在于 dataframe 中
if "&-sell_rsi_pred" not in dataframe.columns:
logger.error("&-sell_rsi_pred 列仍然缺失,策略可能无法正常运行")
raise ValueError("&-sell_rsi_pred 列缺失,无法继续执行策略逻辑")
# 生成 stoploss_pred基于波动率
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std()
dataframe["&-stoploss"] = (-0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)).fillna(-0.1)
dataframe["&-stoploss"] = dataframe["&-stoploss"].clip(-0.35, -0.1)
# 生成 roi_0_pred基于 ROI 参数)
dataframe["&-roi_0"] = ((dataframe["close"] / dataframe["close"].shift(label_period) - 1).clip(0, 0.2)).fillna(0)
# 设置策略级参数
try:
self.buy_rsi.value = float(dataframe["&-buy_rsi_pred"].iloc[-1])
self.sell_rsi.value = float(dataframe["&-sell_rsi_pred"].iloc[-1])
except Exception as e:
logger.error(f"设置 buy_rsi/sell_rsi 失败:{str(e)}")
self.buy_rsi.value = 27
self.sell_rsi.value = 59
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 = 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.ffill(inplace=True)
dataframe.fillna(0, inplace=True)
return dataframe
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
# 改进卖出信号条件
exit_long_conditions = [
(df["rsi"] > df["&-sell_rsi_pred"]), # RSI 高于卖出阈值
(df["volume"] > df["volume"].rolling(window=10).mean()), # 成交量高于近期均值
(df["close"] < df["bb_middleband"]) # 价格低于布林带中轨
]
# 添加详细日志以验证 do_predict 的值
if "do_predict" in df.columns:
logger.debug(f"do_predict 列存在前5行预览\n{df[['do_predict']].head().to_string()}")
else:
logger.warning("do_predict 列不存在,可能未正确加载模型或进行预测。")
if exit_long_conditions:
df.loc[
reduce(lambda x, y: x & y, exit_long_conditions),
"exit_long"
] = 1
if "&-buy_rsi_pred" in df.columns:
logger.debug(f"&-buy_rsi_pred 列存在前5行预览\n{df[['&-buy_rsi_pred']].head().to_string()}")
else:
logger.warning("&-buy_rsi_pred 列不存在,可能未正确生成或被覆盖。")
return df
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
# 改进买入信号条件
# 检查 MACD 列是否存在
if "macd" not in df.columns or "macdsignal" not in df.columns:
logger.error("MACD 或 MACD 信号列缺失,无法生成买入信号。尝试重新计算 MACD 列。")
try:
macd = ta.MACD(df, fastperiod=12, slowperiod=26, signalperiod=9)
df["macd"] = macd["macd"]
df["macdsignal"] = macd["macdsignal"]
logger.info("MACD 列已成功重新计算。")
except Exception as e:
logger.error(f"重新计算 MACD 列时出错:{str(e)}")
raise ValueError("DataFrame 缺少必要的 MACD 列且无法重新计算。")
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"]) # 价格高于布林带中轨
]
# 如果 MACD 列存在,则添加 MACD 金叉条件
if "macd" in df.columns and "macdsignal" in df.columns:
enter_long_conditions.append((df["macd"] > df["macdsignal"]))
# 确保模型预测为买入
enter_long_conditions.append((df["do_predict"] == 1))
# 添加详细日志以验证 do_predict 的值
if "do_predict" in df.columns:
logger.debug(f"do_predict 列存在前5行预览\n{df[['do_predict']].head().to_string()}")
else:
logger.warning("do_predict 列不存在,可能未正确加载模型或进行预测。")
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
) -> 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

View File

@ -1 +0,0 @@
{"$schema":"https://schema.freqtrade.io/schema.json","trading_mode":"spot","margin_mode":"isolated","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,"identifier":"demo1","timeframe":"3m","dry_run_wallet":1000,"cancel_open_orders_on_exit":true,"stoploss":-0.05,"unfilledtimeout":{"entry":5,"exit":15},"exchange":{"name":"okx","key":"REDACTED","secret":"REDACTED","enable_ws":false,"ccxt_config":{"enableRateLimit":true,"rateLimit":500,"options":{"defaultType":"spot"}},"ccxt_async_config":{"enableRateLimit":true,"rateLimit":500,"timeout":20000},"pair_whitelist":["OKB/USDT"],"pair_blacklist":[]},"freqai":{"enabled":true,"identifier":"test175","freqaimodel":"XGBoostRegressor","model_path":"/freqtrade/user_data/models","save_backtesting_prediction":true,"save_backtest_models":true,"backtest_period_days":10,"purge_old_models":true,"load_trained_model":true,"train_period_days":90,"live_retrain_hours":0,"include_predictions_in_final_dataframe":true,"data_kitchen":{"fillna":"ffill","feature_parameters":{"DI_threshold":0.5,"weight_factor":0.9}},"feature_parameters":{"include_timeframes":["5m","15m","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,"feature_selection":{"method":"none"}},"data_split_parameters":{"test_size":0.2,"shuffle":false},"model_training_parameters":{"n_estimators":200,"learning_rate":0.05,"max_depth":6,"subsample":0.8,"colsample_bytree":0.8}},"entry_pricing":{"price_side":"same","use_order_book":true,"order_book_top":1,"price_last_balance":0.0,"check_depth_of_market":{"enabled":false,"bids_to_ask_delta":1}},"exit_pricing":{"price_side":"other","use_order_book":true,"order_book_top":1},"pairlists":[{"method":"StaticPairList"}],"api_server":{"enabled":true,"listen_ip_address":"0.0.0.0","listen_port":8080,"verbosity":"error","enable_openapi":false,"jwt_secret_key":"6a599ab046dbb419014807dffd7b8823bfa7e5df56b17d545485deb87331b4ca","ws_token":"6O5pBDiRigiZrmIsofaE2rkKMJtf9h8zVQ","CORS_origins":[],"username":"freqAdmin","password":"REDACTED"},"use_exit_signal":true,"bot_name":"freqtrade","initial_state":"running","force_entry_enable":false,"internals":{"process_throttle_secs":5,"heartbeat_interval":20,"loglevel":"DEBUG"},"config_files":["/freqtrade/config_examples/config_my_hyperopt.json"]}

View File

@ -1,330 +0,0 @@
Creating freqtrade_old_freqtrade_run ...
Creating freqtrade_old_freqtrade_run ... done
2025-05-07 15:39:20,651 - freqtrade - INFO - freqtrade docker-2025.4-dev-23e4943b
2025-05-07 15:39:20,867 - numexpr.utils - INFO - NumExpr defaulting to 12 threads.
2025-05-07 15:39:22,371 - freqtrade.configuration.load_config - INFO - Using config: /freqtrade/config_examples/config_my_hyperopt.json ...
2025-05-07 15:39:22,373 - freqtrade.loggers - INFO - Enabling colorized output.
2025-05-07 15:39:22,374 - root - INFO - Logfile configured
2025-05-07 15:39:22,374 - freqtrade.loggers - INFO - Verbosity set to 0
2025-05-07 15:39:22,375 - freqtrade.configuration.configuration - INFO - Using additional Strategy lookup path: /freqtrade/templates
2025-05-07 15:39:22,375 - freqtrade.configuration.configuration - INFO - Using max_open_trades: 4 ...
2025-05-07 15:39:22,375 - freqtrade.configuration.configuration - INFO - Parameter --fee detected, setting fee to: 0.0008 ...
2025-05-07 15:39:22,376 - freqtrade.configuration.configuration - INFO - Parameter --timerange detected: 20250405-20250415 ...
2025-05-07 15:39:22,405 - freqtrade.configuration.configuration - INFO - Using user-data directory: /freqtrade/user_data ...
2025-05-07 15:39:22,406 - freqtrade.configuration.configuration - INFO - Using data directory: /freqtrade/user_data/data/okx ...
2025-05-07 15:39:22,407 - freqtrade.configuration.configuration - INFO - Parameter --export detected: trades ...
2025-05-07 15:39:22,407 - freqtrade.configuration.configuration - INFO - Parameter --cache=none detected ...
2025-05-07 15:39:22,407 - freqtrade.configuration.configuration - INFO - Filter trades by timerange: 20250405-20250415
2025-05-07 15:39:22,408 - freqtrade.configuration.configuration - INFO - Using freqaimodel class name: XGBoostRegressor
2025-05-07 15:39:22,409 - freqtrade.exchange.check_exchange - INFO - Checking exchange...
2025-05-07 15:39:22,415 - freqtrade.exchange.check_exchange - INFO - Exchange "okx" is officially supported by the Freqtrade development team.
2025-05-07 15:39:22,415 - freqtrade.configuration.configuration - INFO - Using pairlist from configuration.
2025-05-07 15:39:22,416 - freqtrade.configuration.config_validation - INFO - Validating configuration ...
2025-05-07 15:39:22,418 - freqtrade.commands.optimize_commands - INFO - Starting freqtrade in Backtesting mode
2025-05-07 15:39:22,418 - freqtrade.exchange.exchange - INFO - Instance is running with dry_run enabled
2025-05-07 15:39:22,419 - freqtrade.exchange.exchange - INFO - Using CCXT 4.4.77
2025-05-07 15:39:22,419 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True, 'rateLimit': 500, 'options': {'defaultType': 'spot'}}
2025-05-07 15:39:22,424 - freqtrade.exchange.exchange - INFO - Applying additional ccxt config: {'enableRateLimit': True, 'rateLimit': 500, 'options': {'defaultType': 'spot'}, 'timeout': 20000}
2025-05-07 15:39:22,431 - freqtrade.exchange.exchange - INFO - Using Exchange "OKX"
2025-05-07 15:39:28,076 - freqtrade.resolvers.exchange_resolver - INFO - Using resolved exchange 'Okx'...
2025-05-07 15:39:28,140 - freqtrade.resolvers.iresolver - WARNING - Could not import /freqtrade/templates/BaseHyperOptStrategy.py due to 'invalid syntax (BaseHyperOptStrategy.py, line 190)'
2025-05-07 15:39:28,143 - freqtrade.resolvers.iresolver - INFO - Using resolved strategy FreqaiExampleStrategy from '/freqtrade/templates/FreqaiExampleStrategy.py'...
2025-05-07 15:39:28,143 - freqtrade.strategy.hyper - INFO - Loading parameters from file /freqtrade/templates/FreqaiExampleStrategy.json
2025-05-07 15:39:28,144 - FreqaiExampleStrategy - INFO - FreqAI 模型路径:/freqtrade/user_data/models
2025-05-07 15:39:28,145 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'timeframe' with value in config file: 3m.
2025-05-07 15:39:28,145 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'stoploss' with value in config file: -0.05.
2025-05-07 15:39:28,145 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'stake_currency' with value in config file: USDT.
2025-05-07 15:39:28,146 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'stake_amount' with value in config file: 150.
2025-05-07 15:39:28,146 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'startup_candle_count' with value in config file: 30.
2025-05-07 15:39:28,146 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'unfilledtimeout' with value in config file: {'entry': 5, 'exit': 15, 'exit_timeout_count': 0, 'unit':
'minutes'}.
2025-05-07 15:39:28,147 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'use_exit_signal' with value in config file: True.
2025-05-07 15:39:28,147 - freqtrade.resolvers.strategy_resolver - INFO - Override strategy 'max_open_trades' with value in config file: 4.
2025-05-07 15:39:28,147 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using minimal_roi: {'0': 0.132, '8': 0.047, '14': 0.007, '60': 0}
2025-05-07 15:39:28,148 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using timeframe: 3m
2025-05-07 15:39:28,148 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using stoploss: -0.05
2025-05-07 15:39:28,148 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_stop: True
2025-05-07 15:39:28,148 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_stop_positive: 0.01
2025-05-07 15:39:28,149 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_stop_positive_offset: 0.02
2025-05-07 15:39:28,149 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using trailing_only_offset_is_reached: False
2025-05-07 15:39:28,149 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using use_custom_stoploss: False
2025-05-07 15:39:28,150 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using process_only_new_candles: True
2025-05-07 15:39:28,150 - 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-05-07 15:39:28,150 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using order_time_in_force: {'entry': 'GTC', 'exit': 'GTC'}
2025-05-07 15:39:28,150 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using stake_currency: USDT
2025-05-07 15:39:28,151 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using stake_amount: 150
2025-05-07 15:39:28,151 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using startup_candle_count: 30
2025-05-07 15:39:28,151 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using unfilledtimeout: {'entry': 5, 'exit': 15, 'exit_timeout_count': 0, 'unit': 'minutes'}
2025-05-07 15:39:28,151 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using use_exit_signal: True
2025-05-07 15:39:28,152 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using exit_profit_only: False
2025-05-07 15:39:28,152 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using ignore_roi_if_entry_signal: False
2025-05-07 15:39:28,152 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using exit_profit_offset: 0.0
2025-05-07 15:39:28,153 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using disable_dataframe_checks: False
2025-05-07 15:39:28,153 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using ignore_buying_expired_candle_after: 0
2025-05-07 15:39:28,153 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using position_adjustment_enable: False
2025-05-07 15:39:28,154 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using max_entry_position_adjustment: -1
2025-05-07 15:39:28,154 - freqtrade.resolvers.strategy_resolver - INFO - Strategy using max_open_trades: 4
2025-05-07 15:39:28,154 - freqtrade.configuration.config_validation - INFO - Validating configuration ...
2025-05-07 15:39:28,159 - freqtrade.resolvers.iresolver - INFO - Using resolved pairlist StaticPairList from '/freqtrade/freqtrade/plugins/pairlist/StaticPairList.py'...
2025-05-07 15:39:28,165 - freqtrade.optimize.backtesting - INFO - Using fee 0.0800% from config.
2025-05-07 15:39:28,165 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 3m to 43250
2025-05-07 15:39:28,166 - freqtrade.data.history.history_utils - INFO - Using indicator startup period: 43250 ...
2025-05-07 15:39:28,253 - freqtrade.optimize.backtesting - INFO - Loading data from 2025-01-04 21:30:00 up to 2025-04-15 00:00:00 (100 days).
2025-05-07 15:39:28,254 - freqtrade.optimize.backtesting - INFO - Dataload complete. Calculating indicators
2025-05-07 15:39:28,255 - freqtrade.optimize.backtesting - INFO - Running backtesting for Strategy FreqaiExampleStrategy
2025-05-07 15:39:29,917 - matplotlib.font_manager - INFO - generated new fontManager
2025-05-07 15:39:30,126 - freqtrade.resolvers.iresolver - INFO - Using resolved freqaimodel XGBoostRegressor from '/freqtrade/freqtrade/freqai/prediction_models/XGBoostRegressor.py'...
2025-05-07 15:39:30,127 - freqtrade.freqai.freqai_interface - INFO - Backtesting module configured to save all models.
2025-05-07 15:39:30,127 - freqtrade.freqai.data_drawer - INFO - Could not find existing datadrawer, starting from scratch
2025-05-07 15:39:30,127 - freqtrade.freqai.data_drawer - INFO - Could not find existing historic_predictions, starting from scratch
2025-05-07 15:39:30,128 - freqtrade.freqai.freqai_interface - INFO - Set fresh train queue from whitelist. Queue: ['OKB/USDT']
2025-05-07 15:39:30,129 - freqtrade.strategy.hyper - INFO - Strategy Parameter: buy_rsi = 39.92672300850069
2025-05-07 15:39:30,129 - freqtrade.strategy.hyper - INFO - Strategy Parameter: sell_rsi = 69.92672300850067
2025-05-07 15:39:30,130 - freqtrade.strategy.hyper - INFO - No params for protection found, using default values.
2025-05-07 15:39:30,134 - FreqaiExampleStrategy - INFO - 处理交易对OKB/USDT
2025-05-07 15:39:30,137 - freqtrade.freqai.freqai_interface - INFO - Training 1 timeranges
2025-05-07 15:39:30,139 - freqtrade.freqai.freqai_interface - INFO - Training OKB/USDT, 1/1 pairs from 2025-01-05 00:00:00 to 2025-04-05 00:00:00, 1/1 trains
2025-05-07 15:39:30,139 - freqtrade.freqai.data_kitchen - INFO - Could not find backtesting prediction file at
/freqtrade/user_data/models/test175/backtesting_predictions/cb_okb_1743811200_prediction.feather
2025-05-07 15:39:30,204 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,275 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,350 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,414 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:30,415 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:30,560 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 5m to 25970
2025-05-07 15:39:30,560 - freqtrade.data.dataprovider - INFO - Loading data for OKB/USDT 5m from 2025-01-04 19:50:00 to 2025-04-15 00:00:00
2025-05-07 15:39:30,628 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,667 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,714 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,753 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:30,754 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:30,886 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 15m to 8690
2025-05-07 15:39:30,887 - freqtrade.data.dataprovider - INFO - Loading data for OKB/USDT 15m from 2025-01-04 11:30:00 to 2025-04-15 00:00:00
2025-05-07 15:39:30,928 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,952 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:30,980 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:31,000 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:31,001 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:31,131 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 1h to 2210
2025-05-07 15:39:31,132 - freqtrade.data.dataprovider - INFO - Loading data for OKB/USDT 1h from 2025-01-02 22:00:00 to 2025-04-15 00:00:00
2025-05-07 15:39:31,161 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:31,178 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:31,195 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:31,209 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:31,210 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:31,872 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 3m to 43250
2025-05-07 15:39:31,873 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 3m from 2025-01-04 21:30:00 to 2025-04-15 00:00:00
2025-05-07 15:39:31,974 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,043 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,117 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,176 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:32,176 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:32,407 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 5m to 25970
2025-05-07 15:39:32,407 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 5m from 2025-01-04 19:50:00 to 2025-04-15 00:00:00
2025-05-07 15:39:32,488 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,531 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,577 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,616 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:32,617 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:32,907 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 15m to 8690
2025-05-07 15:39:32,908 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 15m from 2025-01-04 11:30:00 to 2025-04-15 00:00:00
2025-05-07 15:39:32,948 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,970 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:32,995 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:33,014 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:33,015 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:33,340 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 1h to 2210
2025-05-07 15:39:33,340 - freqtrade.data.dataprovider - INFO - Loading data for BTC/USDT 1h from 2025-01-02 22:00:00 to 2025-04-15 00:00:00
2025-05-07 15:39:33,371 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:33,387 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:33,403 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:33,417 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:33,418 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:33,901 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 3m to 43250
2025-05-07 15:39:33,902 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 3m from 2025-01-04 21:30:00 to 2025-04-15 00:00:00
2025-05-07 15:39:34,015 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:34,082 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:34,156 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:34,211 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:34,211 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:34,570 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 5m to 25970
2025-05-07 15:39:34,571 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 5m from 2025-01-04 19:50:00 to 2025-04-15 00:00:00
2025-05-07 15:39:34,642 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:34,684 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:34,735 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:34,773 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:34,774 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:35,282 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 15m to 8690
2025-05-07 15:39:35,283 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 15m from 2025-01-04 11:30:00 to 2025-04-15 00:00:00
2025-05-07 15:39:35,325 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:35,348 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:35,372 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:35,391 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:35,392 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:35,867 - freqtrade.data.dataprovider - INFO - Increasing startup_candle_count for freqai on 1h to 2210
2025-05-07 15:39:35,868 - freqtrade.data.dataprovider - INFO - Loading data for ETH/USDT 1h from 2025-01-02 22:00:00 to 2025-04-15 00:00:00
2025-05-07 15:39:35,899 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:35,916 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:35,933 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量28
2025-05-07 15:39:35,946 - FreqaiExampleStrategy - INFO - 已向 10 个数值型特征添加 2% 噪声
2025-05-07 15:39:35,947 - FreqaiExampleStrategy - INFO - 特征工程完成特征数量11
2025-05-07 15:39:36,739 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对OKB/USDT
2025-05-07 15:39:36,744 - FreqaiExampleStrategy - WARNING - &-buy_rsi_pred 列不存在,正在使用 &-buy_rsi 模拟替代
2025-05-07 15:39:36,746 - FreqaiExampleStrategy - WARNING - &-sell_rsi_pred 列不存在,正在使用 &-buy_rsi_pred + 20 模拟替代
2025-05-07 15:39:36,751 - FreqaiExampleStrategy - INFO - 目标列形状:(43250,)
2025-05-07 15:39:36,753 - FreqaiExampleStrategy - INFO - 目标列预览:
up_or_down &-buy_rsi
0 -0.000589 49.916851
1 -0.000785 49.916851
2 0.000393 49.916851
3 0.000000 49.916851
4 -0.000589 49.916851
2025-05-07 15:39:36,865 - FreqaiExampleStrategy - INFO - 设置 FreqAI 目标交易对OKB/USDT
2025-05-07 15:39:36,871 - FreqaiExampleStrategy - WARNING - &-buy_rsi_pred 列不存在,正在使用 &-buy_rsi 模拟替代
2025-05-07 15:39:36,873 - FreqaiExampleStrategy - WARNING - &-sell_rsi_pred 列不存在,正在使用 &-buy_rsi_pred + 20 模拟替代
2025-05-07 15:39:36,878 - FreqaiExampleStrategy - INFO - 目标列形状:(48050,)
2025-05-07 15:39:36,880 - FreqaiExampleStrategy - INFO - 目标列预览:
up_or_down &-buy_rsi
0 -0.000589 50.084414
1 -0.000785 50.084414
2 0.000393 50.084414
3 0.000000 50.084414
4 -0.000589 50.084414
2025-05-07 15:39:36,994 - freqtrade.freqai.freqai_interface - INFO - Could not find model at /freqtrade/user_data/models/test175/sub-train-OKB_1743811200/cb_okb_1743811200
2025-05-07 15:39:36,995 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Starting training OKB/USDT --------------------
2025-05-07 15:39:37,202 - freqtrade.freqai.data_kitchen - INFO - OKB/USDT: dropped 0 training points due to NaNs in populated dataset 43200.
2025-05-07 15:39:37,203 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Training on data from 2025-01-05 to 2025-04-04 --------------------
2025-05-07 15:39:37,358 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 243 features
2025-05-07 15:39:37,358 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - Training model on 34560 data points
[99] validation_0-rmse:0.20530 validation_1-rmse:0.08804
[199] validation_0-rmse:0.20032 validation_1-rmse:0.06900
2025-05-07 15:43:16,784 - freqtrade.freqai.base_models.BaseRegressionModel - INFO - -------------------- Done training OKB/USDT (219.79 secs) --------------------
2025-05-07 15:43:17,024 - freqtrade.plot.plotting - INFO - Stored plot as /freqtrade/user_data/models/test175/sub-train-OKB_1743811200/cb_okb_1743811200--buy_rsi.html
2025-05-07 15:43:17,025 - freqtrade.freqai.freqai_interface - INFO - Saving backtest model to disk.
2025-05-07 15:43:17,154 - datasieve.pipeline - WARNING - Could not find step di in pipeline, returning None
2025-05-07 15:43:18,218 - FreqaiExampleStrategy - DEBUG - do_predict 列存在前5行预览
do_predict
0 0.0
1 0.0
2 0.0
3 0.0
4 0.0
2025-05-07 15:43:18,225 - FreqaiExampleStrategy - INFO - 动态参数buy_rsi=29.835836601257324, sell_rsi=50.0, stoploss=-0.15, trailing_stop_positive=0.05
2025-05-07 15:43:19,453 - freqtrade.optimize.backtesting - INFO - Backtesting with data from 2025-04-05 00:00:00 up to 2025-04-15 00:00:00 (10 days).
2025-05-07 15:43:19,538 - FreqaiExampleStrategy - ERROR - MACD 或 MACD 信号列缺失,无法生成买入信号。尝试重新计算 MACD 列。
2025-05-07 15:43:19,540 - FreqaiExampleStrategy - INFO - MACD 列已成功重新计算。
2025-05-07 15:43:19,543 - FreqaiExampleStrategy - DEBUG - do_predict 列存在前5行预览
do_predict
0 0.0
1 0.0
2 0.0
3 0.0
4 0.0
2025-05-07 15:43:19,548 - FreqaiExampleStrategy - DEBUG - do_predict 列存在前5行预览
do_predict
0 0.0
1 0.0
2 0.0
3 0.0
4 0.0
2025-05-07 15:43:19,551 - FreqaiExampleStrategy - DEBUG - &-buy_rsi_pred 列存在前5行预览
&-buy_rsi_pred
0 20.0
1 20.0
2 20.0
3 20.0
4 20.0
2025-05-07 15:43:19,724 - freqtrade.misc - INFO - dumping json to "/freqtrade/user_data/backtest_results/backtest-result-2025-05-07_15-43-19.meta.json"
Result for strategy FreqaiExampleStrategy
BACKTESTING REPORT
┏━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Pair ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ OKB/USDT │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
│ TOTAL │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
└──────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
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 │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
│ TOTAL │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
└───────────┴─────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
EXIT REASON STATS
┏━━━━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Exit Reason ┃ Exits ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ roi │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
│ TOTAL │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
└─────────────┴───────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
MIXED TAG STATS
┏━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Enter Tag ┃ Exit Reason ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ long │ roi │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
│ TOTAL │ │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │
└───────────┴─────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┘
SUMMARY METRICS
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
┃ Metric ┃ Value ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
│ Backtesting from │ 2025-04-05 00:00:00 │
│ Backtesting to │ 2025-04-15 00:00:00 │
│ Trading Mode │ Spot │
│ Max open trades │ 1 │
│ │ │
│ Total/Daily Avg Trades │ 2 / 0.2 │
│ Starting balance │ 1000 USDT │
│ Final balance │ 1001.35 USDT │
│ Absolute profit │ 1.35 USDT │
│ Total profit % │ 0.13% │
│ CAGR % │ 5.05% │
│ Sortino │ -100.00 │
│ Sharpe │ 3.82 │
│ Calmar │ -100.00 │
│ SQN │ 1.00 │
│ Profit factor │ 0.00 │
│ Expectancy (Ratio) │ 0.67 (100.00) │
│ Avg. daily profit % │ 0.01% │
│ Avg. stake amount │ 150 USDT │
│ Total trade volume │ 602.313 USDT │
│ │ │
│ Best Pair │ OKB/USDT 0.13% │
│ Worst Pair │ OKB/USDT 0.13% │
│ Best trade │ OKB/USDT 0.90% │
│ Worst trade │ OKB/USDT 0.00% │
│ Best day │ 1.35 USDT │
│ Worst day │ 0 USDT │
│ Days win/draw/lose │ 1 / 1 / 0 │
│ Avg. Duration Winners │ 0:30:00 │
│ Avg. Duration Loser │ 0:00:00 │
│ Max Consecutive Wins / Loss │ 1 / 1 │
│ Rejected Entry signals │ 0 │
│ Entry/Exit Timeouts │ 0 / 0 │
│ │ │
│ Min balance │ 1000 USDT │
│ Max balance │ 1001.35 USDT │
│ Max % of account underwater │ 0.00% │
│ Absolute Drawdown (Account) │ 0.00% │
│ Absolute Drawdown │ 0 USDT │
│ Drawdown high │ 0 USDT │
│ Drawdown low │ 0 USDT │
│ Drawdown Start │ 2025-04-07 04:57:00 │
│ Drawdown End │ 2025-04-07 04:57:00 │
│ Market change │ 6.40% │
└─────────────────────────────┴─────────────────────┘
Backtested 2025-04-05 00:00:00 -> 2025-04-15 00:00:00 | Max open trades : 1
STRATEGY SUMMARY
┏━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Strategy ┃ Trades ┃ Avg Profit % ┃ Tot Profit USDT ┃ Tot Profit % ┃ Avg Duration ┃ Win Draw Loss Win% ┃ Drawdown ┃
┡━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ FreqaiExampleStrategy │ 2 │ 0.45 │ 1.350 │ 0.13 │ 0:54:00 │ 1 1 0 100 │ 0 USDT 0.00% │
└───────────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴───────────────┘