package com.xcong.excoin.modules.okxNewPrice.indicator.strategy; import com.xcong.excoin.modules.okxNewPrice.indicator.BOLL; import com.xcong.excoin.modules.okxNewPrice.indicator.KDJ; import com.xcong.excoin.modules.okxNewPrice.indicator.MACD; import com.xcong.excoin.modules.okxNewPrice.indicator.RSI; import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums; import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums; import com.xcong.excoin.modules.okxNewPrice.okxWs.param.TradeRequestParam; import com.xcong.excoin.modules.okxNewPrice.utils.WsMapBuild; import lombok.extern.slf4j.Slf4j; import java.math.BigDecimal; import java.util.List; /** * 综合技术指标策略实现类,整合MACD、KDJ、RSI、BOLL等指标生成交易信号 */ @Slf4j public class ComprehensiveTechnicalStrategy extends AbstractTechnicalIndicatorStrategy { private final MACD macd; private final KDJ kdj; private final RSI rsi; private final BOLL boll; private BigDecimal prevDif; private BigDecimal prevDea; private BigDecimal prevK; private BigDecimal prevD; public ComprehensiveTechnicalStrategy() { super(); this.strategyName = "综合技术指标策略"; this.macd = new MACD(); this.kdj = new KDJ(); this.rsi = new RSI(); this.boll = new BOLL(); this.prevDif = BigDecimal.ZERO; this.prevDea = BigDecimal.ZERO; this.prevK = new BigDecimal(50); this.prevD = new BigDecimal(50); } @Override public void initialize() { super.initialize(); macd.setDif(BigDecimal.ZERO); macd.setDea(BigDecimal.ZERO); macd.setMacdBar(BigDecimal.ZERO); macd.setPrevFastEMA(null); macd.setPrevSlowEMA(null); macd.setPrevDea(null); kdj.setK(new BigDecimal(50)); kdj.setD(new BigDecimal(50)); kdj.setJ(new BigDecimal(50)); kdj.setPrevK(new BigDecimal(50)); kdj.setPrevD(new BigDecimal(50)); rsi.setRsi(BigDecimal.ZERO); rsi.setPrevAvgGain(BigDecimal.ZERO); rsi.setPrevAvgLoss(BigDecimal.ZERO); boll.setMid(BigDecimal.ZERO); boll.setUpper(BigDecimal.ZERO); boll.setLower(BigDecimal.ZERO); prevDif = BigDecimal.ZERO; prevDea = BigDecimal.ZERO; prevK = new BigDecimal(50); prevD = new BigDecimal(50); log.info("综合技术指标策略初始化完成"); } @Override public TradeRequestParam getSignal(String accountName, String markPx, String posSide) { if (!initialized || priceHistory.isEmpty()) { log.warn("策略未初始化或价格历史为空"); return createTradeRequestParam(accountName, markPx, posSide, TradeSignal.NO_SIGNAL); } try { BigDecimal currentPrice = new BigDecimal(markPx); // 计算所有技术指标 macd.calculate(priceHistory); kdj.calculate(priceHistory); rsi.calculate(priceHistory); boll.calculate(priceHistory); // 生成交易信号 TradeRequestParam param = analyzeSignal(accountName, markPx, posSide, currentPrice); // 更新历史指标值 updateHistoricalIndicatorValues(); return param; } catch (Exception e) { log.error("计算交易信号时发生异常", e); return createTradeRequestParam(accountName, markPx, posSide, TradeSignal.NO_SIGNAL); } } /** * 分析技术指标生成交易信号 */ private TradeRequestParam analyzeSignal(String accountName, String markPx, String posSide, BigDecimal currentPrice) { TradeRequestParam param = createTradeRequestParam(accountName, markPx, posSide, TradeSignal.NO_SIGNAL); param.setTradeType(OrderParamEnums.TRADE_YES.getValue()); param.setInstId(CoinEnums.HE_YUE.getCode()); param.setTdMode(CoinEnums.CROSS.getCode()); param.setOrdType(CoinEnums.ORDTYPE_MARKET.getCode()); // 检查冷静期 String outStr = getAccountConfig(accountName, CoinEnums.OUT.name()); if (OrderParamEnums.OUT_YES.getValue().equals(outStr)) { log.error("冷静中,不允许下单......"); param.setTradeType(OrderParamEnums.TRADE_NO.getValue()); return param; } TradeSignal signal = TradeSignal.NO_SIGNAL; // 根据多空方向分别分析信号 if (CoinEnums.POSSIDE_LONG.getCode().equals(posSide)) { signal = analyzeLongSignal(currentPrice, posSide); } else if (CoinEnums.POSSIDE_SHORT.getCode().equals(posSide)) { signal = analyzeShortSignal(currentPrice, posSide); } else { // 如果没有指定仓位方向,同时分析多头和空头信号 TradeSignal longSignal = analyzeLongSignal(currentPrice, posSide); TradeSignal shortSignal = analyzeShortSignal(currentPrice, posSide); // 优先选择非NO_SIGNAL的信号 if (longSignal != TradeSignal.NO_SIGNAL) { signal = longSignal; } else { signal = shortSignal; } } log.info("账户: {}, 价格: {}, 方向: {}, 生成信号: {}", accountName, markPx, posSide, signal.getName()); // 设置信号参数 setSignalParameters(param, signal); return param; } /** * 分析多头信号 */ private TradeSignal analyzeLongSignal(BigDecimal currentPrice, String posSide) { // 检查超卖条件 if (rsi.isOversold() || rsi.isExtremelyOversold()) { // KDJ超卖且金叉 if ((kdj.isOversold() && kdj.isGoldenCross()) || (boll.isBreakLower(currentPrice) && macd.isGoldenCross(prevDif, prevDea))) { // 如果当前没有仓位,则开多 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_LONG; } // 如果当前是空头仓位,则平空 if (CoinEnums.POSSIDE_SHORT.getCode().equals(posSide)) { return TradeSignal.CLOSE_SHORT; } // 如果当前已经是多头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } } // 检查超买条件 if (rsi.isOverbought() || rsi.isExtremelyOverbought()) { // KDJ超买且死叉 if ((kdj.isOverbought() && kdj.isDeathCross()) || (boll.isBreakUpper(currentPrice) && macd.isDeathCross(prevDif, prevDea))) { // 如果当前是多头仓位,则平多 if (CoinEnums.POSSIDE_LONG.getCode().equals(posSide)) { return TradeSignal.CLOSE_LONG; } // 如果当前没有仓位,则开空 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_SHORT; } // 如果当前已经是空头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } } // 检查MACD金叉死叉 if (macd.isGoldenCross(prevDif, prevDea)) { // 如果当前没有仓位,则开多 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_LONG; } // 如果当前是空头仓位,则平空 if (CoinEnums.POSSIDE_SHORT.getCode().equals(posSide)) { return TradeSignal.CLOSE_SHORT; } // 如果当前已经是多头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } else if (macd.isDeathCross(prevDif, prevDea)) { // 如果当前是多头仓位,则平多 if (CoinEnums.POSSIDE_LONG.getCode().equals(posSide)) { return TradeSignal.CLOSE_LONG; } // 如果当前没有仓位,则开空 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_SHORT; } // 如果当前已经是空头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } return TradeSignal.NO_SIGNAL; } /** * 分析空头信号 */ private TradeSignal analyzeShortSignal(BigDecimal currentPrice, String posSide) { // 检查超买条件 if (rsi.isOverbought() || rsi.isExtremelyOverbought()) { // KDJ超买且死叉 if ((kdj.isOverbought() && kdj.isDeathCross()) || (boll.isBreakUpper(currentPrice) && macd.isDeathCross(prevDif, prevDea))) { // 如果当前没有仓位,则开空 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_SHORT; } // 如果当前是多头仓位,则平多 if (CoinEnums.POSSIDE_LONG.getCode().equals(posSide)) { return TradeSignal.CLOSE_LONG; } // 如果当前已经是空头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } } // 检查超卖条件 if (rsi.isOversold() || rsi.isExtremelyOversold()) { // KDJ超卖且金叉 if ((kdj.isOversold() && kdj.isGoldenCross()) || (boll.isBreakLower(currentPrice) && macd.isGoldenCross(prevDif, prevDea))) { // 如果当前是空头仓位,则平空 if (CoinEnums.POSSIDE_SHORT.getCode().equals(posSide)) { return TradeSignal.CLOSE_SHORT; } // 如果当前没有仓位,则开多 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_LONG; } // 如果当前已经是多头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } } // 检查MACD金叉死叉 if (macd.isGoldenCross(prevDif, prevDea)) { // 如果当前是空头仓位,则平空 if (CoinEnums.POSSIDE_SHORT.getCode().equals(posSide)) { return TradeSignal.CLOSE_SHORT; } // 如果当前没有仓位,则开多 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_LONG; } // 如果当前已经是多头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } else if (macd.isDeathCross(prevDif, prevDea)) { // 如果当前没有仓位,则开空 if (posSide == null || posSide.isEmpty()) { return TradeSignal.OPEN_SHORT; } // 如果当前是多头仓位,则平多 if (CoinEnums.POSSIDE_LONG.getCode().equals(posSide)) { return TradeSignal.CLOSE_LONG; } // 如果当前已经是空头仓位,则保持观望 return TradeSignal.NO_SIGNAL; } return TradeSignal.NO_SIGNAL; } /** * 设置信号参数 */ private void setSignalParameters(TradeRequestParam param, TradeSignal signal) { String side = null; switch (signal) { case BUY: side = CoinEnums.SIDE_BUY.getCode(); break; case SELL: side = CoinEnums.SIDE_SELL.getCode(); break; case OPEN_LONG: side = CoinEnums.SIDE_BUY.getCode(); break; case CLOSE_LONG: side = CoinEnums.SIDE_SELL.getCode(); break; case OPEN_SHORT: side = CoinEnums.SIDE_SELL.getCode(); break; case CLOSE_SHORT: side = CoinEnums.SIDE_BUY.getCode(); break; case STOP_LOSS: // 止损操作,根据当前仓位方向决定买卖方向 side = CoinEnums.POSSIDE_LONG.getCode().equals(param.getPosSide()) ? CoinEnums.SIDE_SELL.getCode() : CoinEnums.SIDE_BUY.getCode(); break; default: param.setTradeType(OrderParamEnums.TRADE_NO.getValue()); return; } param.setSide(side); log.info("设置交易方向: {}", side); } /** * 更新历史指标值 */ private void updateHistoricalIndicatorValues() { prevDif = macd.getDif(); prevDea = macd.getDea(); prevK = kdj.getK(); prevD = kdj.getD(); } /** * 获取账户配置信息 */ private String getAccountConfig(String accountName, String key) { try { // 这里需要根据实际情况获取账户配置信息 // 暂时返回默认值,实际应该从InstrumentsWs或其他配置类中获取 return "NO"; } catch (Exception e) { log.error("获取账户配置信息失败", e); return "NO"; } } }