myTestFreqAI/tools/hyperopt_org.sh
2025-10-14 17:15:32 +08:00

350 lines
12 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 文件中的变量
if [ -f .env ]; then
set -a
source .env
set +a
fi
# 设置默认值
STRATEGY_NAME=${STRATEGY_NAME:-TheForceV7}
CONFIG_FILE=${CONFIG_FILE:-basic.json}
TEST_BRANCH=${TEST_BRANCH:-develop}
# 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
fi
# 如果参数存在但没有值,返回特殊标识"PARAM_WITHOUT_VALUE"
echo "PARAM_WITHOUT_VALUE"
return 0
;;
esac
i=$((i + 1))
done
# 如果参数不存在,返回空字符串
echo ""
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
# 处理命名参数时跳过已解析的参数
parsed_args=()
while [ $# -gt 0 ]; do
case "$1" in
--start-date|--end-date|--pairs|--pairRemoteList|--strategy|-t|--config)
parsed_args+=("$1" "$2")
shift 2
;;
*)
parsed_args+=("$1")
shift
;;
esac
done
set -- "${parsed_args[@]}"
# 使用命名参数解析
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" "$@")
if [ -z "$STRATEGY_ARG" ]; then
STRATEGY_ARG=$(get_param_value "-t" "$@")
fi
CONFIG_ARG=$(get_param_value "--config" "$@")
else
# Use positional parameter parsing
if [ $# -gt 0 ]; then
START_DATE_RAW="$1"
fi
if [ $# -gt 1 ]; then
END_DATE_RAW="$2"
fi
# 参数顺序说明
# 位置参数模式:
# $0 [开始日期] [结束日期] [策略名] [交易对/URL]
# 命名参数模式:
# --start-date=YYYYMMDD --end-date=YYYYMMDD --strategy=NAME --pairs=PAIRS
# 混合使用位置和命名参数时,命名参数优先
if [ $# -gt 2 ]; then
STRATEGY_ARG="$3"
echo "Detected strategy parameter: $STRATEGY_ARG"
fi
# 第4参数处理交易对或URL
if [ $# -gt 3 ]; then
FOURTH_PARAM="$4"
if [[ "$FOURTH_PARAM" == http://* ]] || [[ "$FOURTH_PARAM" == https://* ]]; then
PAIR_REMOTE_LIST_URL="$FOURTH_PARAM"
echo "Detected URL parameter: $PAIR_REMOTE_LIST_URL"
elif [[ "$FOURTH_PARAM" == */USDT ]] || [[ "$FOURTH_PARAM" == */BUSD ]] || [[ "$FOURTH_PARAM" == */USDC ]]; then
PAIRS_ARG="$FOURTH_PARAM"
echo "Detected pair parameter: $PAIRS_ARG"
fi
fi
# 增强策略名检测逻辑
# 增强参数类型校验
if [ $# -gt 3 ]; then
FOURTH_PARAM="$4"
if [[ "$FOURTH_PARAM" =~ ^[0-9]{8}$ ]]; then
echo "错误第4个参数应该是交易对或URL而不是日期"
exit 1
elif [[ "$FOURTH_PARAM" == http://* ]] || [[ "$FOURTH_PARAM" == https://* ]]; then
PAIR_REMOTE_LIST_URL="$FOURTH_PARAM"
echo "检测到远程交易对列表URL: $PAIR_REMOTE_LIST_URL"
elif [[ "$FOURTH_PARAM" == */* ]]; then
PAIRS_ARG="$FOURTH_PARAM"
echo "检测到交易对参数: $PAIRS_ARG"
elif [[ "$FOURTH_PARAM" == *.py ]]; then
echo "警告:策略参数应通过-t或--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" =~ ^[0-9]{8}$ ]]; then
# 处理YYYYMMDD格式
START_DATE=$(date -d "${START_DATE_RAW:0:4}-${START_DATE_RAW:4:2}-${START_DATE_RAW:6:2}" +"%s" 2>/dev/null)
if [ -z "$START_DATE" ]; then
echo "错误:无效的起始日期格式 $START_DATE_RAW,请使用 YYYY-MM-DD 或 YYYYMMDD"
exit 1
fi
elif [[ "$START_DATE_RAW" == *" "* ]]; then
START_DATE=$(date -d "$START_DATE_RAW" +"%s" 2>/dev/null)
if [ -z "$START_DATE" ]; then
echo "错误:无效的起始日期格式 $START_DATE_RAW"
exit 1
fi
else
echo "错误:未知的日期格式 $START_DATE_RAW"
exit 1
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
# 处理交易对参数:优先级为 --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"
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 "No pairs parameter provided, using default pairs: $DEFAULT_PAIRS"
fi
# 如果命令行提供了有效的策略参数,覆盖.env文件设置
if [ -n "$STRATEGY_ARG" ] && [ "$STRATEGY_ARG" != "PARAM_WITHOUT_VALUE" ]; then
# 策略类名保持不变如MyStrategy但文件名使用小写
STRATEGY_CLASS_NAME="$STRATEGY_ARG"
STRATEGY_FILE_NAME="$(echo "$STRATEGY_ARG" | tr '[:upper:]' '[:lower:]').py"
STRATEGY_NAME="$STRATEGY_FILE_NAME"
echo "Overriding strategy with command line parameter: $STRATEGY_CLASS_NAME"
echo "Strategy class name: $STRATEGY_CLASS_NAME"
echo "Strategy file name: $STRATEGY_FILE_NAME"
# 自动匹配策略对应的配置文件(使用小写)
STRATEGY_CONFIG_LOWER="$(echo "$STRATEGY_ARG" | tr '[:upper:]' '[:lower:]').json"
echo "Checking auto-matched config file: freqtrade/templates/$STRATEGY_CONFIG_LOWER"
# 检查小写配置文件
if [ -f "../freqtrade/templates/$STRATEGY_CONFIG_LOWER" ]; then
CONFIG_FILE="$STRATEGY_CONFIG_LOWER"
echo "Auto-matched config file for strategy: $CONFIG_FILE"
else
echo "Warning: Auto-matched config file '$STRATEGY_CONFIG_LOWER' not found in templates directory"
echo "Available config files in templates directory:"
ls ../freqtrade/templates/*.json 2>/dev/null | sed 's|.*/||' || echo "No JSON config files found"
echo "Using current config: $CONFIG_FILE"
fi
fi
# 如果命令行提供了配置参数,覆盖.env文件设置
if [ -n "$CONFIG_ARG" ]; then
CONFIG_FILE="$CONFIG_ARG"
echo "Overriding config with command line parameter: $CONFIG_FILE"
fi
# 检查指定的配置文件是否存在,如果不存在则使用默认配置
echo "Checking config file: freqtrade/templates/$CONFIG_FILE"
if [ ! -f "../freqtrade/templates/$CONFIG_FILE" ]; then
echo "Warning: Config file freqtrade/templates/$CONFIG_FILE not found, using default configuration"
CONFIG_FILE="basic.json"
else
echo "Config file found: freqtrade/templates/$CONFIG_FILE"
fi
# 最后确认STRATEGY_NAME有值
if [ -z "$STRATEGY_NAME" ]; then
echo "Warning: STRATEGY_NAME is empty, using default TheForceV7"
STRATEGY_NAME="TheForceV7"
fi
# 确保STRATEGY_CLASS_NAME有值
if [ -z "$STRATEGY_CLASS_NAME" ]; then
echo "Warning: STRATEGY_CLASS_NAME is empty, setting to STRATEGY_NAME value"
STRATEGY_CLASS_NAME="$STRATEGY_NAME"
fi
# 在参数处理完成后输出最终使用的值
# 显示完整使用帮助
echo "正确用法示例:"
echo "位置参数模式:"
echo " $0 20230901 20231001 MartinGale BTC/USDT"
echo "命名参数模式:"
echo " $0 --start-date=20230901 --end-date=20231001 -t MartinGale"
echo "Using strategy: $STRATEGY_NAME"
echo "Using config: $CONFIG_FILE"
echo "Using testBranch: $TEST_BRANCH"
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 -f result/*
PARAMS_NAME=freqaiprimer
echo "docker-compose run --rm freqtrade hyperopt $PAIRS_FLAG \
--logfile /freqtrade/user_data/logs/freqtrade.log \
--freqaimodel LightGBMRegressorMultiTarget \
--strategy $STRATEGY_CLASS_NAME \
--config /freqtrade/config_examples/$CONFIG_FILE \
--config /freqtrade/templates/${PARAMS_NAME}.json \
--enable-protections \
--strategy-path /freqtrade/templates \
--timerange ${START_DATE}-${END_DATE} \
--random-state 19 \
-e 2500 \
-j 20 \
--hyperopt-loss SharpeHyperOptLossDaily \
--spaces sell \
--fee 0.001"
docker-compose run --rm freqtrade hyperopt $PAIRS_FLAG \
--logfile /freqtrade/user_data/logs/freqtrade.log \
--freqaimodel LightGBMRegressorMultiTarget \
--strategy $STRATEGY_CLASS_NAME \
--config /freqtrade/config_examples/$CONFIG_FILE \
--config /freqtrade/templates/${PARAMS_NAME}.json \
--enable-protections \
--strategy-path /freqtrade/templates \
--timerange ${START_DATE}-${END_DATE} \
--random-state 19 \
-e 2500 \
-j 4 \
--hyperopt-loss SharpeHyperOptLossDaily \
<<<<<<< Updated upstream
--spaces roi stoploss trailing \
=======
--spaces sell \
>>>>>>> Stashed changes
--fee 0.001