This commit is contained in:
薇薇安 2026-01-22 08:50:42 +08:00
parent 5b1370a5a2
commit dc49c2717b
5 changed files with 132 additions and 18 deletions

View File

@ -231,6 +231,14 @@ async def get_trade_stats(
) )
win_loss_ratio = (avg_win_pnl / avg_loss_pnl_abs) if avg_loss_pnl_abs > 0 else None win_loss_ratio = (avg_win_pnl / avg_loss_pnl_abs) if avg_loss_pnl_abs > 0 else None
# 实际盈亏比(所有盈利单的总盈利 / 所有亏损单的总亏损,必须 > 1.5,目标 2.5-3.0
total_win_pnl = sum(float(t["pnl"]) for t in win_trades) if win_trades else 0.0
total_loss_pnl_abs = sum(abs(float(t["pnl"])) for t in loss_trades) if loss_trades else 0.0
actual_profit_loss_ratio = (total_win_pnl / total_loss_pnl_abs) if total_loss_pnl_abs > 0 else None
# 盈利因子(总盈利金额 / 总亏损金额,必须 > 1.1,目标 1.5+
profit_factor = (total_win_pnl / total_loss_pnl_abs) if total_loss_pnl_abs > 0 else None
# 平仓原因分布(用来快速定位胜率低的主要来源:止损/止盈/同步等) # 平仓原因分布(用来快速定位胜率低的主要来源:止损/止盈/同步等)
exit_reason_counts = Counter((t.get("exit_reason") or "unknown") for t in meaningful_trades) exit_reason_counts = Counter((t.get("exit_reason") or "unknown") for t in meaningful_trades)
@ -277,6 +285,14 @@ async def get_trade_stats(
"avg_loss_pnl_abs": avg_loss_pnl_abs, "avg_loss_pnl_abs": avg_loss_pnl_abs,
"avg_win_loss_ratio": win_loss_ratio, "avg_win_loss_ratio": win_loss_ratio,
"avg_win_loss_ratio_target": 3.0, "avg_win_loss_ratio_target": 3.0,
# 实际盈亏比(所有盈利单总盈利 / 所有亏损单总亏损,目标 > 2.0
"actual_profit_loss_ratio": actual_profit_loss_ratio,
"actual_profit_loss_ratio_target": 2.0,
"total_win_pnl": total_win_pnl,
"total_loss_pnl_abs": total_loss_pnl_abs,
# 盈利因子(总盈利 / 总亏损,目标 > 1.2
"profit_factor": profit_factor,
"profit_factor_target": 1.2,
"exit_reason_counts": dict(exit_reason_counts), "exit_reason_counts": dict(exit_reason_counts),
"avg_duration_minutes": avg_duration_minutes, "avg_duration_minutes": avg_duration_minutes,
# 总交易量(名义下单量口径):优先使用 notional_usdt新字段否则回退 entry_price * quantity # 总交易量(名义下单量口径):优先使用 notional_usdt新字段否则回退 entry_price * quantity

View File

@ -539,12 +539,12 @@ class ConfigManager:
# 风险控制 # 风险控制
'STOP_LOSS_PERCENT': eff_get('STOP_LOSS_PERCENT', 0.10), # 默认10% 'STOP_LOSS_PERCENT': eff_get('STOP_LOSS_PERCENT', 0.10), # 默认10%
'TAKE_PROFIT_PERCENT': eff_get('TAKE_PROFIT_PERCENT', 0.30), # 默认30%盈亏比3:1 'TAKE_PROFIT_PERCENT': eff_get('TAKE_PROFIT_PERCENT', 0.25), # 默认25%从30%放宽到25%配合ATR止盈放大盈亏比
'MIN_STOP_LOSS_PRICE_PCT': eff_get('MIN_STOP_LOSS_PRICE_PCT', 0.02), # 默认2% 'MIN_STOP_LOSS_PRICE_PCT': eff_get('MIN_STOP_LOSS_PRICE_PCT', 0.02), # 默认2%
'MIN_TAKE_PROFIT_PRICE_PCT': eff_get('MIN_TAKE_PROFIT_PRICE_PCT', 0.03), # 默认3% 'MIN_TAKE_PROFIT_PRICE_PCT': eff_get('MIN_TAKE_PROFIT_PRICE_PCT', 0.03), # 默认3%
'USE_ATR_STOP_LOSS': eff_get('USE_ATR_STOP_LOSS', True), # 是否使用ATR动态止损 'USE_ATR_STOP_LOSS': eff_get('USE_ATR_STOP_LOSS', True), # 是否使用ATR动态止损
'ATR_STOP_LOSS_MULTIPLIER': eff_get('ATR_STOP_LOSS_MULTIPLIER', 1.8), # ATR止损倍数1.5-2倍 'ATR_STOP_LOSS_MULTIPLIER': eff_get('ATR_STOP_LOSS_MULTIPLIER', 1.8), # ATR止损倍数1.5-2倍
'ATR_TAKE_PROFIT_MULTIPLIER': eff_get('ATR_TAKE_PROFIT_MULTIPLIER', 3.0), # ATR止盈倍数3倍ATR 'ATR_TAKE_PROFIT_MULTIPLIER': eff_get('ATR_TAKE_PROFIT_MULTIPLIER', 4.5), # ATR止盈倍数从3.0提升到4.5,放大盈亏比
'RISK_REWARD_RATIO': eff_get('RISK_REWARD_RATIO', 3.0), # 盈亏比(止损距离的倍数) 'RISK_REWARD_RATIO': eff_get('RISK_REWARD_RATIO', 3.0), # 盈亏比(止损距离的倍数)
'ATR_PERIOD': eff_get('ATR_PERIOD', 14), # ATR计算周期 'ATR_PERIOD': eff_get('ATR_PERIOD', 14), # ATR计算周期
'USE_DYNAMIC_ATR_MULTIPLIER': eff_get('USE_DYNAMIC_ATR_MULTIPLIER', False), # 是否根据波动率动态调整ATR倍数 'USE_DYNAMIC_ATR_MULTIPLIER': eff_get('USE_DYNAMIC_ATR_MULTIPLIER', False), # 是否根据波动率动态调整ATR倍数
@ -569,10 +569,14 @@ class ConfigManager:
'LEVERAGE': eff_get('LEVERAGE', 10), 'LEVERAGE': eff_get('LEVERAGE', 10),
'USE_DYNAMIC_LEVERAGE': eff_get('USE_DYNAMIC_LEVERAGE', True), 'USE_DYNAMIC_LEVERAGE': eff_get('USE_DYNAMIC_LEVERAGE', True),
'MAX_LEVERAGE': eff_get('MAX_LEVERAGE', 15), # 降低到15更保守配合更大的保证金 'MAX_LEVERAGE': eff_get('MAX_LEVERAGE', 15), # 降低到15更保守配合更大的保证金
'USE_TRAILING_STOP': eff_get('USE_TRAILING_STOP', True), # 移动止损:默认关闭(避免过早截断利润,让利润奔跑)
'USE_TRAILING_STOP': eff_get('USE_TRAILING_STOP', False),
'TRAILING_STOP_ACTIVATION': eff_get('TRAILING_STOP_ACTIVATION', 0.10), # 默认10%(给趋势更多空间) 'TRAILING_STOP_ACTIVATION': eff_get('TRAILING_STOP_ACTIVATION', 0.10), # 默认10%(给趋势更多空间)
'TRAILING_STOP_PROTECT': eff_get('TRAILING_STOP_PROTECT', 0.05), # 默认5%(保护更多利润) 'TRAILING_STOP_PROTECT': eff_get('TRAILING_STOP_PROTECT', 0.05), # 默认5%(保护更多利润)
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
'MIN_HOLD_TIME_SEC': eff_get('MIN_HOLD_TIME_SEC', 1800), # 默认30分钟1800秒
# 自动交易过滤(用于提升胜率/控频) # 自动交易过滤(用于提升胜率/控频)
# 说明:这两个 key 需要出现在 TRADING_CONFIG 中,否则 trading_system 在每次 reload_from_redis 后会丢失它们, # 说明:这两个 key 需要出现在 TRADING_CONFIG 中,否则 trading_system 在每次 reload_from_redis 后会丢失它们,
# 导致始终按默认值拦截自动交易(用户在配置页怎么开都没用)。 # 导致始终按默认值拦截自动交易(用户在配置页怎么开都没用)。

View File

@ -79,7 +79,10 @@ const ConfigPanel = ({ currentUser }) => {
// //
MIN_SIGNAL_STRENGTH: 8, MIN_SIGNAL_STRENGTH: 8,
USE_TRAILING_STOP: false, USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
TAKE_PROFIT_PERCENT: 25.0, // 30%25%ATR
MIN_HOLD_TIME_SEC: 1800, // 30
// / // /
SMART_ENTRY_ENABLED: false, SMART_ENTRY_ENABLED: false,
@ -109,7 +112,10 @@ const ConfigPanel = ({ currentUser }) => {
ENTRY_MAX_DRIFT_PCT_RANGING: 0.15, // 0.15% ENTRY_MAX_DRIFT_PCT_RANGING: 0.15, // 0.15%
// //
USE_TRAILING_STOP: false, USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
TAKE_PROFIT_PERCENT: 25.0, // 30%25%ATR
MIN_HOLD_TIME_SEC: 1800, // 30
}, },
}, },
strict: { strict: {
@ -127,7 +133,10 @@ const ConfigPanel = ({ currentUser }) => {
LIMIT_ORDER_OFFSET_PCT: 0.1, LIMIT_ORDER_OFFSET_PCT: 0.1,
ENTRY_CONFIRM_TIMEOUT_SEC: 180, ENTRY_CONFIRM_TIMEOUT_SEC: 180,
USE_TRAILING_STOP: false, USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
TAKE_PROFIT_PERCENT: 25.0, // 30%25%ATR
MIN_HOLD_TIME_SEC: 1800, // 30
}, },
}, },
steady: { steady: {
@ -150,7 +159,10 @@ const ConfigPanel = ({ currentUser }) => {
ENTRY_MAX_DRIFT_PCT_TRENDING: 0.4, ENTRY_MAX_DRIFT_PCT_TRENDING: 0.4,
ENTRY_MAX_DRIFT_PCT_RANGING: 0.2, ENTRY_MAX_DRIFT_PCT_RANGING: 0.2,
USE_TRAILING_STOP: false, USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
TAKE_PROFIT_PERCENT: 25.0, // 30%25%ATR
MIN_HOLD_TIME_SEC: 1800, // 30
}, },
}, },
conservative: { conservative: {
@ -164,9 +176,12 @@ const ConfigPanel = ({ currentUser }) => {
MAX_SCAN_SYMBOLS: 150, MAX_SCAN_SYMBOLS: 150,
MIN_VOLATILITY: 0.02, // MIN_VOLATILITY: 0.02, //
STOP_LOSS_PERCENT: 10.0, // 10% STOP_LOSS_PERCENT: 10.0, // 10%
TAKE_PROFIT_PERCENT: 20.0, // 20% TAKE_PROFIT_PERCENT: 25.0, // 25%20%25%
MIN_STOP_LOSS_PRICE_PCT: 2.0, // 2% MIN_STOP_LOSS_PRICE_PCT: 2.0, // 2%
MIN_TAKE_PROFIT_PRICE_PCT: 3.0 // 3% MIN_TAKE_PROFIT_PRICE_PCT: 3.0, // 3%
USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
MIN_HOLD_TIME_SEC: 1800 // 30
} }
}, },
balanced: { balanced: {
@ -180,9 +195,12 @@ const ConfigPanel = ({ currentUser }) => {
MAX_SCAN_SYMBOLS: 250, MAX_SCAN_SYMBOLS: 250,
MIN_VOLATILITY: 0.018, // MIN_VOLATILITY: 0.018, //
STOP_LOSS_PERCENT: 8.0, // 8% STOP_LOSS_PERCENT: 8.0, // 8%
TAKE_PROFIT_PERCENT: 20.0, // 20%2.5:1 TAKE_PROFIT_PERCENT: 25.0, // 25%20%25%
MIN_STOP_LOSS_PRICE_PCT: 2.0, // 2% MIN_STOP_LOSS_PRICE_PCT: 2.0, // 2%
MIN_TAKE_PROFIT_PRICE_PCT: 3.0 // 3% MIN_TAKE_PROFIT_PRICE_PCT: 3.0, // 3%
USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
MIN_HOLD_TIME_SEC: 1800 // 30
} }
}, },
aggressive: { aggressive: {
@ -196,9 +214,12 @@ const ConfigPanel = ({ currentUser }) => {
MAX_SCAN_SYMBOLS: 350, MAX_SCAN_SYMBOLS: 350,
MIN_VOLATILITY: 0.015, // MIN_VOLATILITY: 0.015, //
STOP_LOSS_PERCENT: 5.0, // 5% STOP_LOSS_PERCENT: 5.0, // 5%
TAKE_PROFIT_PERCENT: 15.0, // 15%3:1 TAKE_PROFIT_PERCENT: 25.0, // 25%15%25%5:1
MIN_STOP_LOSS_PRICE_PCT: 1.5, // 1.5% MIN_STOP_LOSS_PRICE_PCT: 1.5, // 1.5%
MIN_TAKE_PROFIT_PRICE_PCT: 2.0 // 2% MIN_TAKE_PROFIT_PRICE_PCT: 2.0, // 2%
USE_TRAILING_STOP: false, //
ATR_TAKE_PROFIT_MULTIPLIER: 4.5, // ATR3.04.5
MIN_HOLD_TIME_SEC: 1800 // 30
} }
} }
} }

View File

@ -188,12 +188,12 @@ def _get_trading_config():
'TOP_N_SYMBOLS': 50, # 每次扫描后处理的交易对数量增加到50以获取更多推荐 'TOP_N_SYMBOLS': 50, # 每次扫描后处理的交易对数量增加到50以获取更多推荐
'MAX_SCAN_SYMBOLS': 500, # 扫描的最大交易对数量0表示扫描所有 'MAX_SCAN_SYMBOLS': 500, # 扫描的最大交易对数量0表示扫描所有
'STOP_LOSS_PERCENT': 0.10, # 止损百分比相对于保证金默认10% 'STOP_LOSS_PERCENT': 0.10, # 止损百分比相对于保证金默认10%
'TAKE_PROFIT_PERCENT': 0.30, # 止盈百分比相对于保证金默认30%盈亏比3:1 'TAKE_PROFIT_PERCENT': 0.25, # 止盈百分比相对于保证金默认25%从30%放宽配合ATR止盈放大盈亏比
'MIN_STOP_LOSS_PRICE_PCT': 0.02, # 最小止损价格变动百分比如0.02表示2%防止止损过紧默认2% 'MIN_STOP_LOSS_PRICE_PCT': 0.02, # 最小止损价格变动百分比如0.02表示2%防止止损过紧默认2%
'MIN_TAKE_PROFIT_PRICE_PCT': 0.03, # 最小止盈价格变动百分比如0.03表示3%防止止盈过紧默认3% 'MIN_TAKE_PROFIT_PRICE_PCT': 0.03, # 最小止盈价格变动百分比如0.03表示3%防止止盈过紧默认3%
'USE_ATR_STOP_LOSS': True, # 是否使用ATR动态止损优先于固定百分比 'USE_ATR_STOP_LOSS': True, # 是否使用ATR动态止损优先于固定百分比
'ATR_STOP_LOSS_MULTIPLIER': 1.8, # ATR止损倍数1.5-2倍ATR默认1.8 'ATR_STOP_LOSS_MULTIPLIER': 1.8, # ATR止损倍数1.5-2倍ATR默认1.8
'ATR_TAKE_PROFIT_MULTIPLIER': 3.0, # ATR止盈倍数3倍ATR对应3:1盈亏比 'ATR_TAKE_PROFIT_MULTIPLIER': 4.5, # ATR止盈倍数从3.0提升到4.5,放大盈亏比,让利润奔跑
'RISK_REWARD_RATIO': 3.0, # 盈亏比(止损距离的倍数,用于计算止盈) 'RISK_REWARD_RATIO': 3.0, # 盈亏比(止损距离的倍数,用于计算止盈)
'ATR_PERIOD': 14, # ATR计算周期默认14 'ATR_PERIOD': 14, # ATR计算周期默认14
'USE_DYNAMIC_ATR_MULTIPLIER': False, # 是否根据波动率动态调整ATR倍数 'USE_DYNAMIC_ATR_MULTIPLIER': False, # 是否根据波动率动态调整ATR倍数
@ -210,9 +210,13 @@ def _get_trading_config():
'LEVERAGE': 10, # 基础杠杆倍数 'LEVERAGE': 10, # 基础杠杆倍数
'USE_DYNAMIC_LEVERAGE': True, # 是否启用动态杠杆(根据信号强度调整) 'USE_DYNAMIC_LEVERAGE': True, # 是否启用动态杠杆(根据信号强度调整)
'MAX_LEVERAGE': 15, # 最大杠杆倍数降低到15更保守配合更大的保证金 'MAX_LEVERAGE': 15, # 最大杠杆倍数降低到15更保守配合更大的保证金
'USE_TRAILING_STOP': True, # 移动止损:默认关闭(避免过早截断利润,让利润奔跑)
'USE_TRAILING_STOP': False,
'TRAILING_STOP_ACTIVATION': 0.10, # 移动止损激活提高到10%盈利10%后激活,给趋势更多空间) 'TRAILING_STOP_ACTIVATION': 0.10, # 移动止损激活提高到10%盈利10%后激活,给趋势更多空间)
'TRAILING_STOP_PROTECT': 0.05, # 保护利润提高到5%保护5%利润,更合理) 'TRAILING_STOP_PROTECT': 0.05, # 保护利润提高到5%保护5%利润,更合理)
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
'MIN_HOLD_TIME_SEC': 1800, # 默认30分钟1800秒强制延长持仓时间
'POSITION_SYNC_INTERVAL': 60, # 持仓状态同步间隔缩短到1分钟确保状态及时同步 'POSITION_SYNC_INTERVAL': 60, # 持仓状态同步间隔缩短到1分钟确保状态及时同步
# ===== 自动交易过滤(用于提升胜率/控频)===== # ===== 自动交易过滤(用于提升胜率/控频)=====
@ -272,6 +276,9 @@ defaults = {
# 自动交易过滤默认值 # 自动交易过滤默认值
'AUTO_TRADE_ONLY_TRENDING': True, 'AUTO_TRADE_ONLY_TRENDING': True,
'AUTO_TRADE_ALLOW_4H_NEUTRAL': False, 'AUTO_TRADE_ALLOW_4H_NEUTRAL': False,
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
'MIN_HOLD_TIME_SEC': 1800, # 默认30分钟1800秒
} }
for key, value in defaults.items(): for key, value in defaults.items():
if key not in TRADING_CONFIG: if key not in TRADING_CONFIG:

View File

@ -1185,6 +1185,28 @@ class PositionManager:
else: else:
current_price = entry_price current_price = entry_price
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
min_hold_sec = int(config.TRADING_CONFIG.get('MIN_HOLD_TIME_SEC', 1800) or 1800)
entry_time = position_info.get('entryTime')
hold_time_sec = 0
if entry_time:
try:
if isinstance(entry_time, datetime):
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
else:
# 兼容:如果是时间戳或字符串
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
except Exception:
hold_time_sec = 0
# 如果持仓时间不足,禁止平仓(除非是手动平仓)
if hold_time_sec < min_hold_sec:
logger.debug(
f"{symbol} [持仓时间锁] 持仓时间 {hold_time_sec}s < 最小要求 {min_hold_sec}s"
f"禁止自动平仓(强制波段持仓纪律)"
)
continue # 跳过这个持仓,不触发任何平仓逻辑
# 计算当前盈亏(基于保证金) # 计算当前盈亏(基于保证金)
leverage = position_info.get('leverage', 10) leverage = position_info.get('leverage', 10)
position_value = entry_price * quantity position_value = entry_price * quantity
@ -1218,7 +1240,7 @@ class PositionManager:
except Exception as e: except Exception as e:
logger.debug(f"从Redis重新加载配置失败: {e}") logger.debug(f"从Redis重新加载配置失败: {e}")
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', True) use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', False)
if use_trailing: if use_trailing:
trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金 trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金
trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金 trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金
@ -2344,7 +2366,29 @@ class PositionManager:
except Exception as e: except Exception as e:
logger.debug(f"从Redis重新加载配置失败: {e}") logger.debug(f"从Redis重新加载配置失败: {e}")
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', True) # 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
min_hold_sec = int(config.TRADING_CONFIG.get('MIN_HOLD_TIME_SEC', 1800) or 1800)
entry_time = position_info.get('entryTime')
hold_time_sec = 0
if entry_time:
try:
if isinstance(entry_time, datetime):
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
else:
# 兼容:如果是时间戳或字符串
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
except Exception:
hold_time_sec = 0
# 如果持仓时间不足,禁止平仓(除非是手动平仓)
if hold_time_sec < min_hold_sec:
logger.debug(
f"{symbol} [持仓时间锁] 持仓时间 {hold_time_sec}s < 最小要求 {min_hold_sec}s"
f"禁止自动平仓(强制波段持仓纪律)"
)
return # 不触发任何平仓逻辑
use_trailing = config.TRADING_CONFIG.get('USE_TRAILING_STOP', False)
if use_trailing: if use_trailing:
trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金 trailing_activation = config.TRADING_CONFIG.get('TRAILING_STOP_ACTIVATION', 0.01) # 相对于保证金
trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金 trailing_protect = config.TRADING_CONFIG.get('TRAILING_STOP_PROTECT', 0.01) # 相对于保证金
@ -2384,6 +2428,28 @@ class PositionManager:
f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)" f"(保护{trailing_protect*100:.1f}% of margin = {protect_amount:.4f} USDT)"
) )
# 最小持仓时间锁(强制波段持仓纪律,避免分钟级平仓)
min_hold_sec = int(config.TRADING_CONFIG.get('MIN_HOLD_TIME_SEC', 1800) or 1800)
entry_time = position_info.get('entryTime')
hold_time_sec = 0
if entry_time:
try:
if isinstance(entry_time, datetime):
hold_time_sec = int((get_beijing_time() - entry_time).total_seconds())
else:
# 兼容:如果是时间戳或字符串
hold_time_sec = int(time.time() - (float(entry_time) if isinstance(entry_time, (int, float)) else 0))
except Exception:
hold_time_sec = 0
# 如果持仓时间不足,禁止平仓(除非是手动平仓)
if hold_time_sec < min_hold_sec:
logger.debug(
f"{symbol} [持仓时间锁] 持仓时间 {hold_time_sec}s < 最小要求 {min_hold_sec}s"
f"禁止自动平仓(强制波段持仓纪律)"
)
return # 不触发任何平仓逻辑
# 检查止损(基于保证金收益比) # 检查止损(基于保证金收益比)
stop_loss = position_info.get('stopLoss') stop_loss = position_info.get('stopLoss')
should_close = False should_close = False