diff --git a/backend/api/routes/config.py b/backend/api/routes/config.py index 672b49d..3775cab 100644 --- a/backend/api/routes/config.py +++ b/backend/api/routes/config.py @@ -503,6 +503,18 @@ async def get_global_configs( "category": "strategy", "description": "是否启用移动止损(默认关闭,让利润奔跑)", }, + "BLOCK_SHORT_WHEN_BULL_MARKET": { + "value": True, + "type": "boolean", + "category": "strategy", + "description": "市场方案=牛市时禁止开空(与 MARKET_SCHEME 一致时生效,默认 True)", + }, + "BLOCK_LONG_WHEN_BEAR_MARKET": { + "value": True, + "type": "boolean", + "category": "strategy", + "description": "市场方案=熊市时禁止开多(与 MARKET_SCHEME 一致时生效,默认 True)", + }, "ONLY_AUTO_TRADE_CREATES_RECORDS": { "value": True, "type": "boolean", diff --git a/backend/config_manager.py b/backend/config_manager.py index c758d7f..b48aedf 100644 --- a/backend/config_manager.py +++ b/backend/config_manager.py @@ -956,6 +956,9 @@ class ConfigManager: 'MARKET_SCHEME': str(eff_get('MARKET_SCHEME', 'normal') or 'normal').lower(), 'BLOCK_LONG_WHEN_4H_DOWN': eff_get('BLOCK_LONG_WHEN_4H_DOWN', False), # 4H 下跌时禁止开多(熊市/保守用) 'BLOCK_SHORT_WHEN_4H_UP': eff_get('BLOCK_SHORT_WHEN_4H_UP', True), # 4H 上涨时禁止开空(默认 True,避免逆势做空) + # 全局市场方案下禁空/禁多:牛市不推空单、熊市不推多单 + 'BLOCK_SHORT_WHEN_BULL_MARKET': eff_get('BLOCK_SHORT_WHEN_BULL_MARKET', True), # 市场方案=牛市时禁止开空 + 'BLOCK_LONG_WHEN_BEAR_MARKET': eff_get('BLOCK_LONG_WHEN_BEAR_MARKET', True), # 市场方案=熊市时禁止开多 } # 根据市场方案覆盖关键参数(便于快速切换熊市/牛市/保守等预设) diff --git a/trading_system/config.py b/trading_system/config.py index b92b69e..91db1e4 100644 --- a/trading_system/config.py +++ b/trading_system/config.py @@ -359,6 +359,10 @@ DEFAULT_TRADING_CONFIG = { # 持仓监控详细日志:用于排查问题时观察每次检查的当前价/目标价/ROE 等 'POSITION_DETAILED_LOG_ENABLED': False, + # ===== 市场方案与多空过滤(与 MARKET_SCHEME 配合)===== + # 牛市不推空单、熊市不推多单(由 config_manager 根据 MARKET_SCHEME 覆盖) + 'BLOCK_SHORT_WHEN_BULL_MARKET': True, # 市场方案=牛市时禁止开空 + 'BLOCK_LONG_WHEN_BEAR_MARKET': True, # 市场方案=熊市时禁止开多 # ===== 系统单标识(用于同步时区分本系统开仓 vs 手动开仓)===== # 下单时写入 newClientOrderId = SYSTEM_ORDER_ID_PREFIX_时间戳_随机,同步/补建时根据订单 clientOrderId 前缀判断是否系统单 'SYSTEM_ORDER_ID_PREFIX': 'SYS', diff --git a/trading_system/strategy.py b/trading_system/strategy.py index 1a1dd85..6a92615 100644 --- a/trading_system/strategy.py +++ b/trading_system/strategy.py @@ -212,6 +212,16 @@ class TradingStrategy: f"{symbol} 4H 趋势上涨,禁止开空(BLOCK_SHORT_WHEN_4H_UP=true),跳过" ) continue + # 市场方案=牛市时禁止开空、熊市时禁止开多(与 MARKET_SCHEME 一致) + scheme = str(config.TRADING_CONFIG.get("MARKET_SCHEME", "normal") or "normal").lower() + block_short_bull = bool(config.TRADING_CONFIG.get("BLOCK_SHORT_WHEN_BULL_MARKET", True)) + block_long_bear = bool(config.TRADING_CONFIG.get("BLOCK_LONG_WHEN_BEAR_MARKET", True)) + if scheme == "bull" and block_short_bull and trade_direction == "SELL": + logger.info(f"{symbol} 市场方案=牛市,禁止开空(BLOCK_SHORT_WHEN_BULL_MARKET=true),跳过") + continue + if scheme == "bear" and block_long_bear and trade_direction == "BUY": + logger.info(f"{symbol} 市场方案=熊市,禁止开多(BLOCK_LONG_WHEN_BEAR_MARKET=true),跳过") + continue # 开仓前资金费率过滤:避免在费率极端不利于己方时进场 if not await self._check_funding_rate_filter(symbol, trade_direction): logger.info(f"{symbol} 资金费率过滤未通过,跳过开仓") diff --git a/trading_system/trade_recommender.py b/trading_system/trade_recommender.py index f83a6dd..31b3692 100644 --- a/trading_system/trade_recommender.py +++ b/trading_system/trade_recommender.py @@ -369,6 +369,16 @@ class TradeRecommender: 'strength': max(0, signal_strength - 2), 'trend_4h': trend_4h } + # 市场方案=牛市不推空单、熊市不推多单(与 MARKET_SCHEME 一致) + scheme = str(config.TRADING_CONFIG.get("MARKET_SCHEME", "normal") or "normal").lower() + block_short_bull = bool(config.TRADING_CONFIG.get("BLOCK_SHORT_WHEN_BULL_MARKET", True)) + block_long_bear = bool(config.TRADING_CONFIG.get("BLOCK_LONG_WHEN_BEAR_MARKET", True)) + if scheme == "bull" and block_short_bull and direction == "SELL": + reasons.append("❌ 市场方案=牛市,禁止开空(BLOCK_SHORT_WHEN_BULL_MARKET=true),跳过推荐") + return {'should_trade': False, 'direction': direction, 'reason': ', '.join(reasons) if reasons else '牛市禁空', 'strength': max(0, signal_strength - 2), 'trend_4h': trend_4h} + if scheme == "bear" and block_long_bear and direction == "BUY": + reasons.append("❌ 市场方案=熊市,禁止开多(BLOCK_LONG_WHEN_BEAR_MARKET=true),跳过推荐") + return {'should_trade': False, 'direction': direction, 'reason': ', '.join(reasons) if reasons else '熊市禁多', 'strength': max(0, signal_strength - 2), 'trend_4h': trend_4h} # 判断是否应该推荐(使用传入的参数,如果没有则使用config中的值) if min_signal_strength is None: