From 2e6cbd3ee1c2d7e1aa73f4392c79bfbfacbcb67d Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 15 Dec 2025 14:03:36 +0800
Subject: [PATCH] feat(okx): 支持多账号WebSocket连接管理

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java     |  101 +++++++++++
 src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java       |   70 ++++---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java       |   60 +++---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/PositionsWs.java             |   47 +++--
 src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoService.java           |    2 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java                 |    8 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/OrderInfoWs.java             |   37 ++-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/TradeOrderWs.java            |   36 ++-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/AccountWs.java               |   40 ++-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientMain.java        |   15 +
 src/main/java/com/xcong/excoin/modules/okxNewPrice/zhanghu/ApiMessageServiceImpl.java |   11 
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java  |   26 +-
 src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/InstrumentsWs.java           |   33 ++-
 13 files changed, 318 insertions(+), 168 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
index 70069ef..b99d26c 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
@@ -30,15 +30,11 @@
  * @author Administrator
  */
 @Slf4j
-@Component
-@ConditionalOnProperty(prefix = "app", name = "quant", havingValue = "true")
 public class OkxQuantWebSocketClient {
-    @Autowired
-    private WangGeService wangGeService;
-    @Autowired
-    private CaoZuoService caoZuoService;
-    @Autowired
-    private RedisUtils redisUtils;
+    private final WangGeService wangGeService;
+    private final CaoZuoService caoZuoService;
+    private final RedisUtils redisUtils;
+    private final ExchangeInfoEnum account;
 
     private WebSocketClient webSocketClient;
     private ScheduledExecutorService heartbeatExecutor;
@@ -48,6 +44,14 @@
     // 连接状态标志
     private final AtomicBoolean isConnected = new AtomicBoolean(false);
     private final AtomicBoolean isConnecting = new AtomicBoolean(false);
+    
+    public OkxQuantWebSocketClient(ExchangeInfoEnum account, WangGeService wangGeService, 
+                                   CaoZuoService caoZuoService, RedisUtils redisUtils) {
+        this.account = account;
+        this.wangGeService = wangGeService;
+        this.caoZuoService = caoZuoService;
+        this.redisUtils = redisUtils;
+    }
 
     private static final String WS_URL_MONIPAN = "wss://wspap.okx.com:8443/ws/v5/private";
     private static final String WS_URL_SHIPAN = "wss://ws.okx.com:8443/ws/v5/private";
@@ -169,12 +173,12 @@
         }
         
         try {
-            InstrumentsWs.handleEvent();
+            InstrumentsWs.handleEvent(account.name());
             wangGeService.initWangGe();
             SSLConfig.configureSSL();
             System.setProperty("https.protocols", "TLSv1.2,TLSv1.3");
             String WS_URL = WS_URL_MONIPAN;
-            if (ExchangeInfoEnum.OKX_UAT.isAccountType()){
+            if (account.isAccountType()){
                 WS_URL = WS_URL_SHIPAN;
             }
             URI uri = new URI(WS_URL);
@@ -199,7 +203,7 @@
                     // 棜查应用是否正在关闭
                     if (!sharedExecutor.isShutdown()) {
                         resetHeartbeatTimer();
-                        websocketLogin();
+                        websocketLogin(account);
                     } else {
                         log.warn("应用正在关闭,忽略WebSocket连接成功回调");
                     }
@@ -249,8 +253,8 @@
         }
     }
 
-    private void websocketLogin() {
-        LoginWs.websocketLogin(webSocketClient);
+    private void websocketLogin(ExchangeInfoEnum account) {
+        LoginWs.websocketLogin(webSocketClient, account);
     }
 
     private void subscribeBalanceAndPositionChannel(String option) {
@@ -278,7 +282,7 @@
     private void handleWebSocketMessage(String message) {
         try {
             if ("pong".equals(message)) {
-                log.debug("收到心跳响应");
+                log.debug("{}: 收到心跳响应", account.name());
                 cancelPongTimeout();
                 return;
             }
@@ -289,26 +293,26 @@
                 String code = response.getString("code");
                 if ("0".equals(code)) {
                     String connId = response.getString("connId");
-                    log.info("WebSocket登录成功, connId: {}", connId);
+                    log.info("{}: WebSocket登录成功, connId: {}", account.name(), connId);
                     subscribeAccountChannel(SUBSCRIBE);
                     subscribeOrderInfoChannel(SUBSCRIBE);
                     subscribePositionChannel(SUBSCRIBE);
                 } else {
-                    log.error("WebSocket登录失败, code: {}, msg: {}", code, response.getString("msg"));
+                    log.error("{}: WebSocket登录失败, code: {}, msg: {}", account.name(), code, response.getString("msg"));
                 }
             } else if ("subscribe".equals(event)) {
                 subscribeEvent(response);
             } else if ("error".equals(event)) {
-                log.error("订阅错误: code={}, msg={}",
-                         response.getString("code"), response.getString("msg"));
+                log.error("{}: 订阅错误: code={}, msg={}",
+                         account.name(), response.getString("code"), response.getString("msg"));
             } else if ("channel-conn-count".equals(event)) {
-                log.info("连接限制更新: channel={}, connCount={}",
-                         response.getString("channel"), response.getString("connCount"));
+                log.info("{}: 连接限制更新: channel={}, connCount={}",
+                         account.name(), response.getString("channel"), response.getString("connCount"));
             } else {
                 processPushData(response);
             }
         } catch (Exception e) {
-            log.error("处理WebSocket消息失败: {}", message, e);
+            log.error("{}: 处理WebSocket消息失败: {}", account.name(), message, e);
         }
     }
 
@@ -325,13 +329,13 @@
             return;
         }
         if (OrderInfoWs.ORDERINFOWS_CHANNEL.equals(channel)) {
-            OrderInfoWs.initEvent(response);
+            OrderInfoWs.initEvent(response, account.name());
         }
         if (AccountWs.ACCOUNTWS_CHANNEL.equals(channel)) {
-            AccountWs.initEvent(response);
+            AccountWs.initEvent(response, account.name());
         }
         if (PositionsWs.POSITIONSWS_CHANNEL.equals(channel)) {
-            PositionsWs.initEvent(response);
+            PositionsWs.initEvent(response, account.name());
         }
     }
 
@@ -347,30 +351,32 @@
             if (TradeOrderWs.ORDERWS_CHANNEL.equals(op)) {
                 // 直接使用Object类型接收,避免强制类型转换
                 Object data = response.get("data");
-                log.info("收到下单推送结果: {}", JSON.toJSONString(data));
+                log.info("{}: 收到下单推送结果: {}", account.name(), JSON.toJSONString(data));
                 return;
             }
         }
         JSONObject arg = response.getJSONObject("arg");
         if (arg == null) {
-            log.warn("无效的推送数据,缺少 'arg' 字段 :{}",response);
+            log.warn("{}: 无效的推送数据,缺少 'arg' 字段 :{}", account.name(), response);
             return;
         }
 
         String channel = arg.getString("channel");
         if (channel == null) {
-            log.warn("无效的推送数据,缺少 'channel' 字段{}",response);
+            log.warn("{}: 无效的推送数据,缺少 'channel' 字段{}", account.name(), response);
             return;
         }
 
+        // 注意:当前实现中,OrderInfoWs等类使用静态Map存储数据
+        // 这会导致多账号之间的数据冲突。需要进一步修改这些类的设计,让数据存储与特定账号关联
         if (OrderInfoWs.ORDERINFOWS_CHANNEL.equals(channel)) {
-            OrderInfoWs.handleEvent(response, redisUtils);
+            OrderInfoWs.handleEvent(response, redisUtils, account.name());
         }else if (AccountWs.ACCOUNTWS_CHANNEL.equals(channel)) {
-            AccountWs.handleEvent(response);
-            String side = caoZuoService.caoZuo();
-            TradeOrderWs.orderEvent(webSocketClient, side);
+            AccountWs.handleEvent(response, account.name());
+            String side = caoZuoService.caoZuo(account.name());
+            TradeOrderWs.orderEvent(webSocketClient, side, account.name());
         } else if (PositionsWs.POSITIONSWS_CHANNEL.equals(channel)) {
-            PositionsWs.handleEvent(response);
+            PositionsWs.handleEvent(response, account.name());
         } else if (BalanceAndPositionWs.CHANNEL_NAME.equals(channel)) {
             BalanceAndPositionWs.handleEvent(response);
         }
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientMain.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientMain.java
index 063e02b..9eebd2d 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientMain.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientMain.java
@@ -1,16 +1,21 @@
 package com.xcong.excoin.modules.okxNewPrice;
 
+import com.xcong.excoin.modules.okxNewPrice.celue.CaoZuoServiceImpl;
+import com.xcong.excoin.modules.okxNewPrice.wangge.WangGeServiceImpl;
+import com.xcong.excoin.utils.RedisUtils;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
 public class OkxWebSocketClientMain {
     public static void main(String[] args) throws InterruptedException {
-        OkxQuantWebSocketClient clientV2 = new OkxQuantWebSocketClient();
-        // 手动调用初始化方法
-        clientV2.init();
+        // 使用Spring上下文初始化管理器
+        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
+        OkxWebSocketClientManager manager = context.getBean(OkxWebSocketClientManager.class);
 
         // 运行一段时间以观察结果
         Thread.sleep(1200000000L); // 运行一小时
         
         // 关闭连接
-        clientV2.destroy();
-
+        manager.destroy();
     }
 }
\ 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
new file mode 100644
index 0000000..d8981d0
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxWebSocketClientManager.java
@@ -0,0 +1,101 @@
+package com.xcong.excoin.modules.okxNewPrice;
+
+import com.xcong.excoin.modules.okxNewPrice.celue.CaoZuoService;
+import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.ExchangeInfoEnum;
+import com.xcong.excoin.modules.okxNewPrice.wangge.WangGeService;
+import com.xcong.excoin.utils.RedisUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 管理多个OKX WebSocket客户端实例,每个实例对应一个账号
+ */
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "app", name = "quant", havingValue = "true")
+public class OkxWebSocketClientManager {
+    @Autowired
+    private WangGeService wangGeService;
+    @Autowired
+    private CaoZuoService caoZuoService;
+    @Autowired
+    private RedisUtils redisUtils;
+
+    // 存储所有WebSocket客户端实例,key为账号类型名称
+    private final Map<String, OkxQuantWebSocketClient> clientMap = new ConcurrentHashMap<>();
+
+    /**
+     * 初始化方法,在Spring Bean构造完成后执行
+     * 创建并初始化所有账号的WebSocket客户端实例
+     */
+    @PostConstruct
+    public void init() {
+        log.info("开始初始化OkxWebSocketClientManager");
+        
+        // 获取所有ExchangeInfoEnum枚举值
+        ExchangeInfoEnum[] accounts = ExchangeInfoEnum.values();
+        
+        // 为每个账号创建一个WebSocket客户端实例
+        for (ExchangeInfoEnum account : accounts) {
+            try {
+                OkxQuantWebSocketClient client = new OkxQuantWebSocketClient(account, wangGeService, caoZuoService, redisUtils);
+                clientMap.put(account.name(), client);
+                client.init();
+                log.info("已初始化账号 {} 的WebSocket客户端", account.name());
+            } catch (Exception e) {
+                log.error("初始化账号 {} 的WebSocket客户端失败", account.name(), e);
+            }
+        }
+        
+        log.info("OkxWebSocketClientManager初始化完成");
+    }
+
+    /**
+     * 销毁方法,在Spring Bean销毁前执行
+     * 关闭所有WebSocket客户端连接和相关资源
+     */
+    @PreDestroy
+    public void destroy() {
+        log.info("开始销毁OkxWebSocketClientManager");
+        
+        // 关闭所有客户端实例
+        for (Map.Entry<String, OkxQuantWebSocketClient> entry : clientMap.entrySet()) {
+            try {
+                OkxQuantWebSocketClient client = entry.getValue();
+                client.destroy();
+                log.info("已销毁账号 {} 的WebSocket客户端", entry.getKey());
+            } catch (Exception e) {
+                log.error("销毁账号 {} 的WebSocket客户端失败", entry.getKey(), e);
+            }
+        }
+        
+        // 清空客户端映射
+        clientMap.clear();
+        
+        log.info("OkxWebSocketClientManager销毁完成");
+    }
+
+    /**
+     * 获取指定账号的WebSocket客户端实例
+     * @param accountName 账号类型名称
+     * @return WebSocket客户端实例
+     */
+    public OkxQuantWebSocketClient getClient(String accountName) {
+        return clientMap.get(accountName);
+    }
+
+    /**
+     * 获取所有WebSocket客户端实例
+     * @return 所有客户端实例的集合
+     */
+    public Collection<OkxQuantWebSocketClient> getAllClients() {
+        return clientMap.values();
+    }
+}
\ 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 9c83d0f..2a42f06 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
@@ -5,5 +5,5 @@
  */
 public interface CaoZuoService {
 
-    String caoZuo();
+    String caoZuo(String accountName);
 }
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 320423e..e7363bd 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
@@ -39,26 +39,26 @@
      * @return 返回操作类型字符串(如买入BUY、卖出SELL等),如果无有效操作则返回null
      */
     @Override
-    public String caoZuo() {
+    public String caoZuo(String accountName) {
         log.info("开始执行操作CaoZuoServiceImpl......");
-        String accountReadyState = AccountWs.ACCOUNTWSMAP.get(CoinEnums.READY_STATE.name());
+        String accountReadyState = AccountWs.getAccountMap(accountName).get(CoinEnums.READY_STATE.name());
         if (!CoinEnums.READY_STATE_YES.getCode().equals(accountReadyState)) {
             log.info("账户通道未就绪,取消发送");
             return null;
         }
-        BigDecimal positionsReadyState = PositionsWs.POSITIONSWSMAP.get(CoinEnums.READY_STATE.name()) == null
-                ? BigDecimal.ZERO : PositionsWs.POSITIONSWSMAP.get(CoinEnums.READY_STATE.name());
+        BigDecimal positionsReadyState = PositionsWs.getAccountMap(accountName).get(CoinEnums.READY_STATE.name()) == null
+                ? BigDecimal.ZERO : PositionsWs.getAccountMap(accountName).get(CoinEnums.READY_STATE.name());
         if (WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_YES.getCode()).compareTo(positionsReadyState) != 0) {
             log.info("仓位通道未就绪,取消发送");
             return null;
         }
         // 系统设置的开关,等于冷静中,则代表不开仓
-        String outStr = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.OUT.name());
+        String outStr = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.OUT.name());
         if (OrderParamEnums.OUT_YES.getValue().equals(outStr)){
             log.error("冷静中,不允许下单......");
             return null;
         }
-        BigDecimal cashBal = WsMapBuild.parseBigDecimalSafe(AccountWs.ACCOUNTWSMAP.get("cashBal"));
+        BigDecimal cashBal = WsMapBuild.parseBigDecimalSafe(AccountWs.getAccountMap(accountName).get("cashBal"));
 
         // 判断账户余额是否充足
         if (cashBal.compareTo(BigDecimal.ZERO) <= 0){
@@ -69,12 +69,12 @@
          * 判断止损抗压
          */
         // 实际亏损金额
-        BigDecimal realKuiSunAmount = WsMapBuild.parseBigDecimalSafe(AccountWs.ACCOUNTWSMAP.get("upl"));
+        BigDecimal realKuiSunAmount = WsMapBuild.parseBigDecimalSafe(AccountWs.getAccountMap(accountName).get("upl"));
         log.info("未实现盈亏: {}", realKuiSunAmount);
-        String zhiSunPercent = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.ZHI_SUN.name());
+        String zhiSunPercent = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.ZHI_SUN.name());
         BigDecimal zhiSunAmount = cashBal.multiply(new BigDecimal(zhiSunPercent));
         log.info("预期亏损金额: {}", zhiSunAmount);
-        String kangYaPercent = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.KANG_CANG.name());
+        String kangYaPercent = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.KANG_CANG.name());
         BigDecimal  kangYaAmount = cashBal.multiply(new BigDecimal(kangYaPercent));
         log.info("预期抗仓金额: {}", kangYaAmount);
 
@@ -83,7 +83,7 @@
             // 账户预期亏损金额比这个还小时,立即止损
             if (realKuiSunAmount.compareTo(zhiSunAmount) > 0){
                 log.error("账户冷静止损......");
-                WsMapBuild.saveStringToMap(InstrumentsWs.INSTRUMENTSWSMAP, CoinEnums.OUT.name(),  OrderParamEnums.OUT_YES.getValue());
+                WsMapBuild.saveStringToMap(InstrumentsWs.getAccountMap(accountName), CoinEnums.OUT.name(),  OrderParamEnums.OUT_YES.getValue());
                 return OrderParamEnums.OUT.getValue();
             }
             // 判断抗压
@@ -93,22 +93,22 @@
             }
         }
 
-        if (PositionsWs.POSITIONSWSMAP.get("pos") == null){
+        if (PositionsWs.getAccountMap(accountName).get("pos") == null){
             log.error("没有获取到持仓信息,等待初始化......");
             return null;
         }
-        BigDecimal pos = PositionsWs.POSITIONSWSMAP.get("pos");
+        BigDecimal pos = PositionsWs.getAccountMap(accountName).get("pos");
         if (BigDecimal.ZERO.compareTo( pos) >= 0) {
             log.error("持仓数量为零,进行初始化订单");
             return OrderParamEnums.INIT.getValue();
         }
         // 判断是否保证金超标
-        if (PositionsWs.POSITIONSWSMAP.get("imr") == null){
+        if (PositionsWs.getAccountMap(accountName).get("imr") == null){
             log.error("没有获取到持仓信息,等待初始化......");
             return null;
         }
-        BigDecimal ordFrozImr = PositionsWs.POSITIONSWSMAP.get("imr");
-        BigDecimal totalOrderUsdt = WsMapBuild.parseBigDecimalSafe(AccountWs.ACCOUNTWSMAP.get(CoinEnums.TOTAL_ORDER_USDT.name()));
+        BigDecimal ordFrozImr = PositionsWs.getAccountMap(accountName).get("imr");
+        BigDecimal totalOrderUsdt = WsMapBuild.parseBigDecimalSafe(AccountWs.getAccountMap(accountName).get(CoinEnums.TOTAL_ORDER_USDT.name()));
         if (ordFrozImr.compareTo(totalOrderUsdt) >= 0){
             log.error("已满仓......");
             return OrderParamEnums.HOLDING.getValue();
@@ -116,8 +116,8 @@
 
         try {
             // 获取标记价格和平均持仓价格
-            BigDecimal markPx = PositionsWs.POSITIONSWSMAP.get("markPx");
-            BigDecimal avgPx = PositionsWs.POSITIONSWSMAP.get("avgPx");
+            BigDecimal markPx = PositionsWs.getAccountMap(accountName).get("markPx");
+            BigDecimal avgPx = PositionsWs.getAccountMap(accountName).get("avgPx");
             log.info("开仓价格: {}, 当前价格:{},匹配队列中......", avgPx, markPx);
 
             // 初始化网格队列
@@ -126,7 +126,7 @@
             PriorityBlockingQueue<AscBigDecimal> queuePingCang = wangGeService.initPingCang(avgPx, queueAsc);
 
             // 处理订单价格在队列中的情况
-            String orderPrice = OrderInfoWs.ORDERINFOWSMAP.get("orderPrice");
+            String orderPrice = OrderInfoWs.getAccountMap(accountName).get("orderPrice");
             handleOrderPriceInQueues(orderPrice, queueKaiCang, queuePingCang);
             // 判断是加仓还是减仓
             if (avgPx.compareTo(markPx) > 0) {
@@ -139,8 +139,8 @@
                 DescBigDecimal kaiCang = queueKaiCang.peek();
                 if (kaiCang != null && markPx.compareTo(kaiCang.getValue()) <= 0 && avgPx.compareTo(kaiCang.getValue()) >= 0) {
                     log.info("开始加仓...开仓队列价格大于当前价格{}>{}", kaiCang.getValue(), markPx);
-                    WsMapBuild.saveStringToMap(OrderInfoWs.ORDERINFOWSMAP, "orderPrice", String.valueOf(markPx));
-                    boolean buyCntTimeFlag = buyCntTimeEvent(avgPx, markPx);
+                    WsMapBuild.saveStringToMap(OrderInfoWs.getAccountMap(accountName), "orderPrice", String.valueOf(markPx));
+                    boolean buyCntTimeFlag = buyCntTimeEvent(accountName, avgPx, markPx);
                     if (buyCntTimeFlag){
                         log.info("加仓参数准备成功......");
                         return OrderParamEnums.BUY.getValue();
@@ -163,23 +163,23 @@
                 if (pingCang != null && markPx.compareTo(pingCang.getValue()) >= 0 && avgPx.compareTo(pingCang.getValue()) < 0) {
                     log.info("开始减仓...平仓队列价格小于当前价格{}<={}", pingCang.getValue(), markPx);
                     // 手续费
-                    BigDecimal feeValue = PositionsWs.POSITIONSWSMAP.get("fee").multiply(new BigDecimal("2"));
+                    BigDecimal feeValue = PositionsWs.getAccountMap(accountName).get("fee").multiply(new BigDecimal("2"));
                     //未实现收益
-                    BigDecimal uplValue = PositionsWs.POSITIONSWSMAP.get("upl");
+                    BigDecimal uplValue = PositionsWs.getAccountMap(accountName).get("upl");
                     //已实现收益
-                    BigDecimal realizedPnlValue = PositionsWs.POSITIONSWSMAP.get("realizedPnl");
+                    BigDecimal realizedPnlValue = PositionsWs.getAccountMap(accountName).get("realizedPnl");
                     realizedPnlValue = realizedPnlValue.add(feeValue);
 
                     //持仓保证金
-                    BigDecimal imr = PositionsWs.POSITIONSWSMAP.get("imr");
-                    String pingCangImr = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.PING_CANG_SHOUYI.name());
+                    BigDecimal imr = PositionsWs.getAccountMap(accountName).get("imr");
+                    String pingCangImr = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.PING_CANG_SHOUYI.name());
                     BigDecimal imrValue = imr.multiply(new BigDecimal(pingCangImr));
 
                     if (realizedPnlValue.compareTo(BigDecimal.ZERO) <= 0) {
                         BigDecimal realizedPnlValueZheng = realizedPnlValue.multiply(new BigDecimal("-1"));
                         if (uplValue.compareTo(realizedPnlValue) > 0 && uplValue.compareTo(imrValue.add(realizedPnlValueZheng))  >= 0) {
                             log.info("当前未实现盈亏:{}大于预计收益>{},赚钱咯", uplValue, imrValue.add(realizedPnlValueZheng));
-                            WsMapBuild.saveStringToMap(OrderInfoWs.ORDERINFOWSMAP, "orderPrice", String.valueOf(markPx));
+                            WsMapBuild.saveStringToMap(OrderInfoWs.getAccountMap(accountName), "orderPrice", String.valueOf(markPx));
                             return OrderParamEnums.SELL.getValue();
                         }else{
                             log.info("当前未实现盈亏:{}没有大于预计收益>{},钱在路上了", uplValue, imrValue.add(realizedPnlValueZheng));
@@ -187,7 +187,7 @@
                         }
                     }else {
                         if (uplValue.compareTo(imrValue.add(feeValue))  >= 0) {
-                            WsMapBuild.saveStringToMap(OrderInfoWs.ORDERINFOWSMAP, "orderPrice", String.valueOf(markPx));
+                            WsMapBuild.saveStringToMap(OrderInfoWs.getAccountMap(accountName), "orderPrice", String.valueOf(markPx));
                             log.info("当前未实现盈亏:{}大于预计收益>{},赚钱咯", uplValue, imrValue.add(feeValue));
                             return OrderParamEnums.SELL.getValue();
                         }else{
@@ -208,16 +208,16 @@
         }
     }
 
-    private boolean buyCntTimeEvent(BigDecimal avgPx, BigDecimal markPx){
+    private boolean buyCntTimeEvent(String accountName, BigDecimal avgPx, BigDecimal markPx){
         //判断当前价格和开仓价格直接间隔除以间距,取整,获取的数量是否大于等于0,如果大于0,则下单基础张数*倍数
-        String buyCntTime = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.BUY_CNT_TIME.name());
+        String buyCntTime = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.BUY_CNT_TIME.name());
         BigDecimal subtract = avgPx.subtract(markPx);
         BigDecimal divide = subtract.divide(new BigDecimal(buyCntTime), 0, RoundingMode.DOWN);
         if (divide.compareTo(BigDecimal.ZERO) <= 0){
             log.warn("加仓次数间隔时间小于0,不加仓");
             return false;
         }
-        return WsMapBuild.saveStringToMap(TradeOrderWs.TRADEORDERWSMAP, "buyCntTime",String.valueOf(divide));
+        return WsMapBuild.saveStringToMap(TradeOrderWs.getAccountMap(accountName), "buyCntTime",String.valueOf(divide));
     }
 
     /**
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/AccountWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/AccountWs.java
index 401ad3b..bca358b 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/AccountWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/AccountWs.java
@@ -26,7 +26,13 @@
 @Slf4j
 public class AccountWs {
 
-    public static  final Map<String,String> ACCOUNTWSMAP = new ConcurrentHashMap<>();
+    // 使用双层Map,第一层key为账号名称,第二层key为数据key
+    private static final Map<String, Map<String, String>> ACCOUNTWSMAP = new ConcurrentHashMap<>();
+    
+    // 获取指定账号的Map,如果不存在则创建
+    public static Map<String, String> getAccountMap(String accountName) {
+        return ACCOUNTWSMAP.computeIfAbsent(accountName, k -> new ConcurrentHashMap<>());
+    }
     /**
      * 账户频道名称常量
      */
@@ -55,18 +61,19 @@
         }
     }
 
-    public static void initEvent(JSONObject response) {
+    public static void initEvent(JSONObject response, String accountName) {
 //        log.info("订阅成功: {}", response.getJSONObject("arg"));
         JSONObject arg = response.getJSONObject("arg");
-        initParam(arg);
+        initParam(arg, accountName);
     }
 
     /**
      * 处理账户频道推送的数据
      *
      * @param response   推送的 JSON 数据对象
+     * @param accountName 账号名称
      */
-    public static void handleEvent(JSONObject response) {
+    public static void handleEvent(JSONObject response, String accountName) {
 
 
 //        log.info("开始执行AccountWs......{}",ACCOUNTWS_CHANNEL);
@@ -88,7 +95,7 @@
 
                     for (int j = 0; j < detailsArray.size(); j++) {
                         JSONObject detail = detailsArray.getJSONObject(j);
-                        initParam(detail);
+                        initParam(detail, accountName);
                     }
                 } catch (Exception innerEx) {
                     log.warn("处理账户频道数据失败", innerEx);
@@ -105,35 +112,36 @@
     public static final String cashBalKey = "cashBal";
     public static final String eqKey = "eq";
     public static final String uplKey = "upl";
-    private static void initParam(JSONObject detail) {
+    private static void initParam(JSONObject detail, String accountName) {
+        Map<String, String> accountMap = getAccountMap(accountName);
 
         String ccy = WsMapBuild.parseStringSafe( detail.getString(ccyKey));
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, ccyKey, ccy);
+        WsMapBuild.saveStringToMap(accountMap, ccyKey, ccy);
 
         String availBal = WsMapBuild.parseStringSafe(detail.getString(availBalKey));
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, availBalKey, availBal);
+        WsMapBuild.saveStringToMap(accountMap, availBalKey, availBal);
 
         String cashBal = WsMapBuild.parseStringSafe(detail.getString(cashBalKey));
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, cashBalKey, cashBal);
+        WsMapBuild.saveStringToMap(accountMap, cashBalKey, cashBal);
 
         String eq = WsMapBuild.parseStringSafe(detail.getString(eqKey));
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, eqKey, eq);
+        WsMapBuild.saveStringToMap(accountMap, eqKey, eq);
 
         String upl = WsMapBuild.parseStringSafe(detail.getString(uplKey));
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, uplKey, upl);
+        WsMapBuild.saveStringToMap(accountMap, uplKey, upl);
 
         BigDecimal cashBalDecimal = WsMapBuild.parseBigDecimalSafe(cashBal);
         // 根据可用余额计算下单总保证金
-        String total_order_usdtpecent = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.TOTAL_ORDER_USDTPECENT.name());
+        String total_order_usdtpecent = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.TOTAL_ORDER_USDTPECENT.name());
         BigDecimal total_order_usdt_factor = WsMapBuild.parseBigDecimalSafe(total_order_usdtpecent);
         BigDecimal totalOrderUsdt = cashBalDecimal.multiply(total_order_usdt_factor).setScale(2, RoundingMode.DOWN);
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, CoinEnums.TOTAL_ORDER_USDT.name(), String.valueOf(totalOrderUsdt));
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.TOTAL_ORDER_USDT.name(), String.valueOf(totalOrderUsdt));
 
-        WsMapBuild.saveStringToMap(ACCOUNTWSMAP, CoinEnums.READY_STATE.name(), CoinEnums.READY_STATE_YES.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.READY_STATE.name(), CoinEnums.READY_STATE_YES.getCode());
 
         log.info(
-                "账户详情-币种: {}, 可用余额: {}, 现金余额: {}, 余额: {}, 全仓未实现盈亏: {}, 下单总保证金: {}",
-                ccy, availBal, cashBal, eq, upl, totalOrderUsdt
+                "{}: 账户详情-币种: {}, 可用余额: {}, 现金余额: {}, 余额: {}, 全仓未实现盈亏: {}, 下单总保证金: {}",
+                accountName, ccy, availBal, cashBal, eq, upl, totalOrderUsdt
         );
     }
 }
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/InstrumentsWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/InstrumentsWs.java
index fd784d5..04f1f11 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/InstrumentsWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/InstrumentsWs.java
@@ -14,24 +14,29 @@
 @Slf4j
 public class InstrumentsWs {
 
-    public static  final Map<String, String> INSTRUMENTSWSMAP = new ConcurrentHashMap<>();
+    public static final Map<String, Map<String, String>> INSTRUMENTSWSMAP = new ConcurrentHashMap<>();
 
     public static final String INSTRUMENTSWS_CHANNEL = "instruments";
 
-    public static void handleEvent() {
+    public static Map<String, String> getAccountMap(String accountName) {
+        return INSTRUMENTSWSMAP.computeIfAbsent(accountName, k -> new ConcurrentHashMap<>());
+    }
+
+    public static void handleEvent(String accountName) {
 //        log.info("开始执行InstrumentsWs......");
 
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.HE_YUE.name(), CoinEnums.HE_YUE.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.CTVAL.name(), CoinEnums.CTVAL.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.TICKSZ.name(), CoinEnums.TICKSZ.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.MINSZ.name(), CoinEnums.MINSZ.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.OUT.name(),  OrderParamEnums.OUT_NO.getValue());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.LEVERAGE.name(), CoinEnums.LEVERAGE.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.BUY_CNT.name(), CoinEnums.BUY_CNT.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.BUY_CNT_TIME.name(), CoinEnums.BUY_CNT_TIME.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.ZHI_SUN.name(), CoinEnums.ZHI_SUN.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.KANG_CANG.name(), CoinEnums.KANG_CANG.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.PING_CANG_SHOUYI.name(), CoinEnums.PING_CANG_SHOUYI.getCode());
-        WsMapBuild.saveStringToMap(INSTRUMENTSWSMAP, CoinEnums.TOTAL_ORDER_USDTPECENT.name(), CoinEnums.TOTAL_ORDER_USDTPECENT.getCode());
+        Map<String, String> accountMap = getAccountMap(accountName);
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.HE_YUE.name(), CoinEnums.HE_YUE.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.CTVAL.name(), CoinEnums.CTVAL.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.TICKSZ.name(), CoinEnums.TICKSZ.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.MINSZ.name(), CoinEnums.MINSZ.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.OUT.name(),  OrderParamEnums.OUT_NO.getValue());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.LEVERAGE.name(), CoinEnums.LEVERAGE.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.BUY_CNT.name(), CoinEnums.BUY_CNT.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.BUY_CNT_TIME.name(), CoinEnums.BUY_CNT_TIME.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.ZHI_SUN.name(), CoinEnums.ZHI_SUN.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.KANG_CANG.name(), CoinEnums.KANG_CANG.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.PING_CANG_SHOUYI.name(), CoinEnums.PING_CANG_SHOUYI.getCode());
+        WsMapBuild.saveStringToMap(accountMap, CoinEnums.TOTAL_ORDER_USDTPECENT.name(), CoinEnums.TOTAL_ORDER_USDTPECENT.getCode());
     }
 }
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java
index d7face2..eb3e416 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/LoginWs.java
@@ -13,7 +13,7 @@
  */
 @Slf4j
 public class LoginWs {
-    public static void websocketLogin(WebSocketClient webSocketClient) {
+    public static void websocketLogin(WebSocketClient webSocketClient, ExchangeInfoEnum account) {
 
 //        log.info("开始执行LoginWs......");
         try {
@@ -21,10 +21,10 @@
             JSONArray argsArray = new JSONArray();
             JSONObject loginArgs = new JSONObject();
             // 获取登录凭证信息(需要从配置或Redis中获取)
-            String apiKey = ExchangeInfoEnum.OKX_UAT.getApiKey();
-            String passphrase = ExchangeInfoEnum.OKX_UAT.getPassphrase();
+            String apiKey = account.getApiKey();
+            String passphrase = account.getPassphrase();
             String timestamp = String.valueOf(System.currentTimeMillis() /1000);
-            String sign = SignUtils.signWebsocket(timestamp, ExchangeInfoEnum.OKX_UAT.getSecretKey());
+            String sign = SignUtils.signWebsocket(timestamp, account.getSecretKey());
 
             loginArgs.put("apiKey", apiKey);
             loginArgs.put("passphrase", passphrase);
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/OrderInfoWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/OrderInfoWs.java
index 5250828..8dc0946 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/OrderInfoWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/OrderInfoWs.java
@@ -22,7 +22,13 @@
 @Slf4j
 public class OrderInfoWs {
 
-    public static  final Map<String,String> ORDERINFOWSMAP = new ConcurrentHashMap<>();
+    // 使用双层Map,第一层key为账号名称,第二层key为数据key
+    public static final Map<String, Map<String, String>> ORDERINFOWSMAP = new ConcurrentHashMap<>();
+    
+    // 获取指定账号的Map,如果不存在则创建
+    public static Map<String, String> getAccountMap(String accountName) {
+        return ORDERINFOWSMAP.computeIfAbsent(accountName, k -> new ConcurrentHashMap<>());
+    }
 
     public static final String ORDERINFOWS_CHANNEL = "orders";
 
@@ -44,7 +50,7 @@
         }
     }
 
-    public static void initEvent(JSONObject response) {
+    public static void initEvent(JSONObject response, String accountName) {
 //        log.info("订阅成功: {}", response.getJSONObject("arg"));
     }
 
@@ -58,7 +64,7 @@
     private static final String ACCFILLSZ_KEY = "accFillSz";
     private static final String AVGPX_KEY = "avgPx";
     private static final String STATE_KEY = "state";
-    public static void handleEvent(JSONObject response, RedisUtils redisUtils) {
+    public static void handleEvent(JSONObject response, RedisUtils redisUtils, String accountName) {
 
 //        log.info("开始执行OrderInfoWs......");
         try {
@@ -85,30 +91,35 @@
                 String state = detail.getString(STATE_KEY);
 
                 log.info(
-                        "订单详情-币种: {}, 系统编号: {}, 自定义编号: {}, 订单方向: {}, 交易模式: {}," +
+                        "{}: 订单详情-币种: {}, 系统编号: {}, 自定义编号: {}, 订单方向: {}, 交易模式: {}," +
                                 " 累计成交数量: {}, 成交均价: {}, 订单状态: {}",
-                        instId, ordId, clOrdId, side, tdMode,
+                        accountName, instId, ordId, clOrdId, side, tdMode,
                         accFillSz, avgPx,state
                 );
 
-                String clOrdIdStr = TradeOrderWs.TRADEORDERWSMAP.get("clOrdId");
-                String stateStr = TradeOrderWs.TRADEORDERWSMAP.get("state");
+                String clOrdIdStr = TradeOrderWs.getAccountMap(accountName).get("clOrdId");
+                String stateStr = TradeOrderWs.getAccountMap(accountName).get("state");
                 if (
                         StrUtil.isNotBlank(clOrdIdStr)
                                 && clOrdId.equals(clOrdIdStr)
                                 && StrUtil.isNotBlank(stateStr)
                                 && state.equals(stateStr)
                 ){
+                    Map<String, String> accountMap = getAccountMap(accountName);
                     //记录成交均价
-                    if (ORDERINFOWSMAP.get("orderPrice") == null){
-                        WsMapBuild.saveStringToMap(ORDERINFOWSMAP, "orderPrice",avgPx);
+                    if (accountMap.get("orderPrice") == null){
+                        WsMapBuild.saveStringToMap(accountMap, "orderPrice",avgPx);
                     }
-                    WsMapBuild.saveStringToMap(TradeOrderWs.TRADEORDERWSMAP, "state", CoinEnums.ORDER_LIVE.getCode());
+                    WsMapBuild.saveStringToMap(TradeOrderWs.getAccountMap(accountName), "state", CoinEnums.ORDER_LIVE.getCode());
 
-                    WsMapBuild.saveBigDecimalToMap(PositionsWs.POSITIONSWSMAP, CoinEnums.READY_STATE.name(), WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_NO.getCode()));
-                    WsMapBuild.saveStringToMap(AccountWs.ACCOUNTWSMAP, CoinEnums.READY_STATE.name(), CoinEnums.READY_STATE_NO.getCode());
+                    // 使用账号特定的Map
+                    Map<String, BigDecimal> positionsMap = PositionsWs.getAccountMap(accountName);
+                    WsMapBuild.saveBigDecimalToMap(positionsMap, CoinEnums.READY_STATE.name(), WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_NO.getCode()));
+                    
+                    Map<String, String> accountWsMap = AccountWs.getAccountMap(accountName);
+                    WsMapBuild.saveStringToMap(accountWsMap, CoinEnums.READY_STATE.name(), CoinEnums.READY_STATE_NO.getCode());
 
-                    log.info("订单详情已完成: {}, 自定义编号: {}", CoinEnums.HE_YUE.getCode(), clOrdId);
+                    log.info("{}: 订单详情已完成: {}, 自定义编号: {}", accountName, CoinEnums.HE_YUE.getCode(), clOrdId);
                 }
             }
         } catch (Exception e) {
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/PositionsWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/PositionsWs.java
index 75e230a..3b08fde 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/PositionsWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/PositionsWs.java
@@ -19,7 +19,13 @@
 @Slf4j
 public class PositionsWs {
 
-    public static  final Map<String,BigDecimal> POSITIONSWSMAP = new ConcurrentHashMap<>();
+    // 使用双层Map,第一层key为账号名称,第二层key为数据key
+    public static final Map<String, Map<String, BigDecimal>> POSITIONSWSMAP = new ConcurrentHashMap<>();
+    
+    // 获取指定账号的Map,如果不存在则创建
+    public static Map<String, BigDecimal> getAccountMap(String accountName) {
+        return POSITIONSWSMAP.computeIfAbsent(accountName, k -> new ConcurrentHashMap<>());
+    }
 
     public static final String POSITIONSWS_CHANNEL = "positions";
 
@@ -41,13 +47,13 @@
         }
     }
 
-    public static void initEvent(JSONObject response) {
+    public static void initEvent(JSONObject response, String accountName) {
 //        log.info("订阅成功,数据初始化: {}", response.getJSONObject("arg"));
         JSONObject arg = response.getJSONObject("arg");
-        initParam(arg);
+        initParam(arg, accountName);
     }
 
-    public static void handleEvent(JSONObject response) {
+    public static void handleEvent(JSONObject response, String accountName) {
 
 
 //        log.info("开始执行PositionsWs......");
@@ -56,7 +62,7 @@
             if (dataArray == null || dataArray.isEmpty()) {
 //                log.info("账户持仓频道数据为空,已当前价买入,并且初始化网格");
                 JSONObject posData = new JSONObject();
-                initParam(posData);
+                initParam(posData, accountName);
                 return;
             }
 
@@ -87,19 +93,19 @@
                     String fee = posData.getString("fee");
                     String fundingFee = posData.getString("fundingFee");
                     log.info(
-                            "账户持仓频道-产品类型: {}, 保证金模式: {}, 持仓方向: {}, 持仓数量: {}, 开仓平均价: {}, "
+                            "{}: 账户持仓频道-产品类型: {}, 保证金模式: {}, 持仓方向: {}, 持仓数量: {}, 开仓平均价: {}, "
                                     + "未实现收益: {}, 未实现收益率: {}, 杠杆倍数: {}, 预估强平价: {}, 初始保证金: {}, "
                                     + "维持保证金率: {}, 维持保证金: {}, 以美金价值为单位的持仓数量: {}, 占用保证金的币种: {}, "
                                     + "最新成交价: {}, 最新指数价格: {}, 盈亏平衡价: {}, 已实现收益: {}, 累计已结算收益: {}"
                                     + "最新标记价格: {},累计手续费: {},累计持仓费: {},",
-                            instId, mgnMode, posSide, pos, avgPx,
+                            accountName, instId, mgnMode, posSide, pos, avgPx,
                             upl, uplRatio, lever, liqPx, imr,
                             mgnRatio, mmr, notionalUsd, ccy,
                             last, idxPx, bePx, realizedPnl, settledPnl,
                             markPx,fee,fundingFee
                     );
 
-                    initParam(posData);
+                    initParam(posData, accountName);
                 }
             }
         } catch (Exception e) {
@@ -107,18 +113,19 @@
         }
     }
 
-    private static void initParam(JSONObject posData) {
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "avgPx", WsMapBuild.parseBigDecimalSafe(posData.getString("avgPx")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "pos", WsMapBuild.parseBigDecimalSafe(posData.getString("pos")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "upl", WsMapBuild.parseBigDecimalSafe(posData.getString("upl")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "imr", WsMapBuild.parseBigDecimalSafe(posData.getString("imr")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "mgnRatio", WsMapBuild.parseBigDecimalSafe(posData.getString("mgnRatio")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "markPx", WsMapBuild.parseBigDecimalSafe(posData.getString("markPx")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "bePx", WsMapBuild.parseBigDecimalSafe(posData.getString("bePx")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "realizedPnl", WsMapBuild.parseBigDecimalSafe(posData.getString("realizedPnl")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "fee", WsMapBuild.parseBigDecimalSafe(posData.getString("fee")));
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, "fundingFee", WsMapBuild.parseBigDecimalSafe(posData.getString("fundingFee")));
+    private static void initParam(JSONObject posData, String accountName) {
+        Map<String, BigDecimal> accountMap = getAccountMap(accountName);
+        WsMapBuild.saveBigDecimalToMap(accountMap, "avgPx", WsMapBuild.parseBigDecimalSafe(posData.getString("avgPx")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "pos", WsMapBuild.parseBigDecimalSafe(posData.getString("pos")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "upl", WsMapBuild.parseBigDecimalSafe(posData.getString("upl")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "imr", WsMapBuild.parseBigDecimalSafe(posData.getString("imr")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "mgnRatio", WsMapBuild.parseBigDecimalSafe(posData.getString("mgnRatio")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "markPx", WsMapBuild.parseBigDecimalSafe(posData.getString("markPx")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "bePx", WsMapBuild.parseBigDecimalSafe(posData.getString("bePx")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "realizedPnl", WsMapBuild.parseBigDecimalSafe(posData.getString("realizedPnl")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "fee", WsMapBuild.parseBigDecimalSafe(posData.getString("fee")));
+        WsMapBuild.saveBigDecimalToMap(accountMap, "fundingFee", WsMapBuild.parseBigDecimalSafe(posData.getString("fundingFee")));
 
-        WsMapBuild.saveBigDecimalToMap(POSITIONSWSMAP, CoinEnums.READY_STATE.name(), WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_YES.getCode()));
+        WsMapBuild.saveBigDecimalToMap(accountMap, CoinEnums.READY_STATE.name(), WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_YES.getCode()));
     }
 }
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/TradeOrderWs.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/TradeOrderWs.java
index 8d5a1f7..03662c2 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/TradeOrderWs.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/TradeOrderWs.java
@@ -22,20 +22,26 @@
 @Slf4j
 public class TradeOrderWs {
 
-    public static  final Map<String,String> TRADEORDERWSMAP = new ConcurrentHashMap<>();
+    // 使用双层Map,第一层key为账号名称,第二层key为数据key
+    public static  final Map<String, Map<String,String>> TRADEORDERWSMAP = new ConcurrentHashMap<>();
+    
+    // 获取指定账号的Map,如果不存在则创建
+    public static Map<String, String> getAccountMap(String accountName) {
+        return TRADEORDERWSMAP.computeIfAbsent(accountName, k -> new ConcurrentHashMap<>());
+    }
 
     public static final String ORDERWS_CHANNEL = "order";
 
-    public static void orderEvent(WebSocketClient webSocketClient, String side) {
+    public static void orderEvent(WebSocketClient webSocketClient, String side, String accountName) {
 
 //        log.info("开始执行TradeOrderWs......");
-        String accountReadyState = AccountWs.ACCOUNTWSMAP.get(CoinEnums.READY_STATE.name());
+        String accountReadyState = AccountWs.getAccountMap(accountName).get(CoinEnums.READY_STATE.name());
         if (!CoinEnums.READY_STATE_YES.getCode().equals(accountReadyState)) {
             log.info("账户通道未就绪,取消发送");
             return;
         }
-        BigDecimal positionsReadyState = PositionsWs.POSITIONSWSMAP.get(CoinEnums.READY_STATE.name()) == null
-                ? BigDecimal.ZERO : PositionsWs.POSITIONSWSMAP.get(CoinEnums.READY_STATE.name());
+        BigDecimal positionsReadyState = PositionsWs.getAccountMap(accountName).get(CoinEnums.READY_STATE.name()) == null
+                ? BigDecimal.ZERO : PositionsWs.getAccountMap(accountName).get(CoinEnums.READY_STATE.name());
         if (WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_YES.getCode()).compareTo(positionsReadyState) != 0) {
             log.info("仓位通道未就绪,取消发送");
             return;
@@ -52,19 +58,19 @@
         }else if (OrderParamEnums.OUT.getValue().equals(side)){
             log.info("当前状态为止损");
             side = OrderParamEnums.SELL.getValue();
-            buyCnt = String.valueOf(PositionsWs.POSITIONSWSMAP.get("pos"));
+            buyCnt = String.valueOf(PositionsWs.getAccountMap(accountName).get("pos"));
         }else if (OrderParamEnums.INIT.getValue().equals(side)){
             log.info("当前状态为初始化");
             side = OrderParamEnums.BUY.getValue();
-            buyCnt = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.BUY_CNT.name());
+            buyCnt = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.BUY_CNT.name());
         }else if (OrderParamEnums.BUY.getValue().equals(side)){
             log.info("当前状态为加仓");
-            String buyCntTime = TRADEORDERWSMAP.get("buyCntTime");
-            String buyCntStr = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.BUY_CNT.name());
+            String buyCntTime = getAccountMap(accountName).get("buyCntTime");
+            String buyCntStr = InstrumentsWs.getAccountMap(accountName).get(CoinEnums.BUY_CNT.name());
             buyCnt = String.valueOf(new BigDecimal(buyCntTime).multiply(new BigDecimal(buyCntStr)));
         }else if (OrderParamEnums.SELL.getValue().equals(side)){
             log.info("当前状态为减仓");
-            buyCnt = String.valueOf(PositionsWs.POSITIONSWSMAP.get("pos"));
+            buyCnt = String.valueOf(PositionsWs.getAccountMap(accountName).get("pos"));
         }else{
             log.warn("交易状态异常,取消发送");
             return;
@@ -93,12 +99,12 @@
             webSocketClient.send(jsonObject.toJSONString());
             log.info("发送下单频道:{},数量:{}", side, buyCnt);
 
-            WsMapBuild.saveStringToMap(TRADEORDERWSMAP, "buyCntTime",String.valueOf(BigDecimal.ONE));
-            WsMapBuild.saveStringToMap(TRADEORDERWSMAP, "clOrdId", clOrdId);
-            WsMapBuild.saveStringToMap(TRADEORDERWSMAP, "state", CoinEnums.ORDER_FILLED.getCode());
+            WsMapBuild.saveStringToMap(getAccountMap(accountName), "buyCntTime",String.valueOf(BigDecimal.ONE));
+        WsMapBuild.saveStringToMap(getAccountMap(accountName), "clOrdId", clOrdId);
+        WsMapBuild.saveStringToMap(getAccountMap(accountName), "state", CoinEnums.ORDER_FILLED.getCode());
 
-            WsMapBuild.saveBigDecimalToMap(PositionsWs.POSITIONSWSMAP, CoinEnums.READY_STATE.name(), WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_NO.getCode()));
-            WsMapBuild.saveStringToMap(AccountWs.ACCOUNTWSMAP, CoinEnums.READY_STATE.name(), CoinEnums.READY_STATE_NO.getCode());
+            WsMapBuild.saveBigDecimalToMap(PositionsWs.getAccountMap(accountName), CoinEnums.READY_STATE.name(), WsMapBuild.parseBigDecimalSafe(CoinEnums.READY_STATE_NO.getCode()));
+        WsMapBuild.saveStringToMap(AccountWs.getAccountMap(accountName), CoinEnums.READY_STATE.name(), CoinEnums.READY_STATE_NO.getCode());
 
         } catch (Exception e) {
             log.error("下单构建失败", e);
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java
index c970375..59c80ed 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/ExchangeInfoEnum.java
@@ -10,28 +10,28 @@
 public enum ExchangeInfoEnum {
 
     /**
-     * 模拟盘账户信息
+     * 模拟盘账户1信息
      * 存储了模拟盘交易所需的API密钥、秘钥和通过码
      */
-    OKX_UAT("ffb4e79f-fcf5-4afb-82c5-2fbb64123f61",
+    OKX_UAT1("ffb4e79f-fcf5-4afb-82c5-2fbb64123f61",
             "AA06C5ED1D7C7F5AFE6484052E231C55",
+            "Aa12345678@",
+            false),
+
+    /**
+     * 模拟盘账户2信息
+     * 存储了模拟盘交易所需的API密钥、秘钥和通过码
+     */
+    OKX_UAT2("7a023eb2-06c0-4255-9969-b86ea1cef0d7",
+            "D0106A4D63BD22BEAB9CBA8F41219661",
             "Aa12345678@",
             false);
 
     /**
-     * 模拟盘账户信息
+     * 模拟盘账户3信息
      * 存储了模拟盘交易所需的API密钥、秘钥和通过码
      */
-//    OKX_UAT("7a023eb2-06c0-4255-9969-b86ea1cef0d7",
-//            "D0106A4D63BD22BEAB9CBA8F41219661",
-//            "Aa12345678@",
-//            false);
-
-//    /**
-//     * 模拟盘账户信息
-//     * 存储了模拟盘交易所需的API密钥、秘钥和通过码
-//     */
-//    OKX_UAT("0769b50c-2c36-4310-8bd9-cad6bc6c9d8f",
+//    OKX_UAT3("0769b50c-2c36-4310-8bd9-cad6bc6c9d8f",
 //            "7AF4A574BC44907CE76BBFF91F53852D",
 //            "Aa123456@",
 //            false);
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/zhanghu/ApiMessageServiceImpl.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/zhanghu/ApiMessageServiceImpl.java
index 6402d0f..c8b8f0e 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/zhanghu/ApiMessageServiceImpl.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/zhanghu/ApiMessageServiceImpl.java
@@ -19,13 +19,14 @@
         quantApiMessage.setExchange(okx);
         quantApiMessage.setMemberId(1L);
 
-
-        quantApiMessage.setAccountType(ExchangeInfoEnum.OKX_UAT.isAccountType()? "true":"false");
+        // 根据传入的账号名称获取对应的账号信息
+        ExchangeInfoEnum account = ExchangeInfoEnum.valueOf(okx);
+        quantApiMessage.setAccountType(account.isAccountType()? "true":"false");
         quantApiMessage.setState(1);
         quantApiMessage.setIsTrade(1);
-        quantApiMessage.setASecretkey(ExchangeInfoEnum.OKX_UAT.getApiKey());
-        quantApiMessage.setBSecretkey(ExchangeInfoEnum.OKX_UAT.getSecretKey());
-        quantApiMessage.setPassPhrass(ExchangeInfoEnum.OKX_UAT.getPassphrase());
+        quantApiMessage.setASecretkey(account.getApiKey());
+        quantApiMessage.setBSecretkey(account.getSecretKey());
+        quantApiMessage.setPassPhrass(account.getPassphrase());
         return quantApiMessage;
     }
 

--
Gitblit v1.9.1