diff --git a/debug_timerange.sh b/debug_timerange.sh new file mode 100755 index 00000000..14cab7ff --- /dev/null +++ b/debug_timerange.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# 直接测试脚本逻辑 + +# 模拟脚本中的变量设置 +START_DATE_RAW="20260118" +END_DATE_RAW="20260218" + +echo "=== Testing date processing ===" +echo "Input dates:" +echo "START_DATE_RAW: $START_DATE_RAW" +echo "END_DATE_RAW: $END_DATE_RAW" + +# 处理日期格式(模拟脚本中的逻辑) +START_DATE_STR="${START_DATE_RAW:0:4}-${START_DATE_RAW:4:2}-${START_DATE_RAW:6:2}" +END_DATE_STR="${END_DATE_RAW:0:4}-${END_DATE_RAW:4:2}-${END_DATE_RAW:6:2}" + +echo "" +echo "Processed dates:" +echo "START_DATE_STR: $START_DATE_STR" +echo "END_DATE_STR: $END_DATE_STR" + +# 构建 timerange +TIMERANGE_ARG="$START_DATE_STR/$END_DATE_STR" +echo "" +echo "TIMERANGE_ARG: $TIMERANGE_ARG" + +# 检查格式是否正确 +if [[ "$TIMERANGE_ARG" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}/[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then + echo "✓ Timerange format is CORRECT" +else + echo "✗ Timerange format is WRONG" +fi + +# 测试命令行参数 +echo "" +echo "=== Testing command construction ===" +PAIRS_FLAG="--pairs XAUT/USDT" +STRATEGY_NAME="FreqaiPrimer" +FREQAI_MODEL="MyCoolRLModel" + +echo "Full command would be:" +echo "docker-compose run --rm freqtrade backtesting $PAIRS_FLAG --timerange $TIMERANGE_ARG --strategy $STRATEGY_NAME" + +echo "" +echo "=== Testing with actual command ===" +echo "Would execute:" +echo "docker-compose run --rm freqtrade backtesting --pairs XAUT/USDT --timerange 2026-01-18/2026-02-18 --strategy FreqaiPrimer" \ No newline at end of file diff --git a/simple_test.sh b/simple_test.sh new file mode 100755 index 00000000..dfb90c36 --- /dev/null +++ b/simple_test.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# 简化测试脚本 + +# 模拟参数 +START_DATE_RAW="20260118" +END_DATE_RAW="20260218" + +# 处理日期 +START_DATE_STR="${START_DATE_RAW:0:4}-${START_DATE_RAW:4:2}-${START_DATE_RAW:6:2}" +END_DATE_STR="${END_DATE_RAW:0:4}-${END_DATE_RAW:4:2}-${END_DATE_RAW:6:2}" + +# 构建正确的 timerange 格式 +TIMERANGE_ARG="$START_DATE_STR/$END_DATE_STR" + +echo "Testing timerange format:" +echo "START_DATE_STR: $START_DATE_STR" +echo "END_DATE_STR: $END_DATE_STR" +echo "TIMERANGE_ARG: $TIMERANGE_ARG" + +# 测试命令行参数 +CMD="docker-compose run --rm freqtrade backtesting --pairs XAUT/USDT --timerange $TIMERANGE_ARG" +echo "Command would be: $CMD" \ No newline at end of file diff --git a/tools/backtest.sh b/tools/backtest.sh index eaa0ea96..a28514d0 100755 --- a/tools/backtest.sh +++ b/tools/backtest.sh @@ -111,28 +111,22 @@ else 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") +# Parse dates - ONLY process if we have raw dates (not from named parameters) +if [ -z "$START_DATE_RAW" ] && [ -z "$END_DATE_RAW" ] && [ $# -gt 0 ]; then + # If we don't have named parameters and we have positional args, process them + if [ $# -gt 0 ]; then + START_DATE_RAW="$1" + fi + if [ $# -gt 1 ]; then + END_DATE_RAW="$2" + fi fi -if [ -z "$END_DATE_RAW" ]; then - END_DATE_RAW=$(date -d "tomorrow" +"%Y-%m-%d %H:%M:%S") -fi - -# Parse dates +# Process date formats START_DATE_STR="" END_DATE_STR="" -# 从原始参数中提取日期 -if [ $# -gt 0 ]; then - START_DATE_RAW="$1" -fi -if [ $# -gt 1 ]; then - END_DATE_RAW="$2" -fi - -# 处理日期格式 +# Handle date processing if [[ "$START_DATE_RAW" == *" "* ]]; then START_DATE_STR=$(date -d "$START_DATE_RAW" +"%Y-%m-%d") else @@ -147,7 +141,7 @@ else END_DATE_STR="${END_DATE_RAW:0:4}-${END_DATE_RAW:4:2}-${END_DATE_RAW:6:2}" fi -# 确保日期格式正确 +# Validate date formats if [[ ! "$START_DATE_STR" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then echo "Error: Invalid start date format: $START_DATE_STR" exit 1 @@ -158,7 +152,7 @@ if [[ ! "$END_DATE_STR" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then exit 1 fi -# 构建正确的 timerange 格式 (YYYY-MM-DD/YYYY-MM-DD) +# Build correct timerange format (YYYY-MM-DD/YYYY-MM-DD) TIMERANGE_ARG="$START_DATE_STR/$END_DATE_STR" # 处理交易对参数:优先级为 --pairRemoteList > --pairs > 默认值 @@ -226,11 +220,6 @@ rm result/* hyperopt_config="${STRATEGY_NAME%.py}.json" -# Debug: Print date variables to check format -echo "DEBUG: START_DATE_STR = '$START_DATE_STR'" -echo "DEBUG: END_DATE_STR = '$END_DATE_STR'" -echo "DEBUG: TIMERANGE_ARG = '$TIMERANGE_ARG'" - echo "docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --logfile /freqtrade/user_data/logs/freqtrade.log \ --freqaimodel $FREQAI_MODEL \ @@ -282,4 +271,4 @@ cp output.log result/ -f cd tools/ python tradestocsv.py python analytic.py >../result/analytic.log -cd ../ +cd ../ \ No newline at end of file diff --git a/tools/backtest_fixed.sh b/tools/backtest_fixed.sh new file mode 100644 index 00000000..a28514d0 --- /dev/null +++ b/tools/backtest_fixed.sh @@ -0,0 +1,274 @@ +#!/bin/bash + +# 检查 .env 文件 +if [ ! -f ".env" ]; then + echo "⚠️ 本地缺少 .env 文件,请创建并配置。示例内容如下:" + echo "" + 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 + +# 加载 .env 文件中的变量 +export $(grep -v '^#' .env | xargs) +# 设置默认值 +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" + +# Function to extract the value of a parameter +get_param_value() { + local param="$1" + shift + local args=("$@") + local i=0 + + 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="" +FREQAI_MODEL="MyCoolRLModel" + +# 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" "$@") + # 只有当提供了 --freqaimodel 参数时才获取它 + FREQAI_MODEL_PROVIDED=$(get_param_value "--freqaimodel" "$@") + if [ -n "$FREQAI_MODEL_PROVIDED" ]; then + FREQAI_MODEL="$FREQAI_MODEL_PROVIDED" + fi +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" + # Check if it's a -pairs flag (backward compatibility) + elif [[ "$THIRD_PARAM" == -pairs ]]; then + if [ $# -gt 3 ]; then + PAIRS_ARG="$4" + echo "Detected pair parameter: $PAIRS_ARG" + else + echo "Warning: -pairs flag provided but no pairs value" + fi + else + echo "Warning: Third parameter '$THIRD_PARAM' is neither a URL nor a pair" + fi + fi +fi + +# Parse dates - ONLY process if we have raw dates (not from named parameters) +if [ -z "$START_DATE_RAW" ] && [ -z "$END_DATE_RAW" ] && [ $# -gt 0 ]; then + # If we don't have named parameters and we have positional args, process them + if [ $# -gt 0 ]; then + START_DATE_RAW="$1" + fi + if [ $# -gt 1 ]; then + END_DATE_RAW="$2" + fi +fi + +# Process date formats +START_DATE_STR="" +END_DATE_STR="" + +# Handle date processing +if [[ "$START_DATE_RAW" == *" "* ]]; then + START_DATE_STR=$(date -d "$START_DATE_RAW" +"%Y-%m-%d") +else + # 兼容旧格式:20260118 -> 转换为 2026-01-18 + START_DATE_STR="${START_DATE_RAW:0:4}-${START_DATE_RAW:4:2}-${START_DATE_RAW:6:2}" +fi + +if [[ "$END_DATE_RAW" == *" "* ]]; then + END_DATE_STR=$(date -d "$END_DATE_RAW" +"%Y-%m-%d") +else + # 兼容旧格式:20260218 -> 转换为 2026-02-18 + END_DATE_STR="${END_DATE_RAW:0:4}-${END_DATE_RAW:4:2}-${END_DATE_RAW:6:2}" +fi + +# Validate date formats +if [[ ! "$START_DATE_STR" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then + echo "Error: Invalid start date format: $START_DATE_STR" + exit 1 +fi + +if [[ ! "$END_DATE_STR" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then + echo "Error: Invalid end date format: $END_DATE_STR" + exit 1 +fi + +# Build correct timerange format (YYYY-MM-DD/YYYY-MM-DD) +TIMERANGE_ARG="$START_DATE_STR/$END_DATE_STR" + +# 处理交易对参数:优先级为 --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 + # 使用默认的交易对列表 - 只保留Meme类币对 + DEFAULT_PAIRS="BTC/USDT TRUMP/USDT PEPE/USDT KAITO/USDT DOGE/USDT WCT/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 + # 使用默认的交易对列表 - 只保留Meme类币对 + DEFAULT_PAIRS="BTC/USDT TRUMP/USDT PEPE/USDT KAITO/USDT DOGE/USDT WCT/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" +else + # 没有提供任何交易对参数,使用默认值 - 只保留Meme类币对 + DEFAULT_PAIRS="BTC/USDT TRUMP/USDT PEPE/USDT KAITO/USDT DOGE/USDT WCT/USDT" + PAIRS_FLAG="--pairs $DEFAULT_PAIRS" + echo "No pairs parameter provided, using default pairs: $DEFAULT_PAIRS" +fi + +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/* + +hyperopt_config="${STRATEGY_NAME%.py}.json" + +echo "docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ + --logfile /freqtrade/user_data/logs/freqtrade.log \ + --freqaimodel $FREQAI_MODEL \ + --config /freqtrade/config_examples/freqaiprimer.json \ + --config /freqtrade/config_examples/$CONFIG_FILE \ + --strategy-path /freqtrade/templates \ + --strategy $STRATEGY_NAME \ + --timerange $TIMERANGE_ARG \ + --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 $FREQAI_MODEL \ + --config /freqtrade/config_examples/freqaiprimer.json \ + --config /freqtrade/config_examples/$CONFIG_FILE \ + --strategy-path /freqtrade/templates \ + --enable-protections \ + --strategy $STRATEGY_NAME \ + --timerange $TIMERANGE_ARG \ + --fee 0.0008 \ + --breakdown day \ + --cache none >output.log 2>&1 + +sed -i 's/\x1B\[[0-9;]*m//g' output.log + +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 +cp output.log result/ -f +cd tools/ +python tradestocsv.py +python analytic.py >../result/analytic.log +cd ../ \ No newline at end of file