#!/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="" # 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" "$@") STRATEGY_ARG=$(get_param_value "--strategy" "$@") # 支持 -t 作为 --strategy 的简化参数 if [ -z "$STRATEGY_ARG" ]; then STRATEGY_ARG=$(get_param_value "-t" "$@") 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 strategy name elif [[ "$THIRD_PARAM" =~ ^[a-zA-Z0-9]+$ ]]; then STRATEGY_ARG="$THIRD_PARAM" echo "Detected strategy parameter: $STRATEGY_ARG" else echo "Warning: Third parameter '$THIRD_PARAM' is neither a URL nor a pair nor a strategy" 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 # 兼容旧格式: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: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 # 如果命令行提供了策略参数,覆盖 .env 文件中的设置 if [ -n "$STRATEGY_ARG" ]; then STRATEGY_NAME="$STRATEGY_ARG" echo "Overriding strategy from command line: $STRATEGY_NAME" 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/* PARAMS_NAME=freqaiprimer hyperopt_config="${STRATEGY_NAME%.py}.json" echo "docker-compose run --rm freqtrade hyperopt $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 \ --enable-protections \ --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 $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 \ --enable-protections \ --strategy-path /freqtrade/templates \ --timerange ${START_DATE}-${END_DATE} \ -e 500 \ -j 4 \ --hyperopt-loss SharpeHyperOptLossDaily \ --spaces buy sell \ --fee 0.0016