diff --git a/backend/api/routes/config.py b/backend/api/routes/config.py index b26c819..672b49d 100644 --- a/backend/api/routes/config.py +++ b/backend/api/routes/config.py @@ -485,6 +485,18 @@ async def get_global_configs( "category": "scan", "description": "是否排除主流币(BTC、ETH、BNB等),专注于山寨币。山寨币策略建议开启。", }, + "PROFIT_PROTECTION_ENABLED": { + "value": True, + "type": "boolean", + "category": "strategy", + "description": "盈利保护总开关:True=启用保本+移动止损,False=全部关闭(不做保本、不做移动止损)", + }, + "LOCK_PROFIT_AT_BREAKEVEN_AFTER_PCT": { + "value": 0.03, + "type": "number", + "category": "strategy", + "description": "盈利达保证金的该比例时移至保本(如 0.03=3%,0=关闭保本步骤)", + }, "USE_TRAILING_STOP": { "value": False, "type": "boolean", diff --git a/backend/config_manager.py b/backend/config_manager.py index f81228e..c758d7f 100644 --- a/backend/config_manager.py +++ b/backend/config_manager.py @@ -882,7 +882,10 @@ class ConfigManager: 'MAX_LEVERAGE': eff_get('MAX_LEVERAGE', 20), # 动态杠杆上限 20,配合单笔仓位提高收益 'MIN_LEVERAGE': eff_get('MIN_LEVERAGE', 8), # 动态杠杆下限,不低于此值(之前盈利阶段多为 8x,避免被压到 2–4x 导致单笔盈利过少) 'MAX_LEVERAGE_SMALL_CAP': eff_get('MAX_LEVERAGE_SMALL_CAP', 8), # 高波动/小众币最大杠杆,默认 8 与之前盈利阶段一致 - # 移动止损:默认关闭(避免过早截断利润,让利润奔跑) + # 盈利保护总开关与保本:关闭后不执行保本、不执行移动止损 + 'PROFIT_PROTECTION_ENABLED': eff_get('PROFIT_PROTECTION_ENABLED', True), # True=启用保本+移动止损,False=全部关闭 + 'LOCK_PROFIT_AT_BREAKEVEN_AFTER_PCT': eff_get('LOCK_PROFIT_AT_BREAKEVEN_AFTER_PCT', 0.03), # 盈利达保证金比例时移至保本(0.03=3%,0=关闭) + # 移动止损 'USE_TRAILING_STOP': eff_get('USE_TRAILING_STOP', True), # 默认启用(2026-01-27优化:启用移动止损,保护利润) 'TRAILING_STOP_ACTIVATION': eff_get('TRAILING_STOP_ACTIVATION', 0.05), # 默认5%(2026-01-27优化:更早保护利润,避免回吐) 'TRAILING_STOP_PROTECT': eff_get('TRAILING_STOP_PROTECT', 0.025), # 默认2.5%(2026-01-27优化:给回撤足够空间,避免被震荡扫出) diff --git a/backend/database/init.sql b/backend/database/init.sql index 8463ebd..0630834 100644 --- a/backend/database/init.sql +++ b/backend/database/init.sql @@ -234,6 +234,8 @@ INSERT INTO `trading_config` (`config_key`, `config_value`, `config_type`, `cate ('LEVERAGE', '10', 'number', 'strategy', '基础杠杆倍数'), ('USE_DYNAMIC_LEVERAGE', 'true', 'boolean', 'strategy', '是否启用动态杠杆(根据信号强度调整杠杆倍数)'), ('MAX_LEVERAGE', '15', 'number', 'strategy', '最大杠杆倍数(动态杠杆上限,降低到15更保守)'), +('PROFIT_PROTECTION_ENABLED', 'true', 'boolean', 'strategy', '盈利保护总开关:启用保本+移动止损'), +('LOCK_PROFIT_AT_BREAKEVEN_AFTER_PCT', '0.03', 'number', 'strategy', '盈利达保证金比例时移至保本(0.03=3%,0=关闭)'), ('USE_TRAILING_STOP', 'true', 'boolean', 'strategy', '是否使用移动止损'), ('TRAILING_STOP_ACTIVATION', '0.10', 'number', 'strategy', '移动止损激活阈值(盈利10%后激活,给趋势更多空间)'), ('TRAILING_STOP_PROTECT', '0.05', 'number', 'strategy', '移动止损保护利润(保护5%利润,更合理)'), diff --git a/trading_system/position_manager.py b/trading_system/position_manager.py index 694b8e4..57c4611 100644 --- a/trading_system/position_manager.py +++ b/trading_system/position_manager.py @@ -2077,7 +2077,7 @@ class PositionManager: else: logger.debug(f"{symbol} [移动止损] 已禁用(USE_TRAILING_STOP=False),跳过移动止损检查") if use_trailing: - trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金 + trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.10) # 相对于保证金,默认 10% trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金 # ⚠️ 关键修复:配置值格式转换(兼容百分比形式和比例形式) diff --git a/trading_system/risk_manager.py b/trading_system/risk_manager.py index b9b6a0b..8df8a87 100644 --- a/trading_system/risk_manager.py +++ b/trading_system/risk_manager.py @@ -664,28 +664,28 @@ class RiskManager: effective_max = config.get_effective_config('MAX_POSITION_PERCENT', 0.20) base_position_percent = effective_max * signal_multiplier max_position_percent = effective_max * signal_multiplier - min_position_percent = config.TRADING_CONFIG['MIN_POSITION_PERCENT'] - + min_position_percent = config.TRADING_CONFIG['MIN_POSITION_PERCENT'] + # 涨跌幅超过5%时,可以适当增加保证金占比,但必须遵守 MAX_POSITION_PERCENT 上限 - if abs(change_percent) > 5: - position_percent = min( - base_position_percent * 1.5, + if abs(change_percent) > 5: + position_percent = min( + base_position_percent * 1.5, max_position_percent - ) - logger.info(f" 涨跌幅 {change_percent:.2f}% > 5%,使用增强仓位比例: {position_percent*100:.1f}%") - else: - position_percent = base_position_percent - logger.info(f" 涨跌幅 {change_percent:.2f}%,使用标准仓位比例: {position_percent*100:.1f}%") - + ) + logger.info(f" 涨跌幅 {change_percent:.2f}% > 5%,使用增强仓位比例: {position_percent*100:.1f}%") + else: + position_percent = base_position_percent + logger.info(f" 涨跌幅 {change_percent:.2f}%,使用标准仓位比例: {position_percent*100:.1f}%") + # 计算保证金与名义价值 margin_value = available_balance * position_percent notional_value = margin_value * actual_leverage logger.info(f" 计算保证金: {margin_value:.4f} USDT ({position_percent*100:.1f}% of {available_balance:.2f})") logger.info(f" 计算名义价值: {notional_value:.2f} USDT (保证金 {margin_value:.4f} × 杠杆 {actual_leverage}x)") - + # 计算数量 quantity = notional_value / current_price - + logger.info(f" 计算数量: {quantity:.4f}") # 计算名义价值和保证金(如果还未计算)