force up
This commit is contained in:
parent
4df3623b96
commit
e558c1b0bd
95
config_examples/nb.json
Normal file
95
config_examples/nb.json
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
192
freqtrade/templates/TheForceFreqaiStrategy.py
Normal file
192
freqtrade/templates/TheForceFreqaiStrategy.py
Normal 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
|
||||
206
freqtrade/templates/v7-v7-2.diff
Normal file
206
freqtrade/templates/v7-v7-2.diff
Normal 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
187
freqtrade/templates/v7.py
Normal 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
11423
output.log
File diff suppressed because it is too large
Load Diff
11225
output_filted.log
11225
output_filted.log
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
{"FreqaiExampleStrategy":{"run_id":"508f04f53e3b629d04b7cc23f20ff499670e9ae4","backtest_start_time":1746632368,"timeframe":"3m","timeframe_detail":null,"backtest_start_ts":1743811200,"backtest_end_ts":1744675200}}
|
||||
@ -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"
|
||||
}
|
||||
@ -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
|
||||
@ -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"]}
|
||||
@ -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% │
|
||||
└───────────────────────┴────────┴──────────────┴─────────────────┴──────────────┴──────────────┴────────────────────────┴───────────────┘
|
||||
Loading…
x
Reference in New Issue
Block a user