Administrator
7 days ago 27ebdeb8a61d4af070d2ed52f77c814350b6dc54
src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java
@@ -412,35 +412,55 @@
     * @return 是否为震荡市场
     */
    private boolean isRangeMarket(List<BigDecimal> prices) {
        // 强化的震荡市场判断条件
        // 优化的震荡市场判断条件,放宽标准以减少RANGING信号频率
        
        // 1. 高级MA三线收敛(小于2%)
        boolean isMaConverged = advancedMA.calculatePercent().compareTo(new BigDecimal(2)) < 0;
        // 1. 高级MA三线收敛(小于3%,放宽条件)
        boolean isMaConverged = advancedMA.calculatePercent().compareTo(new BigDecimal(3)) < 0;
        
        // 2. RSI中性区间(40-60)
        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(40)) > 0 &&
                              rsi.getRsi().compareTo(new BigDecimal(60)) < 0;
        // 2. RSI中性区间(35-65,放宽条件)
        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(35)) > 0 &&
                              rsi.getRsi().compareTo(new BigDecimal(65)) < 0;
        
        // 3. BOLL带宽收窄(小于0.05)
        boolean isBollNarrow = boll.calculateBandWidth().compareTo(new BigDecimal(0.05)) < 0;
        // 3. BOLL带宽收窄(小于0.06,放宽条件)
        boolean isBollNarrow = boll.calculateBandWidth().compareTo(new BigDecimal(0.06)) < 0;
        
        // 4. MACD柱状图趋近于0(多空力量平衡)
        boolean isMacdBalanced = macd.getMacdBar().abs().compareTo(new BigDecimal(0.01)) < 0;
        // 4. MACD柱状图趋近于0(多空力量平衡,放宽条件)
        boolean isMacdBalanced = macd.getMacdBar().abs().compareTo(new BigDecimal(0.02)) < 0;
        
        // 5. KDJ在中间区域波动(30-70)
        boolean isKdjNeutral = kdj.getK().compareTo(new BigDecimal(30)) > 0 &&
                             kdj.getK().compareTo(new BigDecimal(70)) < 0 &&
                             kdj.getD().compareTo(new BigDecimal(30)) > 0 &&
                             kdj.getD().compareTo(new BigDecimal(70)) < 0 &&
                             kdj.getJ().compareTo(new BigDecimal(30)) > 0 &&
                             kdj.getJ().compareTo(new BigDecimal(70)) < 0;
        // 5. KDJ在中间区域波动(25-75,放宽条件)
        boolean isKdjNeutral = kdj.getK().compareTo(new BigDecimal(25)) > 0 &&
                             kdj.getK().compareTo(new BigDecimal(75)) < 0 &&
                             kdj.getD().compareTo(new BigDecimal(25)) > 0 &&
                             kdj.getD().compareTo(new BigDecimal(75)) < 0 &&
                             kdj.getJ().compareTo(new BigDecimal(20)) > 0 &&
                             kdj.getJ().compareTo(new BigDecimal(80)) < 0;
        
        // 6. 价格波动范围较小(最近20根K线最高价与最低价的比值小于1.05)
        boolean isPriceVolatilityLow = calculatePriceVolatility(prices).compareTo(new BigDecimal(1.05)) < 0;
        // 6. 价格波动范围较小(最近20根K线最高价与最低价的比值小于1.06,放宽条件)
        boolean isPriceVolatilityLow = calculatePriceVolatility(prices).compareTo(new BigDecimal(1.06)) < 0;
        
        // 综合判断:需要满足大部分条件
        return isMaConverged && isRsiNeutral && isBollNarrow &&
               (isMacdBalanced || isKdjNeutral || isPriceVolatilityLow);
        // 综合判断:只需要满足部分条件即可,增加趋势信号的机会
        int rangeConditionsMet = 0;
        if (isMaConverged) {
            rangeConditionsMet++;
        }
        if (isRsiNeutral) {
            rangeConditionsMet++;
        }
        if (isBollNarrow) {
            rangeConditionsMet++;
        }
        if (isMacdBalanced) {
            rangeConditionsMet++;
        }
        if (isKdjNeutral) {
            rangeConditionsMet++;
        }
        if (isPriceVolatilityLow) {
            rangeConditionsMet++;
        }
        // 只有满足4个或以上条件才判定为震荡市场
        return rangeConditionsMet >= 4;
    }
    
    /**
@@ -748,13 +768,25 @@
        // 2. 价格触及BOLL上轨且KDJ超买 → 卖出信号
        // 3. 价格回归BOLL中轨 → 平仓信号
        
        // 价格触及BOLL下轨
        boolean isPriceNearBollLower = currentPrice.compareTo(boll.getLower()) >= 0 &&
                                      currentPrice.compareTo(boll.getLower().multiply(new BigDecimal("1.005"))) <= 0;
        // 检查KDJ极端超买超卖情况
        boolean isKdjJExtremeOverbought = kdj.getJ().compareTo(new BigDecimal("100")) > 0;
        boolean isKdjJExtremeOversold = kdj.getJ().compareTo(new BigDecimal("10")) < 0;
        
        // 价格触及BOLL上轨
        // 价格触及BOLL下轨(基础条件)
        boolean isPriceNearBollLower = currentPrice.compareTo(boll.getLower()) >= 0 &&
                                      currentPrice.compareTo(boll.getLower().multiply(new BigDecimal("1.01"))) <= 0;
        // 价格触及BOLL上轨(基础条件)
        boolean isPriceNearBollUpper = currentPrice.compareTo(boll.getUpper()) <= 0 && 
                                      currentPrice.compareTo(boll.getUpper().multiply(new BigDecimal("0.995"))) >= 0;
                                      currentPrice.compareTo(boll.getUpper().multiply(new BigDecimal("0.99"))) >= 0;
        // 当KDJ-J极度超买/超卖时,放宽BOLL边界要求
        if (isKdjJExtremeOverbought) {
            isPriceNearBollUpper = currentPrice.compareTo(boll.getUpper().multiply(new BigDecimal("0.985"))) >= 0;
        }
        if (isKdjJExtremeOversold) {
            isPriceNearBollLower = currentPrice.compareTo(boll.getLower().multiply(new BigDecimal("1.015"))) <= 0;
        }
        
        // 价格回归BOLL中轨附近
        boolean isPriceNearBollMid = currentPrice.compareTo(boll.getMid().multiply(new BigDecimal("0.998"))) >= 0 && 
@@ -766,19 +798,25 @@
        // 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;
        // RSI超卖(<30)
        boolean isRsiOversold = rsi.getRsi().compareTo(new BigDecimal(30)) < 0;
        
        // 开多逻辑:价格触及BOLL下轨且KDJ超卖且有成交量支持
        if (isPriceNearBollLower && isKdjOversold && isVolumeValid && !hasLongPosition && !hasShortPosition) {
            log.info("区间交易:价格触及BOLL下轨({}), KDJ-J值({})超卖,生成买入信号", boll.getLower(), kdj.getJ());
        // RSI超买(>70)
        boolean isRsiOverbought = rsi.getRsi().compareTo(new BigDecimal(70)) > 0;
        // 成交量验证(当前成交量大于20周期均值的1.1倍)
        boolean isVolumeValid = volumeConfirm(volume) &&
                               volume.get(volume.size() - 1).compareTo(calculateMA(volume, config.getVolumeMaPeriod()).multiply(new BigDecimal("1.1"))) > 0;
        // 开多逻辑:价格触及BOLL下轨且KDJ超卖且RSI超卖且有成交量支持
        if (isPriceNearBollLower && isKdjOversold && isRsiOversold && isVolumeValid && !hasLongPosition && !hasShortPosition) {
            log.info("区间交易:价格触及BOLL下轨({}), KDJ-J值({})超卖,RSI({})超卖,生成买入信号", boll.getLower(), kdj.getJ(), rsi.getRsi());
            return SignalType.BUY;
        }
        
        // 开空逻辑:价格触及BOLL上轨且KDJ超买且有成交量支持
        if (isPriceNearBollUpper && isKdjOverbought && isVolumeValid && !hasLongPosition && !hasShortPosition) {
            log.info("区间交易:价格触及BOLL上轨({}), KDJ-J值({})超买,生成卖出信号", boll.getUpper(), kdj.getJ());
        // 开空逻辑:价格触及BOLL上轨且KDJ超买且RSI超买且有成交量支持
        if (isPriceNearBollUpper && isKdjOverbought && isRsiOverbought && isVolumeValid && !hasLongPosition && !hasShortPosition) {
            log.info("区间交易:价格触及BOLL上轨({}), KDJ-J值({})超买,RSI({})超买,生成卖出信号", boll.getUpper(), kdj.getJ(), rsi.getRsi());
            return SignalType.SELL;
        }