diff --git a/frontend/src/components/TradeList.jsx b/frontend/src/components/TradeList.jsx index 8f669f7..378fb67 100644 --- a/frontend/src/components/TradeList.jsx +++ b/frontend/src/components/TradeList.jsx @@ -271,7 +271,7 @@ const TradeList = () => {
平均持仓时长(分钟)
{Number(stats.avg_duration_minutes || 0).toFixed(0)}
- (仅统计“有意义交易”,且需要 duration_minutes 字段) + (仅统计“有意义交易”;优先使用 duration_minutes,缺失时用 exit_time-entry_time 计算)
)} diff --git a/trading_system/atr_strategy.py b/trading_system/atr_strategy.py index b2e1b89..bdbf085 100644 --- a/trading_system/atr_strategy.py +++ b/trading_system/atr_strategy.py @@ -28,6 +28,25 @@ class ATRStrategy: self.use_dynamic_atr_multiplier = config.TRADING_CONFIG.get('USE_DYNAMIC_ATR_MULTIPLIER', False) self.atr_multiplier_min = config.TRADING_CONFIG.get('ATR_MULTIPLIER_MIN', 1.5) self.atr_multiplier_max = config.TRADING_CONFIG.get('ATR_MULTIPLIER_MAX', 2.5) + + def _refresh_from_config(self) -> None: + """ + 动态刷新配置(重要:配置页修改后希望立即生效)。 + 之前这些参数只在 __init__ 时读取,会导致“改了配置但策略仍按旧值运行”。 + """ + try: + cfg = getattr(config, "TRADING_CONFIG", {}) or {} + self.use_atr = bool(cfg.get('USE_ATR_STOP_LOSS', True)) + self.atr_sl_multiplier = float(cfg.get('ATR_STOP_LOSS_MULTIPLIER', 1.8)) + self.atr_tp_multiplier = float(cfg.get('ATR_TAKE_PROFIT_MULTIPLIER', 3.0)) + self.risk_reward_ratio = float(cfg.get('RISK_REWARD_RATIO', 3.0)) + self.atr_period = int(cfg.get('ATR_PERIOD', 14)) + self.use_dynamic_atr_multiplier = bool(cfg.get('USE_DYNAMIC_ATR_MULTIPLIER', False)) + self.atr_multiplier_min = float(cfg.get('ATR_MULTIPLIER_MIN', 1.5)) + self.atr_multiplier_max = float(cfg.get('ATR_MULTIPLIER_MAX', 2.5)) + except Exception: + # 刷新失败则继续使用旧值(不影响下单流程) + return def calculate_stop_loss( self, @@ -50,6 +69,7 @@ class ATRStrategy: Returns: (止损价格, 止损距离, 详细信息字典) """ + self._refresh_from_config() if not self.use_atr: return None, None, {} @@ -137,6 +157,7 @@ class ATRStrategy: Returns: (止盈价格, 止盈距离, 详细信息字典) """ + self._refresh_from_config() if not self.use_atr: return None, None, {} diff --git a/trading_system/market_scanner.py b/trading_system/market_scanner.py index 2bab2c2..68f110f 100644 --- a/trading_system/market_scanner.py +++ b/trading_system/market_scanner.py @@ -236,7 +236,8 @@ class MarketScanner: rsi = TechnicalIndicators.calculate_rsi(close_prices, period=14) macd = TechnicalIndicators.calculate_macd(close_prices) bollinger = TechnicalIndicators.calculate_bollinger_bands(close_prices, period=20) - atr = TechnicalIndicators.calculate_atr(high_prices, low_prices, close_prices, period=14) + atr_period = int(config.TRADING_CONFIG.get('ATR_PERIOD', 14) or 14) + atr = TechnicalIndicators.calculate_atr(high_prices, low_prices, close_prices, period=atr_period) ema20 = TechnicalIndicators.calculate_ema(close_prices, period=20) ema50 = TechnicalIndicators.calculate_ema(close_prices, period=50) diff --git a/trading_system/strategy.py b/trading_system/strategy.py index 4fb389f..2e9ccfe 100644 --- a/trading_system/strategy.py +++ b/trading_system/strategy.py @@ -138,6 +138,12 @@ class TradingStrategy: logger.debug(f"✓ {symbol} 自动生成推荐成功 (信号强度: {trade_signal.get('strength', 0)}/10)") except Exception as e: logger.warning(f"自动生成推荐失败 {symbol}: {e}") + + # 提升胜率:震荡/未知市场状态不做自动交易(只保留推荐/观察) + # 你当前统计里“止损远多于止盈 + 平均持仓很短”高度符合震荡来回扫损特征。 + if market_regime != 'trending': + logger.info(f"{symbol} 市场状态={market_regime},跳过自动交易(仅生成推荐)") + continue # 检查是否应该自动交易(已有持仓则跳过自动交易,但推荐已生成) if not await self.risk_manager.should_trade(symbol, change_percent):