188 lines
5.9 KiB
Bash
Executable File
188 lines
5.9 KiB
Bash
Executable File
#!/bin/bash
|
||
|
||
# 脚本功能:将 hyperopted.json 中的参数覆盖到 freqaiprimer.json 中的同名参数
|
||
# 用途:hyperopt 优化完成后,自动更新策略配置文件中的最优参数
|
||
|
||
# 定义文件路径
|
||
SRC_JSON="${1:-../result/hyperopted.json}"
|
||
TARGET_JSON="../freqtrade/templates/freqaiprimer.json"
|
||
|
||
echo "════════════════════════════════════════════════════════════════"
|
||
echo "参数覆盖脚本 - 从 hyperopted.json 更新 freqaiprimer.json"
|
||
echo "════════════════════════════════════════════════════════════════"
|
||
echo ""
|
||
echo "源文件: $SRC_JSON"
|
||
echo "目标文件: $TARGET_JSON"
|
||
echo ""
|
||
|
||
# 检查源文件是否存在
|
||
if [ ! -f "$SRC_JSON" ]; then
|
||
echo "❌ 错误:文件 $SRC_JSON 不存在"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查目标文件是否存在
|
||
if [ ! -f "$TARGET_JSON" ]; then
|
||
echo "❌ 错误:文件 $TARGET_JSON 不存在"
|
||
exit 1
|
||
fi
|
||
|
||
# 检查 jq 是否安装
|
||
if ! command -v jq &>/dev/null; then
|
||
echo "❌ 错误:未安装 jq 工具,请先安装 jq"
|
||
exit 1
|
||
fi
|
||
|
||
echo "🔍 正在验证 JSON 文件..."
|
||
|
||
# 验证源文件是否为有效的 JSON
|
||
if ! jq . "$SRC_JSON" >/dev/null 2>&1; then
|
||
echo "❌ 错误:$SRC_JSON 不是有效的 JSON 文件"
|
||
exit 1
|
||
fi
|
||
|
||
# 验证目标文件是否为有效的 JSON
|
||
if ! jq . "$TARGET_JSON" >/dev/null 2>&1; then
|
||
echo "❌ 错误:$TARGET_JSON 不是有效的 JSON 文件"
|
||
exit 1
|
||
fi
|
||
|
||
echo "✅ JSON 文件有效"
|
||
echo ""
|
||
|
||
# 备份原文件
|
||
BACKUP_FILE="${TARGET_JSON}.backup.$(date +%Y%m%d_%H%M%S)"
|
||
cp "$TARGET_JSON" "$BACKUP_FILE"
|
||
echo "💾 已备份原文件至: $BACKUP_FILE"
|
||
echo ""
|
||
|
||
echo "🔄 正在更新参数..."
|
||
echo ""
|
||
|
||
# 定义参数分组
|
||
BUY_PARAMS=(
|
||
"bb_length" "bb_std" "bb_width_threshold" "bb_lower_deviation"
|
||
"h1_max_candles" "h1_max_consecutive_candles" "h1_rapid_rise_threshold"
|
||
"max_entry_adjustments" "min_condition_count" "rsi_bull_threshold"
|
||
"rsi_length" "rsi_oversold" "stochrsi_bull_threshold" "stochrsi_neutral_threshold"
|
||
"volume_multiplier" "add_position_callback" "stake_divisor" "step_coefficient"
|
||
"add_rsi_oversold_threshold" "add_stochrsi_oversold" "add_macd_cross_confirm"
|
||
"add_bb_lower_proximity" "add_volume_confirm" "add_market_state_filter"
|
||
"add_position_decrease_ratio"
|
||
)
|
||
|
||
SELL_PARAMS=(
|
||
"exit_bb_upper_deviation" "exit_volume_multiplier" "rsi_overbought"
|
||
"roi_param_a" "roi_param_k" "roi_param_t"
|
||
"max_reduce_adjustments" "reduce_coefficient" "reduce_profit_base"
|
||
)
|
||
|
||
# 检查参数是否在某个集合中
|
||
is_in_array() {
|
||
local target=$1
|
||
shift
|
||
local array=("$@")
|
||
for item in "${array[@]}"; do
|
||
if [[ "$item" == "$target" ]]; then
|
||
return 0
|
||
fi
|
||
done
|
||
return 1
|
||
}
|
||
|
||
# 统计更新数量
|
||
UPDATED_COUNT=0
|
||
|
||
# 使用 Python 完成复杂的 JSON 操作
|
||
python3 << EOF
|
||
import json
|
||
import sys
|
||
|
||
try:
|
||
# 读取源文件
|
||
with open("$SRC_JSON", 'r') as f:
|
||
src_data = json.load(f)
|
||
|
||
# 读取目标文件
|
||
with open("$TARGET_JSON", 'r') as f:
|
||
target_data = json.load(f)
|
||
|
||
# 获取源参数
|
||
src_params = src_data.get('params', {})
|
||
target_params = target_data.get('params', {})
|
||
|
||
# 定义参数分组
|
||
buy_params = {
|
||
'bb_length', 'bb_std', 'bb_width_threshold', 'bb_lower_deviation',
|
||
'h1_max_candles', 'h1_max_consecutive_candles', 'h1_rapid_rise_threshold',
|
||
'max_entry_adjustments', 'min_condition_count', 'rsi_bull_threshold',
|
||
'rsi_length', 'rsi_oversold', 'stochrsi_bull_threshold', 'stochrsi_neutral_threshold',
|
||
'volume_multiplier', 'add_position_callback', 'stake_divisor', 'step_coefficient',
|
||
'add_rsi_oversold_threshold', 'add_stochrsi_oversold', 'add_macd_cross_confirm',
|
||
'add_bb_lower_proximity', 'add_volume_confirm', 'add_market_state_filter',
|
||
'add_position_decrease_ratio'
|
||
}
|
||
|
||
sell_params = {
|
||
'exit_bb_upper_deviation', 'exit_volume_multiplier', 'rsi_overbought',
|
||
'roi_param_a', 'roi_param_k', 'roi_param_t',
|
||
'max_reduce_adjustments', 'reduce_coefficient', 'reduce_profit_base'
|
||
}
|
||
|
||
updated_count = 0
|
||
|
||
# 遍历源参数
|
||
for param_name, param_value in src_params.items():
|
||
# 判断参数属于哪个 section
|
||
section = None
|
||
if param_name in buy_params:
|
||
section = 'buy'
|
||
elif param_name in sell_params:
|
||
section = 'sell'
|
||
|
||
# 如果识别到 section,并且参数已在目标中存在
|
||
if section and section in target_params and param_name in target_params[section]:
|
||
old_value = target_params[section][param_name]
|
||
target_params[section][param_name] = param_value
|
||
print(f"✓ 更新 {section}.{param_name}: {old_value} → {param_value}")
|
||
updated_count += 1
|
||
|
||
# 写回目标文件
|
||
with open("$TARGET_JSON", 'w') as f:
|
||
json.dump(target_data, f, indent=2, ensure_ascii=False)
|
||
|
||
# 输出统计结果
|
||
print("")
|
||
print("=" * 60)
|
||
if updated_count > 0:
|
||
print(f"✅ 参数覆盖完成!共更新 {updated_count} 个参数")
|
||
else:
|
||
print(f"⚠️ 未找到匹配的参数进行更新")
|
||
print("=" * 60)
|
||
|
||
except json.JSONDecodeError as e:
|
||
print(f"❌ JSON 解析错误: {e}")
|
||
sys.exit(1)
|
||
except Exception as e:
|
||
print(f"❌ 错误: {e}")
|
||
sys.exit(1)
|
||
EOF
|
||
|
||
# 检查 Python 脚本的退出状态
|
||
if [ $? -ne 0 ]; then
|
||
echo ""
|
||
echo "❌ 参数更新失败"
|
||
exit 1
|
||
fi
|
||
|
||
echo ""
|
||
echo "📊 更新后的参数样本:"
|
||
echo ""
|
||
echo "Buy 参数前3个:"
|
||
jq '.params.buy | to_entries | .[0:3][] | " \(.key): \(.value)"' "$TARGET_JSON" | sed 's/"//g'
|
||
echo ""
|
||
echo "Sell 参数前3个:"
|
||
jq '.params.sell | to_entries | .[0:3][] | " \(.key): \(.value)"' "$TARGET_JSON" | sed 's/"//g'
|
||
echo ""
|
||
echo "🎉 脚本执行完成"
|