From cb8b393550321d9c32dbe69ba14700f666e20b65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=87=E8=96=87=E5=AE=89?= Date: Sun, 1 Feb 2026 12:35:56 +0800 Subject: [PATCH] a --- frontend/src/components/GlobalConfig.jsx | 4 +++ trading_system/strategy.py | 32 +++++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/GlobalConfig.jsx b/frontend/src/components/GlobalConfig.jsx index 8957646..6b7f02f 100644 --- a/frontend/src/components/GlobalConfig.jsx +++ b/frontend/src/components/GlobalConfig.jsx @@ -25,6 +25,8 @@ const KEY_LABELS = { SYMBOL_LOSS_COOLDOWN_ENABLED: '连续亏损冷却', SYMBOL_MAX_CONSECUTIVE_LOSSES: '连续亏损次数阈值', SYMBOL_LOSS_COOLDOWN_SEC: '冷却时间(秒)', + RSI_EXTREME_REVERSE_ENABLED: 'RSI 极端反向(超买反空/超卖反多)', + RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H: 'RSI 反向仅允许 4H 中性', } const ConfigItem = ({ label, config, onUpdate, disabled }) => { @@ -481,6 +483,8 @@ const GlobalConfig = () => { SYMBOL_LOSS_COOLDOWN_SEC: { value: 3600, type: 'number', category: 'strategy', description: '连续亏损后的冷却时间(秒),默认1小时。' }, BETA_FILTER_ENABLED: { value: true, type: 'boolean', category: 'strategy', description: '大盘共振过滤:BTC/ETH 下跌时屏蔽多单。' }, BETA_FILTER_THRESHOLD: { value: -0.005, type: 'number', category: 'strategy', description: '大盘共振阈值(比例,如 -0.005 表示 -0.5%)。' }, + RSI_EXTREME_REVERSE_ENABLED: { value: false, type: 'boolean', category: 'strategy', description: '开启后:原信号做多但 RSI 超买(≥做多上限)时改为做空;原信号做空但 RSI 超卖(≤做空下限)时改为做多。属均值回归思路,可填补超买超卖时不下单的空置;默认关闭。' }, + RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H: { value: true, type: 'boolean', category: 'strategy', description: '建议开启:仅在 4H 趋势为中性时允许 RSI 反向单,避免在强趋势里逆势抄底/摸顶,降低风险。关闭则反向可与 4H 同向(仍受“禁止逆4H趋势”约束)。' }, } const loadConfigs = async () => { diff --git a/trading_system/strategy.py b/trading_system/strategy.py index 4d0b448..66a1f5c 100644 --- a/trading_system/strategy.py +++ b/trading_system/strategy.py @@ -472,12 +472,15 @@ class TradingStrategy: pass should_trade = signal_strength >= min_signal_strength and direction is not None - # ===== RSI / 24h 涨跌幅过滤:做多不追高、做空不杀跌 ===== + # ===== RSI / 24h 涨跌幅过滤:做多不追高、做空不杀跌;可选 RSI 极端反向(超买反空/超卖反多)===== + # 反向属于“逆短期超买超卖”的均值回归,在强趋势里逆势风险大;可选“仅4H中性时反向”以降低风险。 + reversed_by_rsi = False try: max_rsi_long = config.TRADING_CONFIG.get('MAX_RSI_FOR_LONG', 70) max_change_long = config.TRADING_CONFIG.get('MAX_CHANGE_PERCENT_FOR_LONG', 25) min_rsi_short = config.TRADING_CONFIG.get('MIN_RSI_FOR_SHORT', 30) max_change_short = config.TRADING_CONFIG.get('MAX_CHANGE_PERCENT_FOR_SHORT', 10) + rsi_extreme_reverse = bool(config.TRADING_CONFIG.get('RSI_EXTREME_REVERSE_ENABLED', False)) change_pct = symbol_info.get('changePercent') if change_pct is not None and not isinstance(change_pct, (int, float)): change_pct = float(change_pct) if change_pct else None @@ -489,8 +492,13 @@ class TradingStrategy: try: rsi_val = float(rsi) if rsi_val >= max_rsi_long: - should_trade = False - reasons.append(f"❌ 做多RSI过滤:RSI={rsi_val:.1f}≥{max_rsi_long}(超买区不追多)") + if rsi_extreme_reverse: + direction = 'SELL' + reversed_by_rsi = True + reasons.append(f"RSI超买({rsi_val:.1f}≥{max_rsi_long})反向做空") + else: + should_trade = False + reasons.append(f"❌ 做多RSI过滤:RSI={rsi_val:.1f}≥{max_rsi_long}(超买区不追多)") except (TypeError, ValueError): pass if should_trade and change_pct is not None and change_pct > max_change_long: @@ -502,16 +510,28 @@ class TradingStrategy: try: rsi_val = float(rsi) if rsi_val <= min_rsi_short: - should_trade = False - reasons.append(f"❌ 做空RSI过滤:RSI={rsi_val:.1f}≤{min_rsi_short}(超卖区不追空)") + if rsi_extreme_reverse: + direction = 'BUY' + reversed_by_rsi = True + reasons.append(f"RSI超卖({rsi_val:.1f}≤{min_rsi_short})反向做多") + else: + should_trade = False + reasons.append(f"❌ 做空RSI过滤:RSI={rsi_val:.1f}≤{min_rsi_short}(超卖区不追空)") except (TypeError, ValueError): pass - if should_trade and change_pct is not None and change_pct > max_change_short: + if should_trade and direction == 'SELL' and change_pct is not None and change_pct > max_change_short: should_trade = False reasons.append(f"❌ 做空涨跌幅过滤:24h涨幅={change_pct:.1f}%>{max_change_short}%(24h仍大涨不做空)") except Exception as e: logger.debug(f"{symbol} RSI/涨跌幅过滤失败(忽略): {e}") + # 安全约束:RSI 反向仅允许在 4H 中性时执行(避免在强趋势里逆势抄底/摸顶) + if reversed_by_rsi and should_trade and direction: + only_neutral_4h = bool(config.TRADING_CONFIG.get('RSI_EXTREME_REVERSE_ONLY_NEUTRAL_4H', True)) + if only_neutral_4h and trend_4h != 'neutral': + should_trade = False + reasons.append(f"❌ RSI反向仅允许4H中性时执行(当前4H={trend_4h or 'unknown'},避免逆势风险)") + # ===== 15m 短周期方向过滤:避免“上涨中做空 / 下跌中做多” ===== # 思路: # - 使用最近 N 根 15m K 线的总涨跌幅来确认短期方向