From 97b7f914d060b2a052299416384fc80e061f4b1d Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 06 Jan 2026 13:49:58 +0800
Subject: [PATCH] refactor(MacdEmaStrategy): 调整多头和空头开仓条件的逻辑顺序

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/MacdMaStrategy.java |   82 ++++++++++++++++++++++++----------------
 1 files changed, 49 insertions(+), 33 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/MacdMaStrategy.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/MacdMaStrategy.java
index 7568e2b..f5ebaf3 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/MacdMaStrategy.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/MacdMaStrategy.java
@@ -1,22 +1,29 @@
 /**
  * MACD和MA组合交易策略实现类
- * 基于15分钟K线数据生成交易信号并确定持仓方向
+ * 基于多时间粒度K线数据生成交易信号并确定持仓方向
  *
  * 该策略综合考虑了EMA指标、MACD指标、价格突破信号和波动率因素,
  * 形成了一套完整的开仓、平仓和持仓管理机制。
+ * 支持1分钟(K线)和日线(K线)级别的数据输入,数据顺序要求从新到旧排列。
  */
 package com.xcong.excoin.modules.okxNewPrice.indicator.macdAndMatrategy;
 
 import lombok.extern.slf4j.Slf4j;
 
 import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 /**
  * MACD和MA组合交易策略实现
  * <p>
  * 该策略利用EMA交叉、MACD指标、价格突破信号和波动率过滤,
- * 为15分钟K线级别交易提供综合决策支持。
+ * 为多时间粒度K线级别交易提供综合决策支持。
+ * <p>
+ * 数据输入要求:
+ * - historicalPrices1M:1分钟K线收盘价列表,顺序从新到旧
+ * - historicalPrices1D:日线K线收盘价列表,顺序从新到旧
  */
 @Slf4j
 public class MacdMaStrategy {
@@ -127,8 +134,8 @@
     /**
      * 分析历史价格数据并生成交易指令
      *
-     * @param historicalPrices 历史价格序列
-     * @param historical1DayPrices 日线历史价格序列
+     * @param historicalPrices 历史价格序列(1分钟K线收盘价),顺序从新到旧
+     * @param historical1DayPrices 日线历史价格序列,顺序从新到旧
      * @param operation 操作类型(open/close)
      * @return 交易指令(包含side和posSide),如果没有交易信号则返回null
      */
@@ -148,9 +155,9 @@
     /**
      * 分析最新价格数据并生成开仓信号
      *
-     * @param closePrices 收盘价序列
-     * @param close1DPrices 日线收盘价序列
-     * @return 生成的交易信号(LONG、SHORT或NONE)
+     * @param closePrices 1分钟K线收盘价序列,顺序从新到旧
+     * @param close1DPrices 日线K线收盘价序列,顺序从新到旧
+     * @return 生成的交易信号(LONG_BUY、SHORT_SELL或NONE)
      */
     public PositionType analyzeOpen(List<BigDecimal> closePrices, List<BigDecimal> close1DPrices) {
         // 数据检查:确保有足够的数据点进行计算(需要足够数据计算200日EMA)
@@ -162,17 +169,17 @@
         // 计算MACD指标
         MACDResult macdResult = MACDCalculator.calculateMACD(
                 closePrices, shortPeriod, longPeriod, signalPeriod);
-         log.info("MACD计算结果:{}", macdResult.getMacdData().get(macdResult.getMacdData().size() - 1));
+         log.info("MACD计算结果:{}", macdResult.getMacdData().get(0));
 
         // 多头开仓条件检查
         if (isLongEntryCondition(macdResult, closePrices, close1DPrices)) {
-            log.info("多头开仓信号,价格:{}", closePrices.get(closePrices.size() - 1));
+            log.info("多头开仓信号,价格:{}", closePrices.get(0));
             return PositionType.LONG_BUY;
         }
 
         // 空头开仓条件检查
         if (isShortEntryCondition(macdResult, closePrices, close1DPrices)) {
-            log.info("空头开仓信号,价格:{}", closePrices.get(closePrices.size() - 1));
+            log.info("空头开仓信号,价格:{}", closePrices.get(0));
             return PositionType.SHORT_SELL;
         }
         
@@ -183,8 +190,8 @@
     /**
      * 分析最新价格数据并生成平仓信号
      *
-     * @param closePrices 收盘价序列
-     * @param close1DPrices 日线收盘价序列
+     * @param closePrices 1分钟K线收盘价序列,顺序从新到旧
+     * @param close1DPrices 日线K线收盘价序列,顺序从新到旧
      * @return 生成的交易信号(LONG_SELL、SHORT_BUY或NONE)
      */
     public PositionType analyzeClose(List<BigDecimal> closePrices, List<BigDecimal> close1DPrices) {
@@ -199,7 +206,7 @@
                 closePrices, shortPeriod, longPeriod, signalPeriod);
 
         // 最新收盘价
-        BigDecimal latestPrice = closePrices.get(closePrices.size() - 1);
+        BigDecimal latestPrice = closePrices.get(0);
 
         if (isLongExitCondition(macdResult, latestPrice)) {
             log.info("多头平仓信号,价格:{}", latestPrice);
@@ -253,15 +260,19 @@
      * 多头开仓条件检查
      *
      * @param macdResult MACD计算结果
-     * @param closePrices 收盘价序列
-     * @param close1DPrices 日线收盘价序列
+     * @param closePrices 1分钟K线收盘价序列,顺序从新到旧
+     * @param close1DPrices 日线K线收盘价序列,顺序从新到旧
      * @return 是否满足多头开仓条件
      */
     private boolean isLongEntryCondition(MACDResult macdResult, List<BigDecimal> closePrices, List<BigDecimal> close1DPrices) {
         // 1. 计算200日EMA(趋势过滤)
-        List<BigDecimal> trendEma = EMACalculator.calculateEMA(close1DPrices, trendPeriod, true);
+        // 复制并反转日线数据,确保从旧到新计算EMA
+        List<BigDecimal> reversed1DPrices = new ArrayList<>(close1DPrices);
+        Collections.reverse(reversed1DPrices);
+        List<BigDecimal> trendEma = EMACalculator.calculateEMA(reversed1DPrices, trendPeriod, true);
         BigDecimal latestTrendEma = trendEma.get(trendEma.size() - 1);
-        BigDecimal latestPrice = closePrices.get(closePrices.size() - 1);
+        BigDecimal latestPrice = closePrices.get(0);
+        log.info( "200日EMA:{}, 最新价格:{}", latestTrendEma,  latestPrice);
         
         // 2. 价格必须位于200日EMA上方(多头趋势确认)
         boolean isAboveTrend = latestPrice.compareTo(latestTrendEma) > 0;
@@ -286,15 +297,20 @@
      * 空头开仓条件检查
      * 
      * @param macdResult MACD计算结果
-     * @param closePrices 收盘价序列
-     * @param close1DPrices 日线收盘价序列
+     * @param closePrices 1分钟K线收盘价序列,顺序从新到旧
+     * @param close1DPrices 日线K线收盘价序列,顺序从新到旧
      * @return 是否满足空头开仓条件
      */
     private boolean isShortEntryCondition(MACDResult macdResult, List<BigDecimal> closePrices, List<BigDecimal> close1DPrices) {
         // 1. 计算200日EMA(趋势过滤)
-        List<BigDecimal> trendEma = EMACalculator.calculateEMA(close1DPrices, trendPeriod, true);
+        // 复制并反转日线数据,确保从旧到新计算EMA
+        List<BigDecimal> reversed1DPrices = new ArrayList<>(close1DPrices);
+        Collections.reverse(reversed1DPrices);
+        List<BigDecimal> trendEma = EMACalculator.calculateEMA(reversed1DPrices, trendPeriod, true);
         BigDecimal latestTrendEma = trendEma.get(trendEma.size() - 1);
-        BigDecimal latestPrice = closePrices.get(closePrices.size() - 1);
+        BigDecimal latestPrice = closePrices.get(0);
+
+        log.info( "200日EMA:{}, 最新价格:{}", latestTrendEma,  latestPrice);
         
         // 2. 价格必须位于200日EMA下方(空头趋势确认)
         boolean isBelowTrend = latestPrice.compareTo(latestTrendEma) < 0;
@@ -328,8 +344,8 @@
         // 多头平仓条件:MACD柱状线动量减弱(由正转弱)
         List<PriceData> macdData = macdResult.getMacdData();
         if (macdData.size() >= 2) {
-            PriceData latest = macdData.get(macdData.size() - 1);
-            PriceData previous = macdData.get(macdData.size() - 2);
+            PriceData latest = macdData.get(0); // 最新数据
+            PriceData previous = macdData.get(1); // 前一个数据
 
             // 柱状线由正转弱:前一根为正,当前绝对值减小
             boolean momentumWeakening = previous.getMacdHist().compareTo(BigDecimal.ZERO) >= 0 && 
@@ -351,8 +367,8 @@
         // 空头平仓条件:MACD柱状线动量减弱(由负转弱)
         List<PriceData> macdData = macdResult.getMacdData();
         if (macdData.size() >= 2) {
-            PriceData latest = macdData.get(macdData.size() - 1);
-            PriceData previous = macdData.get(macdData.size() - 2);
+            PriceData latest = macdData.get(0); // 最新数据
+            PriceData previous = macdData.get(1); // 前一个数据
             
             // 柱状线由负转弱:前一根为负,当前绝对值减小
             boolean momentumWeakening = previous.getMacdHist().compareTo(BigDecimal.ZERO) <= 0 &&
@@ -380,8 +396,8 @@
             return false;
         }
 
-        PriceData latest = macdData.get(macdData.size() - 1);
-        PriceData previous = macdData.get(macdData.size() - 2);
+        PriceData latest = macdData.get(0);
+        PriceData previous = macdData.get(1);
         
         // 金叉判断:DIF从下往上穿过DEA
         return previous.getDif().compareTo(previous.getDea()) < 0 && 
@@ -402,8 +418,8 @@
             return false;
         }
 
-        PriceData latest = macdData.get(macdData.size() - 1);
-        PriceData previous = macdData.get(macdData.size() - 2);
+        PriceData latest = macdData.get(0);
+        PriceData previous = macdData.get(1);
         
         // 死叉判断:DIF从上往下穿过DEA
         return previous.getDif().compareTo(previous.getDea()) > 0 && 
@@ -424,8 +440,8 @@
             return false;
         }
 
-        PriceData latest = macdData.get(macdData.size() - 1);
-        PriceData previous = macdData.get(macdData.size() - 2);
+        PriceData latest = macdData.get(0); // 最新数据
+        PriceData previous = macdData.get(1); // 前一个数据
         
         // 柱状线由负转正:前一根为负,当前为正
         return previous.getMacdHist().compareTo(BigDecimal.ZERO) <= 0 && 
@@ -446,8 +462,8 @@
             return false;
         }
 
-        PriceData latest = macdData.get(macdData.size() - 1);
-        PriceData previous = macdData.get(macdData.size() - 2);
+        PriceData latest = macdData.get(0); // 最新数据
+        PriceData previous = macdData.get(1); // 前一个数据
         
         // 柱状线由正转负:前一根为正,当前为负
         return previous.getMacdHist().compareTo(BigDecimal.ZERO) >= 0 && 

--
Gitblit v1.9.1