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/BearishSignalDetector.java | 132 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 132 insertions(+), 0 deletions(-)
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BearishSignalDetector.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BearishSignalDetector.java
new file mode 100644
index 0000000..c537e84
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/BearishSignalDetector.java
@@ -0,0 +1,132 @@
+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 bearishSignal = BearishSignalDetector.isBearishSignalFormed(macdResult, closePrices);
+ */
+public class BearishSignalDetector {
+ /**
+ * 判断是否形成做空信号
+ *
+ * @param macdResult 包含MACD数据和有效起始索引的结果对象
+ * @param closePrices 收盘价列表
+ * @return 是否形成信号
+ */
+ public static boolean isBearishSignalFormed(MACDResult macdResult, List<BigDecimal> closePrices) {
+ List<PriceData> macdData = macdResult.getMacdData();
+ int startIdx = macdResult.getStartIndex();
+
+ // 校验数据长度(至少需要两个有效DIF点)
+ if (macdData.size() < 2 || closePrices.size() < startIdx + macdData.size()) {
+ return false;
+ }
+
+ int currentMacdIndex = macdData.size() - 1;
+ int currentCloseIndex = startIdx + currentMacdIndex;
+
+ // 1. 判断顶背离
+ boolean isTopDivergence = isTopDivergence(macdData, closePrices, currentMacdIndex, startIdx);
+
+ // 2. 判断死叉
+ boolean isDeathCross = isDeathCross(macdData, currentMacdIndex);
+
+ return isTopDivergence && isDeathCross;
+ }
+
+ /**
+ * 判断顶背离(需确保earlierHigh在recentHigh之前)
+ */
+ private static boolean isTopDivergence(List<PriceData> macdData, List<BigDecimal> closePrices,
+ int currentMacdIndex, int startIdx) {
+ // 计算对应closePrices的索引
+ int currentCloseIndex = startIdx + currentMacdIndex;
+ if (currentCloseIndex < 10 || macdData.size() < 5) {
+ return false;
+ }
+
+ // 寻找最近的价格高点(至少在当前点的前2根K线范围内)
+ int recentHighCloseIndex = findRecentHighWithRetrace(closePrices, currentCloseIndex - 5, currentCloseIndex);
+ if (recentHighCloseIndex == -1) {
+ return false;
+ }
+
+ // 寻找更早的高点(确保在recentHigh之前)
+ int earlierHighCloseIndex = findRecentHighWithRetrace(closePrices, startIdx, recentHighCloseIndex - 1);
+ if (earlierHighCloseIndex == -1) {
+ return false;
+ }
+
+ // 转换为macdData的索引
+ int recentHighMacdIndex = recentHighCloseIndex - startIdx;
+ int earlierHighMacdIndex = earlierHighCloseIndex - startIdx;
+
+ // 判断价格创新高但DIF走低
+ BigDecimal recentHighPrice = closePrices.get(recentHighCloseIndex);
+ BigDecimal earlierHighPrice = closePrices.get(earlierHighCloseIndex);
+ boolean isPriceHigher = recentHighPrice.compareTo(earlierHighPrice) > 0;
+
+ BigDecimal recentDif = macdData.get(recentHighMacdIndex).getDif();
+ BigDecimal earlierDif = macdData.get(earlierHighMacdIndex).getDif();
+ boolean isDifLower = recentDif.compareTo(earlierDif) < 0;
+
+ return isPriceHigher && isDifLower;
+ }
+
+ /**
+ * 寻找有效的高点(高点后需有至少1根K线下跌)
+ */
+ private static int findRecentHighWithRetrace(List<BigDecimal> prices, int startIndex, int endIndex) {
+ if (startIndex < 0 || endIndex >= prices.size() || startIndex >= endIndex) {
+ return -1;
+ }
+
+ int highIndex = -1;
+ BigDecimal highPrice = BigDecimal.ZERO;
+
+ // 从右向左搜索,找到第一个有效高点
+ for (int i = endIndex; i >= startIndex; i--) {
+ if (prices.get(i).compareTo(highPrice) > 0) {
+ highPrice = prices.get(i);
+ highIndex = i;
+ }
+
+ // 检查高点后是否有回调
+ if (highIndex != -1 && i < endIndex) {
+ if (prices.get(i + 1).compareTo(highPrice) < 0) {
+ return highIndex; // 找到确认回调的高点
+ }
+ }
+ }
+
+ return highIndex;
+ }
+
+
+ /**
+ * 判断是否形成死叉(DIF下穿DEA)
+ *
+ * @param macdData MACD计算结果数据列表
+ * @param currentIndex 当前数据点索引
+ * @return 是否形成死叉
+ */
+ private static boolean isDeathCross(List<PriceData> macdData, int currentIndex) {
+ if (currentIndex < 1) {
+ return false;
+ }
+
+ PriceData current = macdData.get(currentIndex);
+ PriceData previous = macdData.get(currentIndex - 1);
+
+ // 前一期DIF >= DEA,当前期DIF < DEA
+ return previous.getDif().compareTo(previous.getDea()) >= 0 &&
+ current.getDif().compareTo(current.getDea()) < 0;
+ }
+
+}
\ No newline at end of file
--
Gitblit v1.9.1