package com.xcong.excoin.modules.okxNewPrice.indicator;
|
|
import lombok.Getter;
|
import lombok.Setter;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.math.BigDecimal;
|
import java.util.List;
|
|
/**
|
* MA (Moving Average) 指标实现
|
* 支持不同周期的简单移动平均线(SMA)和指数移动平均线(EMA)
|
*/
|
@Slf4j
|
@Getter
|
@Setter
|
public class MA extends IndicatorBase {
|
|
// 常用周期
|
public static final int MA5 = 5;
|
public static final int MA10 = 10;
|
public static final int MA20 = 20;
|
public static final int MA30 = 30;
|
public static final int MA60 = 60;
|
|
private BigDecimal ma5 = BigDecimal.ZERO;
|
private BigDecimal ma10 = BigDecimal.ZERO;
|
private BigDecimal ma20 = BigDecimal.ZERO;
|
private BigDecimal ma30 = BigDecimal.ZERO;
|
private BigDecimal ma60 = BigDecimal.ZERO;
|
|
private BigDecimal ema5 = BigDecimal.ZERO;
|
private BigDecimal ema10 = BigDecimal.ZERO;
|
private BigDecimal ema20 = BigDecimal.ZERO;
|
private BigDecimal ema30 = BigDecimal.ZERO;
|
private BigDecimal ema60 = BigDecimal.ZERO;
|
|
private BigDecimal prevEma5 = null;
|
private BigDecimal prevEma10 = null;
|
private BigDecimal prevEma20 = null;
|
private BigDecimal prevEma30 = null;
|
private BigDecimal prevEma60 = null;
|
|
/**
|
* 计算所有周期的MA指标
|
* @param prices 价格列表
|
*/
|
public void calculate(List<BigDecimal> prices) {
|
if (prices == null || prices.size() < 1) {
|
return;
|
}
|
|
// 计算SMA
|
if (prices.size() >= MA5) {
|
ma5 = calculateMA(prices, MA5);
|
}
|
if (prices.size() >= MA10) {
|
ma10 = calculateMA(prices, MA10);
|
}
|
if (prices.size() >= MA20) {
|
ma20 = calculateMA(prices, MA20);
|
}
|
if (prices.size() >= MA30) {
|
ma30 = calculateMA(prices, MA30);
|
}
|
if (prices.size() >= MA60) {
|
ma60 = calculateMA(prices, MA60);
|
}
|
|
// 计算EMA
|
prevEma5 = calculateEMA(prices, MA5, prevEma5);
|
ema5 = prevEma5;
|
|
prevEma10 = calculateEMA(prices, MA10, prevEma10);
|
ema10 = prevEma10;
|
|
prevEma20 = calculateEMA(prices, MA20, prevEma20);
|
ema20 = prevEma20;
|
|
prevEma30 = calculateEMA(prices, MA30, prevEma30);
|
ema30 = prevEma30;
|
|
prevEma60 = calculateEMA(prices, MA60, prevEma60);
|
ema60 = prevEma60;
|
|
log.debug("MA计算结果 - MA5: {}, MA10: {}, MA20: {}, MA30: {}, MA60: {}",
|
ma5, ma10, ma20, ma30, ma60);
|
log.debug("EMA计算结果 - EMA5: {}, EMA10: {}, EMA20: {}, EMA30: {}, EMA60: {}",
|
ema5, ema10, ema20, ema30, ema60);
|
}
|
|
/**
|
* 判断短期均线是否上穿长期均线(金叉)
|
* @param shortMA 短期均线
|
* @param longMA 长期均线
|
* @param prevShortMA 前一期短期均线
|
* @param prevLongMA 前一期长期均线
|
* @return 是否形成金叉
|
*/
|
public boolean isGoldenCross(BigDecimal shortMA, BigDecimal longMA,
|
BigDecimal prevShortMA, BigDecimal prevLongMA) {
|
return prevShortMA != null && prevLongMA != null &&
|
prevShortMA.compareTo(prevLongMA) < 0 &&
|
shortMA.compareTo(longMA) > 0;
|
}
|
|
/**
|
* 判断短期均线是否下穿长期均线(死叉)
|
* @param shortMA 短期均线
|
* @param longMA 长期均线
|
* @param prevShortMA 前一期短期均线
|
* @param prevLongMA 前一期长期均线
|
* @return 是否形成死叉
|
*/
|
public boolean isDeathCross(BigDecimal shortMA, BigDecimal longMA,
|
BigDecimal prevShortMA, BigDecimal prevLongMA) {
|
return prevShortMA != null && prevLongMA != null &&
|
prevShortMA.compareTo(prevLongMA) > 0 &&
|
shortMA.compareTo(longMA) < 0;
|
}
|
|
/**
|
* 判断价格是否上穿均线
|
* @param price 当前价格
|
* @param ma 均线值
|
* @param prevPrice 前一期价格
|
* @param prevMA 前一期均线值
|
* @return 是否上穿
|
*/
|
public boolean isPriceCrossUp(BigDecimal price, BigDecimal ma,
|
BigDecimal prevPrice, BigDecimal prevMA) {
|
return prevPrice != null && prevMA != null &&
|
prevPrice.compareTo(prevMA) < 0 &&
|
price.compareTo(ma) > 0;
|
}
|
|
/**
|
* 判断价格是否下穿均线
|
* @param price 当前价格
|
* @param ma 均线值
|
* @param prevPrice 前一期价格
|
* @param prevMA 前一期均线值
|
* @return 是否下穿
|
*/
|
public boolean isPriceCrossDown(BigDecimal price, BigDecimal ma,
|
BigDecimal prevPrice, BigDecimal prevMA) {
|
return prevPrice != null && prevMA != null &&
|
prevPrice.compareTo(prevMA) > 0 &&
|
price.compareTo(ma) < 0;
|
}
|
}
|