From 6d4c2127b45c37b02fc1b02a4feb8e6d6439b9e8 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 29 Dec 2025 14:16:28 +0800
Subject: [PATCH] fix(trading): 修复MACD策略信号处理逻辑
---
src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java | 133 +++++++++++++++++++++++++++++++++++--------
1 files changed, 107 insertions(+), 26 deletions(-)
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java
index 25cba55..0da46e6 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java
@@ -10,18 +10,50 @@
/**
* MA (Moving Average) 指标实现
* 支持不同周期的简单移动平均线(SMA)和指数移动平均线(EMA)
+ *
+ * 作用:
+ * 1. 平滑价格波动,识别趋势方向
+ * 2. 短周期MA上穿长周期MA形成金叉,提示买入信号
+ * 3. 短周期MA下穿长周期MA形成死叉,提示卖出信号
+ * 4. 价格上穿/下穿MA线,也可作为买卖参考
+ *
+ * 价格参数类型:
+ * - 参数名称:prices
+ * - 参数类型:List<BigDecimal>
+ * - 参数说明:需要至少1个价格数据点用于计算,根据不同周期需求更多数据点
+ *
+ * 推荐时间粒度及优缺点:
+ * 1. 1分钟(1m):
+ * - 优点:反应迅速,适合超短线交易
+ * - 缺点:噪音多,容易产生虚假信号
+ * 2. 5分钟(5m):
+ * - 优点:平衡了反应速度和噪音过滤
+ * - 缺点:仍有一定噪音
+ * 3. 15分钟(15m):
+ * - 优点:适合日内交易,信号相对可靠
+ * - 缺点:反应速度较慢
+ * 4. 1小时(1h)及以上:
+ * - 优点:趋势信号明确,虚假信号少
+ * - 缺点:反应滞后,不适合短线交易
*/
@Slf4j
@Getter
@Setter
public class MA extends IndicatorBase {
- // 常用周期
- public static final int MA5 = 5;
- public static final int MA10 = 10;
- public static final int MA20 = 20;
- public static final int MA30 = 30;
- public static final int MA60 = 60;
+ // 默认周期
+ public static final int DEFAULT_MA5 = 5;
+ public static final int DEFAULT_MA10 = 10;
+ public static final int DEFAULT_MA20 = 20;
+ public static final int DEFAULT_MA30 = 30;
+ public static final int DEFAULT_MA60 = 60;
+
+ // 动态周期参数
+ private int ma5Period;
+ private int ma10Period;
+ private int ma20Period;
+ private int ma30Period;
+ private int ma60Period;
private BigDecimal ma5 = BigDecimal.ZERO;
private BigDecimal ma10 = BigDecimal.ZERO;
@@ -41,52 +73,101 @@
private BigDecimal prevEma30 = null;
private BigDecimal prevEma60 = null;
+ // 构造函数使用默认周期
+ public MA() {
+ this.ma5Period = DEFAULT_MA5;
+ this.ma10Period = DEFAULT_MA10;
+ this.ma20Period = DEFAULT_MA20;
+ this.ma30Period = DEFAULT_MA30;
+ this.ma60Period = DEFAULT_MA60;
+ }
+
/**
- * 计算所有周期的MA指标
+ * 计算所有周期的MA指标(使用当前周期设置)
* @param prices 价格列表
*/
public void calculate(List<BigDecimal> prices) {
+ calculate(prices, null);
+ }
+
+ /**
+ * 计算所有周期的MA指标,并支持动态周期调整
+ * @param prices 价格列表
+ * @param volatility 标准化波动率(ATR百分比),用于动态调整周期
+ */
+ public void calculate(List<BigDecimal> prices, BigDecimal volatility) {
if (prices == null || prices.size() < 1) {
return;
}
+ // 如果提供了波动率,则动态调整周期
+ if (volatility != null) {
+ adjustPeriodsByVolatility(volatility);
+ }
+
// 计算SMA
- if (prices.size() >= MA5) {
- ma5 = calculateMA(prices, MA5);
+ if (prices.size() >= ma5Period) {
+ ma5 = calculateMA(prices, ma5Period);
}
- if (prices.size() >= MA10) {
- ma10 = calculateMA(prices, MA10);
+ if (prices.size() >= ma10Period) {
+ ma10 = calculateMA(prices, ma10Period);
}
- if (prices.size() >= MA20) {
- ma20 = calculateMA(prices, MA20);
+ if (prices.size() >= ma20Period) {
+ ma20 = calculateMA(prices, ma20Period);
}
- if (prices.size() >= MA30) {
- ma30 = calculateMA(prices, MA30);
+ if (prices.size() >= ma30Period) {
+ ma30 = calculateMA(prices, ma30Period);
}
- if (prices.size() >= MA60) {
- ma60 = calculateMA(prices, MA60);
+ if (prices.size() >= ma60Period) {
+ ma60 = calculateMA(prices, ma60Period);
}
// 计算EMA
- prevEma5 = calculateEMA(prices, MA5, prevEma5);
+ prevEma5 = calculateEMA(prices, ma5Period, prevEma5);
ema5 = prevEma5;
- prevEma10 = calculateEMA(prices, MA10, prevEma10);
+ prevEma10 = calculateEMA(prices, ma10Period, prevEma10);
ema10 = prevEma10;
- prevEma20 = calculateEMA(prices, MA20, prevEma20);
+ prevEma20 = calculateEMA(prices, ma20Period, prevEma20);
ema20 = prevEma20;
- prevEma30 = calculateEMA(prices, MA30, prevEma30);
+ prevEma30 = calculateEMA(prices, ma30Period, prevEma30);
ema30 = prevEma30;
- prevEma60 = calculateEMA(prices, MA60, prevEma60);
+ prevEma60 = calculateEMA(prices, ma60Period, prevEma60);
ema60 = prevEma60;
- log.debug("MA计算结果 - MA5: {}, MA10: {}, MA20: {}, MA30: {}, MA60: {}",
- ma5, ma10, ma20, ma30, ma60);
- log.debug("EMA计算结果 - EMA5: {}, EMA10: {}, EMA20: {}, EMA30: {}, EMA60: {}",
- ema5, ema10, ema20, ema30, ema60);
+ log.info("MA计算结果 - MA5({}): {}, MA10({}): {}, MA20({}): {}, MA30({}): {}, MA60({}): {}",
+ ma5Period, ma5, ma10Period, ma10, ma20Period, ma20, ma30Period, ma30, ma60Period, ma60);
+ log.info("EMA计算结果 - EMA5({}): {}, EMA10({}): {}, EMA20({}): {}, EMA30({}): {}, EMA60({}): {}",
+ ma5Period, ema5, ma10Period, ema10, ma20Period, ema20, ma30Period, ema30, ma60Period, ema60);
+ }
+
+ /**
+ * 根据波动率调整MA周期
+ * @param volatility 标准化波动率(ATR百分比)
+ */
+ private void adjustPeriodsByVolatility(BigDecimal volatility) {
+ // 根据波动率缩放均线周期
+ // 3%、5%、8%作为ATR阈值
+ BigDecimal lowVolatility = new BigDecimal(3);
+ BigDecimal midVolatility = new BigDecimal(5);
+ BigDecimal highVolatility = new BigDecimal(8);
+
+ // 快速MA周期 (ma5)
+ ma5Period = volatility.compareTo(lowVolatility) < 0 ? 10 : 6;
+
+ // 中期MA周期 (ma10, ma20)
+ ma10Period = volatility.compareTo(midVolatility) < 0 ? 10 : 8;
+ ma20Period = volatility.compareTo(midVolatility) < 0 ? 21 : 13;
+
+ // 长期MA周期 (ma30, ma60)
+ ma30Period = volatility.compareTo(highVolatility) < 0 ? 30 : 24;
+ ma60Period = volatility.compareTo(highVolatility) < 0 ? 50 : 34;
+
+ log.info("根据波动率{}调整MA周期: ma5={}, ma10={}, ma20={}, ma30={}, ma60={}",
+ volatility, ma5Period, ma10Period, ma20Period, ma30Period, ma60Period);
}
/**
--
Gitblit v1.9.1