From 084bb8457b44f765b32365cb09f613ea871634dc Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 05 Jan 2026 17:32:22 +0800
Subject: [PATCH] refactor(trading): 优化MACD和MA组合交易策略支持多时间粒度
---
src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/macdAndMatrategy/MacdMaStrategy.java | 70 +++++++++++++++++++---------------
1 files changed, 39 insertions(+), 31 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..48f80ab 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,9 +1,10 @@
/**
* MACD和MA组合交易策略实现类
- * 基于15分钟K线数据生成交易信号并确定持仓方向
+ * 基于多时间粒度K线数据生成交易信号并确定持仓方向
*
* 该策略综合考虑了EMA指标、MACD指标、价格突破信号和波动率因素,
* 形成了一套完整的开仓、平仓和持仓管理机制。
+ * 支持1分钟(K线)和日线(K线)级别的数据输入,数据顺序要求从新到旧排列。
*/
package com.xcong.excoin.modules.okxNewPrice.indicator.macdAndMatrategy;
@@ -16,7 +17,11 @@
* MACD和MA组合交易策略实现
* <p>
* 该策略利用EMA交叉、MACD指标、价格突破信号和波动率过滤,
- * 为15分钟K线级别交易提供综合决策支持。
+ * 为多时间粒度K线级别交易提供综合决策支持。
+ * <p>
+ * 数据输入要求:
+ * - historicalPrices1M:1分钟K线收盘价列表,顺序从新到旧
+ * - historicalPrices1D:日线K线收盘价列表,顺序从新到旧
*/
@Slf4j
public class MacdMaStrategy {
@@ -127,8 +132,8 @@
/**
* 分析历史价格数据并生成交易指令
*
- * @param historicalPrices 历史价格序列
- * @param historical1DayPrices 日线历史价格序列
+ * @param historicalPrices 历史价格序列(1分钟K线收盘价),顺序从新到旧
+ * @param historical1DayPrices 日线历史价格序列,顺序从新到旧
* @param operation 操作类型(open/close)
* @return 交易指令(包含side和posSide),如果没有交易信号则返回null
*/
@@ -148,9 +153,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 +167,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 +188,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 +204,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 +258,16 @@
* 多头开仓条件检查
*
* @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);
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 +292,17 @@
* 空头开仓条件检查
*
* @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);
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 +336,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 +359,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 +388,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 +410,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 +432,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 +454,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