From da6d3fe292ceb46622eabcd344e29dc678438c31 Mon Sep 17 00:00:00 2001 From: "zhangkun9038@dingtalk.com" Date: Fri, 8 Aug 2025 21:53:23 +0800 Subject: [PATCH] =?UTF-8?q?hyperopt=20=E9=9C=80=E8=A6=81=E6=90=BA=E5=B8=A6?= =?UTF-8?q?=E4=B8=A4=E4=B8=AA=E6=97=A5=E6=9C=9F=E5=8F=82=E6=95=B0,?= =?UTF-8?q?=E7=B1=BB=E4=BC=BC:=20'2025-06-02=2008:00'=20'2025-06-04=2008:0?= =?UTF-8?q?0'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tools/hyperopt.sh | 295 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 226 insertions(+), 69 deletions(-) diff --git a/tools/hyperopt.sh b/tools/hyperopt.sh index 3a12f1c..6ace3de 100755 --- a/tools/hyperopt.sh +++ b/tools/hyperopt.sh @@ -4,10 +4,10 @@ if [ ! -f ".env" ]; then echo "⚠️ 本地缺少 .env 文件,请创建并配置。示例内容如下:" echo "" - echo "STRATEGY_NAME=FreqaiPrimer" - echo "CONFIG_FILE=FreqaiPrimer.json" - echo "TEST_BRANCH=freqaiprimer-deviation-test" - echo "DRYRUN_BRANCH=freqaiprimer-deviation-dryrun" + echo "STRATEGY_NAME=TheForceV7" + echo "CONFIG_FILE=basic.json" + echo "TEST_BRANCH=theforce-noai-test" + echo "DRYRUN_BRANCH=theforce-noai-dryrun" echo "" exit 1 fi @@ -15,101 +15,258 @@ fi # 加载 .env 文件中的变量 export $(grep -v '^#' .env | xargs) # 设置默认值 -STRATEGY_NAME=${STRATEGY_NAME:-FreqaiPrimer} -CONFIG_FILE=${CONFIG_FILE:-FreqaiPrimer.json} -PARAMS_NAME=$(echo "$STRATEGY_NAME" | tr '[:upper:]' '[:lower:]') +STRATEGY_NAME=${STRATEGY_NAME:-TheForceV7} +CONFIG_FILE=${CONFIG_FILE:-basic.json} echo "Using strategy: $STRATEGY_NAME" echo "Using config: $CONFIG_FILE" echo "Using testBranch: $TEST_BRANCH" -# Parse command line arguments -START_DATE=${1:-$(date -d "2 days ago" +"%Y%m%d")} -END_DATE=${2:-$(date -d "tomorrow" +"%Y%m%d")} -# Parse command line arguments -START_DATE_RAW=${1:-$(date -d "2 days ago" +"%Y-%m-%d %H:%M:%S")} -END_DATE_RAW=${2:-$(date -d "tomorrow" +"%Y-%m-%d %H:%M:%S")} -# Parse command line arguments -START_DATE_RAW=${1:-$(date -d "2 days ago" +"%Y-%m-%d 00:00")} -END_DATE_RAW=${2:-$(date -d "today" +"%Y-%m-%d 00:00")} +# Function to extract the value of a parameter +get_param_value() { + local param="$1" + shift + local args=("$@") + local i=0 -# Convert raw date strings to timestamps + while [ $i -lt ${#args[@]} ]; do + case "${args[$i]}" in + $param=*) + echo "${args[$i]#*=}" + return 0 + ;; + $param) + # Check if the next argument exists and does not start with a dash + if [ $((i + 1)) -lt ${#args[@]} ] && [[ "${args[$((i + 1))]}" != -* ]]; then + echo "${args[$((i + 1))]}" + return 0 + else + echo "Error: Missing value for parameter $param" >&2 + exit 1 + fi + ;; + esac + i=$((i + 1)) + done + return 0 +} + +# Check if we have named parameters +HAS_NAMED_PARAMS=false +for arg in "$@"; do + if [[ "$arg" == --* ]]; then + HAS_NAMED_PARAMS=true + break + fi +done + +# Initialize variables +START_DATE_RAW="" +END_DATE_RAW="" +PAIRS_ARG="" +PAIR_REMOTE_LIST_URL="" + +# Parse parameters based on whether we have named parameters +if [ "$HAS_NAMED_PARAMS" = true ]; then + # Use named parameter parsing + START_DATE_RAW=$(get_param_value "--start-date" "$@") + END_DATE_RAW=$(get_param_value "--end-date" "$@") + PAIRS_ARG=$(get_param_value "--pairs" "$@") + PAIR_REMOTE_LIST_URL=$(get_param_value "--pairRemoteList" "$@") +else + # Use positional parameter parsing + if [ $# -gt 0 ]; then + START_DATE_RAW="$1" + fi + if [ $# -gt 1 ]; then + END_DATE_RAW="$2" + fi + if [ $# -gt 2 ]; then + THIRD_PARAM="$3" + # Check if it's a URL + if [[ "$THIRD_PARAM" == http://* ]] || [[ "$THIRD_PARAM" == https://* ]]; then + PAIR_REMOTE_LIST_URL="$THIRD_PARAM" + echo "Detected URL parameter: $PAIR_REMOTE_LIST_URL" + # Check if it's a pair like "*/USDT" + elif [[ "$THIRD_PARAM" == */USDT ]] || [[ "$THIRD_PARAM" == */BUSD ]] || [[ "$THIRD_PARAM" == */USDC ]]; then + PAIRS_ARG="$THIRD_PARAM" + echo "Detected pair parameter: $PAIRS_ARG" + else + echo "Warning: Third parameter '$THIRD_PARAM' is neither a URL nor a pair" + fi + fi +fi + +# Set default values if parameters not provided +if [ -z "$START_DATE_RAW" ]; then + START_DATE_RAW=$(date -d "2 days ago" +"%Y-%m-%d %H:%M:%S") +fi + +if [ -z "$END_DATE_RAW" ]; then + END_DATE_RAW=$(date -d "tomorrow" +"%Y-%m-%d %H:%M:%S") +fi + +# Parse dates if [[ "$START_DATE_RAW" == *" "* ]]; then START_DATE=$(date -d "$START_DATE_RAW" +"%s") else - START_DATE=$(date -d "${START_DATE_RAW} 00:00:00" +"%s") + # 兼容旧格式:20250616 -> 转换为 2025-06-16 00:00:00 再转为时间戳 + START_DATE=$(date -d "${START_DATE_RAW:0:4}-${START_DATE_RAW:4:2}-${START_DATE_RAW:6:2} 00:00:00" +"%s") fi if [[ "$END_DATE_RAW" == *" "* ]]; then END_DATE=$(date -d "$END_DATE_RAW" +"%s") else - END_DATE=$(date -d "${END_DATE_RAW} 00:00:00" +"%s") + END_DATE=$(date -d "${END_DATE_RAW:0:4}-${END_DATE_RAW:4:2}-${END_DATE_RAW:6:2} 00:00:00" +"%s") +fi + +# Format end_date for URL parameter (YYYY-MM-DD format) +END_DATE_FORMATTED=$(date -d "@$END_DATE" "+%Y-%m-%d") + +# 处理交易对参数:优先级为 --pairRemoteList > --pairs > 默认值 +if [ -n "$PAIR_REMOTE_LIST_URL" ]; then + # 从远程API获取交易对列表 + echo "Fetching pairs from remote URL: $PAIR_REMOTE_LIST_URL" + pairs_json=$(curl -s "$PAIR_REMOTE_LIST_URL") + + # 检查API响应是否成功 + if [[ $? -ne 0 || -z "$pairs_json" ]]; then + echo "Error: Failed to fetch pairs from remote URL, using --pairs parameter or default" + if [ -n "$PAIRS_ARG" ]; then + PAIRS_FLAG="--pairs $PAIRS_ARG" + echo "Using pairs from --pairs parameter: $PAIRS_ARG" + else + # 使用默认的交易对列表 + DEFAULT_PAIRS="BTC/USDT TON/USDT DOT/USDT XRP/USDT OKB/USDT SOL/USDT DOGE/USDT WCT/USDT TRUMP/USDT SUI/USDT PEPE/USDT TRB/USDT MASK/USDT UNI/USDT KAITO/USDT" + PAIRS_FLAG="--pairs $DEFAULT_PAIRS" + echo "Using default pairs: $DEFAULT_PAIRS" + fi + else + # 解析JSON并提取交易对,将连字符替换为斜杠 + remote_pairs=$(echo "$pairs_json" | python3 -c " +import sys, json +data = json.load(sys.stdin) +pairs = [pair.replace('-', '/') for pair in data.get('pairlist', [])] +print(' '.join(pairs) if pairs else '') +") + + # 如果解析成功且有交易对 + if [[ -n "$remote_pairs" ]]; then + PAIRS_FLAG="--pairs $remote_pairs" + echo "Successfully fetched $(echo "$remote_pairs" | wc -w) pairs from remote URL" + echo "Pairs: $remote_pairs" + else + echo "Error: Failed to parse or empty pairlist from remote URL, using --pairs parameter or default" + if [ -n "$PAIRS_ARG" ]; then + PAIRS_FLAG="--pairs $PAIRS_ARG" + echo "Using pairs from --pairs parameter: $PAIRS_ARG" + else + # 使用默认的交易对列表 + DEFAULT_PAIRS="BTC/USDT TON/USDT DOT/USDT XRP/USDT OKB/USDT SOL/USDT DOGE/USDT WCT/USDT TRUMP/USDT SUI/USDT PEPE/USDT TRB/USDT MASK/USDT UNI/USDT KAITO/USDT" + PAIRS_FLAG="--pairs $DEFAULT_PAIRS" + echo "Using default pairs: $DEFAULT_PAIRS" + fi + fi + fi +elif [ -n "$PAIRS_ARG" ]; then + # 使用 --pairs 参数提供的交易对 + PAIRS_FLAG="--pairs $PAIRS_ARG" + echo "Using pairs from --pairs parameter: $PAIRS_ARG" + echo "Number of pairs: $(echo "$PAIRS_ARG" | wc -w)" +else + # 优先从指定URL获取交易对列表 + echo "Fetching pairs from primary URL with date parameter..." + PRIMARY_URL="http://pairlist.xl.home/api/pairlist?mute=true&count=30&date=${END_DATE_FORMATTED}" + echo "Requesting: $PRIMARY_URL" + + pairs_json=$(curl -s "$PRIMARY_URL") + + # 检查API响应是否成功 + if [[ $? -ne 0 || -z "$pairs_json" ]]; then + echo "Error: Failed to fetch pairs from primary URL, using default pairs" + # 使用默认的交易对列表 + DEFAULT_PAIRS="BTC/USDT TON/USDT DOT/USDT XRP/USDT OKB/USDT SOL/USDT DOGE/USDT WCT/USDT TRUMP/USDT SUI/USDT PEPE/USDT TRB/USDT MASK/USDT UNI/USDT KAITO/USDT" + PAIRS_FLAG="--pairs $DEFAULT_PAIRS" + echo "Using default pairs: $DEFAULT_PAIRS" + else + # 解析JSON并提取交易对,将连字符替换为斜杠 + remote_pairs=$(echo "$pairs_json" | python3 -c " +import sys, json +data = json.load(sys.stdin) +pairs = [pair.replace('-', '/') for pair in data.get('pairlist', [])] +print(' '.join(pairs) if pairs else '') +") + + # 如果解析成功且有交易对 + if [[ -n "$remote_pairs" ]]; then + PAIRS_FLAG="--pairs $remote_pairs" + echo "Successfully fetched $(echo "$remote_pairs" | wc -w) pairs from primary URL" + echo "Pairs: $remote_pairs" + else + echo "Error: Failed to parse or empty pairlist from primary URL, using default pairs" + # 使用默认的交易对列表 + DEFAULT_PAIRS="BTC/USDT TON/USDT DOT/USDT XRP/USDT OKB/USDT SOL/USDT DOGE/USDT WCT/USDT TRUMP/USDT SUI/USDT PEPE/USDT TRB/USDT MASK/USDT UNI/USDT KAITO/USDT" + PAIRS_FLAG="--pairs $DEFAULT_PAIRS" + echo "Using default pairs: $DEFAULT_PAIRS" + fi + fi fi -echo "Start timestamp: $START_TIMESTAMP" -echo "End timestamp: $END_TIMESTAMP" cd ../ source .venv/bin/activate rm -rf user_data/models/* rm -rf ./freqtrade/user_data/data/backtest_results/* rm -fr ./user_data/dryrun_results/* +rm result/* -#docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1 -echo "docker-compose run --rm freqtrade hyperopt \ +hyperopt_config="${STRATEGY_NAME%.py}.json" + +echo "docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --logfile /freqtrade/user_data/logs/freqtrade.log \ --freqaimodel LightGBMRegressorMultiTarget \ - --strategy $STRATEGY_NAME \ --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ --strategy-path /freqtrade/templates \ - --timerange ${START_DATE}-${END_DATE} \ - -e 100 \ - -j 4 \ - --hyperopt-loss ShortTradeDurHyperOptLoss \ - --spaces buy sell trailing \ - --fee 0.0016" -docker-compose run --rm freqtrade hyperopt \ + --strategy $STRATEGY_NAME \ + --timerange $START_DATE-$END_DATE \ + --fee 0.0008 \ + --breakdown day \ + --cache none >output.log" + +docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --logfile /freqtrade/user_data/logs/freqtrade.log \ --freqaimodel LightGBMRegressorMultiTarget \ - --strategy $STRATEGY_NAME \ --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ --strategy-path /freqtrade/templates \ - --timerange ${START_DATE}-${END_DATE} \ - -e 100 \ - -j 4 \ - --hyperopt-loss SharpeHyperOptLoss \ - --spaces buy sell trailing \ - --fee 0.0016 + --strategy $STRATEGY_NAME \ + --timerange $START_DATE-$END_DATE \ + --fee 0.0008 \ + --breakdown day \ + --cache none >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 +rm ./result/*.json -fr +rm ./result/*.py -fr +mv ./user_data/backtest_results/* ./result/ -# rm ./result/*.json -fr -# rm ./result/*.py -fr -# mv ./user_data/backtest_results/* ./result/ -# -# cd ./result -# # 查找当前目录下的所有 zip 文件 -# zip_files=(*.zip) -# -# # 检查是否只有一个 zip 文件 -# if [ ${#zip_files[@]} -eq 1 ]; then -# # 解压缩该 zip 文件到当前目录 -# unzip "${zip_files[0]}" -# rm *.zip -# rm *.feather -# else -# echo "当前目录下没有 zip 文件或者有多个 zip 文件,无法操作。" -# fi -# -# cd - -# sed -i 's/\x1B\[[0-9;]*m//g' output.log -# #python3 ../filter.py -# cp output.log result/ -f -# cd tools/ -# python tradestocsv.py -# python analytic.py >../result/analytic.log -# cd ../ +cd ./result +# 查找当前目录下的所有 zip 文件 +zip_files=(*.zip) + +# 检查是否只有一个 zip 文件 +if [ ${#zip_files[@]} -eq 1 ]; then + # 解压缩该 zip 文件到当前目录 + unzip "${zip_files[0]}" + rm *.zip + rm *.feather +else + echo "当前目录下没有 zip 文件或者有多个 zip 文件,无法操作。" +fi + +cd - +sed -i 's/\x1B\[[0-9;]*m//g' output.log +cp output.log result/ -f +cd tools/ +python tradestocsv.py +python analytic.py >../result/analytic.log +cd ../