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.List; /** * Advanced MA (Moving Average) 指标实现 * 支持扩展周期的指数移动平均线(EMA),用于三重EMA交叉系统 */ @Slf4j @Getter @Setter public class AdvancedMA extends IndicatorBase { // 扩展周期 - 三重EMA交叉系统 public static final int EMA9 = 9; public static final int EMA21 = 21; public static final int EMA55 = 55; private BigDecimal ema9 = BigDecimal.ZERO; private BigDecimal ema21 = BigDecimal.ZERO; private BigDecimal ema55 = BigDecimal.ZERO; private BigDecimal prevEma9 = null; private BigDecimal prevEma21 = null; private BigDecimal prevEma55 = null; /** * 计算三重EMA交叉系统的指标 * @param prices 价格列表 */ public void calculateTripleEMA(List prices) { if (prices == null || prices.isEmpty()) { return; } // 计算三重EMA prevEma9 = calculateEMA(prices, EMA9, prevEma9); ema9 = prevEma9; prevEma21 = calculateEMA(prices, EMA21, prevEma21); ema21 = prevEma21; prevEma55 = calculateEMA(prices, EMA55, prevEma55); ema55 = prevEma55; log.debug("三重EMA计算结果 - EMA9: {}, EMA21: {}, EMA55: {}", ema9, ema21, ema55); } /** * 判断三重EMA多头排列 * 当9EMA > 21EMA > 55EMA时触发多头条件 * @return 是否形成多头排列 */ public boolean isBullish() { return ema9.compareTo(ema21) > 0 && ema21.compareTo(ema55) > 0; } /** * 判断三重EMA空头排列 * 当9EMA < 21EMA < 55EMA时触发空头条件 * @return 是否形成空头排列 */ public boolean isBearish() { return ema9.compareTo(ema21) < 0 && ema21.compareTo(ema55) < 0; } /** * 计算三线粘合度 * 用于自动过滤震荡行情 * @return 粘合度百分比,值越小表示越粘合 */ public BigDecimal calculatePercent() { // 计算最大值和最小值 BigDecimal max = ema9.max(ema21).max(ema55); BigDecimal min = ema9.min(ema21).min(ema55); // 计算平均价 BigDecimal avg = ema9.add(ema21).add(ema55).divide(new BigDecimal(3), 8, RoundingMode.HALF_UP); // 计算粘合度: (最大值 - 最小值) / 平均值 * 100% if (avg.compareTo(BigDecimal.ZERO) == 0) { return BigDecimal.ZERO; } return max.subtract(min).divide(avg, 8, RoundingMode.HALF_UP).multiply(new BigDecimal(100)); } /** * 检查是否处于震荡行情(三线粘合) * 当三线粘合度 < 2% 时判定为震荡行情 * @return 是否处于震荡行情 */ public boolean isUpAndDown() { BigDecimal bigDecimal = calculatePercent(); return bigDecimal.compareTo(new BigDecimal(2)) < 0; } }