package com.deepchart.utils; import com.deepchart.entity.KDJData; import com.deepchart.entity.StockDailyData; import java.util.*; /** * KD指标分析工具类 */ public class KDUtil { private static final int N = 9; // 默认周期长度 private static final double SMOOTH_K = 1.0 / 3; // K 平滑系数 private static final double SMOOTH_D = 1.0 / 3; // D 平滑系数 private static List calculateKD(List dataList) { if (dataList == null || dataList.size() < N) { throw new IllegalArgumentException("数据不足,至少需要" + N + "条记录"); } List kdList = new ArrayList<>(); Deque highs = new ArrayDeque<>(N); Deque lows = new ArrayDeque<>(N); Double prevK = null; Double prevD = null; for (int i = 0; i < dataList.size(); i++) { StockDailyData data = dataList.get(i); highs.offerLast(data.getHighPrice()); lows.offerLast(data.getLowPrice()); if (highs.size() > N) { highs.pollFirst(); lows.pollFirst(); } if (i >= N - 1) { double hhv = Collections.max(highs); double llv = Collections.min(lows); double rsv = ((data.getClosePrice() - llv) / (hhv - llv)) * 100; double kValue = (prevK == null ? rsv : prevK * (1 - SMOOTH_K) + rsv * SMOOTH_K); double dValue = (prevD == null ? kValue : prevD * (1 - SMOOTH_D) + kValue * SMOOTH_D); kdList.add(new KDJData(data.getDate(), rsv, kValue, dValue, 0)); prevK = kValue; prevD = dValue; } else { kdList.add(new KDJData(data.getDate(), 0, 0, 0, 0)); // 占位符 } } return kdList; } public static String generateReport(List stockDataList) { List kdList = calculateKD(stockDataList); StringBuilder report = new StringBuilder(); report.append("📈 股票KD指标分析报告\n"); report.append("=======================\n"); if (kdList.isEmpty()) { report.append("❌ 数据不足,无法生成分析。\n"); return report.toString(); } KDJData latest = kdList.get(kdList.size() - 1); KDJData previous = kdList.size() >= 2 ? kdList.get(kdList.size() - 2) : null; double k = latest.getK(); double d = latest.getD(); // 判断超买或超卖 if (k > 80 && d > 80) { report.append("🔴 当前处于【超买】状态,注意回调风险。\n"); } else if (k < 20 && d < 20) { report.append("🟢 当前处于【超卖】状态,关注反弹机会。\n"); } else { report.append("🟡 当前处于中性区域,暂无明显买卖信号。\n"); } // 判断金叉/死叉 if (previous != null) { boolean isGoldenCross = previous.getK() <= previous.getD() && k > d; boolean isDeathCross = previous.getK() >= previous.getD() && k < d; if (isGoldenCross && d < 30) { report.append("✨ 出现金叉(K线上穿D线),特别是在低位,是潜在买入信号。\n"); } else if (isDeathCross && d > 70) { report.append("⚠️ 出现死叉(K线下穿D线),尤其是在高位,建议谨慎卖出。\n"); } } // 多空趋势判断 if (k > 50 && d > 50 && k > d) { report.append("⬆️ 当前为多头趋势,可考虑持股观望。\n"); } else if (k < 50 && d < 50 && k < d) { report.append("⬇️ 当前为空头趋势,宜控制仓位。\n"); } else { report.append("🔄 当前为震荡行情,短线操作更适宜。\n"); } return report.toString(); } }