diff --git a/freqtrade/templates/freqaiprimer.json b/freqtrade/templates/freqaiprimer.json index c49660ae..07922534 100644 --- a/freqtrade/templates/freqaiprimer.json +++ b/freqtrade/templates/freqaiprimer.json @@ -15,8 +15,6 @@ "max_open_trades": 5 }, "buy": { - "stake_divisor": 2, - "add_position_callback": 0.053, "bb_length": 13, "bb_lower_deviation": 1.04, "bb_std": 3.0, diff --git a/freqtrade/templates/freqaiprimer.py b/freqtrade/templates/freqaiprimer.py index 28c0fc3a..f82a3262 100644 --- a/freqtrade/templates/freqaiprimer.py +++ b/freqtrade/templates/freqaiprimer.py @@ -103,8 +103,10 @@ class FreqaiPrimer(IStrategy): h1_max_consecutive_candles = IntParameter(1, 4, default=2, optimize=True, load=True, space='buy') # 定义可优化参数 max_entry_adjustments = IntParameter(2, 5, default=3, optimize=True, load=True, space='buy') # 最大加仓次数 - add_position_callback = DecimalParameter(0.03, 0.06, decimals=3, default=0.047, optimize=True, load=True, space='buy') # 加仓回调百分比 - stake_divisor = IntParameter(2, 4, default=2, optimize=False, load=True, space='buy') # 加仓金额分母 + add_position_callback = DecimalParameter(0.02, 0.06, decimals=3, default=0.043, optimize=False, load=True, space='buy') # 加仓回调百分比 + add_position_growth = DecimalParameter(1.5, 3.0, decimals=2, default=4.5, optimize=False, load=True, space='buy') # 加仓金额增长因子,保留2位小数用于hyperopt优化 + add_position_multiplier = DecimalParameter(0.2, 10.5, decimals=2, default=0.86, optimize=False, load=True, space='buy') # 加仓间隔系数,保留2位小数用于hyperopt优化 + stake_divisor = DecimalParameter(2.0, 12.0, decimals=2, default=9.3, optimize=False, load=True, space='buy') # 加仓金额分母(小数类型,保留2位小数) # 线性ROI参数 - 用于线性函数: y = (a * (x + k)) + t roi_param_a = DecimalParameter(-0.0002, -0.00005, decimals=5, default=-0.0001, optimize=True, load=True, space='sell') # 系数a @@ -596,7 +598,7 @@ class FreqaiPrimer(IStrategy): return exit_ratio - def adjust_trade_position(self, trade: 'Trade', current_time, current_rate: float, + def adjust_trade_position(self, trade: 'Trade', current_time, current_rate: float, current_profit: float, min_stake: float, max_stake: float, **kwargs) -> float: """ 根据用户要求实现加仓逻辑 @@ -605,41 +607,44 @@ class FreqaiPrimer(IStrategy): """ # 获取当前交易对 pair = trade.pair - + # 获取当前交易的加仓次数 entry_count = len(trade.orders) # 获取所有入场订单数量 - + # 如果已经达到最大加仓次数,则不再加仓 if entry_count - 1 >= self.max_entry_adjustments.value: return 0.0 - + # 获取初始入场价格和当前价格的差值百分比 initial_price = trade.open_rate if initial_price == 0: return 0.0 price_diff_pct = (current_rate - initial_price) / initial_price - + + # 计算加仓次数(从1开始计数) + adjustment_count = entry_count - 1 # 已加仓次数 + # 检查价格回调是否达到加仓间隔 dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) current_state = dataframe['market_state'].iloc[-1] if 'market_state' in dataframe.columns else 'neutral' - - if price_diff_pct <= -self.add_position_callback.value and current_state not in ['bear', 'weak_bear']: + + # 计算当前所需的加仓间隔百分比 = 基础间隔 * (系数 ^ 已加仓次数) + current_callback = self.add_position_callback.value * (self.add_position_multiplier.value ** adjustment_count) + + if price_diff_pct <= -current_callback: # 计算初始入场金额 initial_stake = trade.orders[0].cost # 第一笔订单的成本 - - # 计算加仓次数(从1开始计数) - adjustment_count = entry_count - 1 # 已加仓次数 - + # 计算加仓金额: (initial_stake / stake_divisor) ^ (adjustment_count + 1) - additional_stake = (initial_stake / self.stake_divisor.value) ** (adjustment_count + 1) - + additional_stake = (initial_stake / self.stake_divisor.value) * (self.add_position_growth.value ** (adjustment_count + 1)) + # 确保加仓金额在允许的范围内 additional_stake = max(min_stake, min(additional_stake, max_stake - trade.stake_amount)) - + #logger.info(f"[{pair}] 触发加仓: 第{adjustment_count + 1}次加仓, 初始金额{initial_stake:.2f}, \ # 加仓金额{additional_stake:.2f}, 价格差{price_diff_pct:.2%}, 当前利润{current_profit:.2%}") - + return additional_stake - + # 不符合加仓条件,返回0 return 0.0 diff --git a/tools/calculate_dca.sh b/tools/calculate_dca.sh new file mode 100755 index 00000000..2fa166ab --- /dev/null +++ b/tools/calculate_dca.sh @@ -0,0 +1,141 @@ +#!/bin/bash + +# freqai 加仓策略计算器 (DCA Calculator) +# 根据 FreqaiPrimer 策略的5个参数进行计算 + +# 设置默认值 (与您的 freqaiprimer.py 代码中一致) +MAX_ENTRY_ADJUSTMENTS=4 +ADD_POSITION_CALLBACK=0.025 +ADD_POSITION_GROWTH=2.97 +ADD_POSITION_MULTIPLIER=1.78 +STAKE_DIVISOR=4.6 +INITIAL_STAKE=75 + +# 函数:显示使用帮助 +usage() { + echo "Usage: $0 [OPTIONS]" + echo "计算FreqaiPrimer策略的加仓计划" + echo "" + echo "选项:" + echo " -h, --help 显示此帮助信息" + echo " -m, --max-adjustments N 最大加仓次数 (默认: $MAX_ENTRY_ADJUSTMENTS)" + echo " -c, --callback FLOAT 基础回调百分比 (默认: $ADD_POSITION_CALLBACK)" + echo " -g, --growth FLOAT 加仓金额增长因子 (默认: $ADD_POSITION_GROWTH)" + echo " -p, --multiplier FLOAT 加仓间隔系数 (默认: $ADD_POSITION_MULTIPLIER)" + echo " -d, --divisor FLOAT 加仓金额分母 (默认: $STAKE_DIVISOR)" + echo " -s, --stake FLOAT 首次入场金额 (默认: $INITIAL_STAKE USDT)" + exit 1 +} + +# 解析命令行参数 +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + usage + ;; + -m|--max-adjustments) + MAX_ENTRY_ADJUSTMENTS="$2" + shift 2 + ;; + -c|--callback) + ADD_POSITION_CALLBACK="$2" + shift 2 + ;; + -g|--growth) + ADD_POSITION_GROWTH="$2" + shift 2 + ;; + -p|--multiplier) + ADD_POSITION_MULTIPLIER="$2" + shift 2 + ;; + -d|--divisor) + STAKE_DIVISOR="$2" + shift 2 + ;; + -s|--stake) + INITIAL_STAKE="$2" + shift 2 + ;; + *) + echo "未知参数: $1" + usage + ;; + esac +done + +# 检查 bc 是否安装 +if ! command -v bc &> /dev/null; then + echo "错误: 计算需要 'bc' 工具,请先安装。" + echo "在 Ubuntu/Debian 上: sudo apt-get install bc" + echo "在 CentOS/RHEL 上: sudo yum install bc" + exit 1 +fi + +# 计算并输出结果 +echo "==================================================" +echo " FreqaiPrimer 加仓策略计算报告" +echo "==================================================" +echo "初始入场金额: ${INITIAL_STAKE} USDT" +echo "最大加仓次数: ${MAX_ENTRY_ADJUSTMENTS}" +echo "基础回调阈值: $(awk "BEGIN {printf \"%.3f\", ${ADD_POSITION_CALLBACK}*100}")%" +echo "增长因子 (G): ${ADD_POSITION_GROWTH}" +echo "间隔系数 (M): ${ADD_POSITION_MULTIPLIER}" +echo "金额分母 (D): ${STAKE_DIVISOR}" +echo "==================================================" +printf "%-8s %-12s %-12s %-12s %-12s\n" "阶段" "累计跌幅" "本次下滑" "加仓金额" "累计投入" +printf "%-8s %-12s %-12s %-12s %-12s\n" "--------" "------------" "------------" "------------" "------------" + +# 初始化变量 +total_investment=$INITIAL_STAKE +current_callback=$ADD_POSITION_CALLBACK +previous_callback=0 + +# 循环计算每次加仓 +for ((i=0; i<=MAX_ENTRY_ADJUSTMENTS; i++)); do + # 计算当前阶段名称 + if [ $i -eq 0 ]; then + stage="首次开仓" + else + stage="第${i}次加仓" + fi + + # 计算累计跌幅 (从初始价算起) + cumulative_drop=$(echo "$current_callback * 100" | bc -l) + + # 计算本次加仓与上一次之间的实际价格下滑 + if [ $i -eq 0 ]; then + price_slip="--" + else + actual_slip=$(echo "($current_callback - $previous_callback) * 100" | bc -l) + price_slip=$(printf "%.2f%%" $actual_slip) + fi + + # 计算加仓金额 + if [ $i -eq 0 ]; then + stake_amount=$INITIAL_STAKE + else + # additional_stake = (initial_stake / stake_divisor) * (add_position_growth) ^ (adjustment_count + 1) + exponent=$((i + 1)) + stake_amount=$(echo "scale=2; ($INITIAL_STAKE / $STAKE_DIVISOR) * e(l($ADD_POSITION_GROWTH) * $exponent)" | bc -l) + fi + + # 更新累计投入 + total_investment=$(echo "scale=2; $total_investment + $stake_amount" | bc -l) + + # 格式化输出 + printf "%-8s %-12s %-12s %-12s %-12s\n" \ + "$stage" \ + "$(printf "%.2f%%" $cumulative_drop)" \ + "$price_slip" \ + "$(printf "%.2f" $stake_amount)" \ + "$(printf "%.2f" $total_investment)" + + # 为下一次迭代准备 + previous_callback=$current_callback + current_callback=$(echo "$current_callback * $ADD_POSITION_MULTIPLIER" | bc -l) +done + +echo "==================================================" +echo "总投入资金: ${total_investment} USDT" +echo "=================================================="