| | |
| | | // 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 && |
| | |
| | | // 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; |
| | | } |
| | | |