backtest hyperopt都可以了

This commit is contained in:
Ubuntu 2025-05-17 18:48:33 +08:00
parent d748c37f6a
commit c232264487
5 changed files with 189 additions and 133 deletions

View File

@ -35,10 +35,7 @@
}, },
"pair_whitelist": [ "pair_whitelist": [
"BTC/USDT", "BTC/USDT",
"OKB/USDT", "SOL/USDT"
"TON/USDT",
"SOL/USDT",
"DOT/USDT"
], ],
"pair_blacklist": [] "pair_blacklist": []
}, },
@ -70,7 +67,7 @@
"freqaimodel": "CatboostClassifier", "freqaimodel": "CatboostClassifier",
"purge_old_models": 2, "purge_old_models": 2,
"train_period_days": 15, "train_period_days": 15,
"identifier": "test77", "identifier": "test58",
"train_period_days": 30, "train_period_days": 30,
"backtest_period_days": 10, "backtest_period_days": 10,
"live_retrain_hours": 0, "live_retrain_hours": 0,

View File

@ -0,0 +1,32 @@
{
"strategy_name": "FreqaiPrimer",
"params": {
"max_open_trades": {
"max_open_trades": 4
},
"buy": {
"buy_rsi": 39.01486243151008
},
"sell": {
"sell_rsi": 69.01486243151008
},
"protection": {},
"roi": {
"0": 0.21500000000000002,
"8": 0.081,
"38": 0.028,
"57": 0
},
"stoploss": {
"stoploss": -0.029
},
"trailing": {
"trailing_stop": true,
"trailing_stop_positive": 0.246,
"trailing_stop_positive_offset": 0.33799999999999997,
"trailing_only_offset_is_reached": true
}
},
"ft_stratparam_v": 1,
"export_time": "2025-05-17 10:28:46.008125+00:00"
}

View File

@ -1,9 +1,7 @@
import logging import logging
import numpy as np import numpy as np
import pandas as pd
from functools import reduce from functools import reduce
import talib.abstract as ta import talib.abstract as ta
from typing import Dict, List, Optional
from pandas import DataFrame from pandas import DataFrame
from technical import qtpylib from technical import qtpylib
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
@ -11,29 +9,32 @@ from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class FreqaiPrimer(IStrategy): class FreqaiPrimer(IStrategy):
minimal_roi = {} minimal_roi = {
stoploss = 0.0 0: 0.135,
9: 0.052,
15: 0.007,
60: 0
}
stoploss = -0.263
trailing_stop = True trailing_stop = True
trailing_stop_positive = 0.324
trailing_stop_positive_offset = 0.411
trailing_only_offset_is_reached = False
max_open_trades = 4
process_only_new_candles = True process_only_new_candles = True
use_exit_signal = True use_exit_signal = True
startup_candle_count: int = 40 startup_candle_count: int = 40
can_short = False can_short = False
# Hyperopt 参数 buy_rsi = IntParameter(low=10, high=50, default=30, space="buy", optimize=False, load=True)
buy_rsi = IntParameter(low=10, high=50, default=27, space="buy", optimize=False, load=True) sell_rsi = IntParameter(low=50, high=90, default=70, space="sell", optimize=False, load=True)
sell_rsi = IntParameter(low=50, high=90, default=59, space="sell", optimize=False, load=True) roi_0 = DecimalParameter(low=0.01, high=0.2, default=0.135, space="roi", optimize=True, load=True)
roi_0 = DecimalParameter(low=0.01, high=0.2, default=0.038, space="roi", optimize=True, load=True) roi_15 = DecimalParameter(low=0.005, high=0.1, default=0.052, 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.007, 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.263, space="stoploss", optimize=True, load=True)
stoploss_param = DecimalParameter(low=-0.25, high=-0.05, default=-0.1, space="stoploss", optimize=True, load=True) trailing_stop_positive_param = DecimalParameter(low=0.1, high=0.5, default=0.324, space="trailing", optimize=True, load=True)
trailing_stop_positive_offset_param = DecimalParameter(low=0.2, high=0.6, default=0.411, space="trailing", optimize=True, load=True)
# 保护机制
protections = [
{"method": "StoplossGuard", "stop_duration": 60, "lookback_period": 120},
{"method": "MaxDrawdown", "lookback_period": 120, "max_allowed_drawdown": 0.05}
]
# FreqAI 配置
freqai_info = { freqai_info = {
"model": "LightGBMRegressor", "model": "LightGBMRegressor",
"feature_parameters": { "feature_parameters": {
@ -47,9 +48,9 @@ class FreqaiPrimer(IStrategy):
"shuffle": False, "shuffle": False,
}, },
"model_training_parameters": { "model_training_parameters": {
"n_estimators": 100, "n_estimators": 200,
"learning_rate": 0.1, "learning_rate": 0.05,
"num_leaves": 15, # 降低以减少警告 "num_leaves": 31,
"verbose": -1, "verbose": -1,
}, },
} }
@ -64,16 +65,6 @@ class FreqaiPrimer(IStrategy):
"do_predict": {"do_predict": {"color": "brown"}}, "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 feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame: def feature_engineering_expand_all(self, dataframe: DataFrame, period: int, metadata: dict, **kwargs) -> DataFrame:
dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period) dataframe["%-rsi-period"] = ta.RSI(dataframe, timeperiod=period)
@ -96,7 +87,6 @@ class FreqaiPrimer(IStrategy):
dataframe = dataframe.replace([np.inf, -np.inf], 0) dataframe = dataframe.replace([np.inf, -np.inf], 0)
dataframe = dataframe.ffill() dataframe = dataframe.ffill()
dataframe = dataframe.fillna(0) dataframe = dataframe.fillna(0)
logger.info(f"最终数据框列:\n{dataframe.columns.to_list()}")
return dataframe return dataframe
def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame: def feature_engineering_expand_basic(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
@ -109,11 +99,14 @@ class FreqaiPrimer(IStrategy):
return dataframe return dataframe
def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame: def feature_engineering_standard(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
if len(dataframe["close"]) < 20:
logger.warning(f"数据不足 {len(dataframe)} 根 K 线,%-volatility 可能不完整")
dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek dataframe["%-day_of_week"] = dataframe["date"].dt.dayofweek
dataframe["%-hour_of_day"] = dataframe["date"].dt.hour dataframe["%-hour_of_day"] = dataframe["date"].dt.hour
dataframe = dataframe.replace([np.inf, -np.inf], 0) dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
dataframe = dataframe.ffill() dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
dataframe = dataframe.fillna(0) dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
return dataframe return dataframe
def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame: def set_freqai_targets(self, dataframe: DataFrame, metadata: dict, **kwargs) -> DataFrame:
@ -124,16 +117,22 @@ class FreqaiPrimer(IStrategy):
try: try:
label_period = self.freqai_info["feature_parameters"]["label_period_candles"] label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std() if "%-volatility" not in dataframe.columns:
logger.info(f"Generated %-volatility column: {dataframe['%-volatility'].head().to_string()}") logger.warning("缺少 %-volatility 列,强制重新生成")
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14).shift(-label_period) dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
dataframe["&-buy_rsi"] = ta.RSI(dataframe, timeperiod=14)
dataframe["&-buy_rsi"] = dataframe["&-buy_rsi"].shift(-label_period).ffill().bfill()
for col in ["&-buy_rsi", "%-volatility"]: for col in ["&-buy_rsi", "%-volatility"]:
dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0) dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
dataframe[col] = dataframe[col].ffill() dataframe[col] = dataframe[col].ffill()
dataframe[col] = dataframe[col].fillna(0) dataframe[col] = dataframe[col].fillna(0)
if dataframe[col].isna().any(): if dataframe[col].isna().any():
logger.warning(f"目标列 {col} 仍包含 NaN检查数据生成逻辑") logger.warning(f"目标列 {col} 仍包含 NaN数据预览:\n{dataframe[col].tail(10)}")
except Exception as e: except Exception as e:
logger.error(f"创建 FreqAI 目标失败:{str(e)}") logger.error(f"创建 FreqAI 目标失败:{str(e)}")
raise raise
@ -143,12 +142,10 @@ class FreqaiPrimer(IStrategy):
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
logger.info(f"处理交易对:{metadata['pair']}") logger.info(f"处理交易对:{metadata['pair']}")
logger.info(f"开始 FreqAI 处理,交易对:{metadata['pair']}") logger.debug(f"输入特征列:{list(dataframe.columns)}")
logger.info(f"输入数据框列:\n{dataframe.columns.to_list()}")
dataframe = self.freqai.start(dataframe, metadata, self) dataframe = self.freqai.start(dataframe, metadata, self)
logger.info(f"FreqAI 处理后数据框列:\n{dataframe.columns.to_list()}") logger.debug(f"FreqAI 输出特征列:{list(dataframe.columns)}")
# 计算传统指标
dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14)
bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2)
dataframe["bb_lowerband"] = bollinger["lower"] dataframe["bb_lowerband"] = bollinger["lower"]
@ -156,70 +153,58 @@ class FreqaiPrimer(IStrategy):
dataframe["bb_upperband"] = bollinger["upper"] dataframe["bb_upperband"] = bollinger["upper"]
dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9) dataframe["tema"] = ta.TEMA(dataframe, timeperiod=9)
# 生成 up_or_down 信号
label_period = self.freqai_info["feature_parameters"]["label_period_candles"] label_period = self.freqai_info["feature_parameters"]["label_period_candles"]
dataframe["up_or_down"] = np.where( dataframe["up_or_down"] = np.where(
dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0 dataframe["close"].shift(-label_period) > dataframe["close"], 1, 0
) )
# 预填充 NaN
dataframe = dataframe.ffill()
dataframe = dataframe.fillna(0)
if "&-buy_rsi" in dataframe.columns: if "&-buy_rsi" in dataframe.columns:
if "%-volatility" not in dataframe.columns or dataframe["%-volatility"].isna().any(): if "%-volatility" not in dataframe.columns:
logger.error("Critical column '%-volatility' is missing or contains NaN values.") logger.warning("缺少 %-volatility 列,强制重新生成")
raise ValueError("Missing or invalid '%-volatility' column") dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20, min_periods=1).std()
# 派生其他目标 dataframe["%-volatility"] = dataframe["%-volatility"].replace([np.inf, -np.inf], 0)
dataframe["%-volatility"] = dataframe["%-volatility"].ffill()
dataframe["%-volatility"] = dataframe["%-volatility"].fillna(0)
dataframe["&-sell_rsi"] = dataframe["&-buy_rsi"] + 30 dataframe["&-sell_rsi"] = dataframe["&-buy_rsi"] + 30
dataframe["%-volatility"] = dataframe["close"].pct_change().rolling(20).std() dataframe["&-stoploss"] = self.stoploss - (dataframe["%-volatility"] * 5).clip(-0.05, 0.05)
dataframe["&-stoploss"] = -0.1 - (dataframe["%-volatility"] * 10).clip(0, 0.25)
dataframe["&-roi_0"] = (dataframe["close"].shift(-label_period) / dataframe["close"] - 1).clip(0, 0.2) dataframe["&-roi_0"] = (dataframe["close"].shift(-label_period) / dataframe["close"] - 1).clip(0, 0.2)
# 计算预测值并减少 NaN for col in ["&-buy_rsi", "&-sell_rsi", "&-stoploss", "&-roi_0"]:
dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(5, min_periods=1).mean().clip(10, 50) dataframe[col] = dataframe[col].replace([np.inf, -np.inf], 0)
dataframe["sell_rsi_pred"] = dataframe["&-sell_rsi"].rolling(5, min_periods=1).mean().clip(50, 90) dataframe[col] = dataframe[col].ffill()
dataframe["stoploss_pred"] = dataframe["&-stoploss"].clip(-0.25, -0.05) dataframe[col] = dataframe[col].fillna(0)
dataframe["buy_rsi_pred"] = dataframe["&-buy_rsi"].rolling(5).mean().clip(10, 50)
dataframe["sell_rsi_pred"] = dataframe["&-sell_rsi"].rolling(5).mean().clip(50, 90)
dataframe["stoploss_pred"] = dataframe["&-stoploss"].clip(-0.35, -0.1)
dataframe["roi_0_pred"] = dataframe["&-roi_0"].clip(0.01, 0.2) dataframe["roi_0_pred"] = dataframe["&-roi_0"].clip(0.01, 0.2)
# 处理 NaN for col in ["buy_rsi_pred", "sell_rsi_pred", "stoploss_pred", "roi_0_pred"]:
for col in ["buy_rsi_pred", "sell_rsi_pred", "stoploss_pred", "roi_0_pred", "&-sell_rsi", "&-stoploss", "&-roi_0"]:
if dataframe[col].isna().any(): if dataframe[col].isna().any():
logger.warning(f"{col} 包含 NaN填充为默认值") logger.warning(f"{col} 包含 NaN填充为默认值")
mean_value = dataframe[col].mean() dataframe[col] = dataframe[col].ffill()
if pd.isna(mean_value): dataframe[col] = dataframe[col].fillna(dataframe[col].mean())
logger.warning(f"{col} 均值仍为 NaN使用默认值")
mean_value = {
"buy_rsi_pred": 30,
"sell_rsi_pred": 70,
"stoploss_pred": -0.1,
"roi_0_pred": 0.05,
"&-sell_rsi": 70,
"&-stoploss": -0.1,
"&-roi_0": 0.05
}.get(col, 0)
dataframe[col] = dataframe[col].fillna(mean_value)
# 动态追踪止盈
dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3) dataframe["trailing_stop_positive"] = (dataframe["roi_0_pred"] * 0.5).clip(0.01, 0.3)
dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.75).clip(0.02, 0.4) dataframe["trailing_stop_positive_offset"] = (dataframe["roi_0_pred"] * 0.75).clip(0.02, 0.4)
# 设置动态参数
self.stoploss = float(dataframe["stoploss_pred"].iloc[-1])
self.buy_rsi.value = float(dataframe["buy_rsi_pred"].iloc[-1]) self.buy_rsi.value = float(dataframe["buy_rsi_pred"].iloc[-1])
self.sell_rsi.value = float(dataframe["sell_rsi_pred"].iloc[-1]) self.sell_rsi.value = float(dataframe["sell_rsi_pred"].iloc[-1])
self.stoploss = float(self.stoploss_param.value)
self.minimal_roi = { self.minimal_roi = {
0: float(self.roi_0.value), 0: float(self.roi_0.value),
15: float(self.roi_15.value), 15: float(self.roi_15.value),
30: float(self.roi_30.value), 30: float(self.roi_30.value),
60: 0.0 60: 0
} }
self.trailing_stop_positive = float(dataframe["trailing_stop_positive"].iloc[-1]) self.trailing_stop_positive = float(self.trailing_stop_positive_param.value)
self.trailing_stop_positive_offset = float(dataframe["trailing_stop_positive_offset"].iloc[-1]) self.trailing_stop_positive_offset = float(self.trailing_stop_positive_offset_param.value)
logger.info(f"minimal_roi 键:{list(self.minimal_roi.keys())}")
logger.info(f"动态参数buy_rsi={self.buy_rsi.value}, sell_rsi={self.sell_rsi.value}, " 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}") f"stoploss={self.stoploss}, trailing_stop_positive={self.trailing_stop_positive}")
else:
logger.warning(f"&-buy_rsi 列缺失,跳过 FreqAI 预测逻辑,检查 freqai.start 输出")
dataframe = dataframe.replace([np.inf, -np.inf], 0) dataframe = dataframe.replace([np.inf, -np.inf], 0)
dataframe = dataframe.ffill() dataframe = dataframe.ffill()
@ -227,12 +212,13 @@ class FreqaiPrimer(IStrategy):
logger.info(f"up_or_down 值统计:\n{dataframe['up_or_down'].value_counts().to_string()}") logger.info(f"up_or_down 值统计:\n{dataframe['up_or_down'].value_counts().to_string()}")
logger.info(f"do_predict 值统计:\n{dataframe['do_predict'].value_counts().to_string()}") logger.info(f"do_predict 值统计:\n{dataframe['do_predict'].value_counts().to_string()}")
logger.debug(f"最终特征列:{list(dataframe.columns)}")
return dataframe return dataframe
def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame: def populate_entry_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
enter_long_conditions = [ enter_long_conditions = [
qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"] + (5 if metadata["pair"] == "BTC/USDT" else 0)), qtpylib.crossed_above(df["rsi"], df["buy_rsi_pred"]),
df["tema"] > df["tema"].shift(1), df["tema"] > df["tema"].shift(1),
df["volume"] > 0, df["volume"] > 0,
df["do_predict"] == 1, df["do_predict"] == 1,
@ -247,17 +233,15 @@ class FreqaiPrimer(IStrategy):
def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame: def populate_exit_trend(self, df: DataFrame, metadata: dict) -> DataFrame:
exit_long_conditions = [ exit_long_conditions = [
(qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"])) | qtpylib.crossed_above(df["rsi"], df["sell_rsi_pred"]),
(df["close"] < df["close"].shift(1) * 0.98) | (df["close"] < df["close"].shift(1) * 0.97),
(df["close"] < df["bb_lowerband"]),
df["volume"] > 0, df["volume"] > 0,
df["do_predict"] == 1, df["do_predict"] == 1,
df["up_or_down"] == 0 df["up_or_down"] == 0
] ]
time_exit = (df["date"] >= df["date"].shift(1) + pd.Timedelta(days=1)) if exit_long_conditions:
df.loc[ df.loc[
(reduce(lambda x, y: x & y, exit_long_conditions)) | time_exit, reduce(lambda x, y: x & y, exit_long_conditions),
"exit_long" "exit_long"
] = 1 ] = 1
return df return df
@ -266,9 +250,28 @@ class FreqaiPrimer(IStrategy):
self, pair: str, order_type: str, amount: float, rate: float, self, pair: str, order_type: str, amount: float, rate: float,
time_in_force: str, current_time, entry_tag, side: str, **kwargs time_in_force: str, current_time, entry_tag, side: str, **kwargs
) -> bool: ) -> bool:
try:
df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) df, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = df.iloc[-1].squeeze() if df is None or df.empty:
if side == "long": logger.warning(f"无法获取 {pair} 的分析数据,拒绝交易")
if rate > (last_candle["close"] * (1 + 0.001)):
return False return False
last_candle = df.iloc[-1].squeeze()
if "close" not in last_candle or np.isnan(last_candle["close"]):
logger.warning(f"{pair} 的最新 K 线缺少有效 close 价格,拒绝交易")
return False
if side == "long":
max_rate = last_candle["close"] * (1 + 0.0025) # 0.25% 滑点阈值
if rate > max_rate:
logger.debug(f"拒绝 {pair} 的买入,价格 {rate} 超过最大允许价格 {max_rate}")
return False
elif side == "short":
logger.warning(f"{pair} 尝试做空,但策略不支持做空 (can_short={self.can_short})")
return False
logger.debug(f"确认 {pair} 的交易side={side}, rate={rate}, close={last_candle['close']}")
return True return True
except Exception as e:
logger.error(f"确认 {pair} 交易时出错:{str(e)}")
return False

View File

@ -34,6 +34,17 @@ rm result/*
hyperopt_config="${STRATEGY_NAME%.py}.json" hyperopt_config="${STRATEGY_NAME%.py}.json"
#docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1 #docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1
echo "docker-compose run --rm freqtrade backtesting \
--logfile /freqtrade/user_data/logs/freqtrade.log \
--freqaimodel LightGBMRegressor \
--config /freqtrade/config_examples/$CONFIG_FILE \
--strategy-path /freqtrade/templates \
--strategy $STRATEGY_NAME \
--timerange $START_DATE-$END_DATE \
--fee 0.0008 \
--cache none >output.log"
docker-compose run --rm freqtrade backtesting \ docker-compose run --rm freqtrade backtesting \
--logfile /freqtrade/user_data/logs/freqtrade.log \ --logfile /freqtrade/user_data/logs/freqtrade.log \
--freqaimodel LightGBMRegressor \ --freqaimodel LightGBMRegressor \
@ -42,6 +53,7 @@ docker-compose run --rm freqtrade backtesting \
--strategy $STRATEGY_NAME \ --strategy $STRATEGY_NAME \
--timerange $START_DATE-$END_DATE \ --timerange $START_DATE-$END_DATE \
--fee 0.0008 \ --fee 0.0008 \
--breakdown day \
--cache none >output.log 2>&1 --cache none >output.log 2>&1
sed -i 's/\x1B\[[0-9;]*m//g' output.log sed -i 's/\x1B\[[0-9;]*m//g' output.log

View File

@ -32,45 +32,57 @@ rm -rf ./freqtrade/user_data/data/backtest_results/*
rm -fr ./user_data/dryrun_results/* rm -fr ./user_data/dryrun_results/*
#docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1 #docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1
freqtrade hyperopt \ echo "docker-compose run --rm freqtrade hyperopt \
--logfile ./user_data/logs/freqtrade.log \ --logfile /freqtrade/user_data/logs/freqtrade.log \
--freqaimodel XGBoostRegressor \ --freqaimodel LightGBMRegressor \
--strategy $STRATEGY_NAME \ --strategy $STRATEGY_NAME \
--config config_examples/$CONFIG_FILE \ --config /freqtrade/config_examples/$CONFIG_FILE \
--strategy-path ./freqtrade/templates \ --strategy-path /freqtrade/templates \
--timerange ${START_DATE}-${END_DATE} \ --timerange ${START_DATE}-${END_DATE} \
--epochs 100 \ -e 200 \
--hyperopt-loss ShortTradeDurHyperOptLoss \ --hyperopt-loss ShortTradeDurHyperOptLoss \
--spaces stoploss \ --spaces roi stoploss trailing \
--fee 0.0016"
docker-compose run --rm freqtrade hyperopt \
--logfile /freqtrade/user_data/logs/freqtrade.log \
--freqaimodel LightGBMRegressor \
--strategy $STRATEGY_NAME \
--config /freqtrade/config_examples/$CONFIG_FILE \
--strategy-path /freqtrade/templates \
--timerange ${START_DATE}-${END_DATE} \
-e 200 \
--hyperopt-loss ShortTradeDurHyperOptLoss \
--spaces roi stoploss trailing \
--fee 0.0016 --fee 0.0016
#>output.log 2>&1 #>output.log 2>&1
#sed -i 's/\x1B\[[0-9;]*m//g' output.log #sed -i 's/\x1B\[[0-9;]*m//g' output.log
#python3 tools/filter.py #python3 tools/filter.py
rm ./result/*.json -fr # rm ./result/*.json -fr
rm ./result/*.py -fr # rm ./result/*.py -fr
mv ./user_data/backtest_results/* ./result/ # mv ./user_data/backtest_results/* ./result/
#
cd ./result # cd ./result
# 查找当前目录下的所有 zip 文件 # # 查找当前目录下的所有 zip 文件
zip_files=(*.zip) # zip_files=(*.zip)
#
# 检查是否只有一个 zip 文件 # # 检查是否只有一个 zip 文件
if [ ${#zip_files[@]} -eq 1 ]; then # if [ ${#zip_files[@]} -eq 1 ]; then
# 解压缩该 zip 文件到当前目录 # # 解压缩该 zip 文件到当前目录
unzip "${zip_files[0]}" # unzip "${zip_files[0]}"
rm *.zip # rm *.zip
rm *.feather # rm *.feather
else # else
echo "当前目录下没有 zip 文件或者有多个 zip 文件,无法操作。" # echo "当前目录下没有 zip 文件或者有多个 zip 文件,无法操作。"
fi # fi
#
cd - # cd -
sed -i 's/\x1B\[[0-9;]*m//g' output.log # sed -i 's/\x1B\[[0-9;]*m//g' output.log
#python3 ../filter.py # #python3 ../filter.py
cp output.log result/ -f # cp output.log result/ -f
cd tools/ # cd tools/
python tradestocsv.py # python tradestocsv.py
python analytic.py >../result/analytic.log # python analytic.py >../result/analytic.log
cd ../ # cd ../