From 2911432f3d146791edda5e911909d2360953842b Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 23 Dec 2025 18:05:58 +0800
Subject: [PATCH] feat(indicator): 优化交易策略并调整日志级别

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java            |    2 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java |   98 ++++++++++++++++++++++++++++----
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java             |    2 
 src/main/resources/logback-spring.xml                                             |    2 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java             |   10 +-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java            |    4 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java      |    2 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java              |    6 +-
 8 files changed, 98 insertions(+), 28 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java
index 41e0278..4308fcb 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java
@@ -74,7 +74,7 @@
         prevEma55 = calculateEMA(prices, EMA55, prevEma55);
         ema55 = prevEma55;
 
-        log.debug("三重EMA计算结果 - EMA9: {}, EMA21: {}, EMA55: {}", 
+        log.info("三重EMA计算结果 - EMA9: {}, EMA21: {}, EMA55: {}",
                 ema9, ema21, ema55);
     }
 
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java
index 7ab8b78..7075f88 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java
@@ -82,7 +82,7 @@
         upper = mid.add(bandWidth).setScale(8, RoundingMode.HALF_UP);
         lower = mid.subtract(bandWidth).setScale(8, RoundingMode.HALF_UP);
         
-        log.debug("BOLL计算结果 - 中轨: {}, 上轨: {}, 下轨: {}", mid, upper, lower);
+        log.info("BOLL计算结果 - 中轨: {}, 上轨: {}, 下轨: {}", mid, upper, lower);
     }
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java
index 142cdd5..7148f4e 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java
@@ -108,23 +108,23 @@
                 .subtract(d.multiply(new BigDecimal(2)))
                 .setScale(8, RoundingMode.HALF_UP);
         
-        log.debug("KDJ计算结果 - K: {}, D: {}, J: {}", k, d, j);
+        log.info("KDJ计算结果 - K: {}, D: {}, J: {}", k, d, j);
     }
 
     /**
-     * 判断超买(K > 80)
+     * 判断超买(J > 85)
      * @return 是否超买
      */
     public boolean isOverbought() {
-        return k.compareTo(new BigDecimal(80)) > 0;
+        return j.compareTo(new BigDecimal(85)) > 0;
     }
 
     /**
-     * 判断超卖(K < 20)
+     * 判断超卖(J < 15)
      * @return 是否超卖
      */
     public boolean isOversold() {
-        return k.compareTo(new BigDecimal(20)) < 0;
+        return j.compareTo(new BigDecimal(15)) < 0;
     }
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java
index e288c00..0da46e6 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java
@@ -138,9 +138,9 @@
         prevEma60 = calculateEMA(prices, ma60Period, prevEma60);
         ema60 = prevEma60;
 
-        log.debug("MA计算结果 - MA5({}): {}, MA10({}): {}, MA20({}): {}, MA30({}): {}, MA60({}): {}", 
+        log.info("MA计算结果 - MA5({}): {}, MA10({}): {}, MA20({}): {}, MA30({}): {}, MA60({}): {}",
                 ma5Period, ma5, ma10Period, ma10, ma20Period, ma20, ma30Period, ma30, ma60Period, ma60);
-        log.debug("EMA计算结果 - EMA5({}): {}, EMA10({}): {}, EMA20({}): {}, EMA30({}): {}, EMA60({}): {}", 
+        log.info("EMA计算结果 - EMA5({}): {}, EMA10({}): {}, EMA20({}): {}, EMA30({}): {}, EMA60({}): {}",
                 ma5Period, ema5, ma10Period, ema10, ma20Period, ema20, ma30Period, ema30, ma60Period, ema60);
     }
 
@@ -166,7 +166,7 @@
         ma30Period = volatility.compareTo(highVolatility) < 0 ? 30 : 24;
         ma60Period = volatility.compareTo(highVolatility) < 0 ? 50 : 34;
 
-        log.debug("根据波动率{}调整MA周期: ma5={}, ma10={}, ma20={}, ma30={}, ma60={}", 
+        log.info("根据波动率{}调整MA周期: ma5={}, ma10={}, ma20={}, ma30={}, ma60={}",
                 volatility, ma5Period, ma10Period, ma20Period, ma30Period, ma60Period);
     }
 
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
index c2f869f..0cd2a15 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
@@ -112,7 +112,7 @@
         // 计算MACD柱状图
         macdBar = dif.subtract(dea).multiply(new BigDecimal(2)).setScale(8, RoundingMode.HALF_UP);
         
-        log.debug("MACD计算结果 - DIF: {}, DEA: {}, MACD柱状图: {}, 参数: fast={}, slow={}, signal={}", 
+        log.info("MACD计算结果 - DIF: {}, DEA: {}, MACD柱状图: {}, 参数: fast={}, slow={}, signal={}",
                 dif, dea, macdBar, fastPeriod, slowPeriod, signalPeriod);
     }
 
@@ -137,7 +137,7 @@
             signalPeriod = 5;
         }
 
-        log.debug("根据波动率{}调整MACD周期: fast={}, slow={}, signal={}", 
+        log.info("根据波动率{}调整MACD周期: fast={}, slow={}, signal={}",
                 volatility, fastPeriod, slowPeriod, signalPeriod);
     }
 
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java
index 7bbb32b..3e05082 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java
@@ -108,7 +108,7 @@
                     .setScale(8, RoundingMode.HALF_UP);
         }
 
-        log.debug("RSI计算结果 - RSI({}): {}", period, rsi);
+        log.info("RSI计算结果 - RSI({}): {}", period, rsi);
     }
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java
index 0605d0f..5c9a04d 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java
@@ -109,43 +109,43 @@
         // 计算所有指标
         calculateIndicators(prices, high, low, close);
 
-        // 检查是否为震荡市场,如果是,则无信号
+        // 检查是否为震荡市场,如果是,则执行区间交易策略
         if (isRangeMarket()) {
-            log.debug("当前市场为震荡行情,不产生信号");
-            return SignalType.NONE;
+            log.info("当前市场为震荡行情,执行区间交易策略");
+            return generateRangeTradingSignal(currentPrice, volume, hasLongPosition, hasShortPosition);
         }
 
         // 黑天鹅事件过滤
         if (blackSwanFilter(fundingRate, hasLargeTransfer, hasUpcomingEvent)) {
-            log.debug("黑天鹅事件过滤触发,不产生信号");
+            log.info("黑天鹅事件过滤触发,不产生信号");
             return SignalType.NONE;
         }
 
         // 开多信号
         if (shouldOpenLong(currentPrice, prices, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && !hasLongPosition && !hasShortPosition) {
-            log.debug("生成买入信号");
+            log.info("生成买入信号");
             return SignalType.BUY;
         }
 
         // 开空信号
         if (shouldOpenShort(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && !hasLongPosition && !hasShortPosition) {
-            log.debug("生成卖出信号");
+            log.info("生成卖出信号");
             return SignalType.SELL;
         }
 
         // 平多信号
         if (shouldCloseLong(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && hasLongPosition) {
-            log.debug("生成平多信号");
+            log.info("生成平多信号");
             return SignalType.CLOSE_BUY;
         }
 
         // 平空信号
         if (shouldCloseShort(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && hasShortPosition) {
-            log.debug("生成平空信号");
+            log.info("生成平空信号");
             return SignalType.CLOSE_SELL;
         }
 
-        log.debug("未生成信号");
+        log.info("未生成信号");
         return SignalType.NONE;
     }
 
@@ -257,6 +257,7 @@
 
     /**
      * 成交量验证辅助方法
+     * 增强版:当前成交量需大于20周期均量的1.2倍,以过滤无量反弹/回调的假信号
      * @param volume 成交量列表
      * @return 是否通过成交量验证
      */
@@ -269,8 +270,8 @@
         BigDecimal volumeMA = calculateMA(volume, config.getVolumeMaPeriod());
         BigDecimal currentVolume = volume.get(volume.size() - 1);
 
-        // 成交量需要大于均线
-        return currentVolume.compareTo(volumeMA) > 0;
+        // 增强验证:成交量需要大于1.2倍均线
+        return currentVolume.compareTo(volumeMA.multiply(new BigDecimal("1.2"))) > 0;
     }
 
     /**
@@ -327,7 +328,7 @@
 
         // 使用动态参数计算指标
         if (config.isEnableDynamicParams()) {
-            log.debug("使用动态参数计算指标,波动率: {}", volatility);
+            log.info("使用动态参数计算指标,波动率: {}", volatility);
             ma.calculate(prices, volatility);
             macd.calculate(prices, volatility);
         } else {
@@ -355,6 +356,8 @@
 
         return isMaConverged && isRsiNeutral && isBollNarrow;
     }
+
+
 
     /**
      * 根据15分钟时间框架指标确定市场方向(做多/做空/震荡)
@@ -547,6 +550,71 @@
     }
     
     /**
+     * 生成区间交易信号
+     * 在震荡行情下,使用BOLL通道作为区间边界,结合KDJ指标生成交易信号
+     * @param currentPrice 当前价格
+     * @param volume 成交量列表
+     * @param hasLongPosition 是否当前持有做多仓位
+     * @param hasShortPosition 是否当前持有做空仓位
+     * @return 交易信号
+     */
+    private SignalType generateRangeTradingSignal(BigDecimal currentPrice, List<BigDecimal> volume, 
+                                                 boolean hasLongPosition, boolean hasShortPosition) {
+        // 区间交易策略逻辑:
+        // 1. 价格触及BOLL下轨且KDJ超卖 → 买入信号
+        // 2. 价格触及BOLL上轨且KDJ超买 → 卖出信号
+        // 3. 价格回归BOLL中轨 → 平仓信号
+        
+        // 价格触及BOLL下轨
+        boolean isPriceNearBollLower = currentPrice.compareTo(boll.getLower()) >= 0 && 
+                                      currentPrice.compareTo(boll.getLower().multiply(new BigDecimal("1.005"))) <= 0;
+        
+        // 价格触及BOLL上轨
+        boolean isPriceNearBollUpper = currentPrice.compareTo(boll.getUpper()) <= 0 && 
+                                      currentPrice.compareTo(boll.getUpper().multiply(new BigDecimal("0.995"))) >= 0;
+        
+        // 价格回归BOLL中轨附近
+        boolean isPriceNearBollMid = currentPrice.compareTo(boll.getMid().multiply(new BigDecimal("0.998"))) >= 0 && 
+                                    currentPrice.compareTo(boll.getMid().multiply(new BigDecimal("1.002"))) <= 0;
+        
+        // KDJ超卖(使用调整后的阈值)
+        boolean isKdjOversold = kdj.getJ().compareTo(new BigDecimal(15)) < 0;
+        
+        // KDJ超买(使用调整后的阈值)
+        boolean isKdjOverbought = kdj.getJ().compareTo(new BigDecimal(85)) > 0;
+        
+        // 成交量验证(当前成交量大于20周期均值的1.2倍)
+        boolean isVolumeValid = volumeConfirm(volume) && 
+                               volume.get(volume.size() - 1).compareTo(calculateMA(volume, config.getVolumeMaPeriod()).multiply(new BigDecimal("1.2"))) > 0;
+        
+        // 开多逻辑:价格触及BOLL下轨且KDJ超卖且有成交量支持
+        if (isPriceNearBollLower && isKdjOversold && isVolumeValid && !hasLongPosition && !hasShortPosition) {
+            log.info("区间交易:价格触及BOLL下轨({}), KDJ-J值({})超卖,生成买入信号", boll.getLower(), kdj.getJ());
+            return SignalType.BUY;
+        }
+        
+        // 开空逻辑:价格触及BOLL上轨且KDJ超买且有成交量支持
+        if (isPriceNearBollUpper && isKdjOverbought && isVolumeValid && !hasLongPosition && !hasShortPosition) {
+            log.info("区间交易:价格触及BOLL上轨({}), KDJ-J值({})超买,生成卖出信号", boll.getUpper(), kdj.getJ());
+            return SignalType.SELL;
+        }
+        
+        // 平多逻辑:价格回归BOLL中轨
+        if (isPriceNearBollMid && hasLongPosition) {
+            log.info("区间交易:价格回归BOLL中轨({}),生成平多信号", boll.getMid());
+            return SignalType.CLOSE_BUY;
+        }
+        
+        // 平空逻辑:价格回归BOLL中轨
+        if (isPriceNearBollMid && hasShortPosition) {
+            log.info("区间交易:价格回归BOLL中轨({}),生成平空信号", boll.getMid());
+            return SignalType.CLOSE_SELL;
+        }
+        
+        return SignalType.NONE;
+    }
+    
+    /**
      * 计算动态杠杆倍数
      * 杠杆倍数 = 基础杠杆 * (波动率阈值/当前波动率)
      * @param high 最高价列表
@@ -572,7 +640,7 @@
         // 限制杠杆范围在1x-10x之间
         leverage = leverage.min(new BigDecimal(10)).max(BigDecimal.ONE);
         
-        log.debug("动态杠杆计算 - 基础杠杆: {}, 波动率阈值: {}, 当前波动率: {}, 计算杠杆: {}", 
+        log.info("动态杠杆计算 - 基础杠杆: {}, 波动率阈值: {}, 当前波动率: {}, 计算杠杆: {}",
                 config.getBaseLeverage(), volatilityThreshold, currentVolatility, leverage);
         
         return leverage;
@@ -685,6 +753,8 @@
         return direction == Direction.LONG ? ma.getEma20() : ma.getEma20();
     }
     
+
+
     /**
      * 黑天鹅事件过滤
      * 规避重大事件前后30分钟、链上大额转账、异常资金费率
@@ -708,7 +778,7 @@
         boolean shouldAvoid = isAbnormalFundingRate || hasLargeTransfer || hasUpcomingEvent;
         
         if (shouldAvoid) {
-            log.debug("黑天鹅事件过滤触发 - 资金费率异常: {}, 大额转账: {}, 即将发生重大事件: {}", 
+            log.info("黑天鹅事件过滤触发 - 资金费率异常: {}, 大额转账: {}, 即将发生重大事件: {}",
                     isAbnormalFundingRate, hasLargeTransfer, hasUpcomingEvent);
         }
         
diff --git a/src/main/resources/logback-spring.xml b/src/main/resources/logback-spring.xml
index f6fa98a..0d0bf1b 100644
--- a/src/main/resources/logback-spring.xml
+++ b/src/main/resources/logback-spring.xml
@@ -141,7 +141,7 @@
         <logger name="java.sql" level="DEBUG" />
     </springProfile>
 
-    <root level="debug">
+    <root level="info">
         <appender-ref ref="CONSOLE" />
         <appender-ref ref="DEBUG_FILE" />
         <appender-ref ref="INFO_FILE" />

--
Gitblit v1.9.1