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