From 4884ebffeed775d63dbf7bb7d0ece8182f10c344 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Fri, 26 Dec 2025 18:19:46 +0800
Subject: [PATCH] fix(okxNewPrice): 解决交易订单为空时的空指针异常

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BullishSignalDetector.java |   87 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 87 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BullishSignalDetector.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BullishSignalDetector.java
new file mode 100644
index 0000000..b6265e6
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BullishSignalDetector.java
@@ -0,0 +1,87 @@
+package com.xcong.excoin.modules.okxNewPrice.indicator.macdAndMatrategy;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 示例用法
+ * // 计算MACD结果(包含起始索引)
+ * MACDCalculator.MACDResult macdResult = MACDCalculator.calculateMACD(closePrices, 12, 26, 9);
+ *
+ * // 检测做多信号
+ * boolean bullishSignal = BullishSignalDetector.isBullishSignalFormed(macdResult, closePrices);
+ */
+public class BullishSignalDetector {
+    public static boolean isBullishSignalFormed(MACDResult macdResult, List<BigDecimal> closePrices) {
+        List<PriceData> macdData = macdResult.getMacdData();
+        int startIdx = macdResult.getStartIndex();
+
+        // 校验MACD数据和收盘价长度合法性
+        if (closePrices.size() < 34 || macdData.size() < 2 || startIdx + macdData.size() > closePrices.size()) {
+            return false;
+        }
+
+        int currentMacdIndex = macdData.size() - 1;
+        int currentCloseIndex = startIdx + currentMacdIndex;
+
+        // 1. 金叉判断
+        boolean isGoldenCross = isGoldenCross(macdData, currentMacdIndex);
+
+        // 2. MACD柱动量增强
+        boolean isMacdHistExpanding = isMacdHistExpanding(macdData, currentMacdIndex);
+
+        // 3. 价格突破前15周期高点
+        boolean isPriceBreakout = isPriceBreakout(closePrices, currentCloseIndex, 15);
+
+        return isGoldenCross && isMacdHistExpanding && isPriceBreakout;
+    }
+
+    private static boolean isGoldenCross(List<PriceData> macdData, int currentMacdIndex) {
+        if (currentMacdIndex < 1 || currentMacdIndex >= macdData.size()) {
+            return false;
+        }
+
+        PriceData current = macdData.get(currentMacdIndex);
+        PriceData previous = macdData.get(currentMacdIndex - 1);
+
+        return previous.getDif().compareTo(previous.getDea()) <= 0 &&
+                current.getDif().compareTo(current.getDea()) > 0;
+    }
+
+    private static boolean isMacdHistExpanding(List<PriceData> macdData, int currentMacdIndex) {
+        if (currentMacdIndex < 2 || currentMacdIndex >= macdData.size()) {
+            return false;
+        }
+
+        BigDecimal currentHist = macdData.get(currentMacdIndex).getMacdHist();
+        BigDecimal prevHist = macdData.get(currentMacdIndex - 1).getMacdHist();
+        BigDecimal prevPrevHist = macdData.get(currentMacdIndex - 2).getMacdHist();
+
+        boolean isPositive = currentHist.compareTo(BigDecimal.ZERO) > 0;
+        boolean isExpanding = prevPrevHist.compareTo(prevHist) <= 0 &&
+                prevHist.compareTo(currentHist) < 0;
+
+        return isPositive && isExpanding;
+    }
+
+    private static boolean isPriceBreakout(List<BigDecimal> closePrices, int currentCloseIndex, int period) {
+        if (currentCloseIndex < period || period <= 0) {
+            return false;
+        }
+
+        int startSearchIdx = Math.max(currentCloseIndex - period, 0);
+        BigDecimal maxPreviousPrice = closePrices.get(startSearchIdx);
+
+        for (int i = startSearchIdx + 1; i < currentCloseIndex; i++) {
+            if (i >= closePrices.size()) {
+                break;
+            }
+            BigDecimal price = closePrices.get(i);
+            if (price.compareTo(maxPreviousPrice) > 0) {
+                maxPreviousPrice = price;
+            }
+        }
+
+        return closePrices.get(currentCloseIndex).compareTo(maxPreviousPrice) > 0;
+    }
+}
\ No newline at end of file

--
Gitblit v1.9.1