diff --git a/trading_system/config.py b/trading_system/config.py index ba2231a..2ac3144 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -44,7 +44,7 @@ try: except ImportError: # python-dotenv 未安装时忽略 pass -except Exception as e: +except Exception: # 加载 .env 文件失败时忽略,不影响程序运行 # logger.warning(f"[config.py] 加载ATS_ACCOUNT_ID时出错: {e}") # 调试信息,已禁用 pass # ⚠️ 2026-01-27修复:添加pass语句,修复IndentationError @@ -264,6 +264,13 @@ def _get_trading_config(): # 趋势状态缓存的 TTL(秒),用于控制一轮趋势的“有效期” 'TREND_STATE_TTL_SEC': 3600, + # ===== 推荐系统优化(优先推荐“入场时机不算太晚”的趋势单)===== + # 是否在生成推荐时启用趋势入场时机过滤(仅对趋势市场的顺势推荐生效) + # - 会对比当前价与趋势信号价的偏离,如果已经沿趋势方向走得太远,则不再生成该推荐 + 'RECO_USE_TREND_ENTRY_FILTER': True, + # 推荐系统使用的最大允许趋势幅度(相对于趋势信号价),默认与自动交易相同或略微更严格 + 'RECO_MAX_TREND_MOVE_BEFORE_ENTRY': 0.04, + # ===== 智能入场(方案C)===== # 根治方案:默认关闭。关闭后回归“纯限价单模式”(不追价/不市价兜底/未成交撤单跳过) 'SMART_ENTRY_ENABLED': True, # 开启智能入场,提高成交率 diff --git a/trading_system/trade_recommender.py b/trading_system/trade_recommender.py index b245c5c..ad94d1f 100644 --- a/trading_system/trade_recommender.py +++ b/trading_system/trade_recommender.py @@ -407,7 +407,66 @@ class TradeRecommender: direction = trade_signal['direction'] if not direction: return None - + + # ===== 趋势入场时机过滤(推荐侧,仅对趋势市场的顺势推荐生效)===== + try: + use_trend_filter = bool(config.TRADING_CONFIG.get('RECO_USE_TREND_ENTRY_FILTER', False)) + if use_trend_filter and getattr(self.client, "redis_cache", None): + market_regime = symbol_info.get('marketRegime', 'unknown') + # 只在趋势市场中,对顺势推荐做“太晚不追”的过滤 + if market_regime == 'trending' and direction in ('BUY', 'SELL'): + trend_state_key = f"trend_state:{symbol}" + trend_state = None + try: + trend_state = await self.client.redis_cache.get(trend_state_key) + except Exception: + trend_state = None + + if trend_state: + trend_dir = (trend_state.get('direction') or '').upper() + signal_price = trend_state.get('signal_price') + try: + signal_price = float(signal_price) if signal_price is not None else None + except Exception: + signal_price = None + + # 当前用于判断的参考价格:优先ticker价,其次技术分析价 + price_now = current_price or analysis_price + + if signal_price and price_now: + # 允许的最大趋势幅度:优先推荐专用配置,否则回退到自动交易的阈值 + max_move = float( + config.TRADING_CONFIG.get( + 'RECO_MAX_TREND_MOVE_BEFORE_ENTRY', + config.TRADING_CONFIG.get('MAX_TREND_MOVE_BEFORE_ENTRY', 0.05), + ) + or 0.05 + ) + + move_pct = 0.0 + too_late = False + + if direction == 'BUY' and trend_dir == 'BUY': + if price_now > signal_price: + move_pct = (price_now - signal_price) / signal_price + if move_pct > max_move: + too_late = True + elif direction == 'SELL' and trend_dir == 'SELL': + if price_now < signal_price: + move_pct = (signal_price - price_now) / signal_price + if move_pct > max_move: + too_late = True + + if too_late: + logger.info( + f"{symbol} [推荐过滤] 趋势方向={trend_dir}, " + f"信号价={signal_price:.6f}, 当前价={price_now:.6f}, " + f"累计趋势幅度={move_pct*100:.2f}%>推荐上限={max_move*100:.2f}%,跳过该推荐(入场时机偏晚)" + ) + return None + except Exception as e: + logger.debug(f"{symbol} 趋势入场推荐过滤出错(忽略,仅影响当前推荐): {e}") + # 先计算建议挂单价(限价单),然后用“挂单价”作为止损/止盈的基准入场价 # 否则会出现:止损按 current_price 算、但挂单按回调价算 → 止损/挂单价不匹配,甚至相等 limit_price_offset_pct = config.TRADING_CONFIG.get('LIMIT_ORDER_OFFSET_PCT', 0.5) # 默认0.5%