package com.xcong.excoin.modules.okxNewPrice.indicator;
|
|
import lombok.Getter;
|
import lombok.Setter;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.util.ArrayList;
|
import java.util.List;
|
|
/**
|
* MACD (Moving Average Convergence Divergence) 指标实现
|
* 计算逻辑:
|
* 1. DIF = EMA(12) - EMA(26)
|
* 2. DEA = EMA(DIF, 9)
|
* 3. MACD柱状图 = (DIF - DEA) * 2
|
*/
|
@Slf4j
|
@Getter
|
@Setter
|
public class MACD extends IndicatorBase {
|
|
private static final int FAST_PERIOD = 12;
|
private static final int SLOW_PERIOD = 26;
|
private static final int SIGNAL_PERIOD = 9;
|
|
private BigDecimal dif = BigDecimal.ZERO;
|
private BigDecimal dea = BigDecimal.ZERO;
|
private BigDecimal macdBar = BigDecimal.ZERO;
|
private BigDecimal prevFastEMA = null;
|
private BigDecimal prevSlowEMA = null;
|
private BigDecimal prevDea = null;
|
|
/**
|
* 计算MACD指标
|
* @param prices 价格列表
|
*/
|
public void calculate(List<BigDecimal> prices) {
|
if (prices == null || prices.size() < 2) {
|
return;
|
}
|
|
// 计算快速EMA
|
prevFastEMA = calculateEMA(prices, FAST_PERIOD, prevFastEMA);
|
|
// 计算慢速EMA
|
prevSlowEMA = calculateEMA(prices, SLOW_PERIOD, prevSlowEMA);
|
|
// 计算DIF
|
dif = prevFastEMA.subtract(prevSlowEMA).setScale(8, RoundingMode.HALF_UP);
|
|
// 计算DEA
|
List<BigDecimal> difList = new ArrayList<>();
|
difList.add(dif);
|
prevDea = calculateEMA(difList, SIGNAL_PERIOD, prevDea);
|
dea = prevDea.setScale(8, RoundingMode.HALF_UP);
|
|
// 计算MACD柱状图
|
macdBar = dif.subtract(dea).multiply(new BigDecimal(2)).setScale(8, RoundingMode.HALF_UP);
|
|
log.debug("MACD计算结果 - DIF: {}, DEA: {}, MACD柱状图: {}", dif, dea, macdBar);
|
}
|
|
/**
|
* 判断金叉信号(DIF上穿DEA)
|
* @return 是否形成金叉
|
*/
|
public boolean isGoldenCross(BigDecimal previousDIF, BigDecimal previousDEA) {
|
return previousDIF.compareTo(previousDEA) < 0 && dif.compareTo(dea) > 0;
|
}
|
|
/**
|
* 判断死叉信号(DIF下穿DEA)
|
* @return 是否形成死叉
|
*/
|
public boolean isDeathCross(BigDecimal previousDIF, BigDecimal previousDEA) {
|
return previousDIF.compareTo(previousDEA) > 0 && dif.compareTo(dea) < 0;
|
}
|
}
|