Administrator
2025-12-25 5755881472e2060832dc7f626109a68aa71fce90
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
package com.xcong.excoin.modules.okxNewPrice.indicator.macdAndMatrategy;
 
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
 
/**
 * 波动率指标实现类
 * 
 * 波动率是衡量价格波动程度的技术指标,反映市场的活跃度和风险水平。
 * 本类通过计算价格的标准差来衡量波动率,使用高精度BigDecimal计算避免精度损失。
 * 
 * 【核心功能】
 * 1. 计算指定周期内价格的波动率(标准差)
 * 2. 使用牛顿迭代法实现BigDecimal的平方根计算,确保金融计算的高精度要求
 * 3. 提供获取最新计算结果的接口
 * 
 * 【使用场景】
 * - 在MACD+MA策略中,用于过滤低波动率的市场环境(波动率<1%时跳过交易)
 * - 适用于各种时间周期的价格数据,通常使用20日或30日周期
 * 【注意事项】
 * - 波动率指标对市场流动性和交易活跃度敏感
 * - 低波动率可能预示着市场趋势即将发生变化
 */
public class Volatility {
    /**
     * 波动率计算的周期
     */
    private final int period;
    
    /**
     * 最新计算的波动率值
     */
    private BigDecimal volatility = BigDecimal.ZERO;
 
    /**
     * 构造方法
     * 
     * @param period 波动率计算的周期
     */
    public Volatility(int period) {
        this.period = period;
    }
 
    /**
     * 计算波动率
     * 
     * @param prices 历史价格数据列表
     */
    public void calculate(List<BigDecimal> prices) {
        // 如果价格数据不足计算周期,不进行计算
        if (prices.size() < period) {
            return;
        }
 
        BigDecimal sum = BigDecimal.ZERO;
        BigDecimal avg = calculateAverage(prices); // 计算平均价格
        
        // 计算每个价格与平均价格的偏差平方和
        for (int i = prices.size()-period; i < prices.size(); i++) {
            BigDecimal dev = prices.get(i).subtract(avg);
            sum = sum.add(dev.pow(2));
        }
        
        // 计算方差,保留8位小数
        BigDecimal variance = sum.divide(new BigDecimal(period), 8, RoundingMode.HALF_UP);
        
        // 计算标准差(波动率),使用牛顿迭代法确保高精度
        volatility = sqrt(variance, 8);
    }
 
    /**
     * 计算价格平均值
     * 
     * @param prices 历史价格数据列表
     * @return 平均价格
     */
    private BigDecimal calculateAverage(List<BigDecimal> prices) {
        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);
    }
 
    /**
     * 计算BigDecimal的平方根(牛顿迭代法)
     * 
     * @param value 要计算平方根的数值
     * @param scale 结果的精度(小数位数)
     * @return 平方根结果
     */
    private BigDecimal sqrt(BigDecimal value, int scale) {
        // 负数没有实数平方根,返回0
        if (value.compareTo(BigDecimal.ZERO) < 0) {
            return BigDecimal.ZERO;
        }
        
        // 使用牛顿迭代法计算平方根
        BigDecimal x = value.divide(new BigDecimal(2), scale, RoundingMode.HALF_UP); // 初始猜测值
        BigDecimal prev;
        
        do {
            prev = x;
            // 牛顿迭代公式:x(n+1) = (x(n) + value/x(n))/2
            x = x.add(value.divide(x, scale, RoundingMode.HALF_UP)).divide(new BigDecimal(2), scale, RoundingMode.HALF_UP);
        } while (x.subtract(prev).abs().compareTo(BigDecimal.ONE.movePointLeft(scale)) > 0); // 直到满足精度要求
        
        return x;
    }
 
    /**
     * 获取最新的波动率计算结果
     * 
     * @return 波动率值
     */
    public BigDecimal getValue() {
        return volatility;
    }
}