Administrator
5 days ago 9c95b584fb82289f199ae554ea92f5494e39a945
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
package com.xcong.excoin.modules.okxNewPrice.indicator;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 技术指标基础类,提供通用计算方法
 */
public abstract class IndicatorBase {
 
    /**
     * 计算移动平均值
     * @param prices 价格列表
     * @param period 周期
     * @return 移动平均值
     */
    protected BigDecimal calculateMA(List<BigDecimal> prices, int period) {
        if (prices == null || prices.size() < period) {
            return BigDecimal.ZERO;
        }
        BigDecimal sum = BigDecimal.ZERO;
        for (int i = prices.size() - period; i < prices.size(); i++) {
            sum = sum.add(prices.get(i));
        }
        return sum.divide(new BigDecimal(period), 8, RoundingMode.HALF_UP);
    }
 
    /**
     * 计算指数移动平均值
     * @param prices 价格列表
     * @param period 周期
     * @param prevEMA 前一个EMA值
     * @return 指数移动平均值
     */
    protected BigDecimal calculateEMA(List<BigDecimal> prices, int period, BigDecimal prevEMA) {
        if (prices == null || prices.size() == 0) {
            return BigDecimal.ZERO;
        }
        if (prevEMA == null || prevEMA.compareTo(BigDecimal.ZERO) == 0) {
            return calculateMA(prices, Math.min(period, prices.size()));
        }
        BigDecimal k = new BigDecimal(2).divide(new BigDecimal(period + 1), 8, RoundingMode.HALF_UP);
        BigDecimal currentPrice = prices.get(prices.size() - 1);
        return currentPrice.multiply(k).add(prevEMA.multiply(BigDecimal.ONE.subtract(k)));
    }
 
    /**
     * 计算标准差
     * @param prices 价格列表
     * @param period 周期
     * @return 标准差
     */
    protected BigDecimal calculateStdDev(List<BigDecimal> prices, int period) {
        if (prices == null || prices.size() < period) {
            return BigDecimal.ZERO;
        }
        BigDecimal ma = calculateMA(prices, period);
        BigDecimal sumSquares = BigDecimal.ZERO;
        for (int i = prices.size() - period; i < prices.size(); i++) {
            BigDecimal diff = prices.get(i).subtract(ma);
            sumSquares = sumSquares.add(diff.multiply(diff));
        }
        BigDecimal variance = sumSquares.divide(new BigDecimal(period), 8, RoundingMode.HALF_UP);
        return sqrt(variance);
    }
 
    /**
     * 计算平方根(简化实现)
     * @param value 输入值
     * @return 平方根
     */
    protected BigDecimal sqrt(BigDecimal value) {
        if (value.compareTo(BigDecimal.ZERO) < 0) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(Math.sqrt(value.doubleValue())).setScale(8, RoundingMode.HALF_UP);
    }
 
    /**
     * 获取最近的价格数据
     * @param prices 所有价格数据
     * @param period 周期
     * @return 最近period个价格数据
     */
    protected List<BigDecimal> getRecentPrices(List<BigDecimal> prices, int period) {
        if (prices == null || prices.size() == 0) {
            return new ArrayList<>();
        }
        int startIndex = Math.max(0, prices.size() - period);
        return prices.subList(startIndex, prices.size());
    }
}