From 4884ebffeed775d63dbf7bb7d0ece8182f10c344 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Fri, 26 Dec 2025 18:19:46 +0800
Subject: [PATCH] fix(okxNewPrice): 解决交易订单为空时的空指针异常

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/EMACalculator.java |   89 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/EMACalculator.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/EMACalculator.java
new file mode 100644
index 0000000..d1e0a1d
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/EMACalculator.java
@@ -0,0 +1,89 @@
+/**
+ * 指数移动平均线(EMA)计算器
+ * <p>
+ * EMA(Exponential Moving Average)是一种加权移动平均线,对近期价格赋予更高权重,
+ * 对远期价格赋予较低权重,能够更敏感地反映价格变化趋势。
+ * 本计算器提供了EMA的多种计算方式,支持使用SMA作为初始值或使用第一个价格作为初始值。
+ */
+package com.xcong.excoin.modules.okxNewPrice.indicator.macdAndMatrategy;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 指数移动平均线(EMA)计算器
+ *
+ * <p>计算公式:EMA(today) = Price(today) * k + EMA(yesterday) * (1 - k)</p>
+ * <p>其中:k = 2 / (period + 1),period为EMA的周期</p>
+ */
+public class EMACalculator {
+    /**
+     * 计算价格序列的指数移动平均线(EMA)
+     *
+     * @param prices      价格序列,使用BigDecimal确保计算精度
+     * @param period      EMA计算周期
+     * @param initialSMA  是否使用SMA(简单移动平均线)作为初始值
+     * @return 计算得到的EMA序列,与输入价格序列一一对应
+     * @throws IllegalArgumentException 当输入参数无效时抛出异常
+     */
+    public static List<BigDecimal> calculateEMA(List<BigDecimal> prices, int period, boolean initialSMA) {
+        if (prices == null || prices.isEmpty() || period <= 0) {
+            throw new IllegalArgumentException("Invalid input parameters.");
+        }
+        if (initialSMA && prices.size() < period) {
+            throw new IllegalArgumentException("Prices list too short for initial SMA.");
+        }
+
+        // 计算权重因子k = 2 / (period + 1)
+        BigDecimal alpha = BigDecimal.valueOf(2.0).divide(BigDecimal.valueOf(period + 1), 10, RoundingMode.HALF_UP);
+        List<BigDecimal> ema = new ArrayList<>();
+
+        if (initialSMA) {
+            // 使用SMA作为初始EMA值(前period个价格的平均值)
+            BigDecimal sum = BigDecimal.ZERO;
+            for (int i = 0; i < period; i++) {
+                sum = sum.add(prices.get(i));
+            }
+            BigDecimal sma = sum.divide(BigDecimal.valueOf(period), 10, RoundingMode.HALF_UP);
+            ema.add(sma);
+
+            // 从第period+1个数据点开始计算后续EMA值
+            for (int i = period; i < prices.size(); i++) {
+                BigDecimal price = prices.get(i);
+                BigDecimal prevEMA = ema.get(ema.size() - 1);
+                // EMA计算公式:Price(today) * alpha + EMA(yesterday) * (1 - alpha)
+                BigDecimal emaToday = price.multiply(alpha)
+                        .add(prevEMA.multiply(BigDecimal.ONE.subtract(alpha)))
+                        .setScale(10, RoundingMode.HALF_UP);
+                ema.add(emaToday);
+            }
+        } else {
+            // 使用第一个价格作为初始EMA值,并从第二个数据点开始计算
+            ema.add(prices.get(0));
+            for (int i = 1; i < prices.size(); i++) {
+                BigDecimal price = prices.get(i);
+                BigDecimal prevEMA = ema.get(ema.size() - 1);
+                // EMA计算公式:Price(today) * alpha + EMA(yesterday) * (1 - alpha)
+                BigDecimal emaToday = price.multiply(alpha)
+                        .add(prevEMA.multiply(BigDecimal.ONE.subtract(alpha)))
+                        .setScale(10, RoundingMode.HALF_UP);
+                ema.add(emaToday);
+            }
+        }
+
+        return ema;
+    }
+
+    /**
+     * 计算价格序列的指数移动平均线(EMA),默认使用SMA作为初始值
+     *
+     * @param prices 价格序列
+     * @param period EMA计算周期
+     * @return 计算得到的EMA序列
+     */
+    public static List<BigDecimal> calculateEMA(List<BigDecimal> prices, int period) {
+        return calculateEMA(prices, period, true);
+    }
+}
\ No newline at end of file

--
Gitblit v1.9.1