diff --git a/dryrun.sh b/dryrun.sh new file mode 100644 index 00000000..e69de29b diff --git a/tools/backtest.sh b/tools/backtest.sh index adc1b9bb..c3877e89 100755 --- a/tools/backtest.sh +++ b/tools/backtest.sh @@ -21,50 +21,22 @@ 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 - while [[ $# -gt 0 ]]; do - case "$1" in - $param=*) - echo "${1#*=}" - return - ;; - $param) - # Check if the next argument exists and does not start with a dash - if [[ -n "$2" && "$2" != -* ]]; then - echo "$2" - return - else - echo "Error: Missing value for parameter $param" >&2 - exit 1 - fi - ;; - esac - shift - done - echo "" - return -} - # Parse command line arguments -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" "$@") - -# 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") +START_DATE=${1:-$(date -d "2 days ago" +"%Y%m%d")} +END_DATE=${2:-$(date -d "tomorrow" +"%Y%m%d")} +PAIRS_ARG=${3:-""} # Optional --pairs argument for docker-compose +PARAMS_NAME=$(echo "$STRATEGY_NAME" | tr '[:upper:]' '[:lower:]') +# If PAIRS_ARG is provided, format it for docker-compose +if [ -n "$PAIRS_ARG" ]; then + PAIRS_FLAG="--pairs $PAIRS_ARG" +else + PAIRS_FLAG="" fi +# 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")} -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 @@ -78,57 +50,6 @@ 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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - 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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - fi - fi - fi -elif [ -n "$PAIRS_ARG" ]; then - # 使用 --pairs 参数提供的交易对 - PAIRS_FLAG="--pairs $PAIRS_ARG" - echo "Using pairs from --pairs parameter: $PAIRS_ARG" -else - # 没有提供任何交易对参数 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" -fi - cd ../ source .venv/bin/activate rm -rf user_data/models/* @@ -137,6 +58,7 @@ rm -fr ./user_data/dryrun_results/* rm result/* hyperopt_config="${STRATEGY_NAME%.py}.json" +#docker-compose -f docker-compose_backtest.yml run --rm freqtrade >output.log 2>&1 echo "docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --logfile /freqtrade/user_data/logs/freqtrade.log \ @@ -146,9 +68,8 @@ echo "docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --strategy $STRATEGY_NAME \ --timerange $START_DATE-$END_DATE \ --fee 0.0008 \ - --breakdown day \ --cache none >output.log" - +#LightGBMRegressorMultiTarget docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --logfile /freqtrade/user_data/logs/freqtrade.log \ --freqaimodel LightGBMRegressorMultiTarget \ @@ -159,1051 +80,10 @@ docker-compose run --rm freqtrade backtesting $PAIRS_FLAG \ --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 ../ -``` - -## 新增功能说明 - -### 1. 新增参数 `--pairRemoteList` -- **作用**:指定一个返回交易对列表的API URL -- **优先级**:最高优先级,如果提供则忽略 `--pairs` 参数 -- **示例**: - ```bash - ./backtest.sh --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" - ``` - -### 2. 交易对参数优先级 -参数优先级从高到低: -1. `--pairRemoteList`:从远程API获取交易对 -2. `--pairs`:使用命令行指定的交易对 -3. 无参数:使用Freqtrade默认的交易对 - -### 3. 远程API处理逻辑 -- 使用 `curl` 获取API响应 -- 使用Python解析JSON,提取 `pairlist` 数组 -- 将连字符格式(如 "BTC-USDT")转换为斜杠格式("BTC/USDT") -- 包含完整的错误处理机制 - -### 4. 使用示例 - -```bash -# 使用远程API获取交易对 -./backtest.sh --start-date 20250616 --end-date 20250618 --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" - -# 使用远程API(简洁格式) -./backtest.sh --pairRemoteList=http://pairlist.xl.home/api/pairlist?mute=true&count=50 - -# 混合使用参数 -./backtest.sh --start-date=20250616 --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" --end-date 20250618 - -# 回退到 --pairs 参数(当API失败时) -./backtest.sh --pairRemoteList "http://invalid-url.com" --pairs BTC/USDT,SOL/USDT -``` - -这个修改使得脚本能够灵活地从远程API获取动态交易对列表,同时保持了向后兼容性和健壮的错误处理能力。 - -------- - -- Datetime: 2025-08-05 13:15:57 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - - tools/dryrun.sh - -> dryrun.sh 也按照此方式进行修改 -> - - -我将按照 `backtest.sh` 的修改方式,为 `dryrun.sh` 脚本添加命名参数支持。以下是完整的修改: - -```bash -#!/bin/bash - -set -e # 出错立即停止 - -# 检查 .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 - export $(grep -v '^#' .env | xargs) -else - echo "⚠️ 缺少 .env 文件,请创建并配置 TEST_BRANCH 和 DRYRUN_BRANCH" - exit 1 -fi - -# 获取当前分支名 -current_branch=$(git rev-parse --abbrev-ref HEAD) - -# 检查当前分支是否匹配 TEST_BRANCH 或 DRYRUN_BRANCH -if [[ "$current_branch" != "$TEST_BRANCH" && "$current_branch" != "$DRYRUN_BRANCH" ]]; then - echo "⚠️ 错误:当前分支 '$current_branch' 不符合环境变量配置要求。" - echo "请确保当前分支与 .env 文件中的 TEST_BRANCH 或 DRYRUN_BRANCH 配置一致。" - echo "TEST_BRANCH=$TEST_BRANCH" - echo "DRYRUN_BRANCH=$DRYRUN_BRANCH" - exit 1 -else - echo "✅ 当前分支 '$current_branch' 符合环境变量配置要求。" -fi - -# 如果当前分支名称包含 "dryrun",执行 git reset --hard -if [[ "$current_branch" == *"dryrun"* ]]; then - echo "当前分支为 '$current_branch',正在执行 git reset --hard 以确保代码干净..." - git reset --hard - if [ $? -ne 0 ]; then - echo "⚠️ 执行 git reset --hard 失败,请检查 Git 状态。" - exit 1 - fi - echo "Git 工作区已清理。" -fi - -# Function to extract the value of a parameter -get_param_value() { - local param="$1" - shift - while [[ $# -gt 0 ]]; do - case "$1" in - $param=*) - echo "${1#*=}" - return - ;; - $param) - # Check if the next argument exists and does not start with a dash - if [[ -n "$2" && "$2" != -* ]]; then - echo "$2" - return - else - echo "Error: Missing value for parameter $param" >&2 - exit 1 - fi - ;; - esac - shift - done - echo "" - return -} - -# Parse command line arguments -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" "$@") - -# 加载 .env 文件中的变量 -export $(grep -v '^#' .env | xargs) -# 设置默认值 -STRATEGY_NAME=${STRATEGY_NAME:-TheForceV7} -CONFIG_FILE=${CONFIG_FILE:-basic.json} -PARAMS_NAME=$(echo "$STRATEGY_NAME" | tr '[:upper:]' '[:lower:]') - -echo "Using strategy: $STRATEGY_NAME" -echo "Using config: $CONFIG_FILE" -echo "Using testBranch: $TEST_BRANCH" - -# Set default values if parameters not provided -if [ -z "$START_DATE_RAW" ]; then - START_DATE_RAW=$(date -d "2 days ago" +"%Y%m%d") -fi - -if [ -z "$END_DATE_RAW" ]; then - END_DATE_RAW=$(date -d "tomorrow" +"%Y%m%d") -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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - 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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - fi - fi - fi -elif [ -n "$PAIRS_ARG" ]; then - # 使用 --pairs 参数提供的交易对 - PAIRS_FLAG="--pairs $PAIRS_ARG" - echo "Using pairs from --pairs parameter: $PAIRS_ARG" -else - # 没有提供任何交易对参数 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" -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/* || true - -hyperopt_config="${STRATEGY_NAME%.py}.json" -docker rm $(docker ps -aq) -f || true - -# 获取当前 Git Commit 的前 8 位 -GIT_COMMIT_SHORT=$(git rev-parse HEAD | cut -c 1-8) - -echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \ - --logfile /freqtrade/user_data/logs/freqtrade.log \ - --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \ - --dry-run \ - --freqaimodel LightGBMRegressorMultiTarget \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ - --strategy $STRATEGY_NAME \ - --config /freqtrade/freqtrade/templates/${STRATEGY_NAME}.json \ - --fee 0.0008 \ - --strategy-path /freqtrade/templates" - -docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \ - $PAIRS_FLAG \ - --logfile /freqtrade/user_data/logs/freqtrade.log \ - --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \ - --dry-run \ - --freqaimodel LightGBMRegressorMultiTarget \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ - --strategy $STRATEGY_NAME \ - --config /freqtrade/freqtrade/templates/${STRATEGY_NAME}.json \ - --fee 0.0008 \ - --strategy-path /freqtrade/templates -``` - -## 主要变更 - -### 1. 添加命名参数支持 -- `--start-date`:指定开始日期 -- `--end-date`:指定结束日期 -- `--pairs`:指定交易对 -- `--pairRemoteList`:从远程API获取交易对列表 - -### 2. 统一参数处理逻辑 -与 `backtest.sh` 保持一致的参数解析方式: -- 使用 `get_param_value` 函数解析参数 -- 支持 `--param=value` 和 `--param value` 两种格式 -- 完整的错误处理机制 - -### 3. 交易对处理逻辑 -与 `backtest.sh` 完全相同的交易对优先级逻辑: -1. `--pairRemoteList`:从远程API获取 -2. `--pairs`:使用命令行指定 -3. 无参数:使用默认值 - -### 4. 使用示例 - -```bash -# 使用默认日期范围 -./dryrun.sh - -# 指定开始和结束日期 -./dryrun.sh --start-date 20250616 --end-date 20250618 - -# 指定交易对 -./dryrun.sh --pairs BTC/USDT,SOL/USDT - -# 从远程API获取交易对 -./dryrun.sh --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" - -# 组合使用所有参数 -./dryrun.sh --start-date 20250616 --end-date 20250618 --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" -``` - -这个修改使得 `dryrun.sh` 与 `backtest.sh` 在参数处理上保持一致,提高了脚本的可维护性和用户体验。 - -------- - -- Datetime: 2025-08-05 13:16:41 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - - tools/dryrun.sh - -> 停止 -> - - -好的,我已经完成了 `dryrun.sh` 脚本的修改,使其支持命名参数,包括新增的 `--pairRemoteList` 参数。修改后的脚本具有以下特性: - -1. 支持 `--start-date`、`--end-date`、`--pairs` 和 `--pairRemoteList` 命名参数 -2. 参数优先级:`--pairRemoteList` > `--pairs` > 默认值 -3. 从远程API获取交易对列表时,会将连字符格式(如 "BTC-USDT")转换为斜杠格式("BTC/USDT") -4. 包含完整的错误处理机制,当API调用失败时会回退到其他参数或默认行为 - -如果您需要我继续完成脚本的剩余部分或进行其他修改,请告诉我。 - -------- - -- Datetime: 2025-08-05 13:17:05 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - - tools/dryrun.sh - -> 停 - - -好的,我已经停止了所有操作。如果您有任何其他问题或需要进一步的帮助,请随时告诉我。 - -------- - -- Datetime: 2025-08-05 13:18:07 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - - tools/dryrun.sh - -> dryrun也进行类似的修改, 值增加 --pairsRemoteList 参数 以及进行相应的处置, 无需增加 start-date, end-date这些恶参数 - - -Error: { - exit = 35, - message = 'post https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions - curl error exit_code=35 stderr={ "curl: (35) error:0A000126:SSL routines::unexpected eof while reading" }', - stderr = '{ "curl: (35) error:0A000126:SSL routines::unexpected eof while reading" }' -} - -------- - -- Datetime: 2025-08-05 13:18:16 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - - tools/dryrun.sh - -> -> > dryrun也进行类似的修改, 值增加 --pairsRemoteList 参数 以及进行相应的处置, 无需增加 start-date, end-date这些恶参数 - - -我将修改 `dryrun.sh` 脚本,只添加 `--pairRemoteList` 参数支持,而不添加日期相关参数。以下是修改后的完整脚本: - -```bash -#!/bin/bash - -set -e # 出错立即停止 - -# 检查 .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 - export $(grep -v '^#' .env | xargs) -else - echo "⚠️ 缺少 .env 文件,请创建并配置 TEST_BRANCH 和 DRYRUN_BRANCH" - exit 1 -fi - -# 获取当前分支名 -current_branch=$(git rev-parse --abbrev-ref HEAD) - -# 检查当前分支是否匹配 TEST_BRANCH 或 DRYRUN_BRANCH -if [[ "$current_branch" != "$TEST_BRANCH" && "$current_branch" != "$DRYRUN_BRANCH" ]]; then - echo "⚠️ 错误:当前分支 '$current_branch' 不符合环境变量配置要求。" - echo "请确保当前分支与 .env 文件中的 TEST_BRANCH 或 DRYRUN_BRANCH 配置一致。" - echo "TEST_BRANCH=$TEST_BRANCH" - echo "DRYRUN_BRANCH=$DRYRUN_BRANCH" - exit 1 -else - echo "✅ 当前分支 '$current_branch' 符合环境变量配置要求。" -fi - -# 如果当前分支名称包含 "dryrun",执行 git reset --hard -if [[ "$current_branch" == *"dryrun"* ]]; then - echo "当前分支为 '$current_branch',正在执行 git reset --hard 以确保代码干净..." - git reset --hard - if [ $? -ne 0 ]; then - echo "⚠️ 执行 git reset --hard 失败,请检查 Git 状态。" - exit 1 - fi - echo "Git 工作区已清理。" -fi - -# Function to extract the value of a parameter -get_param_value() { - local param="$1" - shift - while [[ $# -gt 0 ]]; do - case "$1" in - $param=*) - echo "${1#*=}" - return - ;; - $param) - # Check if the next argument exists and does not start with a dash - if [[ -n "$2" && "$2" != -* ]]; then - echo "$2" - return - else - echo "Error: Missing value for parameter $param" >&2 - exit 1 - fi - ;; - esac - shift - done - echo "" - return -} - -# Parse command line arguments -PAIRS_ARG=$(get_param_value "--pairs" "$@") -PAIR_REMOTE_LIST_URL=$(get_param_value "--pairRemoteList" "$@") - -# 加载 .env 文件中的变量 -export $(grep -v '^#' .env | xargs) -# 设置默认值 -STRATEGY_NAME=${STRATEGY_NAME:-TheForceV7} -CONFIG_FILE=${CONFIG_FILE:-basic.json} -PARAMS_NAME=$(echo "$STRATEGY_NAME" | tr '[:upper:]' '[:lower:]') - -echo "Using strategy: $STRATEGY_NAME" -echo "Using config: $CONFIG_FILE" -echo "Using testBranch: $TEST_BRANCH" - -# 处理交易对参数:优先级为 --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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - 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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - fi - fi - fi -elif [ -n "$PAIRS_ARG" ]; then - # 使用 --pairs 参数提供的交易对 - PAIRS_FLAG="--pairs $PAIRS_ARG" - echo "Using pairs from --pairs parameter: $PAIRS_ARG" -else - # 没有提供任何交易对参数 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" -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/* || true - -hyperopt_config="${STRATEGY_NAME%.py}.json" -docker rm $(docker ps -aq) -f || true - -# 获取当前 Git Commit 的前 8 位 -GIT_COMMIT_SHORT=$(git rev-parse HEAD | cut -c 1-8) - -echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \ - --logfile /freqtrade/user_data/logs/freqtrade.log \ - --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \ - --dry-run \ - --freqaimodel LightGBMRegressorMultiTarget \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ - --strategy $STRATEGY_NAME \ - --config /freqtrade/freqtrade/templates/${STRATEGY_NAME}.json \ - --fee 0.0008 \ - --strategy-path /freqtrade/templates" - -docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \ - $PAIRS_FLAG \ - --logfile /freqtrade/user_data/logs/freqtrade.log \ - --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \ - --dry-run \ - --freqaimodel LightGBMRegressorMultiTarget \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ - --strategy $STRATEGY_NAME \ - --config /freqtrade/freqtrade/templates/${STRATEGY_NAME}.json \ - --fee 0.0008 \ - --strategy-path /freqtrade/templates -``` - -## 主要变更 - -1. **添加 `--pairRemoteList` 参数支持**:允许从远程API获取交易对列表 -2. **保留 `--pairs` 参数**:支持通过命令行指定交易对 -3. **参数优先级**:`--pairRemoteList` > `--pairs` > 默认值 -4. **不添加日期参数**:如您要求,没有添加 `--start-date` 和 `--end-date` 参数 -5. **统一的交易对处理逻辑**:与 `backtest.sh` 保持一致的处理方式 - -### 使用示例 - -```bash -# 使用默认配置 -./dryrun.sh - -# 指定交易对 -./dryrun.sh --pairs BTC/USDT,SOL/USDT - -# 从远程API获取交易对 -./dryrun.sh --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" - -# 组合使用(远程API优先级更高) -./dryrun.sh --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" --pairs BTC/USDT -``` - -这个修改使得 `dryrun.sh` 脚本能够灵活地从远程API获取动态交易对列表,同时保持了简单性和向后兼容性。 - -------- - -- Datetime: 2025-08-05 13:56:50 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - - tools/dryrun.sh - - tools/live.sh - -> live.sh也改成这种形式 -> - - -我将修改 `live.sh` 脚本,使其支持 `--pairs` 和 `--pairRemoteList` 参数,与 `backtest.sh` 和 `dryrun.sh` 保持一致。以下是修改后的完整脚本: - -```bash -#!/bin/bash - -set -e # 出错立即停止 - -# 检查 .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 - export $(grep -v '^#' .env | xargs) -else - echo "⚠️ 缺少 .env 文件,请创建并配置 TEST_BRANCH 和 DRYRUN_BRANCH" - exit 1 -fi - -# 获取当前分支名 -current_branch=$(git rev-parse --abbrev-ref HEAD) - -# 检查当前分支是否匹配 TEST_BRANCH 或 DRYRUN_BRANCH -if [[ "$current_branch" != "$TEST_BRANCH" && "$current_branch" != "$DRYRUN_BRANCH" ]]; then - echo "⚠️ 错误:当前分支 '$current_branch' 不符合环境变量配置要求。" - echo "请确保当前分支与 .env 文件中的 TEST_BRANCH 或 DRYRUN_BRANCH 配置一致。" - echo "TEST_BRANCH=$TEST_BRANCH" - echo "DRYRUN_BRANCH=$DRYRUN_BRANCH" - exit 1 -else - echo "✅ 当前分支 '$current_branch' 符合环境变量配置要求。" -fi - -# 如果当前分支名称包含 "dryrun",执行 git reset --hard -if [[ "$current_branch" == *"dryrun"* ]]; then - echo "当前分支为 '$current_branch',正在执行 git reset --hard 以确保代码干净..." - git reset --hard - if [ $? -ne 0 ]; then - echo "⚠️ 执行 git reset --hard 失败,请检查 Git 状态。" - exit 1 - fi - echo "Git 工作区已清理。" -fi - -# Function to extract the value of a parameter -get_param_value() { - local param="$1" - shift - while [[ $# -gt 0 ]]; do - case "$1" in - $param=*) - echo "${1#*=}" - return - ;; - $param) - # Check if the next argument exists and does not start with a dash - if [[ -n "$2" && "$2" != -* ]]; then - echo "$2" - return - else - echo "Error: Missing value for parameter $param" >&2 - exit 1 - fi - ;; - esac - shift - done - echo "" - return -} - -# Parse command line arguments -PAIRS_ARG=$(get_param_value "--pairs" "$@") -PAIR_REMOTE_LIST_URL=$(get_param_value "--pairRemoteList" "$@") - -# 加载 .env 文件中的变量 -export $(grep -v '^#' .env | xargs) -# 设置默认值 -STRATEGY_NAME=${STRATEGY_NAME:-TheForceV7} -CONFIG_FILE=${CONFIG_FILE:-basic.json} -# 设置 PARAMS_NAME 为 STRATEGY_NAME 的小写形式 -PARAMS_NAME=$(echo "$STRATEGY_NAME" | tr '[:upper:]' '[:lower:]') - -echo "Using strategy: $STRATEGY_NAME" -echo "Using config: $CONFIG_FILE" -echo "Using testBranch: $TEST_BRANCH" - -# 处理交易对参数:优先级为 --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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - 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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - fi - fi - fi -elif [ -n "$PAIRS_ARG" ]; then - # 使用 --pairs 参数提供的交易对 - PAIRS_FLAG="--pairs $PAIRS_ARG" - echo "Using pairs from --pairs parameter: $PAIRS_ARG" -else - # 没有提供任何交易对参数 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" -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/* || true - -hyperopt_config="${STRATEGY_NAME%.py}.json" -docker rm $(docker ps -aq) -f || true - -# 获取当前 Git Commit 的前 8 位 -GIT_COMMIT_SHORT=$(git rev-parse HEAD | cut -c 1-8) -echo "docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \ - --logfile /freqtrade/user_data/logs/freqtrade.log \ - --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \ - --freqaimodel LightGBMRegressorMultiTarget \ - --fee 0.0008 - --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ - --config /freqtrade/config_examples/live.json \ - --strategy $STRATEGY_NAME \ - --strategy-path /freqtrade/templates" - -docker-compose run -d --rm --name freqtrade-dryrun-${GIT_COMMIT_SHORT} -p 8080:8080 freqtrade trade \ - $PAIRS_FLAG \ - --logfile /freqtrade/user_data/logs/freqtrade.log \ - --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite \ - --freqaimodel LightGBMRegressorMultiTarget \ - --fee 0.0008 \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --config /freqtrade/templates/${PARAMS_NAME}.json \ - --config /freqtrade/config_examples/live.json \ - --strategy $STRATEGY_NAME \ - --strategy-path /freqtrade/templates -``` - -## 主要变更 - -1. **添加 `--pairRemoteList` 参数支持**:允许从远程API获取交易对列表 -2. **保留 `--pairs` 参数**:支持通过命令行指定交易对 -3. **参数优先级**:`--pairRemoteList` > `--pairs` > 默认值 -4. **统一的交易对处理逻辑**:与 `backtest.sh` 和 `dryrun.sh` 保持一致的处理方式 -5. **移除日期参数**:如您要求,没有添加 `--start-date` 和 `--end-date` 参数 - -### 使用示例 - -```bash -# 使用默认配置 -./live.sh - -# 指定交易对 -./live.sh --pairs BTC/USDT,SOL/USDT - -# 从远程API获取交易对 -./live.sh --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" - -# 组合使用(远程API优先级更高) -./live.sh --pairRemoteList "http://pairlist.xl.home/api/pairlist?mute=true&count=50" --pairs BTC/USDT -``` - -这个修改使得 `live.sh` 脚本能够灵活地从远程API获取动态交易对列表,同时保持了与其他脚本的一致性和向后兼容性。 - -------- - -- Datetime: 2025-08-05 17:51:16 - -- Model: _qwen3/qwen-plus-latest - -- Selected files: - - tools/backtest.sh - -> 为了兼容老的调用方式, 当没有提供 带key的参数 只提供了 value形式的参数的化, -> 1. 第一个参数代表start, -> 2. 第二个参数代表end, -> 3. 第三个参数如果类似 “*/USDT” 就直接当单个币对传入 -> 3. 第三个参数如果是个url, 就当作pair_remote_list 传入 - - -我将修改 `backtest.sh` 脚本,使其兼容老的调用方式。以下是完整的修改: - -```bash -#!/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 - while [[ $# -gt 0 ]]; do - case "$1" in - $param=*) - echo "${1#*=}" - return - ;; - $param) - # Check if the next argument exists and does not start with a dash - if [[ -n "$2" && "$2" != -* ]]; then - echo "$2" - return - else - echo "Error: Missing value for parameter $param" >&2 - exit 1 - fi - ;; - esac - shift - done - echo "" - return -} - -# Parse command line arguments -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" "$@") - -# Check if we have positional parameters (no named parameters) -HAS_NAMED_PARAMS=false -for arg in "$@"; do - if [[ "$arg" == --* ]]; then - HAS_NAMED_PARAMS=true - break - fi -done - -# If no named parameters, treat as positional parameters -if [ "$HAS_NAMED_PARAMS" = false ] && [ $# -gt 0 ]; then - # First parameter is start date - START_DATE_RAW="$1" - - # Second parameter is end date (if provided) - if [ $# -gt 1 ]; then - END_DATE_RAW="$2" - fi - - # Third parameter is pairs or URL - 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 ]]; 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 in format */USDT" - 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 - -# 处理交易对参数:优先级为 --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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - 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 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" - fi - fi - fi -elif [ -n "$PAIRS_ARG" ]; then - # 使用 --pairs 参数提供的交易对 - PAIRS_FLAG="--pairs $PAIRS_ARG" - echo "Using pairs from --pairs parameter: $PAIRS_ARG" -else - # 没有提供任何交易对参数 - PAIRS_FLAG="" - echo "No pairs parameter provided, using freqtrade default" -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 LightGBMRegressorMultiTarget \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --strategy-path /freqtrade/templates \ - --strategy $STRATEGY_NAME \ - --enable-protections \ - --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 \ - --config /freqtrade/config_examples/$CONFIG_FILE \ - --strategy-path /freqtrade/templates \ - --strategy $STRATEGY_NAME \ - --timerange $START_DATE-$END_DATE \ - --enable-protections \ - --fee 0.0008 \ - --breakdown day \ - --cache none >output.log 2>&1 - 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/ @@ -1224,6 +104,7 @@ 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