Administrator
2025-12-29 2cb4335ce706ccb451ccc7edb92fd89b5ad427e2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
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交叉系统
 * 
 * 作用:
 * 1. 基于三重EMA交叉系统识别趋势方向和强度
 * 2. 当9EMA > 21EMA > 55EMA时形成多头排列,提示上涨趋势
 * 3. 当9EMA < 21EMA < 55EMA时形成空头排列,提示下跌趋势
 * 4. 计算三线粘合度,自动过滤震荡行情
 * 
 * 价格参数类型:
 * - 参数名称:prices
 * - 参数类型:List<BigDecimal>
 * - 参数说明:需要至少1个价格数据点用于计算,根据不同周期需求更多数据点
 * 
 * 推荐时间粒度及优缺点:
 * 1. 5分钟(5m):
 *    - 优点:适合短线三重EMA交叉策略
 *    - 缺点:需要频繁监控,容易受短期波动影响
 * 2. 15分钟(15m):
 *    - 优点:平衡了信号可靠性和反应速度
 *    - 缺点:仍有一定噪音
 * 3. 1小时(1h):
 *    - 优点:信号较为可靠,适合中期趋势跟踪
 *    - 缺点:反应较慢
 * 4. 4小时(4h)及以上:
 *    - 优点:趋势信号明确,适合长期持仓
 *    - 缺点:反应滞后,入场点较晚
 */
@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<BigDecimal> 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.info("三重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;
    }
}