fix live.sh

This commit is contained in:
zhangkun9038@dingtalk.com 2025-08-08 18:54:58 +08:00
parent af11dfc2b7
commit 3a04501be6

View File

@ -1,256 +1,89 @@
#!/bin/bash
set -e # 出错立即停止
### 函数定义区 ###
# 1. 从SQLite数据库获取当前开放交易的币对列表
get_open_trades_pairs() {
local db_path="$1"
local pairs=()
if [ ! -f "$db_path" ]; then
echo "⚠️ 交易数据库文件 $db_path 不存在,开放交易对列表为空" >&2
echo ""
return
fi
local query_result=$(sqlite3 -header -csv "$db_path" "SELECT id, pair, open_date, amount, open_rate, max_rate, close_profit, stake_amount FROM trades WHERE is_open = 1 ORDER BY open_date DESC LIMIT 10;")
pairs=($(echo "$query_result" | awk -F ',' 'NR > 1 {print $2}' | tr -d '"'))
echo "从数据库获取到开放交易对: ${pairs[*]}" >&2
echo "${pairs[@]}"
}
# 2. 从远程接口获取币对列表
get_remote_pairs() {
local remote_url="$1"
local pairs=()
if [ -z "$remote_url" ]; then
echo "⚠️ 未提供远程币对列表URL远程币对列表为空" >&2
echo ""
return
fi
echo "正在从远程URL获取币对列表: $remote_url" >&2
local pairs_json=$(curl -s "$remote_url")
if [ $? -ne 0 ] || [ -z "$pairs_json" ]; then
echo "⚠️ 远程币对列表获取失败,使用空列表" >&2
echo ""
return
fi
local parsed_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 "$parsed_pairs" ]; then
pairs=($parsed_pairs)
echo "从远程获取到币对: ${pairs[*]}" >&2
else
echo "⚠️ 远程币对列表解析为空" >&2
fi
echo "${pairs[@]}"
}
# 3. 合并并去重两个币对列表
merge_and_deduplicate_pairs() {
local -a db_pairs=($1)
local -a remote_pairs=($2)
local -a merged=()
merged=($(printf "%s\n" "${db_pairs[@]}" "${remote_pairs[@]}" | sort -u | tr '\n' ' '))
echo "合并去重后的币对列表: ${merged[*]}" >&2
echo "${merged[@]}"
}
# 4. 验证JSON文件格式是否有效
validate_json_file() {
local json_path="$1"
if ! command -v jq &>/dev/null; then
echo "❌ 未安装jq工具请先安装jq" >&2
exit 1
fi
if [ ! -f "$json_path" ]; then
echo "❌ JSON配置文件 $json_path 不存在" >&2
exit 1
fi
if ! jq . "$json_path" >/dev/null 2>&1; then
echo "❌ JSON文件格式错误$json_path" >&2
exit 1
fi
}
# 5. 更新live.json中的pair_whitelist
update_live_json_pair_whitelist() {
local json_path="$1"
local -a pairlist=($2)
validate_json_file "$json_path"
local json_array=$(printf '%s\n' "${pairlist[@]}" | jq -R . | jq -s .)
echo "正在更新 $json_path 中的exchange.pair_whitelist..." >&2
jq --argjson pairs "$json_array" '.exchange.pair_whitelist = $pairs' "$json_path" >"$json_path.tmp" && mv "$json_path.tmp" "$json_path"
if [ $? -eq 0 ]; then
echo "✅ 成功更新 $json_path新的pair_whitelist包含 ${#pairlist[@]} 个币对" >&2
else
echo "❌ 更新 $json_path 失败" >&2
exit 1
fi
}
# 6. 停止并移除指定名称的容器
remove_existing_container() {
local container_name="$1"
if [ -z "$container_name" ]; then
echo "⚠️ 容器名称为空,跳过移除操作" >&2
return
fi
# 查找以 freqtrade-dryrun 开头的所有容器
matching_containers=$(docker ps -a --format '{{.Names}}' | grep '^freqtrade-dryrun')
if [ -n "$matching_containers" ]; then
echo "发现以下以 freqtrade-dryrun 开头的容器: $matching_containers" >&2
# 遍历每个匹配的容器并执行停止和删除操作
for container in $matching_containers; do
echo "正在停止并移除容器: $container" >&2
# 停止容器
if ! docker stop "$container" >&2; then
echo "⚠️ 停止容器 $container 失败,尝试强制移除..." >&2
fi
# 移除容器
if docker rm "$container" >&2; then
echo "✅ 已成功移除容器 $container" >&2
else
echo "❌ 移除容器 $container 失败,请手动处理" >&2
exit 1
fi
done
else
echo "未发现以 freqtrade-dryrun 开头的容器,无需移除" >&2
fi
}
### 主逻辑区 ###
# 检查 .env 文件
if [ ! -f ".env" ]; then
echo "⚠️ 本地缺少 .env 文件,请创建并配置" >&2
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
# 加载 .env 变量
export $(grep -v '^#' .env | xargs)
# 检查必要环境变量
if [ -z "$TEST_BRANCH" ] || [ -z "$DRYRUN_BRANCH" ]; then
echo "⚠️ .env 文件缺少 TEST_BRANCH 或 DRYRUN_BRANCH 配置" >&2
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' 不符合配置要求" >&2
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' 符合配置要求" >&2
echo "✅ 当前分支 '$current_branch' 符合环境变量配置要求。"
fi
# dryrun分支清理
if [[ "$current_branch" == *"dryrun"* ]]; then
echo "当前为dryrun分支执行git reset --hard清理工作区..." >&2
git reset --hard || {
echo "⚠️ git reset失败"
# 如果当前分支名称包含 "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
}
echo "Git工作区已清理" >&2
fi
echo "Git 工作区已清理。"
fi
# 设置默认远程币对列表URL支持命令行参数覆盖
DEFAULT_PAIR_REMOTE_URL="http://pairlist.xl.home/api/pairlist?mute=true&count=30"
PAIR_REMOTE_LIST_URL="$DEFAULT_PAIR_REMOTE_URL"
# 解析命令行参数:如果提供则覆盖默认值
while [[ $# -gt 0 ]]; do
case "$1" in
--pairRemoteList=*)
PAIR_REMOTE_LIST_URL="${1#*=}"
shift
;;
--pairRemoteList)
if [[ -n "$2" && "$2" != -* ]]; then
PAIR_REMOTE_LIST_URL="$2"
shift 2
else
echo "错误:--pairRemoteList需要指定值" >&2
exit 1
fi
;;
*)
shift
;;
esac
done
# 加载策略配置
# 加载 .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 "使用策略: $STRATEGY_NAME" >&2
echo "使用配置: $CONFIG_FILE" >&2
echo "测试分支: $TEST_BRANCH" >&2
echo "远程币对列表URL: $PAIR_REMOTE_LIST_URL" >&2 # 显示当前使用的URL
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")}
### 核心:处理币对列表 ###
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
# 1. 获取数据库币对(使用绝对路径)
db_path="/home/ubuntu/freqtrade/user_data/tradesv3.sqlite"
db_pairs=$(get_open_trades_pairs "$db_path")
# 2. 获取远程币对
remote_pairs=$(get_remote_pairs "$PAIR_REMOTE_LIST_URL")
# 3. 合并去重
merged_pairs=$(merge_and_deduplicate_pairs "$db_pairs" "$remote_pairs")
# 4. 更新配置文件
update_live_json_pair_whitelist "../config_examples/live.json" "$merged_pairs"
### 启动容器 ###
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)
CONTAINER_NAME="freqtrade-dryrun-${GIT_COMMIT_SHORT}"
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"
echo "准备启动容器: $CONTAINER_NAME" >&2
# 移除已存在的同名容器
remove_existing_container "$CONTAINER_NAME"
# 启动新容器
echo "启动容器: $CONTAINER_NAME" >&2
docker-compose run -d --rm \
--name "$CONTAINER_NAME" \
-p 8080:8080 \
freqtrade trade \
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 \
@ -258,13 +91,5 @@ docker-compose run -d --rm \
--config /freqtrade/config_examples/$CONFIG_FILE \
--config /freqtrade/templates/${PARAMS_NAME}.json \
--config /freqtrade/config_examples/live.json \
--enable-protections \
--strategy $STRATEGY_NAME \
--strategy-path /freqtrade/templates
if [ $? -eq 0 ]; then
echo "✅ 容器 $CONTAINER_NAME 启动完成" >&2
else
echo "❌ 容器启动失败" >&2
exit 1
fi