From c5faaa1111091280365100c95e7e06930b98ee4b Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 23 Dec 2025 16:21:44 +0800
Subject: [PATCH] feat(indicator): 添加15分钟交易策略和指标详细说明

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteStrategyExample.java |   81 +
 src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java              |   17 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/CoinEnums.java                  |    4 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java                |   76 +
 src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoService.java                    |    2 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingStrategy.java |  237 +++++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MA.java                           |  133 ++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java                         |   26 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java              |  738 ++++++++++++++++++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java                          |   26 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/Kline.java                      |   22 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxKlineWebSocketClient.java                |  652 +++++++++++++++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java                          |   25 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java                         |   95 ++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingExample.java  |  214 +++++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java                   |   25 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/IndicatorBase.java                |   67 +
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/StrategyParam.java              |   11 
 18 files changed, 2,406 insertions(+), 45 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxKlineWebSocketClient.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxKlineWebSocketClient.java
new file mode 100644
index 0000000..424fc76
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxKlineWebSocketClient.java
@@ -0,0 +1,652 @@
+package com.xcong.excoin.modules.okxNewPrice;
+
+import cn.hutool.core.collection.CollUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.xcong.excoin.modules.okxNewPrice.celue.CaoZuoService;
+import com.xcong.excoin.modules.okxNewPrice.indicator.TradingStrategy;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.*;
+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.Kline;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.param.TradeRequestParam;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.wanggeList.WangGeListEnum;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.wanggeList.WangGeListService;
+import com.xcong.excoin.modules.okxNewPrice.okxpi.config.ExchangeInfoEnum;
+import com.xcong.excoin.modules.okxNewPrice.okxpi.config.ExchangeLoginService;
+import com.xcong.excoin.modules.okxNewPrice.utils.SSLConfig;
+import com.xcong.excoin.modules.okxNewPrice.utils.WsParamBuild;
+import com.xcong.excoin.utils.RedisUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.handshake.ServerHandshake;
+
+import java.math.BigDecimal;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+/**
+ * OKX 新价格 WebSocket 客户端类,用于连接 OKX 的 WebSocket 接口,
+ * 实时获取并处理标记价格(mark price)数据,并将价格信息存储到 Redis 中。
+ * 同时支持心跳检测、自动重连以及异常恢复机制。
+ * @author Administrator
+ */
+@Slf4j
+public class OkxKlineWebSocketClient {
+    private final RedisUtils redisUtils;
+    private final CaoZuoService caoZuoService;
+    private final OkxWebSocketClientManager clientManager;
+    private final WangGeListService wangGeListService;
+
+    private WebSocketClient webSocketClient;
+    private ScheduledExecutorService heartbeatExecutor;
+    private volatile ScheduledFuture<?> pongTimeoutFuture;
+    private final AtomicReference<Long> lastMessageTime = new AtomicReference<>(System.currentTimeMillis());
+
+    // 连接状态标志
+    private final AtomicBoolean isConnected = new AtomicBoolean(false);
+    private final AtomicBoolean isConnecting = new AtomicBoolean(false);
+    private final AtomicBoolean isInitialized = new AtomicBoolean(false);
+
+    private static final String CHANNEL = "candle15m";
+
+    // 心跳超时时间(秒),小于30秒
+    private static final int HEARTBEAT_TIMEOUT = 10;
+
+    // 共享线程池用于重连等异步任务
+    private final ExecutorService sharedExecutor = Executors.newCachedThreadPool(r -> {
+        Thread t = new Thread(r, "okx-ws-kline-worker");
+        t.setDaemon(true);
+        return t;
+    });
+
+    public OkxKlineWebSocketClient(RedisUtils redisUtils,
+                                   CaoZuoService caoZuoService, OkxWebSocketClientManager clientManager,
+                                   WangGeListService wangGeListService) {
+        this.redisUtils = redisUtils;
+        this.caoZuoService = caoZuoService;
+        this.clientManager = clientManager;
+        this.wangGeListService = wangGeListService;
+    }
+
+    /**
+     * 初始化方法,创建并初始化WebSocket客户端实例
+     */
+    public void init() {
+        if (!isInitialized.compareAndSet(false, true)) {
+            log.warn("OkxKlineWebSocketClient 已经初始化过,跳过重复初始化");
+            return;
+        }
+        connect();
+        startHeartbeat();
+    }
+
+    /**
+     * 销毁方法,关闭WebSocket连接和相关资源
+     */
+    public void destroy() {
+        log.info("开始销毁OkxKlineWebSocketClient");
+
+        // 设置关闭标志,避免重连
+        if (sharedExecutor != null && !sharedExecutor.isShutdown()) {
+            sharedExecutor.shutdown();
+        }
+
+        if (webSocketClient != null && webSocketClient.isOpen()) {
+            try {
+                webSocketClient.closeBlocking();
+            } catch (InterruptedException e) {
+                Thread.currentThread().interrupt();
+                log.warn("关闭WebSocket连接时被中断");
+            }
+        }
+
+        shutdownExecutorGracefully(heartbeatExecutor);
+        if (pongTimeoutFuture != null) {
+            pongTimeoutFuture.cancel(true);
+        }
+        shutdownExecutorGracefully(sharedExecutor);
+
+        log.info("OkxKlineWebSocketClient销毁完成");
+    }
+
+    private static final String WS_URL_MONIPAN = "wss://wspap.okx.com:8443/ws/v5/business";
+    private static final String WS_URL_SHIPAN = "wss://ws.okx.com:8443/ws/v5/business";
+    private static final boolean isAccountType = true;
+
+    /**
+     * 建立与 OKX WebSocket 服务器的连接。
+     * 设置回调函数以监听连接打开、接收消息、关闭和错误事件。
+     */
+    private void connect() {
+        // 避免重复连接
+        if (isConnecting.get()) {
+            log.info("连接已在进行中,跳过重复连接请求");
+            return;
+        }
+        
+        if (!isConnecting.compareAndSet(false, true)) {
+            log.info("连接已在进行中,跳过重复连接请求");
+            return;
+        }
+        
+        try {
+            SSLConfig.configureSSL();
+            System.setProperty("https.protocols", "TLSv1.2,TLSv1.3");
+            String WS_URL = WS_URL_MONIPAN;
+            if (isAccountType){
+                WS_URL = WS_URL_SHIPAN;
+            }
+            URI uri = new URI(WS_URL);
+            
+            // 关闭之前的连接(如果存在)
+            if (webSocketClient != null) {
+                try {
+                    webSocketClient.closeBlocking();
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    log.warn("关闭之前连接时被中断");
+                }
+            }
+            
+            webSocketClient = new WebSocketClient(uri) {
+                @Override
+                public void onOpen(ServerHandshake handshake) {
+                    log.info("OKX kline WebSocket连接成功");
+                    isConnected.set(true);
+                    isConnecting.set(false);
+                    
+                    // 检查应用是否正在关闭
+                    if (sharedExecutor != null && !sharedExecutor.isShutdown()) {
+                        resetHeartbeatTimer();
+                        subscribeChannels();
+                    } else {
+                        log.warn("应用正在关闭,忽略WebSocket连接成功回调");
+                    }
+                }
+
+                @Override
+                public void onMessage(String message) {
+                    lastMessageTime.set(System.currentTimeMillis());
+                    handleWebSocketMessage(message);
+                    resetHeartbeatTimer();
+                }
+
+                @Override
+                public void onClose(int code, String reason, boolean remote) {
+                    log.warn("OKX kline WebSocket连接关闭: code={}, reason={}", code, reason);
+                    isConnected.set(false);
+                    isConnecting.set(false);
+                    cancelPongTimeout();
+
+                    if (sharedExecutor != null && !sharedExecutor.isShutdown() && !sharedExecutor.isTerminated()) {
+                        sharedExecutor.execute(() -> {
+                            try {
+                                reconnectWithBackoff();
+                            } catch (InterruptedException e) {
+                                Thread.currentThread().interrupt();
+                                log.error("重连线程被中断", e);
+                            } catch (Exception e) {
+                                log.error("重连失败", e);
+                            }
+                        });
+                    } else {
+                        log.warn("共享线程池已关闭,无法执行重连任务");
+                    }
+                }
+
+                @Override
+                public void onError(Exception ex) {
+                    log.error("OKX New Price WebSocket发生错误", ex);
+                    isConnected.set(false);
+                }
+            };
+
+            webSocketClient.connect();
+        } catch (URISyntaxException e) {
+            log.error("WebSocket URI格式错误", e);
+            isConnecting.set(false);
+        }
+    }
+
+    /**
+     * 订阅指定交易对的价格通道。
+     * 构造订阅请求并发送给服务端。
+     */
+    private void subscribeChannels() {
+        JSONObject subscribeMsg = new JSONObject();
+        subscribeMsg.put("op", "subscribe");
+
+        JSONArray argsArray = new JSONArray();
+        JSONObject arg = new JSONObject();
+        arg.put("channel", CHANNEL);
+        arg.put("instId", CoinEnums.HE_YUE.getCode());
+        argsArray.add(arg);
+
+        subscribeMsg.put("args", argsArray);
+        webSocketClient.send(subscribeMsg.toJSONString());
+        log.info("已发送 K线频道订阅请求,订阅通道数: {}", argsArray.size());
+    }
+
+    /**
+     * 处理从 WebSocket 收到的消息。
+     * 包括订阅确认、错误响应、心跳响应以及实际的数据推送。
+     *
+     * @param message 来自 WebSocket 的原始字符串消息
+     */
+    private void handleWebSocketMessage(String message) {
+        try {
+            JSONObject response = JSON.parseObject(message);
+            String event = response.getString("event");
+
+            if ("subscribe".equals(event)) {
+                log.info(" K线频道订阅成功: {}", response.getJSONObject("arg"));
+            } else if ("error".equals(event)) {
+                log.error(" K线频道订阅错误: code={}, msg={}",
+                         response.getString("code"), response.getString("msg"));
+            } else if ("pong".equals(event)) {
+                log.debug("收到pong响应");
+                cancelPongTimeout();
+            } else {
+                processPushData(response);
+            }
+        } catch (Exception e) {
+            log.error("处理WebSocket消息失败: {}", message, e);
+        }
+    }
+
+    /**
+     * 解析并处理价格推送数据。
+     * 将最新的标记价格存入 Redis 并触发后续业务逻辑比较处理。
+     * 当价格变化时,调用CaoZuoService的caoZuo方法,触发所有账号的量化操作
+     *
+     * @param response 包含价格数据的 JSON 对象
+     */
+    private void processPushData(JSONObject response) {
+        try {
+            /**
+             * {
+             *   "arg": {
+             *     "channel": "candle1D",
+             *     "instId": "BTC-USDT"
+             *   },
+             *   "data": [
+             *     [
+             *       "1629993600000",
+             *       "42500",
+             *       "48199.9",
+             *       "41006.1",
+             *       "41006.1",
+             *       "3587.41204591",
+             *       "166741046.22583129",
+             *       "166741046.22583129",
+             *       "0"
+             *     ]
+             *   ]
+             * }
+             */
+            JSONObject arg = response.getJSONObject("arg");
+            if (arg == null) {
+                log.warn("{}: 无效的推送数据,缺少 'arg' 字段", response);
+                return;
+            }
+
+            String channel = arg.getString("channel");
+            if (channel == null) {
+                log.warn("{}: 无效的推送数据,缺少 'channel' 字段", response);
+                return;
+            }
+
+            String instId = arg.getString("instId");
+            if (instId == null) {
+                log.warn("{}: 无效的推送数据,缺少 'instId' 字段", response);
+                return;
+            }
+
+            if (CHANNEL.equals(channel) && CoinEnums.HE_YUE.getCode().equals(instId)) {
+                JSONArray dataArray = response.getJSONArray("data");
+                if (dataArray == null || dataArray.isEmpty()) {
+                    log.warn("K线频道数据为空");
+                    return;
+                }
+                JSONArray data = dataArray.getJSONArray(0);
+                BigDecimal openPx = new BigDecimal(data.getString(1));
+                BigDecimal highPx = new BigDecimal(data.getString(2));
+                BigDecimal lowPx = new BigDecimal(data.getString(3));
+                BigDecimal closePx = new BigDecimal(data.getString(4));
+                BigDecimal vol = new BigDecimal(data.getString(5));
+                /**
+                 * K线状态
+                 * 0:K线未完结
+                 * 1:K线已完结
+                 */
+                String confirm = data.getString(8);
+                if ("1".equals(confirm)){
+                    //调用策略
+                    // 创建交易策略
+                    TradingStrategy tradingStrategy = new TradingStrategy();
+
+                    // 生成100个15分钟价格数据点
+                    List<Kline> kline15MinuteData = getKlineDataByInstIdAndBar(instId, "15m");
+                    //stream流获取kline15MinuteData中的o数据的集合
+                    List<BigDecimal> prices = kline15MinuteData.stream()
+                            .map(Kline::getO)
+                            .collect(Collectors.toList());
+
+                    // 生成对应的高、低、收盘价数据
+                    List<BigDecimal> high = kline15MinuteData.stream()
+                            .map(Kline::getH)
+                            .collect(Collectors.toList());
+                    List<BigDecimal> low = kline15MinuteData.stream()
+                            .map(Kline::getL)
+                            .collect(Collectors.toList());
+                    List<BigDecimal> close = kline15MinuteData.stream()
+                            .map(Kline::getC)
+                            .collect(Collectors.toList());
+
+                    // 生成成交量数据
+                    List<BigDecimal> volume = kline15MinuteData.stream()
+                            .map(Kline::getVol)
+                            .collect(Collectors.toList());
+
+                    // 获取最新价格
+                    BigDecimal currentPrice = closePx;
+
+                    // 生成多周期价格数据(5分钟、1小时、4小时)
+                    List<Kline> kline5MinuteData = getKlineDataByInstIdAndBar(instId, "5m");
+                    List<BigDecimal> fiveMinPrices = kline5MinuteData.stream()
+                            .map(Kline::getC)
+                            .collect(Collectors.toList());
+                    List<Kline> kline60MinuteData = getKlineDataByInstIdAndBar(instId, "1H");
+                    List<BigDecimal> oneHourPrices = kline60MinuteData.stream()
+                            .map(Kline::getC)
+                            .collect(Collectors.toList());
+                    List<Kline> kline240MinuteData = getKlineDataByInstIdAndBar(instId, "4H");
+                    List<BigDecimal> fourHourPrices = kline240MinuteData.stream()
+                            .map(Kline::getC)
+                            .collect(Collectors.toList());
+
+                    // 其他参数
+                    BigDecimal fundingRate = new BigDecimal("0.001"); // 正常资金费率
+                    boolean hasLargeTransfer = false; // 无大额转账
+                    boolean hasUpcomingEvent = false; // 无即将到来的重大事件
+                    // 确定市场方向
+                    TradingStrategy.Direction direction = tradingStrategy.getDirection(prices, high, low, close, currentPrice);
+                    System.out.println("市场方向(15分钟): " + direction);
+                    if (direction == TradingStrategy.Direction.RANGING){
+                        return;
+                    }
+
+                    /**
+                     * 获取当前网格信息
+                     *      根据当前网格的持仓方向获取反方向是否存在持仓
+                     *      如果持有,直接止损
+                     */
+                    Collection<OkxQuantWebSocketClient> allClients = clientManager.getAllClients();
+                    //如果为空,则直接返回
+                    if (allClients.isEmpty()) {
+                        return;
+                    }
+                    // 获取所有OkxQuantWebSocketClient实例
+                    for (OkxQuantWebSocketClient client : clientManager.getAllClients()) {
+                        String accountName = client.getAccountName();
+                        if (accountName != null) {
+                            TradingStrategy.SignalType signal = TradingStrategy.SignalType.NONE;
+                            TradeRequestParam tradeRequestParam = new TradeRequestParam();
+                            // 检查当前持仓状态
+                            boolean hasLongPosition = false;  // 示例:无当前做多持仓
+                            boolean hasShortPosition = false; // 示例:无当前做空持仓
+                            //先判断账户是否有持多仓
+                            String positionLongAccountName = PositionsWs.initAccountName(accountName, CoinEnums.POSSIDE_LONG.getCode());
+                            BigDecimal imrLong = PositionsWs.getAccountMap(positionLongAccountName).get("imr");
+                            if (imrLong != null && imrLong.compareTo(BigDecimal.ZERO) > 0){
+                                log.info("账户{}有持多仓", accountName);
+                                hasLongPosition = true;
+
+                            }
+                            //先判断账户是否有持空仓
+                            String positionShortAccountName = PositionsWs.initAccountName(accountName, CoinEnums.POSSIDE_LONG.getCode());
+                            BigDecimal imrShort = PositionsWs.getAccountMap(positionShortAccountName).get("imr");
+                            if (imrShort != null && imrShort.compareTo(BigDecimal.ZERO) > 0){
+                                log.info("账户{}有持空仓", accountName);
+                                hasShortPosition = true;
+                            }
+                            signal = tradingStrategy.generateSignal(prices, high, low, close, volume, currentPrice,
+                                    hasLongPosition, hasShortPosition,
+                                    fiveMinPrices, oneHourPrices, fourHourPrices,
+                                    fundingRate, hasLargeTransfer, hasUpcomingEvent);
+                            log.info("账户{}交易信号: " + signal, accountName);
+                            if (TradingStrategy.SignalType.NONE == signal) {
+                                continue;
+                            }else if (TradingStrategy.SignalType.BUY == signal){
+                                tradeRequestParam = caoZuoService.caoZuoStrategy(accountName, String.valueOf(currentPrice), CoinEnums.POSSIDE_LONG.getCode());
+                                tradeRequestParam.setSide(CoinEnums.SIDE_BUY.getCode());
+                                String clOrdId = WsParamBuild.getOrderNum(CoinEnums.SIDE_BUY.getCode());
+                                tradeRequestParam.setClOrdId(clOrdId);
+                                String sz = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.BUY_CNT_INIT.name());
+                                tradeRequestParam.setSz(sz);
+                                TradeOrderWs.orderEvent(client.getWebSocketClient(), tradeRequestParam);
+                            }else if (TradingStrategy.SignalType.SELL == signal){
+                                tradeRequestParam = caoZuoService.caoZuoStrategy(accountName, String.valueOf(currentPrice), CoinEnums.POSSIDE_SHORT.getCode());
+                                tradeRequestParam.setSide(CoinEnums.SIDE_SELL.getCode());
+                                String clOrdId = WsParamBuild.getOrderNum(CoinEnums.SIDE_SELL.getCode());
+                                tradeRequestParam.setClOrdId(clOrdId);
+                                String sz = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.BUY_CNT_INIT.name());
+                                tradeRequestParam.setSz(sz);
+                                TradeOrderWs.orderEvent(client.getWebSocketClient(), tradeRequestParam);
+                            }else if (TradingStrategy.SignalType.CLOSE_BUY == signal){
+                                tradeRequestParam = caoZuoService.caoZuoStrategy(accountName, String.valueOf(currentPrice), CoinEnums.POSSIDE_LONG.getCode());
+                                tradeRequestParam.setSide(CoinEnums.SIDE_SELL.getCode());
+                                String clOrdId = WsParamBuild.getOrderNum(CoinEnums.SIDE_SELL.getCode());
+                                tradeRequestParam.setClOrdId(clOrdId);
+                                BigDecimal pos = PositionsWs.getAccountMap(PositionsWs.initAccountName(accountName, CoinEnums.POSSIDE_LONG.getCode())).get("pos");
+                                if (BigDecimal.ZERO.compareTo( pos) >= 0) {
+                                    tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+                                }
+                                tradeRequestParam.setSz(String.valueOf( pos));
+                                TradeOrderWs.orderEvent(client.getWebSocketClient(), tradeRequestParam);
+                            }else if (TradingStrategy.SignalType.CLOSE_SELL == signal){
+                                tradeRequestParam = caoZuoService.caoZuoStrategy(accountName, String.valueOf(currentPrice), CoinEnums.POSSIDE_SHORT.getCode());
+                                tradeRequestParam.setSide(CoinEnums.SIDE_BUY.getCode());
+                                String clOrdId = WsParamBuild.getOrderNum(CoinEnums.SIDE_BUY.getCode());
+                                tradeRequestParam.setClOrdId(clOrdId);
+                                BigDecimal pos = PositionsWs.getAccountMap(PositionsWs.initAccountName(accountName, CoinEnums.POSSIDE_SHORT.getCode())).get("pos");
+                                if (BigDecimal.ZERO.compareTo( pos) >= 0) {
+                                    tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+                                }
+                                tradeRequestParam.setSz(String.valueOf( pos));
+                                TradeOrderWs.orderEvent(client.getWebSocketClient(), tradeRequestParam);
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception e) {
+            log.error("处理 K线频道推送数据失败", e);
+        }
+    }
+
+
+
+    /**
+     * 触发所有账号的量化操作
+     * @param markPx 当前标记价格
+     */
+    private void triggerQuantOperations(String markPx) {
+        try {
+            // 1. 判断当前价格属于哪个网格
+            WangGeListEnum gridByPriceNew = WangGeListEnum.getGridByPrice(new BigDecimal(markPx));
+            if (gridByPriceNew == null) {
+                log.error("当前 K线频道{}不在任何网格范围内,无法触发量化操作", markPx);
+                return;
+            }
+
+        } catch (Exception e) {
+            log.error("触发量化操作失败", e);
+        }
+    }
+
+    private List<Kline> getKlineDataByInstIdAndBar(String instId, String bar) {
+
+
+        LinkedHashMap<String, Object> requestParam = new LinkedHashMap<>();
+        requestParam.put("instId",instId);
+        requestParam.put("bar",bar);
+        requestParam.put("limit","100");
+        String result = ExchangeLoginService.getInstance(ExchangeInfoEnum.OKX_UAT.name()).lineHistory(requestParam);
+        log.info("加载OKX-KLINE,{}", result);
+        JSONObject json = JSON.parseObject(result);
+        String data = json.getString("data");
+        List<String[]> klinesList = JSON.parseArray(data, String[].class);
+        if(CollUtil.isEmpty(klinesList)){
+            return  null;
+        }
+        ArrayList<Kline> objects = new ArrayList<>();
+        for(String[] s : klinesList) {
+            Kline kline = new Kline();
+            kline.setTs(s[0]);
+            kline.setO(new BigDecimal(s[1]));
+            kline.setH(new BigDecimal(s[2]));
+            kline.setL(new BigDecimal(s[3]));
+            kline.setC(new BigDecimal(s[4]));
+            kline.setVol(new BigDecimal(s[5]));
+            kline.setConfirm(s[8]);
+            objects.add(kline);
+        }
+        return objects;
+    }
+
+    /**
+     * 构建 Redis Key
+     */
+    private String buildRedisKey(String instId) {
+        return "PRICE_" + instId.replace("-", "");
+    }
+
+    /**
+     * 启动心跳检测任务。
+     * 使用 ScheduledExecutorService 定期检查是否需要发送 ping 请求来维持连接。
+     */
+    private void startHeartbeat() {
+        if (heartbeatExecutor != null && !heartbeatExecutor.isTerminated()) {
+            heartbeatExecutor.shutdownNow();
+        }
+
+        heartbeatExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
+            Thread t = new Thread(r, "okx-kline-heartbeat");
+            t.setDaemon(true);
+            return t;
+        });
+
+        heartbeatExecutor.scheduleWithFixedDelay(this::checkHeartbeatTimeout, 25, 25, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 重置心跳计时器。
+     * 当收到新消息或发送 ping 后取消当前超时任务并重新安排下一次超时检查。
+     */
+    private synchronized void resetHeartbeatTimer() {
+        cancelPongTimeout();
+
+        if (heartbeatExecutor != null && !heartbeatExecutor.isShutdown()) {
+            pongTimeoutFuture = heartbeatExecutor.schedule(this::checkHeartbeatTimeout,
+                    HEARTBEAT_TIMEOUT, TimeUnit.SECONDS);
+        }
+    }
+
+    /**
+     * 检查心跳超时情况。
+     * 若长时间未收到任何消息则主动发送 ping 请求保持连接活跃。
+     */
+    private void checkHeartbeatTimeout() {
+        // 只有在连接状态下才检查心跳
+        if (!isConnected.get()) {
+            return;
+        }
+        
+        long currentTime = System.currentTimeMillis();
+        long lastTime = lastMessageTime.get();
+
+        if (currentTime - lastTime >= HEARTBEAT_TIMEOUT * 1000L) {
+            sendPing();
+        }
+    }
+
+    /**
+     * 发送 ping 请求至 WebSocket 服务端。
+     * 用于维持长连接有效性。
+     */
+    private void sendPing() {
+        try {
+            if (webSocketClient != null && webSocketClient.isOpen()) {
+                JSONObject ping = new JSONObject();
+                ping.put("op", "ping");
+                webSocketClient.send(ping.toJSONString());
+                log.debug("发送ping请求");
+            }
+        } catch (Exception e) {
+            log.warn("发送ping失败", e);
+        }
+    }
+
+    /**
+     * 取消当前的心跳超时任务。
+     * 在收到 pong 或其他有效消息时调用此方法避免不必要的断开重连。
+     */
+    private synchronized void cancelPongTimeout() {
+        if (pongTimeoutFuture != null && !pongTimeoutFuture.isDone()) {
+            pongTimeoutFuture.cancel(true);
+        }
+    }
+
+    /**
+     * 执行 WebSocket 重连操作。
+     * 在连接意外中断后尝试重新建立连接。
+     */
+    private void reconnectWithBackoff() throws InterruptedException {
+        int attempt = 0;
+        int maxAttempts = 3;
+        long delayMs = 5000;
+
+        while (attempt < maxAttempts) {
+            try {
+                Thread.sleep(delayMs);
+                connect();
+                return;
+            } catch (Exception e) {
+                log.warn("第{}次重连失败", attempt + 1, e);
+                delayMs *= 2;
+                attempt++;
+            }
+        }
+
+        log.error("超过最大重试次数({})仍未连接成功", maxAttempts);
+    }
+
+    /**
+     * 优雅关闭线程池
+     */
+    private void shutdownExecutorGracefully(ExecutorService executor) {
+        if (executor == null || executor.isTerminated()) {
+            return;
+        }
+        try {
+            executor.shutdown();
+            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
+                executor.shutdownNow();
+            }
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            executor.shutdownNow();
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java
index be64554..4f23fb8 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java
@@ -3,8 +3,6 @@
 import com.xcong.excoin.modules.okxNewPrice.celue.CaoZuoService;
 import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.ExchangeInfoEnum;
 import com.xcong.excoin.modules.okxNewPrice.okxWs.wanggeList.WangGeListService;
-import com.xcong.excoin.modules.okxNewPrice.wangge.WangGeService;
-import com.xcong.excoin.rabbit.pricequeue.WebsocketPriceService;
 import com.xcong.excoin.utils.RedisUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,7 +32,8 @@
     private final Map<String, OkxQuantWebSocketClient> quantClientMap = new ConcurrentHashMap<>();
     
     // 存储OkxNewPriceWebSocketClient实例
-    private OkxNewPriceWebSocketClient newPriceClient;
+    private OkxKlineWebSocketClient klinePriceClient;
+
 
     /**
      * 初始化方法,在Spring Bean构造完成后执行
@@ -46,8 +45,8 @@
         
         // 初始化价格WebSocket客户端
         try {
-            newPriceClient = new OkxNewPriceWebSocketClient(redisUtils, caoZuoService, this, wangGeListService);
-            newPriceClient.init();
+            klinePriceClient = new OkxKlineWebSocketClient(redisUtils, caoZuoService, this, wangGeListService);
+            klinePriceClient.init();
             log.info("已初始化OkxNewPriceWebSocketClient");
         } catch (Exception e) {
             log.error("初始化OkxNewPriceWebSocketClient失败", e);
@@ -80,9 +79,9 @@
         log.info("开始销毁OkxWebSocketClientManager");
         
         // 关闭价格WebSocket客户端
-        if (newPriceClient != null) {
+        if (klinePriceClient != null) {
             try {
-                newPriceClient.destroy();
+                klinePriceClient.destroy();
                 log.info("已销毁OkxNewPriceWebSocketClient");
             } catch (Exception e) {
                 log.error("销毁OkxNewPriceWebSocketClient失败", e);
@@ -127,7 +126,7 @@
      * 获取OkxNewPriceWebSocketClient实例
      * @return 价格WebSocket客户端实例
      */
-    public OkxNewPriceWebSocketClient getNewPriceClient() {
-        return newPriceClient;
+    public OkxKlineWebSocketClient getKlineWebSocketClient() {
+        return klinePriceClient;
     }
 }
\ No newline at end of file
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoService.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoService.java
index e53aa38..645c35d 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoService.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoService.java
@@ -7,6 +7,8 @@
  */
 public interface CaoZuoService {
 
+    TradeRequestParam caoZuoStrategy(String accountName, String markPx, String posSide);
+
     TradeRequestParam caoZuoHandler(String accountName, String markPx, String posSide);
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java
index a912b74..304ad4c 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java
@@ -40,6 +40,82 @@
     private final RedisUtils redisUtils;
     private final TechnicalIndicatorStrategy technicalIndicatorStrategy;
 
+    @Override
+    public TradeRequestParam caoZuoStrategy(String accountName, String markPx, String posSide) {
+        TradeRequestParam tradeRequestParam = new TradeRequestParam();
+        tradeRequestParam.setAccountName(accountName);
+        tradeRequestParam.setInstId(CoinEnums.HE_YUE.getCode());
+        tradeRequestParam.setTdMode(CoinEnums.CROSS.getCode());
+        tradeRequestParam.setPosSide(posSide);
+        tradeRequestParam.setOrdType(CoinEnums.ORDTYPE_MARKET.getCode());
+
+        log.info("操作账户:{},当前价格: {},仓位方向: {}", accountName,markPx,posSide);
+        /**
+         * 准备工作
+         * 1、准备好下单的基本信息
+         */
+        // 系统设置的开关,等于冷静中,则代表不开仓
+        String outStr = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.OUT.name());
+        if (OrderParamEnums.OUT_YES.getValue().equals(outStr)){
+            log.error("冷静中,不允许下单......");
+            tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+            return tradeRequestParam;
+        }
+        BigDecimal cashBal = WsMapBuild.parseBigDecimalSafe(AccountWs.getAccountMap(accountName).get("cashBal"));
+        /**
+         * 判断止损抗压
+         */
+        BigDecimal realKuiSunAmount = WsMapBuild.parseBigDecimalSafe(AccountWs.getAccountMap(accountName).get("upl"));
+        log.info("实际盈亏金额: {}", realKuiSunAmount);
+        String zhiSunPercent = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.ZHI_SUN.name());
+        BigDecimal zhiSunAmount = cashBal.multiply(new BigDecimal(zhiSunPercent));
+        log.info("预期亏损金额: {}", zhiSunAmount);
+        String kangYaPercent = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.KANG_CANG.name());
+        BigDecimal  kangYaAmount = cashBal.multiply(new BigDecimal(kangYaPercent));
+        log.info("预期抗仓金额: {}", kangYaAmount);
+
+        if (realKuiSunAmount.compareTo(BigDecimal.ZERO) < 0){
+            realKuiSunAmount = realKuiSunAmount.multiply(new BigDecimal("-1"));
+            // 账户预期亏损金额比这个还小时,立即止损
+            if (realKuiSunAmount.compareTo(zhiSunAmount) > 0){
+                log.error("账户冷静止损......");
+                WsMapBuild.saveStringToMap(InstrumentsWs.getAccountMap(accountName), CoinEnums.OUT.name(),  OrderParamEnums.OUT_YES.getValue());
+                tradeRequestParam.setTradeType(OrderParamEnums.TRADE_YES.getValue());
+                return caoZuoZhiSunEvent(accountName, markPx, posSide);
+            }
+            // 判断抗压
+            if (realKuiSunAmount.compareTo(kangYaAmount) > 0 && realKuiSunAmount.compareTo(zhiSunAmount) <= 0){
+                log.error("账户紧张扛仓......");
+                tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+                return tradeRequestParam;
+            }
+        }
+
+        String positionAccountName = PositionsWs.initAccountName(accountName, posSide);
+        // 判断是否保证金超标
+        if (PositionsWs.getAccountMap(positionAccountName).get("imr") == null){
+            log.error("没有获取到持仓信息,等待初始化......");
+            tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+            return tradeRequestParam;
+        }
+        BigDecimal ordFrozImr = PositionsWs.getAccountMap(positionAccountName).get("imr");
+        BigDecimal totalOrderUsdt = WsMapBuild.parseBigDecimalSafe(AccountWs.getAccountMap(accountName).get(CoinEnums.TOTAL_ORDER_USDT.name()))
+                .divide(new BigDecimal("2"), RoundingMode.DOWN);
+        if (ordFrozImr.compareTo(totalOrderUsdt) >= 0){
+            log.error("已满仓......");
+            tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+            return tradeRequestParam;
+        }
+
+        if (PositionsWs.getAccountMap(positionAccountName).get("pos") == null){
+            log.error("没有获取到持仓信息,等待初始化......");
+            tradeRequestParam.setTradeType(OrderParamEnums.TRADE_NO.getValue());
+            return tradeRequestParam;
+        }
+        tradeRequestParam.setTradeType(OrderParamEnums.TRADE_YES.getValue());
+        return chooseEvent(tradeRequestParam);
+    }
+
     /**
      * 执行主要的操作逻辑,包括读取合约状态、获取市场价格信息,
      * 并根据当前持仓均价和标记价格决定是否执行买卖操作。
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java
index a7e3aad..41e0278 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/AdvancedMA.java
@@ -11,6 +11,31 @@
 /**
  * Advanced MA (Moving Average) 指标实现
  * 支持扩展周期的指数移动平均线(EMA),用于三重EMA交叉系统
+ * 
+ * 作用:
+ * 1. 基于三重EMA交叉系统识别趋势方向和强度
+ * 2. 当9EMA > 21EMA > 55EMA时形成多头排列,提示上涨趋势
+ * 3. 当9EMA < 21EMA < 55EMA时形成空头排列,提示下跌趋势
+ * 4. 计算三线粘合度,自动过滤震荡行情
+ * 
+ * 价格参数类型:
+ * - 参数名称:prices
+ * - 参数类型:List<BigDecimal>
+ * - 参数说明:需要至少1个价格数据点用于计算,根据不同周期需求更多数据点
+ * 
+ * 推荐时间粒度及优缺点:
+ * 1. 5分钟(5m):
+ *    - 优点:适合短线三重EMA交叉策略
+ *    - 缺点:需要频繁监控,容易受短期波动影响
+ * 2. 15分钟(15m):
+ *    - 优点:平衡了信号可靠性和反应速度
+ *    - 缺点:仍有一定噪音
+ * 3. 1小时(1h):
+ *    - 优点:信号较为可靠,适合中期趋势跟踪
+ *    - 缺点:反应较慢
+ * 4. 4小时(4h)及以上:
+ *    - 优点:趋势信号明确,适合长期持仓
+ *    - 缺点:反应滞后,入场点较晚
  */
 @Slf4j
 @Getter
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java
index 8f00e0c..7ab8b78 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/BOLL.java
@@ -14,6 +14,32 @@
  * 1. 中轨(MB)= N日移动平均线
  * 2. 上轨(UP)= 中轨 + K倍标准差
  * 3. 下轨(DN)= 中轨 - K倍标准差
+ * 
+ * 作用:
+ * 1. 测量价格波动范围和市场宽度
+ * 2. 价格突破上轨,提示超买或趋势加速
+ * 3. 价格跌破下轨,提示超卖或趋势加速
+ * 4. 轨道收窄,提示即将发生剧烈波动
+ * 5. 价格回归轨道内,提示趋势可能反转
+ * 
+ * 价格参数类型:
+ * - 参数名称:prices
+ * - 参数类型:List<BigDecimal>
+ * - 参数说明:需要至少20个(默认周期)价格数据点用于计算
+ * 
+ * 推荐时间粒度及优缺点:
+ * 1. 1分钟(1m):
+ *    - 优点:反应迅速,适合超短线突破策略
+ *    - 缺点:布林带宽度窄,假突破多
+ * 2. 5分钟(5m):
+ *    - 优点:布林带宽度适中,突破信号相对可靠
+ *    - 缺点:仍有一定假突破
+ * 3. 15分钟(15m):
+ *    - 优点:适合日内交易,突破信号较为可靠
+ *    - 缺点:反应速度较慢
+ * 4. 1小时(1h)及以上:
+ *    - 优点:布林带宽度稳定,突破信号可靠
+ *    - 缺点:反应滞后,不适合短线交易
  */
 @Slf4j
 @Getter
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteStrategyExample.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteStrategyExample.java
new file mode 100644
index 0000000..ed1b226
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteStrategyExample.java
@@ -0,0 +1,81 @@
+package com.xcong.excoin.modules.okxNewPrice.indicator;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 15分钟交易策略使用示例
+ * 展示如何使用FifteenMinuteTradingStrategy处理100个15分钟价格数据点
+ */
+public class FifteenMinuteStrategyExample {
+
+    public static void main(String[] args) {
+        // 1. 创建策略实例
+        FifteenMinuteTradingStrategy strategy = new FifteenMinuteTradingStrategy();
+
+        // 2. 准备100个15分钟价格数据(这里使用模拟数据,用户可以替换为真实数据)
+        List<BigDecimal> prices = generateSampleFifteenMinuteData();
+        System.out.println("已加载 " + prices.size() + " 个15分钟价格数据点");
+        
+        // 3. 获取当前价格
+        BigDecimal currentPrice = prices.get(prices.size() - 1);
+        System.out.println("当前价格: " + currentPrice);
+
+        // 4. 示例1:获取多空方向
+        System.out.println("\n=== 多空方向分析 ===");
+        FifteenMinuteTradingStrategy.Direction direction = strategy.getDirection(prices);
+        System.out.println("当前市场方向: " + direction);
+
+        // 5. 示例2:获取开仓平仓信号(假设当前没有持仓)
+        System.out.println("\n=== 开仓平仓信号分析(无持仓)===");
+        FifteenMinuteTradingStrategy.PositionSignal signal1 = 
+            strategy.getPositionSignal(prices, false, false);
+        System.out.println("无持仓时的信号: " + signal1);
+
+        // 6. 示例3:获取开仓平仓信号(假设当前持有多仓)
+        System.out.println("\n=== 开仓平仓信号分析(持有多仓)===");
+        FifteenMinuteTradingStrategy.PositionSignal signal2 = 
+            strategy.getPositionSignal(prices, true, false);
+        System.out.println("持有多仓时的信号: " + signal2);
+
+        // 7. 示例4:获取开仓平仓信号(假设当前持有空仓)
+        System.out.println("\n=== 开仓平仓信号分析(持有空仓)===");
+        FifteenMinuteTradingStrategy.PositionSignal signal3 = 
+            strategy.getPositionSignal(prices, false, true);
+        System.out.println("持有空仓时的信号: " + signal3);
+
+        // 8. 示例5:获取完整交易结果
+        System.out.println("\n=== 完整交易结果分析 ===");
+        FifteenMinuteTradingStrategy.TradingResult result = 
+            strategy.getTradingResult(prices, false, false);
+        System.out.println("市场方向: " + result.getDirection());
+        System.out.println("交易信号: " + result.getSignal());
+        System.out.println("\n指标状态详情:");
+        System.out.println(result.getIndicatorStatus());
+    }
+
+    /**
+     * 生成模拟的15分钟价格数据(100个数据点)
+     * 用户可以替换为真实的价格数据
+     * @return 15分钟价格数据列表
+     */
+    private static List<BigDecimal> generateSampleFifteenMinuteData() {
+        List<BigDecimal> prices = new ArrayList<>();
+        
+        // 模拟ETH价格数据(从2400开始,有一定波动)
+        BigDecimal basePrice = new BigDecimal(2400);
+        
+        for (int i = 0; i < 100; i++) {
+            // 添加一些随机波动,但保持整体上升趋势
+            double random = (Math.random() - 0.48) * 10; // -5 到 5 的随机波动,略微偏向上行
+            BigDecimal price = basePrice.add(new BigDecimal(random));
+            prices.add(price.setScale(2, BigDecimal.ROUND_HALF_UP));
+            
+            // 整体缓慢上升
+            basePrice = basePrice.add(new BigDecimal(0.2));
+        }
+        
+        return prices;
+    }
+}
\ No newline at end of file
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingExample.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingExample.java
new file mode 100644
index 0000000..d98eccf
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingExample.java
@@ -0,0 +1,214 @@
+package com.xcong.excoin.modules.okxNewPrice.indicator;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * 15分钟交易策略示例
+ * 演示如何使用交易策略与15分钟时间框架数据
+ * 展示如何获取方向信号和交易信号
+ */
+public class FifteenMinuteTradingExample {
+
+    public static void main(String[] args) {
+        // 创建交易策略
+        TradingStrategy tradingStrategy = new TradingStrategy();
+
+        // 生成100个15分钟价格数据点
+        List<BigDecimal> prices = generateSampleFifteenMinuteData(100);
+        
+        // 生成对应的高、低、收盘价数据
+        List<BigDecimal> high = generateHighPrices(prices);
+        List<BigDecimal> low = generateLowPrices(prices);
+        List<BigDecimal> close = new ArrayList<>(prices); // 使用价格作为收盘价
+        
+        // 生成成交量数据
+        List<BigDecimal> volume = generateVolumeData(prices.size());
+
+        // 获取最新价格
+        BigDecimal currentPrice = prices.get(prices.size() - 1);
+        
+        // 生成多周期价格数据(5分钟、1小时、4小时)
+        List<BigDecimal> fiveMinPrices = generateSampleFifteenMinuteData(100);
+        List<BigDecimal> oneHourPrices = generateSampleFifteenMinuteData(100);
+        List<BigDecimal> fourHourPrices = generateSampleFifteenMinuteData(100);
+        
+        // 其他参数
+        BigDecimal fundingRate = new BigDecimal("0.001"); // 正常资金费率
+        boolean hasLargeTransfer = false; // 无大额转账
+        boolean hasUpcomingEvent = false; // 无即将到来的重大事件
+
+        // 确定市场方向
+        TradingStrategy.Direction direction = tradingStrategy.getDirection(prices, high, low, close, currentPrice);
+        System.out.println("市场方向(15分钟): " + direction);
+
+        // 检查当前持仓状态
+        boolean hasLongPosition = false;  // 示例:无当前做多持仓
+        boolean hasShortPosition = false; // 示例:无当前做空持仓
+
+        // 生成交易信号(开仓/平仓)
+        TradingStrategy.SignalType signal = tradingStrategy.generateSignal(prices, high, low, close, volume, currentPrice, 
+                                                                          hasLongPosition, hasShortPosition, 
+                                                                          fiveMinPrices, oneHourPrices, fourHourPrices,
+                                                                          fundingRate, hasLargeTransfer, hasUpcomingEvent);
+        System.out.println("交易信号(15分钟): " + signal);
+
+        // 显示指标状态用于分析
+        System.out.println("\n指标状态:");
+        System.out.println(tradingStrategy.getIndicatorStatus());
+
+        // 计算动态杠杆
+        BigDecimal dynamicLeverage = tradingStrategy.calculateDynamicLeverage(high, low, close);
+        System.out.println("\n动态杠杆倍数: " + dynamicLeverage);
+
+        // 基于信号模拟持仓变化
+        if (signal == TradingStrategy.SignalType.BUY) {
+            System.out.println("\n=== 执行开多操作 ===");
+            hasLongPosition = true;
+            
+            // 演示三段式止盈策略
+            BigDecimal entryPrice = currentPrice;
+            BigDecimal positionSize = new BigDecimal(100);
+            TradingStrategy.ProfitTakingResult profitTakingResult = 
+                tradingStrategy.calculateThreeStepProfitTaking(entryPrice, currentPrice, direction, positionSize);
+            System.out.println("三段式止盈信号: " + profitTakingResult.getSignal());
+            System.out.println("应平仓仓位大小: " + profitTakingResult.getClosePositionSize());
+        } else if (signal == TradingStrategy.SignalType.SELL) {
+            System.out.println("\n=== 执行开空操作 ===");
+            hasShortPosition = true;
+            
+            // 演示三段式止盈策略
+            BigDecimal entryPrice = currentPrice;
+            BigDecimal positionSize = new BigDecimal(100);
+            TradingStrategy.ProfitTakingResult profitTakingResult = 
+                tradingStrategy.calculateThreeStepProfitTaking(entryPrice, currentPrice, direction, positionSize);
+            System.out.println("三段式止盈信号: " + profitTakingResult.getSignal());
+            System.out.println("应平仓仓位大小: " + profitTakingResult.getClosePositionSize());
+        } else if (signal == TradingStrategy.SignalType.CLOSE_BUY) {
+            System.out.println("\n=== 执行平多操作 ===");
+            hasLongPosition = false;
+        } else if (signal == TradingStrategy.SignalType.CLOSE_SELL) {
+            System.out.println("\n=== 执行平空操作 ===");
+            hasShortPosition = false;
+        } else {
+            System.out.println("\n无需交易操作。");
+        }
+
+        // 现有做多持仓的模拟示例
+        System.out.println("\n=== 现有做多持仓的模拟 ===");
+        hasLongPosition = true;
+        hasShortPosition = false;
+        signal = tradingStrategy.generateSignal(prices, high, low, close, volume, currentPrice, 
+                                               hasLongPosition, hasShortPosition, 
+                                               fiveMinPrices, oneHourPrices, fourHourPrices,
+                                               fundingRate, hasLargeTransfer, hasUpcomingEvent);
+        System.out.println("有做多持仓时的交易信号: " + signal);
+
+        // 现有做空持仓的模拟示例
+        System.out.println("\n=== 现有做空持仓的模拟 ===");
+        hasLongPosition = false;
+        hasShortPosition = true;
+        signal = tradingStrategy.generateSignal(prices, high, low, close, volume, currentPrice, 
+                                               hasLongPosition, hasShortPosition, 
+                                               fiveMinPrices, oneHourPrices, fourHourPrices,
+                                               fundingRate, hasLargeTransfer, hasUpcomingEvent);
+        System.out.println("有做空持仓时的交易信号: " + signal);
+        
+        // 模拟盈利场景演示三段式止盈
+        System.out.println("\n=== 三段式止盈盈利场景演示 ===");
+        BigDecimal entryPrice = new BigDecimal(2500.0);
+        BigDecimal currentPriceProfit = new BigDecimal(2700.0); // 模拟盈利价格
+        BigDecimal positionSize = new BigDecimal(100);
+        TradingStrategy.ProfitTakingResult profitTakingResult = 
+            tradingStrategy.calculateThreeStepProfitTaking(entryPrice, currentPriceProfit, TradingStrategy.Direction.LONG, positionSize);
+        System.out.println("入场价格: " + entryPrice);
+        System.out.println("当前价格: " + currentPriceProfit);
+        System.out.println("三段式止盈信号: " + profitTakingResult.getSignal());
+        System.out.println("应平仓仓位大小: " + profitTakingResult.getClosePositionSize());
+    }
+
+    /**
+     * 生成具有真实波动的15分钟价格数据
+     * @param size 要生成的数据点数量
+     * @return 价格数据列表
+     */
+    private static List<BigDecimal> generateSampleFifteenMinuteData(int size) {
+        List<BigDecimal> prices = new ArrayList<>();
+        Random random = new Random();
+
+        // 以基础价格开始(ETH示例价格)
+        BigDecimal basePrice = new BigDecimal(2500.0);
+        prices.add(basePrice);
+
+        // 生成具有真实波动的后续价格
+        for (int i = 1; i < size; i++) {
+            // 创建价格趋势(轻微上升偏向)
+            BigDecimal trend = new BigDecimal(0.1).multiply(new BigDecimal(i));
+            // 添加随机波动(每个周期±2%)
+            BigDecimal volatility = new BigDecimal(random.nextDouble() * 0.04 - 0.02);
+            // 计算新价格
+            BigDecimal newPrice = basePrice.add(trend).multiply(BigDecimal.ONE.add(volatility));
+            // 四舍五入到2位小数
+            newPrice = newPrice.setScale(2, BigDecimal.ROUND_HALF_UP);
+            prices.add(newPrice);
+        }
+
+        return prices;
+    }
+    
+    /**
+     * 生成最高价数据
+     * @param prices 价格数据
+     * @return 最高价数据列表
+     */
+    private static List<BigDecimal> generateHighPrices(List<BigDecimal> prices) {
+        List<BigDecimal> high = new ArrayList<>();
+        Random random = new Random();
+        
+        for (BigDecimal price : prices) {
+            // 最高价比当前价格高0-2%
+            BigDecimal highPrice = price.multiply(BigDecimal.ONE.add(new BigDecimal(random.nextDouble() * 0.02)));
+            high.add(highPrice.setScale(2, BigDecimal.ROUND_HALF_UP));
+        }
+        
+        return high;
+    }
+    
+    /**
+     * 生成最低价数据
+     * @param prices 价格数据
+     * @return 最低价数据列表
+     */
+    private static List<BigDecimal> generateLowPrices(List<BigDecimal> prices) {
+        List<BigDecimal> low = new ArrayList<>();
+        Random random = new Random();
+        
+        for (BigDecimal price : prices) {
+            // 最低价比当前价格低0-2%
+            BigDecimal lowPrice = price.multiply(BigDecimal.ONE.subtract(new BigDecimal(random.nextDouble() * 0.02)));
+            low.add(lowPrice.setScale(2, BigDecimal.ROUND_HALF_UP));
+        }
+        
+        return low;
+    }
+    
+    /**
+     * 生成成交量数据
+     * @param size 数据点数量
+     * @return 成交量数据列表
+     */
+    private static List<BigDecimal> generateVolumeData(int size) {
+        List<BigDecimal> volume = new ArrayList<>();
+        Random random = new Random();
+        
+        for (int i = 0; i < size; i++) {
+            // 生成1000-10000之间的随机成交量
+            BigDecimal vol = new BigDecimal(random.nextInt(9001) + 1000);
+            volume.add(vol);
+        }
+        
+        return volume;
+    }
+}
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingStrategy.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingStrategy.java
new file mode 100644
index 0000000..6510022
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/FifteenMinuteTradingStrategy.java
@@ -0,0 +1,237 @@
+package com.xcong.excoin.modules.okxNewPrice.indicator;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 15分钟时间粒度的交易策略实现
+ * 专门针对100个15分钟数据点设计的策略,包含明确的多空方向选择和开仓平仓方法
+ */
+@Slf4j
+public class FifteenMinuteTradingStrategy {
+
+    @Getter
+    @Setter
+    public static class TradingResult {
+        private Direction direction;      // 多空方向
+        private PositionSignal signal;    // 开仓平仓信号
+        private String indicatorStatus;   // 指标状态
+        
+        public TradingResult(Direction direction, PositionSignal signal, String indicatorStatus) {
+            this.direction = direction;
+            this.signal = signal;
+            this.indicatorStatus = indicatorStatus;
+        }
+    }
+
+    public enum Direction {
+        LONG,    // 多头方向
+        SHORT,   // 空头方向
+        RANGING  // 震荡行情
+    }
+
+    public enum PositionSignal {
+        OPEN_LONG,    // 开多仓
+        OPEN_SHORT,   // 开空仓
+        CLOSE_LONG,   // 平多仓
+        CLOSE_SHORT,  // 平空仓
+        HOLD,         // 持有
+        STAY_OUT      // 观望
+    }
+
+    private final MA ma;
+    private final AdvancedMA advancedMA;
+    private final BOLL boll;
+    private final KDJ kdj;
+    private final MACD macd;
+    private final RSI rsi;
+
+    public FifteenMinuteTradingStrategy() {
+        // 15分钟数据优化的参数配置
+        this.ma = new MA();
+        this.advancedMA = new AdvancedMA();
+        this.boll = new BOLL(20, 2.0);  // BOLL使用默认20周期
+        this.kdj = new KDJ(9);          // KDJ使用默认9周期
+        this.macd = new MACD();         // MACD使用默认12/26/9周期
+        this.rsi = new RSI(14);         // RSI使用默认14周期
+    }
+
+    /**
+     * 计算所有指标
+     * @param prices 15分钟价格数据(至少100个数据点)
+     */
+    private void calculateIndicators(List<BigDecimal> prices) {
+        ma.calculate(prices);
+        advancedMA.calculateTripleEMA(prices);
+        boll.calculate(prices);
+        kdj.calculate(prices);
+        macd.calculate(prices);
+        rsi.calculate(prices);
+    }
+
+    /**
+     * 判断市场是否处于震荡行情
+     * @return 是否为震荡行情
+     */
+    private boolean isRangeMarket() {
+        // AdvancedMA三线粘合 + RSI(40-60) + BOLL带宽收窄
+        boolean isMaConverged = advancedMA.calculatePercent().compareTo(new BigDecimal(2)) < 0;
+        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(40)) > 0 && 
+                              rsi.getRsi().compareTo(new BigDecimal(60)) < 0;
+        boolean isBollNarrow = boll.calculateBandWidth().compareTo(new BigDecimal(0.05)) < 0;
+
+        return isMaConverged && isRsiNeutral && isBollNarrow;
+    }
+
+    /**
+     * 获取多空方向选择
+     * @param prices 15分钟价格数据(100个数据点)
+     * @return 多空方向
+     */
+    public Direction getDirection(List<BigDecimal> prices) {
+        if (prices == null || prices.size() < 100) {
+            throw new IllegalArgumentException("需要至少100个15分钟价格数据点");
+        }
+
+        calculateIndicators(prices);
+
+        // 震荡过滤
+        if (isRangeMarket()) {
+            return Direction.RANGING;
+        }
+
+        BigDecimal currentPrice = prices.get(prices.size() - 1);
+
+        // 多头信号判断:MA多头排列 + MACD金叉 + RSI(30-70) + BOLL价格在上轨与中轨之间
+        boolean isLongSignal = 
+            ma.getEma5().compareTo(ma.getEma10()) > 0 &&  // MA5 > MA10
+            ma.getEma10().compareTo(ma.getEma20()) > 0 && // MA10 > MA20
+            macd.getDif().compareTo(macd.getDea()) > 0 && // MACD金叉
+            rsi.getRsi().compareTo(new BigDecimal(30)) > 0 && rsi.getRsi().compareTo(new BigDecimal(70)) < 0 && // RSI(30-70)
+            currentPrice.compareTo(boll.getMid()) > 0 && currentPrice.compareTo(boll.getUpper()) < 0; // BOLL价格在上轨与中轨之间
+
+        // 空头信号判断:MA空头排列 + MACD死叉 + RSI(30-70) + BOLL价格在下轨与中轨之间
+        boolean isShortSignal = 
+            ma.getEma5().compareTo(ma.getEma10()) < 0 &&  // MA5 < MA10
+            ma.getEma10().compareTo(ma.getEma20()) < 0 && // MA10 < MA20
+            macd.getDif().compareTo(macd.getDea()) < 0 && // MACD死叉
+            rsi.getRsi().compareTo(new BigDecimal(30)) > 0 && rsi.getRsi().compareTo(new BigDecimal(70)) < 0 && // RSI(30-70)
+            currentPrice.compareTo(boll.getMid()) < 0 && currentPrice.compareTo(boll.getLower()) > 0; // BOLL价格在下轨与中轨之间
+
+        if (isLongSignal) {
+            return Direction.LONG;
+        } else if (isShortSignal) {
+            return Direction.SHORT;
+        } else {
+            return Direction.RANGING;
+        }
+    }
+
+    /**
+     * 获取开仓平仓策略信号
+     * @param prices 15分钟价格数据(100个数据点)
+     * @param hasLongPosition 当前是否持有多仓
+     * @param hasShortPosition 当前是否持有空仓
+     * @return 开仓平仓信号
+     */
+    public PositionSignal getPositionSignal(List<BigDecimal> prices, boolean hasLongPosition, boolean hasShortPosition) {
+        if (prices == null || prices.size() < 100) {
+            throw new IllegalArgumentException("需要至少100个15分钟价格数据点");
+        }
+
+        calculateIndicators(prices);
+
+        // 震荡过滤
+        if (isRangeMarket()) {
+            return PositionSignal.STAY_OUT;
+        }
+
+        BigDecimal currentPrice = prices.get(prices.size() - 1);
+
+        // 开多信号:MA金叉 + MACD金叉 + KDJ金叉 + RSI中性 + 价格在BOLL中轨上方
+        boolean shouldOpenLong = 
+            ma.getEma5().compareTo(ma.getEma20()) > 0 &&  // MA金叉(5日EMA上穿20日EMA)
+            macd.getDif().compareTo(macd.getDea()) > 0 && macd.getMacdBar().compareTo(BigDecimal.ZERO) > 0 && // MACD金叉且柱状图为正
+            kdj.isGoldenCross() && // KDJ金叉
+            rsi.getRsi().compareTo(new BigDecimal(30)) > 0 && rsi.getRsi().compareTo(new BigDecimal(70)) < 0 && // RSI中性
+            currentPrice.compareTo(boll.getMid()) > 0; // 价格在BOLL中轨上方
+
+        // 开空信号:MA死叉 + MACD死叉 + KDJ死叉 + RSI中性 + 价格在BOLL中轨下方
+        boolean shouldOpenShort = 
+            ma.getEma5().compareTo(ma.getEma20()) < 0 &&  // MA死叉(5日EMA下穿20日EMA)
+            macd.getDif().compareTo(macd.getDea()) < 0 && macd.getMacdBar().compareTo(BigDecimal.ZERO) < 0 && // MACD死叉且柱状图为负
+            kdj.isDeathCross() && // KDJ死叉
+            rsi.getRsi().compareTo(new BigDecimal(30)) > 0 && rsi.getRsi().compareTo(new BigDecimal(70)) < 0 && // RSI中性
+            currentPrice.compareTo(boll.getMid()) < 0; // 价格在BOLL中轨下方
+
+        // 平多信号:MA死叉 + MACD死叉 + RSI超买 + 价格跌破BOLL中轨
+        boolean shouldCloseLong = 
+            (ma.getEma5().compareTo(ma.getEma20()) < 0 && // MA死叉
+            macd.getDif().compareTo(macd.getDea()) < 0 && // MACD死叉
+            (rsi.isOverbought() || rsi.isExtremelyOverbought())) || // RSI超买
+            currentPrice.compareTo(boll.getMid()) < 0; // 价格跌破BOLL中轨
+
+        // 平空信号:MA金叉 + MACD金叉 + RSI超卖 + 价格突破BOLL中轨
+        boolean shouldCloseShort = 
+            (ma.getEma5().compareTo(ma.getEma20()) > 0 && // MA金叉
+            macd.getDif().compareTo(macd.getDea()) > 0 && // MACD金叉
+            (rsi.isOversold() || rsi.isExtremelyOversold())) || // RSI超卖
+            currentPrice.compareTo(boll.getMid()) > 0; // 价格突破BOLL中轨
+
+        // 确定开仓信号
+        if (shouldOpenLong && !hasLongPosition && !hasShortPosition) {
+            return PositionSignal.OPEN_LONG;
+        } else if (shouldOpenShort && !hasLongPosition && !hasShortPosition) {
+            return PositionSignal.OPEN_SHORT;
+        }
+
+        // 确定平仓信号
+        if (shouldCloseLong && hasLongPosition) {
+            return PositionSignal.CLOSE_LONG;
+        } else if (shouldCloseShort && hasShortPosition) {
+            return PositionSignal.CLOSE_SHORT;
+        }
+
+        // 无信号
+        return hasLongPosition || hasShortPosition ? PositionSignal.HOLD : PositionSignal.STAY_OUT;
+    }
+
+    /**
+     * 综合获取交易结果
+     * @param prices 15分钟价格数据(100个数据点)
+     * @param hasLongPosition 当前是否持有多仓
+     * @param hasShortPosition 当前是否持有空仓
+     * @return 包含多空方向和开仓平仓信号的完整交易结果
+     */
+    public TradingResult getTradingResult(List<BigDecimal> prices, boolean hasLongPosition, boolean hasShortPosition) {
+        Direction direction = getDirection(prices);
+        PositionSignal signal = getPositionSignal(prices, hasLongPosition, hasShortPosition);
+        String indicatorStatus = getIndicatorStatus();
+        
+        return new TradingResult(direction, signal, indicatorStatus);
+    }
+
+    /**
+     * 获取当前指标状态
+     * @return 指标状态字符串
+     */
+    private String getIndicatorStatus() {
+        return String.format("MA5: %s, MA20: %s, " +
+                        "MACD-DIF: %s, MACD-DEA: %s, MACD-BAR: %s, " +
+                        "KDJ-K: %s, KDJ-D: %s, KDJ-J: %s, " +
+                        "RSI: %s, " +
+                        "BOLL-UP: %s, BOLL-MID: %s, BOLL-DN: %s, " +
+                        "AdvancedMA-Bullish: %s, Bearish: %s, Percent: %s",
+                ma.getEma5(), ma.getEma20(),
+                macd.getDif(), macd.getDea(), macd.getMacdBar(),
+                kdj.getK(), kdj.getD(), kdj.getJ(),
+                rsi.getRsi(),
+                boll.getUpper(), boll.getMid(), boll.getLower(),
+                advancedMA.isBullish(), advancedMA.isBearish(), advancedMA.calculatePercent());
+    }
+
+}
\ No newline at end of file
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/IndicatorBase.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/IndicatorBase.java
index 6872bfd..055e3fc 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/IndicatorBase.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/IndicatorBase.java
@@ -7,6 +7,22 @@
 
 /**
  * 技术指标基础类,提供通用计算方法
+ * 
+ * 指标组合策略:
+ * 1. 趋势判断(MA/AdvancedMA/MACD):判断价格的整体走势方向
+ * 2. 动量确认(RSI/KDJ):确认当前趋势的强度和可持续性
+ * 3. 波动参考(BOLL):确定价格的合理波动范围和突破时机
+ * 
+ * 多空方向选择逻辑:
+ * - 多头信号:MA多头排列 + MACD金叉 + RSI(30-70) + BOLL价格在上轨与中轨之间
+ * - 空头信号:MA空头排列 + MACD死叉 + RSI(30-70) + BOLL价格在下轨与中轨之间
+ * - 震荡信号:AdvancedMA三线粘合 + RSI(40-60) + BOLL带宽收窄
+ * 
+ * 开仓和平仓策略:
+ * - 开多:MA金叉 + MACD金叉 + KDJ金叉 + RSI(30-70) + 价格突破BOLL中轨
+ * - 开空:MA死叉 + MACD死叉 + KDJ死叉 + RSI(30-70) + 价格跌破BOLL中轨
+ * - 平多:MA死叉 + MACD死叉 + RSI超买(>70) + 价格跌破BOLL中轨
+ * - 平空:MA金叉 + MACD金叉 + RSI超卖(<30) + 价格突破BOLL中轨
  */
 public abstract class IndicatorBase {
 
@@ -91,4 +107,55 @@
         int startIndex = Math.max(0, prices.size() - period);
         return prices.subList(startIndex, prices.size());
     }
+
+    /**
+     * 计算ATR(Average True Range)
+     * @param high 最高价列表
+     * @param low 最低价列表
+     * @param close 收盘价列表
+     * @param period 周期
+     * @return ATR值
+     */
+    protected BigDecimal calculateATR(List<BigDecimal> high, List<BigDecimal> low, List<BigDecimal> close, int period) {
+        if (high == null || low == null || close == null || 
+            high.size() < period || low.size() < period || close.size() < period) {
+            return BigDecimal.ZERO;
+        }
+
+        List<BigDecimal> trList = new ArrayList<>();
+        for (int i = 1; i < high.size(); i++) {
+            BigDecimal trueRange = calculateTrueRange(high.get(i), low.get(i), close.get(i - 1));
+            trList.add(trueRange);
+        }
+
+        // 使用简单移动平均计算ATR
+        return calculateMA(trList, Math.min(period, trList.size()));
+    }
+
+    /**
+     * 计算真实波幅(True Range)
+     * @param high 当前最高价
+     * @param low 当前最低价
+     * @param prevClose 前收盘价
+     * @return 真实波幅
+     */
+    protected BigDecimal calculateTrueRange(BigDecimal high, BigDecimal low, BigDecimal prevClose) {
+        BigDecimal h1 = high.subtract(low);
+        BigDecimal h2 = high.subtract(prevClose).abs();
+        BigDecimal h3 = low.subtract(prevClose).abs();
+        return h1.max(h2).max(h3);
+    }
+
+    /**
+     * 计算标准化波动率(基于ATR)
+     * @param close 收盘价列表
+     * @param atr ATR值
+     * @return 标准化波动率(百分比)
+     */
+    protected BigDecimal normalizeVolatility(List<BigDecimal> close, BigDecimal atr) {
+        if (close == null || close.size() == 0 || atr.compareTo(BigDecimal.ZERO) == 0) {
+            return BigDecimal.ZERO;
+        }
+        return atr.divide(close.get(close.size() - 1), 4, RoundingMode.HALF_UP).multiply(new BigDecimal(100));
+    }
 }
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java
index 6651871..142cdd5 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/KDJ.java
@@ -15,6 +15,31 @@
  * 2. K = 2/3 * 前一日K值 + 1/3 * 当日RSV
  * 3. D = 2/3 * 前一日D值 + 1/3 * 当日K值
  * 4. J = 3*K - 2*D
+ * 
+ * 作用:
+ * 1. 衡量价格的超买超卖状态(K值>80超买,K值<20超卖)
+ * 2. K线上穿D线形成金叉,提示买入信号
+ * 3. K线下穿D线形成死叉,提示卖出信号
+ * 4. J值反映市场的极端状态,J值>100或J值<0为极端行情
+ * 
+ * 价格参数类型:
+ * - 参数名称:prices
+ * - 参数类型:List<BigDecimal>
+ * - 参数说明:需要至少9个(默认周期)价格数据点用于计算
+ * 
+ * 推荐时间粒度及优缺点:
+ * 1. 1分钟(1m):
+ *    - 优点:反应迅速,适合超短线交易
+ *    - 缺点:K值波动剧烈,信号频繁且可靠性低
+ * 2. 5分钟(5m):
+ *    - 优点:K值波动相对稳定,适合短线交易
+ *    - 缺点:仍有一定虚假信号
+ * 3. 15分钟(15m):
+ *    - 优点:信号较为可靠,适合日内交易
+ *    - 缺点:反应速度较慢
+ * 4. 1小时(1h)及以上:
+ *    - 优点:超买超卖信号明确,适合中期交易
+ *    - 缺点:反应滞后,不适合短线交易
  */
 @Slf4j
 @Getter
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..e288c00 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.debug("MA计算结果 - MA5({}): {}, MA10({}): {}, MA20({}): {}, MA30({}): {}, MA60({}): {}", 
+                ma5Period, ma5, ma10Period, ma10, ma20Period, ma20, ma30Period, ma30, ma60Period, ma60);
+        log.debug("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.debug("根据波动率{}调整MA周期: ma5={}, ma10={}, ma20={}, ma30={}, ma60={}", 
+                volatility, ma5Period, ma10Period, ma20Period, ma30Period, ma60Period);
     }
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
index 92c91b9..c2f869f 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/MACD.java
@@ -15,15 +15,47 @@
  * 1. DIF = EMA(12) - EMA(26)
  * 2. DEA = EMA(DIF, 9)
  * 3. MACD柱状图 = (DIF - DEA) * 2
+ * 
+ * 作用:
+ * 1. 识别趋势方向和动能变化
+ * 2. DIF上穿DEA形成金叉,提示买入信号
+ * 3. DIF下穿DEA形成死叉,提示卖出信号
+ * 4. MACD柱状图由负转正,提示多头力量增强
+ * 5. MACD柱状图由正转负,提示空头力量增强
+ * 
+ * 价格参数类型:
+ * - 参数名称:prices
+ * - 参数类型:List<BigDecimal>
+ * - 参数说明:需要至少2个价格数据点用于计算,数据越多计算越准确
+ * 
+ * 推荐时间粒度及优缺点:
+ * 1. 1分钟(1m):
+ *    - 优点:反应迅速,适合超短线交易
+ *    - 缺点:MACD柱状图波动剧烈,信号频繁
+ * 2. 5分钟(5m):
+ *    - 优点:平衡了反应速度和信号可靠性
+ *    - 缺点:仍有一定噪音
+ * 3. 15分钟(15m):
+ *    - 优点:适合日内交易,信号较为可靠
+ *    - 缺点:反应速度较慢
+ * 4. 1小时(1h)及以上:
+ *    - 优点:趋势信号明确,MACD柱状图变化稳定
+ *    - 缺点:反应滞后,不适合短线交易
  */
 @Slf4j
 @Getter
 @Setter
 public class MACD extends IndicatorBase {
 
-    private static final int FAST_PERIOD = 12;
-    private static final int SLOW_PERIOD = 26;
-    private static final int SIGNAL_PERIOD = 9;
+    // 默认周期参数
+    public static final int DEFAULT_FAST_PERIOD = 12;
+    public static final int DEFAULT_SLOW_PERIOD = 26;
+    public static final int DEFAULT_SIGNAL_PERIOD = 9;
+
+    // 动态周期参数
+    private int fastPeriod;
+    private int slowPeriod;
+    private int signalPeriod;
 
     private BigDecimal dif = BigDecimal.ZERO;
     private BigDecimal dea = BigDecimal.ZERO;
@@ -32,20 +64,41 @@
     private BigDecimal prevSlowEMA = null;
     private BigDecimal prevDea = null;
 
+    // 构造函数使用默认周期
+    public MACD() {
+        this.fastPeriod = DEFAULT_FAST_PERIOD;
+        this.slowPeriod = DEFAULT_SLOW_PERIOD;
+        this.signalPeriod = DEFAULT_SIGNAL_PERIOD;
+    }
+
     /**
-     * 计算MACD指标
+     * 计算MACD指标(使用当前周期设置)
      * @param prices 价格列表
      */
     public void calculate(List<BigDecimal> prices) {
+        calculate(prices, null);
+    }
+
+    /**
+     * 计算MACD指标,并支持动态周期调整
+     * @param prices 价格列表
+     * @param volatility 标准化波动率(百分比),用于动态调整周期
+     */
+    public void calculate(List<BigDecimal> prices, BigDecimal volatility) {
         if (prices == null || prices.size() < 2) {
             return;
         }
 
+        // 如果提供了波动率,则动态调整周期
+        if (volatility != null) {
+            adjustPeriodsByVolatility(volatility);
+        }
+
         // 计算快速EMA
-        prevFastEMA = calculateEMA(prices, FAST_PERIOD, prevFastEMA);
+        prevFastEMA = calculateEMA(prices, fastPeriod, prevFastEMA);
         
         // 计算慢速EMA
-        prevSlowEMA = calculateEMA(prices, SLOW_PERIOD, prevSlowEMA);
+        prevSlowEMA = calculateEMA(prices, slowPeriod, prevSlowEMA);
         
         // 计算DIF
         dif = prevFastEMA.subtract(prevSlowEMA).setScale(8, RoundingMode.HALF_UP);
@@ -53,13 +106,39 @@
         // 计算DEA
         List<BigDecimal> difList = new ArrayList<>();
         difList.add(dif);
-        prevDea = calculateEMA(difList, SIGNAL_PERIOD, prevDea);
+        prevDea = calculateEMA(difList, signalPeriod, prevDea);
         dea = prevDea.setScale(8, RoundingMode.HALF_UP);
         
         // 计算MACD柱状图
         macdBar = dif.subtract(dea).multiply(new BigDecimal(2)).setScale(8, RoundingMode.HALF_UP);
         
-        log.debug("MACD计算结果 - DIF: {}, DEA: {}, MACD柱状图: {}", dif, dea, macdBar);
+        log.debug("MACD计算结果 - DIF: {}, DEA: {}, MACD柱状图: {}, 参数: fast={}, slow={}, signal={}", 
+                dif, dea, macdBar, fastPeriod, slowPeriod, signalPeriod);
+    }
+
+    /**
+     * 根据波动率调整MACD周期参数
+     * @param volatility 标准化波动率(百分比)
+     */
+    private void adjustPeriodsByVolatility(BigDecimal volatility) {
+        // 波动率阈值
+        BigDecimal volatilityThreshold = new BigDecimal(15);
+
+        // 根据波动率调整MACD参数
+        if (volatility.compareTo(volatilityThreshold) < 0) {
+            // 低波动率环境,使用默认参数
+            fastPeriod = DEFAULT_FAST_PERIOD;
+            slowPeriod = DEFAULT_SLOW_PERIOD;
+            signalPeriod = DEFAULT_SIGNAL_PERIOD;
+        } else {
+            // 高波动率环境,使用更灵敏的参数
+            fastPeriod = 8;
+            slowPeriod = 17;
+            signalPeriod = 5;
+        }
+
+        log.debug("根据波动率{}调整MACD周期: fast={}, slow={}, signal={}", 
+                volatility, fastPeriod, slowPeriod, signalPeriod);
     }
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java
index b289d1c..7bbb32b 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/RSI.java
@@ -14,6 +14,32 @@
  * 1. 计算N天内的上涨幅度和下跌幅度
  * 2. 计算平均上涨幅度和平均下跌幅度
  * 3. RSI = 100 - (100 / (1 + (平均上涨幅度 / 平均下跌幅度)))
+ * 
+ * 作用:
+ * 1. 衡量市场的相对强弱程度(0-100)
+ * 2. 超买信号:RSI>70表示市场超买,可能回调
+ * 3. 超卖信号:RSI<30表示市场超卖,可能反弹
+ * 4. 极端超买:RSI>80表示市场极度超买
+ * 5. 极端超卖:RSI<20表示市场极度超卖
+ * 
+ * 价格参数类型:
+ * - 参数名称:prices
+ * - 参数类型:List<BigDecimal>
+ * - 参数说明:需要至少15个(默认周期+1)价格数据点用于计算
+ * 
+ * 推荐时间粒度及优缺点:
+ * 1. 1分钟(1m):
+ *    - 优点:反应迅速,适合超短线交易
+ *    - 缺点:RSI波动剧烈,频繁进入超买超卖区域
+ * 2. 5分钟(5m):
+ *    - 优点:RSI波动相对稳定,适合短线交易
+ *    - 缺点:仍有一定虚假超买超卖信号
+ * 3. 15分钟(15m):
+ *    - 优点:超买超卖信号较为可靠,适合日内交易
+ *    - 缺点:反应速度较慢
+ * 4. 1小时(1h)及以上:
+ *    - 优点:超买超卖信号明确,适合中期交易
+ *    - 缺点:反应滞后,不适合短线交易
  */
 @Slf4j
 @Getter
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java
new file mode 100644
index 0000000..0605d0f
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/indicator/TradingStrategy.java
@@ -0,0 +1,738 @@
+package com.xcong.excoin.modules.okxNewPrice.indicator;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 交易策略实现
+ * 展示如何为ETH合约交易(开仓/平仓)组合所有指标
+ */
+@Slf4j
+public class TradingStrategy extends IndicatorBase {
+
+    @Getter
+    @Setter
+    @AllArgsConstructor
+    @NoArgsConstructor
+    public static class StrategyConfig {
+        private int maShortPeriod = 5;      // 短期移动平均周期
+        private int maLongPeriod = 20;      // 长期移动平均周期
+        private int rsiPeriod = 14;         // RSI指标周期
+        private int kdjPeriod = 9;          // KDJ指标周期
+        private int bollPeriod = 20;        // 布林带周期
+        private double bollK = 2.0;         // 布林带标准差倍数
+        private int atrPeriod = 14;         // ATR计算周期
+        private boolean enableDynamicParams = true; // 是否启用动态参数优化
+        private boolean enableMultiTimeframeConfirm = true; // 是否启用多周期确认
+        private int volumeMaPeriod = 20;    // 成交量移动平均周期
+        private boolean enableVolumeConfirm = true; // 是否启用成交量验证
+        
+        // 风险控制参数
+        private BigDecimal baseLeverage = new BigDecimal(3); // 基础杠杆倍数
+        private int volatilityThresholdPeriod = 30; // 波动率阈值计算周期(用于动态杠杆)
+        private boolean enableDynamicLeverage = true; // 是否启用动态杠杆
+        private boolean enableThreeStepProfitTaking = true; // 是否启用三段式止盈
+        private boolean enableBlackSwanFilter = true; // 是否启用黑天鹅事件过滤
+    }
+
+    public enum Direction {
+        LONG,      // 做多方向信号
+        SHORT,     // 做空方向信号
+        RANGING    // 震荡市场
+    }
+
+    public enum SignalType {
+        NONE,      // 无信号
+        BUY,       // 开多信号
+        SELL,      // 开空信号
+        CLOSE_BUY, // 平多信号
+        CLOSE_SELL // 平空信号
+    }
+
+    private final StrategyConfig config;
+    private final MA ma;
+    private final AdvancedMA advancedMA;
+    private final BOLL boll;
+    private final KDJ kdj;
+    private final MACD macd;
+    private final RSI rsi;
+
+    public TradingStrategy() {
+        this(new StrategyConfig());
+    }
+
+    public TradingStrategy(StrategyConfig config) {
+        this.config = config;
+        this.ma = new MA();
+        this.advancedMA = new AdvancedMA();
+        this.boll = new BOLL(config.getBollPeriod(), config.getBollK());
+        this.kdj = new KDJ(config.getKdjPeriod());
+        this.macd = new MACD();
+        this.rsi = new RSI(config.getRsiPeriod());
+    }
+
+    /**
+     * 计算所有指标并生成交易信号
+     * @param prices 价格数据
+     * @param high 最高价列表
+     * @param low 最低价列表
+     * @param close 收盘价列表
+     * @param volume 成交量列表
+     * @param currentPrice 当前价格
+     * @param hasLongPosition 是否当前持有做多仓位
+     * @param hasShortPosition 是否当前持有做空仓位
+     * @param fiveMinPrices 5分钟价格数据(多周期确认)
+     * @param oneHourPrices 1小时价格数据(多周期确认)
+     * @param fourHourPrices 4小时价格数据(多周期确认)
+     * @param fundingRate 当前资金费率(用于黑天鹅过滤)
+     * @param hasLargeTransfer 是否有大额转账(用于黑天鹅过滤)
+     * @param hasUpcomingEvent 是否有即将到来的重大事件(用于黑天鹅过滤)
+     * @return 交易信号
+     */
+    public SignalType generateSignal(List<BigDecimal> prices, List<BigDecimal> high,
+                                    List<BigDecimal> low, List<BigDecimal> close,
+                                    List<BigDecimal> volume, BigDecimal currentPrice,
+                                    boolean hasLongPosition, boolean hasShortPosition,
+                                    List<BigDecimal> fiveMinPrices,
+                                    List<BigDecimal> oneHourPrices,
+                                    List<BigDecimal> fourHourPrices,
+                                    BigDecimal fundingRate,
+                                    boolean hasLargeTransfer,
+                                    boolean hasUpcomingEvent) {
+        // 计算所有指标
+        calculateIndicators(prices, high, low, close);
+
+        // 检查是否为震荡市场,如果是,则无信号
+        if (isRangeMarket()) {
+            log.debug("当前市场为震荡行情,不产生信号");
+            return SignalType.NONE;
+        }
+
+        // 黑天鹅事件过滤
+        if (blackSwanFilter(fundingRate, hasLargeTransfer, hasUpcomingEvent)) {
+            log.debug("黑天鹅事件过滤触发,不产生信号");
+            return SignalType.NONE;
+        }
+
+        // 开多信号
+        if (shouldOpenLong(currentPrice, prices, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && !hasLongPosition && !hasShortPosition) {
+            log.debug("生成买入信号");
+            return SignalType.BUY;
+        }
+
+        // 开空信号
+        if (shouldOpenShort(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && !hasLongPosition && !hasShortPosition) {
+            log.debug("生成卖出信号");
+            return SignalType.SELL;
+        }
+
+        // 平多信号
+        if (shouldCloseLong(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && hasLongPosition) {
+            log.debug("生成平多信号");
+            return SignalType.CLOSE_BUY;
+        }
+
+        // 平空信号
+        if (shouldCloseShort(currentPrice, volume, fiveMinPrices, oneHourPrices, fourHourPrices) && hasShortPosition) {
+            log.debug("生成平空信号");
+            return SignalType.CLOSE_SELL;
+        }
+
+        log.debug("未生成信号");
+        return SignalType.NONE;
+    }
+
+    /**
+     * 多周期确认辅助方法(看涨)
+     * @param fiveMinPrices 5分钟价格数据
+     * @param oneHourPrices 1小时价格数据
+     * @param fourHourPrices 4小时价格数据
+     * @return 是否有足够的多周期确认
+     */
+    private boolean multiTimeframeConfirm(List<BigDecimal> fiveMinPrices,
+                                         List<BigDecimal> oneHourPrices,
+                                         List<BigDecimal> fourHourPrices) {
+        if (!config.isEnableMultiTimeframeConfirm()) {
+            return true; // 如果未启用多周期确认,则默认返回true
+        }
+
+        int confirmCount = 0;
+
+        // 检查5分钟周期
+        if (hasBullishTrend(fiveMinPrices)) {
+            confirmCount++;
+        }
+
+        // 检查1小时周期
+        if (hasBullishTrend(oneHourPrices)) {
+            confirmCount++;
+        }
+
+        // 检查4小时周期
+        if (hasBullishTrend(fourHourPrices)) {
+            confirmCount++;
+        }
+
+        // 至少需要2个周期确认
+        return confirmCount >= 2;
+    }
+    
+    /**
+     * 多周期确认辅助方法(看跌)
+     * @param fiveMinPrices 5分钟价格数据
+     * @param oneHourPrices 1小时价格数据
+     * @param fourHourPrices 4小时价格数据
+     * @return 是否有足够的多周期确认
+     */
+    private boolean multiTimeframeBearishConfirm(List<BigDecimal> fiveMinPrices,
+                                         List<BigDecimal> oneHourPrices,
+                                         List<BigDecimal> fourHourPrices) {
+        if (!config.isEnableMultiTimeframeConfirm()) {
+            return true; // 如果未启用多周期确认,则默认返回true
+        }
+
+        int confirmCount = 0;
+
+        // 检查5分钟周期
+        if (hasBearishTrend(fiveMinPrices)) {
+            confirmCount++;
+        }
+
+        // 检查1小时周期
+        if (hasBearishTrend(oneHourPrices)) {
+            confirmCount++;
+        }
+
+        // 检查4小时周期
+        if (hasBearishTrend(fourHourPrices)) {
+            confirmCount++;
+        }
+
+        // 至少需要2个周期确认
+        return confirmCount >= 2;
+    }
+
+    /**
+     * 检查指定周期是否有看涨趋势
+     * @param prices 价格数据
+     * @return 是否有看涨趋势
+     */
+    private boolean hasBullishTrend(List<BigDecimal> prices) {
+        if (prices == null || prices.size() < 20) {
+            return false; // 数据不足
+        }
+
+        // 创建临时MA指标用于判断趋势
+        MA tempMA = new MA();
+        tempMA.calculate(prices);
+
+        // 简单的趋势判断:短期MA > 长期MA
+        return tempMA.getEma5().compareTo(tempMA.getEma20()) > 0;
+    }
+
+    /**
+     * 检查指定周期是否有看跌趋势
+     * @param prices 价格数据
+     * @return 是否有看跌趋势
+     */
+    private boolean hasBearishTrend(List<BigDecimal> prices) {
+        if (prices == null || prices.size() < 20) {
+            return false; // 数据不足
+        }
+
+        // 创建临时MA指标用于判断趋势
+        MA tempMA = new MA();
+        tempMA.calculate(prices);
+
+        // 简单的趋势判断:短期MA < 长期MA
+        return tempMA.getEma5().compareTo(tempMA.getEma20()) < 0;
+    }
+
+    /**
+     * 成交量验证辅助方法
+     * @param volume 成交量列表
+     * @return 是否通过成交量验证
+     */
+    private boolean volumeConfirm(List<BigDecimal> volume) {
+        if (!config.isEnableVolumeConfirm() || volume == null || volume.size() < config.getVolumeMaPeriod()) {
+            return true; // 如果未启用成交量验证或数据不足,则默认返回true
+        }
+
+        // 计算成交量移动平均
+        BigDecimal volumeMA = calculateMA(volume, config.getVolumeMaPeriod());
+        BigDecimal currentVolume = volume.get(volume.size() - 1);
+
+        // 成交量需要大于均线
+        return currentVolume.compareTo(volumeMA) > 0;
+    }
+
+    /**
+     * 量价背离检测
+     * 检测价格上涨/下跌但成交量萎缩的情况,或价格和成交量趋势不一致
+     * @param prices 价格列表
+     * @param volume 成交量列表
+     * @return 是否存在量价背离
+     */
+    private boolean hasPriceVolumeDivergence(List<BigDecimal> prices, List<BigDecimal> volume) {
+        if (!config.isEnableVolumeConfirm() || prices == null || volume == null || prices.size() < 3 || volume.size() < 3) {
+            return false; // 如果未启用成交量验证或数据不足,则默认返回false
+        }
+
+        // 获取最近3个周期的价格和成交量
+        BigDecimal currentPrice = prices.get(prices.size() - 1);
+        BigDecimal prevPrice1 = prices.get(prices.size() - 2);
+        BigDecimal prevPrice2 = prices.get(prices.size() - 3);
+        
+        BigDecimal currentVolume = volume.get(volume.size() - 1);
+        BigDecimal prevVolume1 = volume.get(volume.size() - 2);
+        BigDecimal prevVolume2 = volume.get(volume.size() - 3);
+
+        // 计算价格趋势
+        boolean priceTrendUp = currentPrice.compareTo(prevPrice1) > 0 && prevPrice1.compareTo(prevPrice2) > 0;
+        boolean priceTrendDown = currentPrice.compareTo(prevPrice1) < 0 && prevPrice1.compareTo(prevPrice2) < 0;
+        
+        // 计算成交量趋势
+        boolean volumeTrendUp = currentVolume.compareTo(prevVolume1) > 0 && prevVolume1.compareTo(prevVolume2) > 0;
+        boolean volumeTrendDown = currentVolume.compareTo(prevVolume1) < 0 && prevVolume1.compareTo(prevVolume2) < 0;
+
+        // 检测量价背离
+        // 价格上涨但成交量萎缩
+        boolean bullishDivergence = priceTrendUp && volumeTrendDown;
+        // 价格下跌但成交量萎缩(通常是强势信号,不视为背离)
+        // 价格下跌但成交量放大(可能是恐慌性抛售,视为背离)
+        boolean bearishDivergence = priceTrendDown && volumeTrendUp;
+
+        return bullishDivergence || bearishDivergence;
+    }
+
+    /**
+     * 计算所有指标
+     * @param prices 价格数据
+     * @param high 最高价列表
+     * @param low 最低价列表
+     * @param close 收盘价列表
+     */
+    private void calculateIndicators(List<BigDecimal> prices, List<BigDecimal> high,
+                                    List<BigDecimal> low, List<BigDecimal> close) {
+        // 计算ATR和波动率
+        BigDecimal atr = calculateATR(high, low, close, config.getAtrPeriod());
+        BigDecimal volatility = normalizeVolatility(close, atr);
+
+        // 使用动态参数计算指标
+        if (config.isEnableDynamicParams()) {
+            log.debug("使用动态参数计算指标,波动率: {}", volatility);
+            ma.calculate(prices, volatility);
+            macd.calculate(prices, volatility);
+        } else {
+            ma.calculate(prices);
+            macd.calculate(prices);
+        }
+
+        // 其他指标计算
+        advancedMA.calculateTripleEMA(prices);
+        boll.calculate(prices);
+        kdj.calculate(prices);
+        rsi.calculate(prices);
+    }
+
+    /**
+     * 检查是否为震荡市场
+     * @return 是否为震荡市场
+     */
+    private boolean isRangeMarket() {
+        // 高级MA线收敛 + RSI(40-60) + 布林带收窄
+        boolean isMaConverged = advancedMA.calculatePercent().compareTo(new BigDecimal(2)) < 0;
+        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(40)) > 0 &&
+                              rsi.getRsi().compareTo(new BigDecimal(60)) < 0;
+        boolean isBollNarrow = boll.calculateBandWidth().compareTo(new BigDecimal(0.05)) < 0;
+
+        return isMaConverged && isRsiNeutral && isBollNarrow;
+    }
+
+    /**
+     * 根据15分钟时间框架指标确定市场方向(做多/做空/震荡)
+     * @param prices 价格数据列表
+     * @param high 最高价列表
+     * @param low 最低价列表
+     * @param close 收盘价列表
+     * @param currentPrice 当前价格
+     * @return 市场方向
+     */
+    public Direction getDirection(List<BigDecimal> prices, List<BigDecimal> high,
+                                List<BigDecimal> low, List<BigDecimal> close,
+                                BigDecimal currentPrice) {
+        // 计算所有指标
+        calculateIndicators(prices, high, low, close);
+
+        // 检查是否为震荡市场
+        if (isRangeMarket()) {
+            return Direction.RANGING;
+        }
+
+        // 检查做多方向条件:MA多头排列 + MACD金叉 + RSI中性(30-70) + BOLL价格在上轨和中轨之间
+        boolean isMaBullish = ma.getEma5().compareTo(ma.getEma10()) > 0 &&
+                              ma.getEma10().compareTo(ma.getEma20()) > 0;
+        boolean isMacdGoldenCross = macd.getDif().compareTo(macd.getDea()) > 0;
+        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(30)) > 0 &&
+                              rsi.getRsi().compareTo(new BigDecimal(70)) < 0;
+        boolean isPriceInUpperMid = currentPrice.compareTo(boll.getMid()) > 0 &&
+                                   currentPrice.compareTo(boll.getUpper()) < 0;
+
+        if (isMaBullish && isMacdGoldenCross && isRsiNeutral && isPriceInUpperMid) {
+            return Direction.LONG;
+        }
+
+        // 检查做空方向条件:MA空头排列 + MACD死叉 + RSI中性(30-70) + BOLL价格在下轨和中轨之间
+        boolean isMaBearish = ma.getEma5().compareTo(ma.getEma10()) < 0 &&
+                              ma.getEma10().compareTo(ma.getEma20()) < 0;
+        boolean isMacdDeathCross = macd.getDif().compareTo(macd.getDea()) < 0;
+        boolean isPriceInLowerMid = currentPrice.compareTo(boll.getLower()) > 0 &&
+                                   currentPrice.compareTo(boll.getMid()) < 0;
+
+        if (isMaBearish && isMacdDeathCross && isRsiNeutral && isPriceInLowerMid) {
+            return Direction.SHORT;
+        }
+
+        // 如果没有明确方向,默认为震荡
+        return Direction.RANGING;
+    }
+
+    /**
+     * 根据用户要求检查是否应该开多仓位
+     * 条件:MA金叉 + MACD金叉 + KDJ金叉 + RSI中性 + 价格高于BOLL中轨 + 多周期确认 + 成交量验证
+     * @param currentPrice 当前价格
+     * @param prices 价格数据
+     * @param volume 成交量列表
+     * @param fiveMinPrices 5分钟价格数据
+     * @param oneHourPrices 1小时价格数据
+     * @param fourHourPrices 4小时价格数据
+     * @return 是否应该开多
+     */
+    private boolean shouldOpenLong(BigDecimal currentPrice, List<BigDecimal> prices, List<BigDecimal> volume,
+                                  List<BigDecimal> fiveMinPrices,
+                                  List<BigDecimal> oneHourPrices,
+                                  List<BigDecimal> fourHourPrices) {
+        // MA金叉 (5EMA > 20EMA)
+        boolean isMaGoldenCross = ma.getEma5().compareTo(ma.getEma20()) > 0;
+        // MACD金叉 (DIF > DEA)
+        boolean isMacdGoldenCross = macd.getDif().compareTo(macd.getDea()) > 0;
+        // KDJ金叉 (K线上穿D线)
+        boolean isKdjGoldenCross = kdj.isGoldenCross();
+        // RSI中性 (30-70)
+        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(30)) > 0 &&
+                              rsi.getRsi().compareTo(new BigDecimal(70)) < 0;
+        // 价格高于BOLL中轨
+        boolean isPriceAboveBollMid = currentPrice.compareTo(boll.getMid()) > 0;
+        // 成交量验证
+        boolean isVolumeConfirmed = volumeConfirm(volume);
+        // 量价背离检测
+        boolean isPriceVolumeDivergence = hasPriceVolumeDivergence(prices, volume);
+        // 多周期确认
+        boolean isMultiTimeframeConfirmed = multiTimeframeConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
+
+        return isMaGoldenCross && isMacdGoldenCross && isKdjGoldenCross &&
+               isRsiNeutral && isPriceAboveBollMid && isVolumeConfirmed && 
+               !isPriceVolumeDivergence && isMultiTimeframeConfirmed;
+    }
+
+    /**
+     * 根据用户要求检查是否应该开空仓位
+     * 条件:MA死叉 + MACD死叉 + KDJ死叉 + RSI中性 + 价格低于BOLL中轨 + 多周期确认 + 成交量验证
+     * @param currentPrice 当前价格
+     * @param volume 成交量列表
+     * @param fiveMinPrices 5分钟价格数据
+     * @param oneHourPrices 1小时价格数据
+     * @param fourHourPrices 4小时价格数据
+     * @return 是否应该开空
+     */
+    private boolean shouldOpenShort(BigDecimal currentPrice, List<BigDecimal> volume,
+                                   List<BigDecimal> fiveMinPrices,
+                                   List<BigDecimal> oneHourPrices,
+                                   List<BigDecimal> fourHourPrices) {
+        // MA死叉 (5EMA < 20EMA)
+        boolean isMaDeathCross = ma.getEma5().compareTo(ma.getEma20()) < 0;
+        // MACD死叉 (DIF < DEA)
+        boolean isMacdDeathCross = macd.getDif().compareTo(macd.getDea()) < 0;
+        // KDJ死叉 (K线下穿D线)
+        boolean isKdjDeathCross = kdj.isDeathCross();
+        // RSI中性 (30-70)
+        boolean isRsiNeutral = rsi.getRsi().compareTo(new BigDecimal(30)) > 0 &&
+                              rsi.getRsi().compareTo(new BigDecimal(70)) < 0;
+        // 价格低于BOLL中轨
+        boolean isPriceBelowBollMid = currentPrice.compareTo(boll.getMid()) < 0;
+        // 成交量验证
+        boolean isVolumeConfirmed = volumeConfirm(volume);
+        // 多周期确认(看跌)
+        boolean isMultiTimeframeConfirmed = multiTimeframeBearishConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
+
+        return isMaDeathCross && isMacdDeathCross && isKdjDeathCross &&
+               isRsiNeutral && isPriceBelowBollMid && isVolumeConfirmed && isMultiTimeframeConfirmed;
+    }
+
+    /**
+     * 根据用户要求检查是否应该平多仓位
+     * 条件:MA死叉 + MACD死叉 + RSI超买 + 价格低于BOLL中轨 + 多周期确认
+     * @param currentPrice 当前价格
+     * @param volume 成交量列表
+     * @param fiveMinPrices 5分钟价格数据
+     * @param oneHourPrices 1小时价格数据
+     * @param fourHourPrices 4小时价格数据
+     * @return 是否应该平多
+     */
+    private boolean shouldCloseLong(BigDecimal currentPrice, List<BigDecimal> volume,
+                                   List<BigDecimal> fiveMinPrices,
+                                   List<BigDecimal> oneHourPrices,
+                                   List<BigDecimal> fourHourPrices) {
+        // MA死叉 (5EMA < 20EMA)
+        boolean isMaDeathCross = ma.getEma5().compareTo(ma.getEma20()) < 0;
+        // MACD死叉 (DIF < DEA)
+        boolean isMacdDeathCross = macd.getDif().compareTo(macd.getDea()) < 0;
+        // RSI超买 (>70)
+        boolean isRsiOverbought = rsi.isOverbought();
+        // 价格低于BOLL中轨
+        boolean isPriceBelowBollMid = currentPrice.compareTo(boll.getMid()) < 0;
+        // 多周期确认(看跌)
+        boolean isMultiTimeframeConfirmed = multiTimeframeBearishConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
+
+        return isMaDeathCross && isMacdDeathCross && isRsiOverbought && isPriceBelowBollMid && isMultiTimeframeConfirmed;
+    }
+
+    /**
+     * 根据用户要求检查是否应该平空仓位
+     * 条件:MA金叉 + MACD金叉 + RSI超卖 + 价格高于BOLL中轨 + 多周期确认
+     * @param currentPrice 当前价格
+     * @param volume 成交量列表
+     * @param fiveMinPrices 5分钟价格数据
+     * @param oneHourPrices 1小时价格数据
+     * @param fourHourPrices 4小时价格数据
+     * @return 是否应该平空
+     */
+    private boolean shouldCloseShort(BigDecimal currentPrice, List<BigDecimal> volume,
+                                    List<BigDecimal> fiveMinPrices,
+                                    List<BigDecimal> oneHourPrices,
+                                    List<BigDecimal> fourHourPrices) {
+        // MA金叉 (5EMA > 20EMA)
+        boolean isMaGoldenCross = ma.getEma5().compareTo(ma.getEma20()) > 0;
+        // MACD金叉 (DIF > DEA)
+        boolean isMacdGoldenCross = macd.getDif().compareTo(macd.getDea()) > 0;
+        // RSI超卖 (<30)
+        boolean isRsiOversold = rsi.isOversold();
+        // 价格高于BOLL中轨
+        boolean isPriceAboveBollMid = currentPrice.compareTo(boll.getMid()) > 0;
+        // 多周期确认(看涨)
+        boolean isMultiTimeframeConfirmed = multiTimeframeConfirm(fiveMinPrices, oneHourPrices, fourHourPrices);
+
+        return isMaGoldenCross && isMacdGoldenCross && isRsiOversold && isPriceAboveBollMid && isMultiTimeframeConfirmed;
+    }
+
+    /**
+     * 获取所有指标的当前状态
+     * @return 指标状态字符串
+     */
+    public String getIndicatorStatus() {
+        return String.format("MA5: %s, MA20: %s, ", ma.getEma5(), ma.getEma20()) +
+               String.format("MACD-DIF: %s, MACD-DEA: %s, MACD-BAR: %s, ", macd.getDif(), macd.getDea(), macd.getMacdBar()) +
+               String.format("KDJ-K: %s, KDJ-D: %s, KDJ-J: %s, ", kdj.getK(), kdj.getD(), kdj.getJ()) +
+               String.format("RSI: %s, ", rsi.getRsi()) +
+               String.format("BOLL-MID: %s, BOLL-UP: %s, BOLL-DN: %s, ", boll.getMid(), boll.getUpper(), boll.getLower()) +
+               String.format("AdvancedMA-Bullish: %s, Bearish: %s, Percent: %s",
+               advancedMA.isBullish(), advancedMA.isBearish(), advancedMA.calculatePercent());
+    }
+    
+    /**
+     * 计算动态杠杆倍数
+     * 杠杆倍数 = 基础杠杆 * (波动率阈值/当前波动率)
+     * @param high 最高价列表
+     * @param low 最低价列表
+     * @param close 收盘价列表
+     * @return 动态杠杆倍数
+     */
+    public BigDecimal calculateDynamicLeverage(List<BigDecimal> high, List<BigDecimal> low, List<BigDecimal> close) {
+        if (!config.isEnableDynamicLeverage()) {
+            return config.getBaseLeverage();
+        }
+        
+        // 计算当前ATR和波动率
+        BigDecimal currentAtr = calculateATR(high, low, close, config.getAtrPeriod());
+        BigDecimal currentVolatility = normalizeVolatility(close, currentAtr);
+        
+        // 计算30日ATR移动中位数作为波动率阈值
+        BigDecimal volatilityThreshold = calculateVolatilityThreshold(high, low, close);
+        
+        // 动态计算杠杆倍数
+        BigDecimal leverage = config.getBaseLeverage().multiply(volatilityThreshold).divide(currentVolatility, 2, BigDecimal.ROUND_HALF_UP);
+        
+        // 限制杠杆范围在1x-10x之间
+        leverage = leverage.min(new BigDecimal(10)).max(BigDecimal.ONE);
+        
+        log.debug("动态杠杆计算 - 基础杠杆: {}, 波动率阈值: {}, 当前波动率: {}, 计算杠杆: {}", 
+                config.getBaseLeverage(), volatilityThreshold, currentVolatility, leverage);
+        
+        return leverage;
+    }
+    
+    /**
+     * 计算波动率阈值(30日ATR移动中位数)
+     * @param high 最高价列表
+     * @param low 最低价列表
+     * @param close 收盘价列表
+     * @return 波动率阈值
+     */
+    private BigDecimal calculateVolatilityThreshold(List<BigDecimal> high, List<BigDecimal> low, List<BigDecimal> close) {
+        if (high == null || low == null || close == null || close.size() < config.getVolatilityThresholdPeriod()) {
+            return new BigDecimal(5); // 默认阈值
+        }
+        
+        List<BigDecimal> volatilityList = new ArrayList<>();
+        for (int i = close.size() - config.getVolatilityThresholdPeriod(); i < close.size(); i++) {
+            List<BigDecimal> recentHigh = high.subList(Math.max(0, i - config.getAtrPeriod()), i + 1);
+            List<BigDecimal> recentLow = low.subList(Math.max(0, i - config.getAtrPeriod()), i + 1);
+            List<BigDecimal> recentClose = close.subList(Math.max(0, i - config.getAtrPeriod()), i + 1);
+            
+            BigDecimal atr = calculateATR(recentHigh, recentLow, recentClose, config.getAtrPeriod());
+            BigDecimal volatility = normalizeVolatility(recentClose, atr);
+            volatilityList.add(volatility);
+        }
+        
+        // 计算中位数
+        volatilityList.sort(BigDecimal::compareTo);
+        int midIndex = volatilityList.size() / 2;
+        return volatilityList.get(midIndex);
+    }
+    
+    /**
+     * 三段式止盈策略
+     * 第一目标:BOLL上轨(30%仓位)
+     * 第二目标:斐波那契161.8%(50%仓位)
+     * 第三目标:趋势线破位(20%仓位)
+     * @param entryPrice 入场价格
+     * @param currentPrice 当前价格
+     * @param direction 交易方向
+     * @param positionSize 当前仓位大小
+     * @return 止盈信号和应该平仓的仓位比例
+     */
+    public ProfitTakingResult calculateThreeStepProfitTaking(BigDecimal entryPrice, BigDecimal currentPrice, 
+                                                            Direction direction, BigDecimal positionSize) {
+        if (!config.isEnableThreeStepProfitTaking()) {
+            return new ProfitTakingResult(SignalType.NONE, BigDecimal.ZERO);
+        }
+        
+        // 计算三个止盈目标
+        BigDecimal firstTarget = calculateFirstProfitTarget(entryPrice, currentPrice, direction);
+        BigDecimal secondTarget = calculateSecondProfitTarget(entryPrice, direction);
+        BigDecimal thirdTarget = calculateThirdProfitTarget(currentPrice, direction);
+        
+        // 判断当前价格是否达到目标
+        if (direction == Direction.LONG) {
+            if (currentPrice.compareTo(thirdTarget) >= 0) {
+                // 达到第三目标,平全部仓位
+                return new ProfitTakingResult(SignalType.CLOSE_BUY, positionSize);
+            } else if (currentPrice.compareTo(secondTarget) >= 0) {
+                // 达到第二目标,平50%仓位
+                return new ProfitTakingResult(SignalType.CLOSE_BUY, positionSize.multiply(new BigDecimal("0.5")));
+            } else if (currentPrice.compareTo(firstTarget) >= 0) {
+                // 达到第一目标,平30%仓位
+                return new ProfitTakingResult(SignalType.CLOSE_BUY, positionSize.multiply(new BigDecimal("0.3")));
+            }
+        } else if (direction == Direction.SHORT) {
+            if (currentPrice.compareTo(thirdTarget) <= 0) {
+                // 达到第三目标,平全部仓位
+                return new ProfitTakingResult(SignalType.CLOSE_SELL, positionSize);
+            } else if (currentPrice.compareTo(secondTarget) <= 0) {
+                // 达到第二目标,平50%仓位
+                return new ProfitTakingResult(SignalType.CLOSE_SELL, positionSize.multiply(new BigDecimal("0.5")));
+            } else if (currentPrice.compareTo(firstTarget) <= 0) {
+                // 达到第一目标,平30%仓位
+                return new ProfitTakingResult(SignalType.CLOSE_SELL, positionSize.multiply(new BigDecimal("0.3")));
+            }
+        }
+        
+        return new ProfitTakingResult(SignalType.NONE, BigDecimal.ZERO);
+    }
+    
+    /**
+     * 计算第一止盈目标:BOLL上轨
+     */
+    private BigDecimal calculateFirstProfitTarget(BigDecimal entryPrice, BigDecimal currentPrice, Direction direction) {
+        return direction == Direction.LONG ? boll.getUpper() : boll.getLower();
+    }
+    
+    /**
+     * 计算第二止盈目标:斐波那契161.8%
+     */
+    private BigDecimal calculateSecondProfitTarget(BigDecimal entryPrice, Direction direction) {
+        BigDecimal fibonacciRatio = new BigDecimal("1.618");
+        if (direction == Direction.LONG) {
+            return entryPrice.multiply(BigDecimal.ONE.add(fibonacciRatio.divide(new BigDecimal(100))));
+        } else {
+            return entryPrice.multiply(BigDecimal.ONE.subtract(fibonacciRatio.divide(new BigDecimal(100))));
+        }
+    }
+    
+    /**
+     * 计算第三止盈目标:简单趋势线破位(这里简化为MA5下穿MA20)
+     */
+    private BigDecimal calculateThirdProfitTarget(BigDecimal currentPrice, Direction direction) {
+        // 这里使用简化的趋势线破位判断
+        // 实际应用中可以使用更复杂的趋势线计算
+        return direction == Direction.LONG ? ma.getEma20() : ma.getEma20();
+    }
+    
+    /**
+     * 黑天鹅事件过滤
+     * 规避重大事件前后30分钟、链上大额转账、异常资金费率
+     * @param fundingRate 当前资金费率
+     * @param hasLargeTransfer 是否有大额转账
+     * @param hasUpcomingEvent 是否有即将到来的重大事件
+     * @return 是否应该规避交易
+     */
+    public boolean blackSwanFilter(BigDecimal fundingRate, boolean hasLargeTransfer, boolean hasUpcomingEvent) {
+        if (!config.isEnableBlackSwanFilter()) {
+            return false;
+        }
+        
+        // 资金费率绝对值大于0.2%
+        boolean isAbnormalFundingRate = fundingRate != null && 
+                fundingRate.abs().compareTo(new BigDecimal("0.002")) > 0;
+        
+        // 大额转账监控(这里简化为外部传入)
+        // 重大事件监控(这里简化为外部传入)
+        
+        boolean shouldAvoid = isAbnormalFundingRate || hasLargeTransfer || hasUpcomingEvent;
+        
+        if (shouldAvoid) {
+            log.debug("黑天鹅事件过滤触发 - 资金费率异常: {}, 大额转账: {}, 即将发生重大事件: {}", 
+                    isAbnormalFundingRate, hasLargeTransfer, hasUpcomingEvent);
+        }
+        
+        return shouldAvoid;
+    }
+    
+    /**
+     * 止盈结果类
+     */
+    public static class ProfitTakingResult {
+        private SignalType signal;
+        private BigDecimal closePositionSize;
+        
+        public ProfitTakingResult(SignalType signal, BigDecimal closePositionSize) {
+            this.signal = signal;
+            this.closePositionSize = closePositionSize;
+        }
+        
+        public SignalType getSignal() {
+            return signal;
+        }
+        
+        public BigDecimal getClosePositionSize() {
+            return closePositionSize;
+        }
+    }
+}
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/CoinEnums.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/CoinEnums.java
index b70898d..49fcc6a 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/CoinEnums.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/CoinEnums.java
@@ -50,8 +50,8 @@
     KANG_CANG("抗压比例KANG_CANG","0.9"),
     ZHI_SUN("止损比例ZHI_SUN","0.8"),
     //每次下单的张数
-    BUY_CNT("每次开仓的张数buyCnt","0.1"),
-    BUY_CNT_INIT("每次初始化开仓张数的基础值buyCntInit","0.1"),
+    BUY_CNT("每次开仓的张数buyCnt","0.5"),
+    BUY_CNT_INIT("每次初始化开仓张数的基础值buyCntInit","0.5"),
     BUY_CNT_TIME("每次开仓张数的倍数基础值buyCntTime","20"),
     OUT("是否允许下单out","操作中"),
     CTVAL("合约面值ctVal","0.1"),
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/Kline.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/Kline.java
new file mode 100644
index 0000000..5adafea
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/Kline.java
@@ -0,0 +1,22 @@
+package com.xcong.excoin.modules.okxNewPrice.okxWs.param;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+@Data
+public class Kline{
+    private String ts;
+    private BigDecimal o;
+    private BigDecimal h;
+    private BigDecimal l;
+    private BigDecimal c;
+    private BigDecimal vol;
+    private String confirm;
+
+}
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/StrategyParam.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/StrategyParam.java
new file mode 100644
index 0000000..5dcd018
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/param/StrategyParam.java
@@ -0,0 +1,11 @@
+package com.xcong.excoin.modules.okxNewPrice.okxWs.param;
+
+import lombok.Data;
+
+/**
+ * @author Administrator
+ */
+@Data
+public class StrategyParam {
+    private String accountName;
+}

--
Gitblit v1.9.1