From fe4d5467b8431ef1461bc93e4eba4f9153125da9 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 06 Jan 2026 17:24:42 +0800
Subject: [PATCH] refactor(okxWs): 优化下单参数构建逻辑

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java |  174 ++++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 128 insertions(+), 46 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
index c2f869f..9b63ee2 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
@@ -2,7 +2,6 @@
 
 import lombok.Getter;
 import lombok.Setter;
-import lombok.extern.slf4j.Slf4j;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
@@ -12,37 +11,26 @@
 /**
  * MACD (Moving Average Convergence Divergence) 指标实现
  * 计算逻辑:
- * 1. DIF = EMA(12) - EMA(26)
- * 2. DEA = EMA(DIF, 9)
- * 3. MACD柱状图 = (DIF - DEA) * 2
+ * 1. 快线DIFF = EMA(Close, 12) - EMA(Close, 26)
+ * 2. 慢线DEA = EMA(DIFF, 9)
+ * 3. MACD柱状图 = (DIFF - DEA) * macdBarsMultiplier
  * 
- * 作用:
- * 1. 识别趋势方向和动能变化
- * 2. DIF上穿DEA形成金叉,提示买入信号
- * 3. DIF下穿DEA形成死叉,提示卖出信号
- * 4. MACD柱状图由负转正,提示多头力量增强
- * 5. MACD柱状图由正转负,提示空头力量增强
+ * 核心概念:
+ * 1. DIFF是EMA12与EMA26之间的距离,反映短期与长期趋势的差异
+ * 2. 当DIFF > 0表示EMA12在EMA26上方,代表多头趋势
+ * 3. 当DIFF < 0表示EMA12在EMA26下方,代表空头趋势
+ * 4. DEA是DIFF的EMA平滑线,用于过滤DIFF的波动
+ * 5. MACD柱状图通过放大倍数展示DIFF与DEA之间的关系,便于观察趋势变化
  * 
- * 价格参数类型:
- * - 参数名称:prices
- * - 参数类型:List<BigDecimal>
- * - 参数说明:需要至少2个价格数据点用于计算,数据越多计算越准确
+ * 多空判断:
+ * - 多头机会:DIFF在0轴上且MACD柱状图向上,股价同步上涨
+ * - 空头机会:DIFF在0轴下且MACD柱状图向下,股价同步下跌
  * 
- * 推荐时间粒度及优缺点:
- * 1. 1分钟(1m):
- *    - 优点:反应迅速,适合超短线交易
- *    - 缺点:MACD柱状图波动剧烈,信号频繁
- * 2. 5分钟(5m):
- *    - 优点:平衡了反应速度和信号可靠性
- *    - 缺点:仍有一定噪音
- * 3. 15分钟(15m):
- *    - 优点:适合日内交易,信号较为可靠
- *    - 缺点:反应速度较慢
- * 4. 1小时(1h)及以上:
- *    - 优点:趋势信号明确,MACD柱状图变化稳定
- *    - 缺点:反应滞后,不适合短线交易
+ * 信号过滤:
+ * - 可通过设置macdBarsSmoothingPeriod启用MACD柱状图平滑处理
+ * - 平滑公式:MACD柱状图 = MA((DIFF - DEA) * macdBarsMultiplier, macdBarsSmoothingPeriod)
+ * - 作用:消除柱状图杂讯,使信号更加清晰
  */
-@Slf4j
 @Getter
 @Setter
 public class MACD extends IndicatorBase {
@@ -51,24 +39,43 @@
     public static final int DEFAULT_FAST_PERIOD = 12;
     public static final int DEFAULT_SLOW_PERIOD = 26;
     public static final int DEFAULT_SIGNAL_PERIOD = 9;
+    
+    // 默认MACD柱状图放大倍数
+    public static final int DEFAULT_MACDBARS_MULTIPLIER = 2;
+    // 默认MACD柱状图平滑周期(0表示不平滑)
+    public static final int DEFAULT_MACDBARS_SMOOTHING_PERIOD = 0;
 
-    // 动态周期参数
+    // 周期参数
     private int fastPeriod;
     private int slowPeriod;
     private int signalPeriod;
+    
+    // MACD柱状图参数
+    private int macdBarsMultiplier; // MACD柱状图放大倍数
+    private int macdBarsSmoothingPeriod; // MACD柱状图平滑周期(0表示不平滑)
 
+    // MACD计算结果
     private BigDecimal dif = BigDecimal.ZERO;
     private BigDecimal dea = BigDecimal.ZERO;
     private BigDecimal macdBar = BigDecimal.ZERO;
+    
+    // 历史值缓存
     private BigDecimal prevFastEMA = null;
     private BigDecimal prevSlowEMA = null;
     private BigDecimal prevDea = null;
+    private List<BigDecimal> difHistory = new ArrayList<>(); // 保存历史DIF值,用于计算DEA
+    private List<BigDecimal> rawMacdBarHistory = new ArrayList<>(); // 保存原始MACD柱状图值,用于平滑处理
+    
+    // 最大保存的历史值数量
+    private static final int MAX_HISTORY_SIZE = 50;
 
-    // 构造函数使用默认周期
+    // 构造函数使用默认参数
     public MACD() {
         this.fastPeriod = DEFAULT_FAST_PERIOD;
         this.slowPeriod = DEFAULT_SLOW_PERIOD;
         this.signalPeriod = DEFAULT_SIGNAL_PERIOD;
+        this.macdBarsMultiplier = DEFAULT_MACDBARS_MULTIPLIER;
+        this.macdBarsSmoothingPeriod = DEFAULT_MACDBARS_SMOOTHING_PERIOD;
     }
 
     /**
@@ -85,7 +92,7 @@
      * @param volatility 标准化波动率(百分比),用于动态调整周期
      */
     public void calculate(List<BigDecimal> prices, BigDecimal volatility) {
-        if (prices == null || prices.size() < 2) {
+        if (prices == null || prices.isEmpty()) {
             return;
         }
 
@@ -94,26 +101,81 @@
             adjustPeriodsByVolatility(volatility);
         }
 
-        // 计算快速EMA
+        
+
+        // 计算快速EMA (12日)
         prevFastEMA = calculateEMA(prices, fastPeriod, prevFastEMA);
         
-        // 计算慢速EMA
+        // 计算慢速EMA (26日)
         prevSlowEMA = calculateEMA(prices, slowPeriod, prevSlowEMA);
         
-        // 计算DIF
+        // 计算DIF = EMA(12) - EMA(26)
         dif = prevFastEMA.subtract(prevSlowEMA).setScale(8, RoundingMode.HALF_UP);
         
-        // 计算DEA
-        List<BigDecimal> difList = new ArrayList<>();
-        difList.add(dif);
-        prevDea = calculateEMA(difList, signalPeriod, prevDea);
+        // 将新的DIF值添加到历史记录
+        difHistory.add(dif);
+        // 保持历史记录在合理范围内
+        if (difHistory.size() > MAX_HISTORY_SIZE) {
+            difHistory.remove(0);
+        }
+        
+        // 计算DEA = EMA(DIFF, 9)
+        calculateDEA();
+        
+        // 计算原始MACD柱状图值 = (DIF - DEA) * 放大倍数
+        BigDecimal rawMacdBar = dif.subtract(dea).multiply(new BigDecimal(macdBarsMultiplier)).setScale(8, RoundingMode.HALF_UP);
+        
+        // 将原始MACD柱状图值添加到历史记录
+        rawMacdBarHistory.add(rawMacdBar);
+        // 保持历史记录在合理范围内
+        if (rawMacdBarHistory.size() > MAX_HISTORY_SIZE) {
+            rawMacdBarHistory.remove(0);
+        }
+        
+        // 如果启用了平滑处理,则计算平滑后的MACD柱状图
+        if (macdBarsSmoothingPeriod > 0) {
+            macdBar = smoothMacdBars().setScale(8, RoundingMode.HALF_UP);
+        } else {
+            macdBar = rawMacdBar;
+        }
+        
+        
+    }
+
+    /**
+     * 计算DEA指标
+     */
+    private void calculateDEA() {
+        int difCount = difHistory.size();
+        
+        // 如果没有足够的DIF历史值,无法计算有效的DEA
+        if (difCount == 0) {
+            dea = BigDecimal.ZERO;
+            prevDea = null;
+            return;
+        }
+        
+        // 计算DEA = EMA(DIFF, signalPeriod)
+        // 使用所有DIF历史值来计算初始EMA,然后使用最新值更新
+        prevDea = calculateEMA(difHistory, signalPeriod, prevDea);
         dea = prevDea.setScale(8, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 平滑MACD柱状图
+     * @return 平滑后的MACD柱状图值
+     */
+    private BigDecimal smoothMacdBars() {
+        int historyCount = rawMacdBarHistory.size();
         
-        // 计算MACD柱状图
-        macdBar = dif.subtract(dea).multiply(new BigDecimal(2)).setScale(8, RoundingMode.HALF_UP);
+        // 如果没有足够的历史数据,返回最新的原始值
+        if (historyCount < macdBarsSmoothingPeriod) {
+            return rawMacdBarHistory.get(historyCount - 1);
+        }
         
-        log.debug("MACD计算结果 - DIF: {}, DEA: {}, MACD柱状图: {}, 参数: fast={}, slow={}, signal={}", 
-                dif, dea, macdBar, fastPeriod, slowPeriod, signalPeriod);
+        // 使用简单移动平均平滑MACD柱状图
+        List<BigDecimal> recentMacdBars = rawMacdBarHistory.subList(historyCount - macdBarsSmoothingPeriod, historyCount);
+        return calculateMA(recentMacdBars, macdBarsSmoothingPeriod);
     }
 
     /**
@@ -137,23 +199,43 @@
             signalPeriod = 5;
         }
 
-        log.debug("根据波动率{}调整MACD周期: fast={}, slow={}, signal={}", 
-                volatility, fastPeriod, slowPeriod, signalPeriod);
+        
     }
 
     /**
      * 判断金叉信号(DIF上穿DEA)
+     * @param previousDIF 上一个DIF值
+     * @param previousDEA 上一个DEA值
      * @return 是否形成金叉
      */
     public boolean isGoldenCross(BigDecimal previousDIF, BigDecimal previousDEA) {
-        return previousDIF.compareTo(previousDEA) < 0 && dif.compareTo(dea) > 0;
+        return previousDIF != null && previousDEA != null && 
+               previousDIF.compareTo(previousDEA) < 0 && dif.compareTo(dea) > 0;
     }
 
     /**
      * 判断死叉信号(DIF下穿DEA)
+     * @param previousDIF 上一个DIF值
+     * @param previousDEA 上一个DEA值
      * @return 是否形成死叉
      */
     public boolean isDeathCross(BigDecimal previousDIF, BigDecimal previousDEA) {
-        return previousDIF.compareTo(previousDEA) > 0 && dif.compareTo(dea) < 0;
+        return previousDIF != null && previousDEA != null && 
+               previousDIF.compareTo(previousDEA) > 0 && dif.compareTo(dea) < 0;
+    }
+    
+    /**
+     * 重置MACD指标状态
+     */
+    public void reset() {
+        dif = BigDecimal.ZERO;
+        dea = BigDecimal.ZERO;
+        macdBar = BigDecimal.ZERO;
+        prevFastEMA = null;
+        prevSlowEMA = null;
+        prevDea = null;
+        difHistory.clear();
+        rawMacdBarHistory.clear();
+
     }
 }

--
Gitblit v1.9.1