From abc803a37c3eb804a8c85164c41554eb9d1d44b8 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Fri, 12 Dec 2025 11:41:22 +0800
Subject: [PATCH] refactor(okx): 重构账户与合约 WebSocket 数据处理逻辑
---
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/CoinEnums.java | 75 ++--
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java | 8
src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsParamBuild.java | 53 +++
src/main/java/com/xcong/excoin/modules/okxNewPrice/celue/CaoZuoServiceImpl.java | 232 ++++++---------
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/OrderParamEnums.java | 11
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/PositionsWs.java | 123 +-------
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/InstrumentsWs.java | 39 +-
src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsMapBuild.java | 45 +++
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/OrderInfoWs.java | 29 +
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/TradeOrderWs.java | 101 ++----
src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/AccountWs.java | 139 ++------
11 files changed, 356 insertions(+), 499 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 b71c120..69a0572 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxQuantWebSocketClient.java
@@ -145,7 +145,7 @@
}
try {
- InstrumentsWs.handleEvent(redisUtils);
+ InstrumentsWs.handleEvent();
wangGeService.initWangGe();
SSLConfig.configureSSL();
System.setProperty("https.protocols", "TLSv1.2,TLSv1.3");
@@ -310,11 +310,11 @@
if (OrderInfoWs.ORDERINFOWS_CHANNEL.equals(channel)) {
OrderInfoWs.handleEvent(response, redisUtils);
}else if (AccountWs.ACCOUNTWS_CHANNEL.equals(channel)) {
- AccountWs.handleEvent(response, redisUtils);
+ AccountWs.handleEvent(response);
String side = caoZuoService.caoZuo();
- TradeOrderWs.orderEvent(webSocketClient, redisUtils, side);
+ TradeOrderWs.orderEvent(webSocketClient, side);
} else if (PositionsWs.POSITIONSWS_CHANNEL.equals(channel)) {
- PositionsWs.handleEvent(response, redisUtils);
+ PositionsWs.handleEvent(response);
} else if (BalanceAndPositionWs.CHANNEL_NAME.equals(channel)) {
BalanceAndPositionWs.handleEvent(response);
}
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 68f6774..f6a9df5 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
@@ -4,6 +4,7 @@
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.utils.WsMapBuild;
import com.xcong.excoin.modules.okxNewPrice.wangge.WangGeQueue;
import com.xcong.excoin.modules.okxNewPrice.wangge.WangGeService;
import com.xcong.excoin.rabbit.pricequeue.AscBigDecimal;
@@ -27,98 +28,94 @@
@RequiredArgsConstructor
public class CaoZuoServiceImpl implements CaoZuoService {
- private final RedisUtils redisUtils;
private final WangGeService wangGeService;
-
-
- // 构造Redis键名
- final String coinCode = CoinEnums.HE_YUE.getCode();
- final String instrumentsStateKey = InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + coinCode + ":state";
- final String instrumentsOutKey = InstrumentsWs.INSTRUMENTSWS_CHANNEL+":" + coinCode+":out";
- final String positionsMarkPxKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":markPx";
- final String positionsAvgPxKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":avgPx";
- final String positionsOrderPriceKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":orderPrice";
- final String positionsUplKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":upl";
- final String positionsRealizedPnlKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":realizedPnl";
- final String positionsImrKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":imr";
- final String positionsPosKey = PositionsWs.POSITIONSWS_CHANNEL + ":" + coinCode + ":pos";
/**
* 执行主要的操作逻辑,包括读取合约状态、获取市场价格信息,
* 并根据当前持仓均价和标记价格决定是否执行买卖操作。
*
- * @return 返回操作类型字符串(如买入BUY、卖出SELL等)
+ * @return 返回操作类型字符串(如买入BUY、卖出SELL等),如果无有效操作则返回null
*/
@Override
public String caoZuo() {
- String state = (String) redisUtils.get(instrumentsStateKey);
- log.info("开始执行操作CaoZuoServiceImpl......{}",state);
+ log.info("开始执行操作CaoZuoServiceImpl......");
+ BigDecimal cashBal = AccountWs.ACCOUNTWSMAP.get("cashBal");
+ BigDecimal availBal = AccountWs.ACCOUNTWSMAP.get("availBal");
- String live = (String) redisUtils.getWithDelay(TradeOrderWs.ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state");
- if (!CoinEnums.ORDER_LIVE.getCode().equals( live)){
- log.warn("正在下单中,等待下单结束...");
- }
- // 获取合约执行操作状态
- String outStr = (String) redisUtils.get(instrumentsOutKey);
- if (OrderParamEnums.OUT_YES.getValue().equals(outStr) && OrderParamEnums.STATE_3.getValue().equals(state)){
- log.error("止损过了......冷静一下,等待下次入场......");
+ // 判断账户余额是否充足
+ if (cashBal.compareTo(BigDecimal.ZERO) <= 0){
+ log.error("账户没有钱,请充值......");
return null;
}
- if (OrderParamEnums.STATE_4.getValue().equals(state)) {
- log.error("操作下单中,等待......");
- return OrderParamEnums.ORDERING.getValue();
+
+ // 系统设置的开关,等于冷静中,则代表不开仓
+ String outStr = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.OUT.name());
+ if (OrderParamEnums.OUT_YES.getValue().equals(outStr)){
+ log.error("冷静中,不允许下单......");
+ return null;
+ }
+
+ // 判断当前是否有正在进行的订单操作
+ String state = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.STATE.name());
+ log.info(OrderParamEnums.getNameByValue(state));
+ if (OrderParamEnums.STATE_4.getValue().equals(state)){
+ log.warn("正在下单中,等待下单结束...");
+ return null;
}
if (OrderParamEnums.STATE_3.getValue().equals(state)){
- log.error("持仓盈亏超过下单总保证金,冷静止损......");
- redisUtils.set(instrumentsOutKey, OrderParamEnums.OUT_YES.getValue(), 0);
- return OrderParamEnums.OUT.getValue();
+ log.error("冷静中,不允许下单......");
+ return null;
}
if (OrderParamEnums.STATE_2.getValue().equals(state)){
- log.error("持仓盈亏抗压......");
- return OrderParamEnums.HOLDING.getValue();
+ log.error("账户紧张扛仓......");
+ return null;
}
if (OrderParamEnums.STATE_0.getValue().equals(state)){
- log.error("请检查系统参数,不允许开仓......");
+ log.error("参数异常,不允许开仓......");
+ return null;
+ }
+
+ /**
+ * 判断止损抗压
+ */
+ // 实际亏损金额
+ BigDecimal realKuiSunAmount = cashBal.subtract(availBal);
+ log.info("实际亏损金额: {}", realKuiSunAmount);
+ String zhiSunPercent = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.ZHI_SUN.name());
+ BigDecimal zhiSunAmount = cashBal.multiply(new BigDecimal(zhiSunPercent));
+ log.info("预期亏损金额: {}", realKuiSunAmount);
+ String kangYaPercent = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.KANG_CANG.name());
+ log.info("预期抗仓金额: {}", kangYaPercent);
+ BigDecimal kangYaAmount = cashBal.multiply(new BigDecimal(kangYaPercent));
+
+ // 账户预期亏损金额比这个还小时,立即止损
+ if (realKuiSunAmount.compareTo(zhiSunAmount) > 0){
+ log.error("账户冷静止损......");
+ WsMapBuild.saveStringToMap(InstrumentsWs.INSTRUMENTSWSMAP, CoinEnums.OUT.name(), OrderParamEnums.OUT_YES.getValue());
+ return OrderParamEnums.OUT.getValue();
+ }
+ // 判断抗压
+ if (realKuiSunAmount.compareTo(kangYaAmount) > 0 && realKuiSunAmount.compareTo(zhiSunAmount) <= 0){
+ log.error("账户紧张扛仓......");
return OrderParamEnums.HOLDING.getValue();
}
- String pos = (String) redisUtils.get(positionsPosKey);
- if (StrUtil.isBlank(pos) || BigDecimal.ZERO.compareTo( new BigDecimal(pos)) >= 0) {
- log.error("未获取到持仓数量");
+ BigDecimal ordFroz = AccountWs.ACCOUNTWSMAP.get("ordFroz");
+ if (BigDecimal.ZERO.compareTo( ordFroz) >= 0) {
+ log.error("占用保证金为零,进行初始化订单");
return OrderParamEnums.INIT.getValue();
}
-
- String uplStr = (String) redisUtils.get(positionsUplKey);
- //可使用的总保证金
- String cashBalStrKey = AccountWs.ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":cashBal";
- String cashBalStr = (String) redisUtils.get(cashBalStrKey);
- if (StrUtil.isBlank(cashBalStr) || StrUtil.isBlank(uplStr)){
- return OrderParamEnums.INIT.getValue();
- }
- BigDecimal upl = new BigDecimal(uplStr);
- if (BigDecimal.ZERO.compareTo(upl) >= 0){
- upl = upl.multiply(new BigDecimal("-1"));
- BigDecimal bigDecimal = new BigDecimal(cashBalStr).multiply(new BigDecimal(OrderParamEnums.ZHI_SUN.getValue()));
- if (upl.compareTo(bigDecimal) >= 0) {
- log.error("持仓盈亏超过下单总保证金,止损冷静一天......");
- return OrderParamEnums.OUT.getValue();
- }
- }
-
- log.info(OrderParamEnums.getNameByValue(state));
-
- // 获取标记价格和平均持仓价格
- String markPxObj = (String) redisUtils.get(positionsMarkPxKey);
- String avgPxObj = (String) redisUtils.get(positionsAvgPxKey);
-
- if (StrUtil.isBlank(markPxObj) || StrUtil.isBlank(avgPxObj)) {
- return OrderParamEnums.INIT.getValue();
+ // 判断是否保证金超标
+ BigDecimal totalOrderUsdt = AccountWs.ACCOUNTWSMAP.get(CoinEnums.TOTAL_ORDER_USDT.name());
+ if (ordFroz.compareTo(totalOrderUsdt) >= 0){
+ log.error("已满仓......");
+ return OrderParamEnums.HOLDING.getValue();
}
try {
- BigDecimal markPx = new BigDecimal( markPxObj);
- BigDecimal avgPx = new BigDecimal( avgPxObj);
-
+ // 获取标记价格和平均持仓价格
+ BigDecimal markPx = PositionsWs.POSITIONSWSMAP.get("markPx");
+ BigDecimal avgPx = PositionsWs.POSITIONSWSMAP.get("avgPx");
log.info("开仓价格: {}, 当前价格:{},匹配队列中......", avgPx, markPx);
// 初始化网格队列
@@ -127,10 +124,8 @@
PriorityBlockingQueue<AscBigDecimal> queuePingCang = wangGeService.initPingCang(avgPx, queueAsc);
// 处理订单价格在队列中的情况
- String orderPrice = (String) redisUtils.get(positionsOrderPriceKey);
+ String orderPrice = OrderInfoWs.ORDERINFOWSMAP.get("orderPrice");
handleOrderPriceInQueues(orderPrice, queueKaiCang, queuePingCang);
-
- String side = OrderParamEnums.HOLDING.getValue();
// 判断是加仓还是减仓
if (avgPx.compareTo(markPx) > 0) {
@@ -138,80 +133,53 @@
if (queueKaiCang.isEmpty()) {
// 队列为空
log.info("开始加仓,但是超出了网格设置...");
- return side;
+ return OrderParamEnums.HOLDING.getValue();
}
DescBigDecimal kaiCang = queueKaiCang.peek();
if (kaiCang != null && markPx.compareTo(kaiCang.getValue()) <= 0 && avgPx.compareTo(kaiCang.getValue()) >= 0) {
log.info("开始加仓...开仓队列价格大于当前价格{}>{}", kaiCang.getValue(), markPx);
- side = OrderParamEnums.BUY.getValue();
- redisUtils.set(positionsOrderPriceKey, String.valueOf(kaiCang.getValue()), 0);
+ WsMapBuild.saveStringToMap(OrderInfoWs.ORDERINFOWSMAP, "orderPrice",String.valueOf(kaiCang.getValue()));
+ return OrderParamEnums.BUY.getValue();
} else {
- //判断是否加仓(当前持仓过小,可以加仓)
- boolean isAddCang = doAddCang();
- log.info("加仓过程中发现持仓过小 :{}",isAddCang);
- if (isAddCang){
- log.info("触发加仓......,持仓过小");
- return OrderParamEnums.BUY.getValue();
- }
log.info("未触发加仓......,等待");
+ return OrderParamEnums.HOLDING.getValue();
}
} else if (avgPx.compareTo(markPx) < 0) {
log.info("开始减仓...");
if (queuePingCang.isEmpty()) {
// 队列为空
log.info("开始减仓,但是超出了网格设置...");
- return side;
+ return OrderParamEnums.HOLDING.getValue();
}
AscBigDecimal pingCang = queuePingCang.peek();
if (pingCang != null && markPx.compareTo(pingCang.getValue()) >= 0 && avgPx.compareTo(pingCang.getValue()) < 0) {
log.info("开始减仓...平仓队列价格小于当前价格{}<={}", pingCang.getValue(), markPx);
- //判断当前是否盈利
- String uplstr = (String) redisUtils.get(positionsUplKey);
- String realizedPnl = (String) redisUtils.get(positionsRealizedPnlKey);
- String imr = (String) redisUtils.get(positionsImrKey);
- if (uplstr != null && realizedPnl != null && imr != null) {
- BigDecimal uplValue = new BigDecimal(uplstr);
- BigDecimal realizedPnlValue = new BigDecimal(realizedPnl);
- BigDecimal imrValue = new BigDecimal(imr).multiply(new BigDecimal(OrderParamEnums.PING_CANG_SHOUYI.getValue()));
- 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);
- redisUtils.set(positionsOrderPriceKey, String.valueOf(pingCang.getValue()), 0);
- return OrderParamEnums.SELL.getValue();
- }else{
- //判断是否加仓(当前持仓过小,可以加仓)
- boolean isAddCang = doAddCang();
- log.info("减仓过程中发现持仓过小 :{}",isAddCang);
- if (isAddCang){
- log.info("触发加仓......,持仓过小");
- return OrderParamEnums.BUY.getValue();
- }
- log.info("当前未实现盈亏:{}没有大于预计收益>{},钱在路上了", uplValue, imrValue);
- redisUtils.set(positionsOrderPriceKey, String.valueOf(pingCang.getValue()), 0);
- return OrderParamEnums.HOLDING.getValue();
- }
+ WsMapBuild.saveStringToMap(OrderInfoWs.ORDERINFOWSMAP, "orderPrice",String.valueOf(pingCang.getValue()));
- }else {
- if (uplValue.compareTo(imrValue) >= 0) {
- log.info("当前未实现盈亏:{}大于预计收益>{},赚钱咯", uplValue, imrValue);
- redisUtils.set(positionsOrderPriceKey, String.valueOf(pingCang.getValue()), 0);
- return OrderParamEnums.SELL.getValue();
- }else{
- //判断是否加仓(当前持仓过小,可以加仓)
- boolean isAddCang = doAddCang();
- log.info("减仓过程中发现持仓过小 :{}",isAddCang);
- if (isAddCang){
- log.info("触发加仓......,持仓过小");
- return OrderParamEnums.BUY.getValue();
- }
- log.info("当前未实现盈亏:{}没有大于预计收益>{},钱在路上了", uplValue, imrValue);
- redisUtils.set(positionsOrderPriceKey, String.valueOf(pingCang.getValue()), 0);
- return OrderParamEnums.HOLDING.getValue();
- }
- }
+ // 判断当前是否盈利
+ BigDecimal uplValue = PositionsWs.POSITIONSWSMAP.get("upl");
+ BigDecimal imr = PositionsWs.POSITIONSWSMAP.get("imr");
+ BigDecimal realizedPnlValue = PositionsWs.POSITIONSWSMAP.get("realizedPnl");
+ String pingCangImr = InstrumentsWs.INSTRUMENTSWSMAP.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);
+ return OrderParamEnums.SELL.getValue();
+ }else{
+ log.info("当前未实现盈亏:{}没有大于预计收益>{},钱在路上了", uplValue, imrValue);
+ return OrderParamEnums.HOLDING.getValue();
+ }
}else {
- return OrderParamEnums.HOLDING.getValue();
+ if (uplValue.compareTo(imrValue) >= 0) {
+ log.info("当前未实现盈亏:{}大于预计收益>{},赚钱咯", uplValue, imrValue);
+ return OrderParamEnums.SELL.getValue();
+ }else{
+ log.info("当前未实现盈亏:{}没有大于预计收益>{},钱在路上了", uplValue, imrValue);
+ return OrderParamEnums.HOLDING.getValue();
+ }
}
} else {
log.info("未触发减仓......,等待");
@@ -219,20 +187,11 @@
} else {
log.info("价格波动较小......,等待");
}
-
- return side;
+ return OrderParamEnums.HOLDING.getValue();
} catch (NumberFormatException e) {
log.error("解析价格失败,请检查Redis中的值是否合法", e);
return OrderParamEnums.HOLDING.getValue();
}
- }
-
- private boolean doAddCang() {
- String imr = (String) redisUtils.get(positionsImrKey);
- BigDecimal imrValue = new BigDecimal(StrUtil.isBlank(imr) ? "0" : imr);
- String everyTimeUsdt = (String) redisUtils.get(AccountWs.ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":everyTimeUsdt");
- BigDecimal everyTimeUsdtValue = new BigDecimal(everyTimeUsdt);
- return everyTimeUsdtValue.compareTo(imrValue) >= 0;
}
/**
@@ -258,8 +217,10 @@
log.warn("无效的价格格式: {}", orderPrice);
return;
}
+
// 删除比该价格大的数据
queueKaiCang.removeIf(item -> item.getValue().compareTo(priceDecimal) >= 0);
+
// 打印开仓队列
StringBuilder kaiCangStr = new StringBuilder();
kaiCangStr.append("开仓队列: [");
@@ -292,4 +253,3 @@
log.info(pingCangStr.toString());
}
}
-
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 6d32560..5d27096 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
@@ -1,18 +1,19 @@
package com.xcong.excoin.modules.okxNewPrice.okxWs;
-import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums;
import com.xcong.excoin.modules.okxNewPrice.okxpi.MallUtils;
+import com.xcong.excoin.modules.okxNewPrice.utils.WsMapBuild;
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 java.math.BigDecimal;
import java.math.RoundingMode;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* 账户 WebSocket 处理类,用于订阅 OKX 的账户频道并处理账户信息推送。
@@ -23,23 +24,11 @@
@Slf4j
public class AccountWs {
+ public static final Map<String,BigDecimal> ACCOUNTWSMAP = new ConcurrentHashMap<>();
/**
* 账户频道名称常量
*/
public static final String ACCOUNTWS_CHANNEL = "account";
-
- private static final String CCY_KEY = "ccy";
- private static final String AVAIL_BAL_KEY = "availBal";
- private static final String CASH_BAL_KEY = "cashBal";
- private static final String EQ_KEY = "eq";
- private static final String DETAILS_KEY = "details";
- private static final String DATA_KEY = "data";
-
- // 缓存常用 BigDecimal 常量
- private static final BigDecimal KANG_CANG_THRESHOLD = new BigDecimal(OrderParamEnums.KANG_CANG.getValue());
- private static final BigDecimal ZHI_SUN_THRESHOLD = new BigDecimal(OrderParamEnums.ZHI_SUN.getValue());
- private static final BigDecimal TOTAL_ORDER_USDT_FACTOR = new BigDecimal(OrderParamEnums.TOTAL_ORDER_USDT.getValue());
- private static final BigDecimal EVERY_TIME_USDT_FACTOR = new BigDecimal(OrderParamEnums.EVERY_TIME_USDT.getValue());
/**
* 订阅账户频道
@@ -52,7 +41,7 @@
JSONArray argsArray = new JSONArray();
JSONObject args = new JSONObject();
args.put("channel", ACCOUNTWS_CHANNEL);
- args.put(CCY_KEY, CoinEnums.USDT.getCode());
+ args.put("ccy", CoinEnums.USDT.getCode());
argsArray.add(args);
String connId = MallUtils.getOrderNum(ACCOUNTWS_CHANNEL);
@@ -68,16 +57,13 @@
* 处理账户频道推送的数据
*
* @param response 推送的 JSON 数据对象
- * @param redisUtils Redis 工具类实例,用于存储账户相关信息
*/
- public static void handleEvent(JSONObject response, RedisUtils redisUtils) {
+ public static void handleEvent(JSONObject response) {
- String state = (String) redisUtils.get(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state");
-
- log.info("开始执行AccountWs......{}",state);
+ log.info("开始执行AccountWs......{}",ACCOUNTWS_CHANNEL);
try {
- JSONArray dataArray = response.getJSONArray(DATA_KEY);
+ JSONArray dataArray = response.getJSONArray("data");
if (dataArray == null || dataArray.isEmpty()) {
log.warn("账户频道数据为空");
return;
@@ -86,7 +72,7 @@
for (int i = 0; i < dataArray.size(); i++) {
try {
JSONObject accountData = dataArray.getJSONObject(i);
- JSONArray detailsArray = accountData.getJSONArray(DETAILS_KEY);
+ JSONArray detailsArray = accountData.getJSONArray("details");
if (detailsArray == null || detailsArray.isEmpty()) {
log.warn("账户频道{}数据为空",CoinEnums.USDT.getCode());
continue;
@@ -94,56 +80,43 @@
for (int j = 0; j < detailsArray.size(); j++) {
JSONObject detail = detailsArray.getJSONObject(j);
+ //需要获取的参数
+ String ccyKey = "ccy";
+ String availBalKey = "availBal";
+ String cashBalKey = "cashBal";
+ String eqKey = "eq";
+ String ordFrozKey = "ordFroz";
- String ccy = detail.getString(CCY_KEY);
- String availBalStr = detail.getString(AVAIL_BAL_KEY);
- String cashBalStr = detail.getString(CASH_BAL_KEY);
- String eq = detail.getString(EQ_KEY);
+ BigDecimal ccy = WsMapBuild.parseBigDecimalSafe(detail.getString(ccyKey));
+ WsMapBuild.saveBigDecimalToMap(ACCOUNTWSMAP, ccyKey, ccy);
- if (StrUtil.isBlank(ccy) || StrUtil.isBlank(availBalStr) || StrUtil.isBlank(cashBalStr)) {
- log.warn("账户频道缺失必要字段,跳过处理");
- continue;
- }
+ BigDecimal availBal = WsMapBuild.parseBigDecimalSafe(detail.getString(availBalKey));
+ WsMapBuild.saveBigDecimalToMap(ACCOUNTWSMAP, availBalKey, availBal);
- BigDecimal availBal = parseBigDecimalSafe(availBalStr);
- BigDecimal cashBal = parseBigDecimalSafe(cashBalStr);
+ BigDecimal cashBal = WsMapBuild.parseBigDecimalSafe(detail.getString(cashBalKey));
+ WsMapBuild.saveBigDecimalToMap(ACCOUNTWSMAP, cashBalKey, cashBal);
- if (availBal == null || cashBal == null || cashBal.compareTo(BigDecimal.ZERO) == 0) {
+ BigDecimal eq = WsMapBuild.parseBigDecimalSafe(detail.getString(eqKey));
+ WsMapBuild.saveBigDecimalToMap(ACCOUNTWSMAP, eqKey, eq);
+
+ BigDecimal ordFroz = WsMapBuild.parseBigDecimalSafe(detail.getString(ordFrozKey));
+ WsMapBuild.saveBigDecimalToMap(ACCOUNTWSMAP, ordFrozKey, ordFroz);
+
+ if (cashBal.compareTo(BigDecimal.ZERO) == 0) {
log.warn("账户频道无效的账户余额数据,跳过处理");
continue;
}
- // 可用余额 / 现金余额 比例判断是否允许开仓
- BigDecimal divide = availBal.divide(cashBal, 4, RoundingMode.DOWN);
- if (OrderParamEnums.STATE_4.getValue().equals(state)){
- log.info(OrderParamEnums.STATE_4.getName());
- state = OrderParamEnums.STATE_4.getValue();
- }else if(OrderParamEnums.STATE_3.getValue().equals(state)){
- log.info(OrderParamEnums.STATE_3.getName());
- state = OrderParamEnums.STATE_3.getValue();
- }else{
- if (divide.compareTo(KANG_CANG_THRESHOLD) > 0) {
- log.info(OrderParamEnums.STATE_1.getName());
- state = OrderParamEnums.STATE_1.getValue();
- } else if (divide.compareTo(ZHI_SUN_THRESHOLD) > 0) {
- log.warn(OrderParamEnums.STATE_2.getName());
- state = OrderParamEnums.STATE_2.getValue();
- } else {
- log.error(OrderParamEnums.STATE_3.getName());
- state = OrderParamEnums.STATE_3.getValue();
- }
- }
-
- // 根据可用余额计算下单总保证金与每次下单金额
- BigDecimal totalOrderUsdt = availBal.multiply(TOTAL_ORDER_USDT_FACTOR).setScale(4, RoundingMode.DOWN);
- BigDecimal everyTimeUsdt = totalOrderUsdt.divide(EVERY_TIME_USDT_FACTOR, 4, RoundingMode.DOWN);
+ // 根据可用余额计算下单总保证金
+ String total_order_usdtpecent = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.TOTAL_ORDER_USDTPECENT.name());
+ BigDecimal total_order_usdt_factor = WsMapBuild.parseBigDecimalSafe(total_order_usdtpecent);
+ BigDecimal totalOrderUsdt = availBal.divide(total_order_usdt_factor, 4, RoundingMode.DOWN);
+ WsMapBuild.saveBigDecimalToMap(ACCOUNTWSMAP, CoinEnums.TOTAL_ORDER_USDT.name(), totalOrderUsdt);
log.info(
- "账户详情-币种: {}, 可用余额: {}, 现金余额: {}, 余额: {}, 下单总保证金: {}, 每次下单保证金: {}, 是否允许开仓: {}",
- ccy, availBalStr, cashBalStr, eq, totalOrderUsdt, everyTimeUsdt, state
+ "账户详情-币种: {}, 可用余额: {}, 现金余额: {}, 余额: {}, 占用保证金: {}, 下单总保证金: {}",
+ ccy, availBal, cashBal, eq, ordFroz, totalOrderUsdt
);
-
- saveToRedis(redisUtils, availBalStr, cashBalStr, totalOrderUsdt.toString(), everyTimeUsdt.toString(), state);
}
} catch (Exception innerEx) {
log.warn("处理账户频道数据失败", innerEx);
@@ -154,47 +127,5 @@
}
}
- /**
- * 安全地将字符串解析为 BigDecimal 类型
- *
- * @param value 字符串数值
- * @return 解析后的 BigDecimal 对象,若解析失败则返回 null
- */
- private static BigDecimal parseBigDecimalSafe(String value) {
- try {
- return new BigDecimal(value);
- } catch (NumberFormatException e) {
- log.warn("无法转换为 BigDecimal: {}", value);
- return null;
- }
- }
-
- /**
- * 将账户相关数据保存至 Redis 中
- *
- * @param redisUtils Redis 工具类实例
- * @param availBal 可用余额
- * @param cashBal 现金余额
- * @param totalOrderUsdt 总下单保证金
- * @param everyTimeUsdt 每次下单保证金
- * @param state 当前账户状态(是否可开仓)
- */
- private static void saveToRedis(RedisUtils redisUtils, String availBal, String cashBal,
- String totalOrderUsdt, String everyTimeUsdt, String state) {
- try {
- boolean setResult =
- redisUtils.set(ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":availBal", availBal, 0)
- && redisUtils.set(ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":cashBal", cashBal, 0)
- && redisUtils.set(ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":totalOrderUsdt", totalOrderUsdt, 0)
- && redisUtils.set(ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":everyTimeUsdt", everyTimeUsdt, 0)
- && redisUtils.set(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", state, 0);
-
- if (!setResult) {
- log.warn("Redis set operation failed for key: account:{}", CoinEnums.USDT.getCode());
- }
- } catch (Exception e) {
- log.error("Redis操作异常,key: account:{}, error: {}", CoinEnums.USDT.getCode(), e.getMessage(), e);
- }
- }
}
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 1f2eadf..787e28b 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
@@ -2,8 +2,11 @@
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums;
-import com.xcong.excoin.utils.RedisUtils;
+import com.xcong.excoin.modules.okxNewPrice.utils.WsMapBuild;
import lombok.extern.slf4j.Slf4j;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* @author Administrator
@@ -11,26 +14,24 @@
@Slf4j
public class InstrumentsWs {
+ public static final Map<String, String> INSTRUMENTSWSMAP = new ConcurrentHashMap<>();
+
public static final String INSTRUMENTSWS_CHANNEL = "instruments";
- public static void handleEvent(RedisUtils redisUtils) {
+ public static void handleEvent() {
log.info("开始执行InstrumentsWs......");
- // 将账户数据保存到Redis中,设置过期时间为30分钟
- try {
- boolean setResult =
- redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":instId", CoinEnums.HE_YUE.getCode(), 0)
- && redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":ctVal", "0.01", 0)
- && redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":tickSz", "2", 0)
- && redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":minSz", "2", 0)
- && redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":instIdCode", CoinEnums.HE_YUE.getCode(), 0)
- && redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":state", OrderParamEnums.STATE_0.getValue(), 0)
- && redisUtils.set(INSTRUMENTSWS_CHANNEL+":" + CoinEnums.HE_YUE.getCode()+":out", OrderParamEnums.OUT_NO.getValue(), 0)
- ;
- if (!setResult) {
- log.warn("Redis set operation failed for key: account:{}", CoinEnums.HE_YUE.getCode());
- }
- } catch (Exception e) {
- log.error("Redis操作异常,key: account:{}, error: {}", CoinEnums.HE_YUE.getCode(), e.getMessage(), e);
- }
+
+ 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.STATE.name(), OrderParamEnums.STATE_1.getValue());
+ 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.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());
}
}
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 32908d0..eb4b3be 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
@@ -6,16 +6,22 @@
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums;
import com.xcong.excoin.modules.okxNewPrice.okxpi.MallUtils;
+import com.xcong.excoin.modules.okxNewPrice.utils.WsMapBuild;
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 java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* @author Administrator
*/
@Slf4j
public class OrderInfoWs {
+
+ public static final Map<String,String> ORDERINFOWSMAP = new ConcurrentHashMap<>();
public static final String ORDERINFOWS_CHANNEL = "orders";
@@ -80,8 +86,8 @@
accFillSz, avgPx,state
);
- String clOrdIdStr = (String) redisUtils.get(TradeOrderWs.ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":clOrdId");
- String stateStr = (String) redisUtils.get(TradeOrderWs.ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state");
+ String clOrdIdStr = TradeOrderWs.TRADEORDERWSMAP.get("clOrdId");
+ String stateStr = TradeOrderWs.TRADEORDERWSMAP.get("state");
if (
StrUtil.isNotBlank(clOrdIdStr)
&& clOrdId.equals(clOrdIdStr)
@@ -89,17 +95,20 @@
&& state.equals(stateStr)
&& !CoinEnums.ORDER_LIVE.getCode().equals(state)
){
- boolean setResult = false;
- String outStr = (String) redisUtils.get(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":out");
+ //记录成交均价
+ if (StrUtil.isBlank(ORDERINFOWSMAP.get("orderPrice"))){
+ WsMapBuild.saveStringToMap(ORDERINFOWSMAP, "orderPrice",avgPx);
+ }
+
+ WsMapBuild.saveStringToMap(TradeOrderWs.TRADEORDERWSMAP, "state", CoinEnums.ORDER_LIVE.getCode());
+
+ String outStr = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.OUT.name());
if (OrderParamEnums.OUT_YES.getValue().equals(outStr)){
- setResult = redisUtils.set(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", OrderParamEnums.STATE_3.getValue(), 0);
+ WsMapBuild.saveStringToMap(InstrumentsWs.INSTRUMENTSWSMAP, CoinEnums.STATE.name(), OrderParamEnums.STATE_3.getValue());
}else{
- setResult = redisUtils.set(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", OrderParamEnums.STATE_1.getValue(), 0);
+ WsMapBuild.saveStringToMap(InstrumentsWs.INSTRUMENTSWSMAP, CoinEnums.STATE.name(), OrderParamEnums.STATE_1.getValue());
}
- if (setResult){
- redisUtils.set(TradeOrderWs.ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", CoinEnums.ORDER_LIVE.getCode(), 0);
- log.info("订单详情-币种: {}, 自定义编号: {}, 订单状态: {}", CoinEnums.HE_YUE.getCode(), clOrdId, OrderParamEnums.STATE_1.getValue());
- }
+ log.info("订单详情已完成: {}, 自定义编号: {}", 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 9379534..dad2031 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
@@ -1,20 +1,17 @@
package com.xcong.excoin.modules.okxNewPrice.okxWs;
-import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums;
-import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums;
import com.xcong.excoin.modules.okxNewPrice.okxpi.MallUtils;
+import com.xcong.excoin.modules.okxNewPrice.utils.WsMapBuild;
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.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
import java.math.BigDecimal;
-import java.util.Optional;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* @author Administrator
@@ -22,8 +19,9 @@
@Slf4j
public class PositionsWs {
+ public static final Map<String,BigDecimal> POSITIONSWSMAP = new ConcurrentHashMap<>();
+
public static final String POSITIONSWS_CHANNEL = "positions";
- private static final String REDIS_KEY_PREFIX = POSITIONSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode();
public static void subscribePositionChannel(WebSocketClient webSocketClient, String option) {
try {
@@ -43,7 +41,7 @@
}
}
- public static void handleEvent(JSONObject response, RedisUtils redisUtils) {
+ public static void handleEvent(JSONObject response) {
log.info("开始执行PositionsWs......");
@@ -52,7 +50,7 @@
if (dataArray == null || dataArray.isEmpty()) {
log.info("账户持仓频道数据为空,已当前价买入,并且初始化网格");
JSONObject posData = new JSONObject();
- processPositionData(posData, redisUtils);
+ processPositionData(posData);
return;
}
@@ -92,7 +90,8 @@
last, idxPx, bePx, realizedPnl, settledPnl,
markPx
);
- processPositionData(posData, redisUtils);
+
+ processPositionData(posData);
}
}
} catch (Exception e) {
@@ -100,101 +99,15 @@
}
}
- private static void processPositionData(JSONObject posData, RedisUtils redisUtils) {
- try {
- String avgPx = safeGetString(posData, "avgPx");
- String pos = safeGetString(posData, "pos");
- String upl = safeGetString(posData, "upl");
- String imr = safeGetString(posData, "imr");
- String mgnRatio = safeGetString(posData, "mgnRatio");
- String markPx = safeGetString(posData, "markPx");
- String bePx = safeGetString(posData, "bePx");
- String realizedPnl = safeGetString(posData, "realizedPnl");
+ private static void processPositionData(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")));
- boolean setResult = saveToRedis(redisUtils, avgPx, pos, upl, imr, mgnRatio, markPx, bePx,realizedPnl);
-
- if (setResult) {
- calculateAndSaveBuyCount(redisUtils);
- } else {
- log.warn("Redis操作失败");
- }
- } catch (Exception e) {
- log.error("Redis操作异常", e);
- }
- }
-
- private static boolean saveToRedis(RedisUtils redisUtils,
- String avgPx, String pos, String upl,
- String imr, String mgnRatio, String markPx, String bePx, String realizedPnl) {
- return redisUtils.set(REDIS_KEY_PREFIX + ":avgPx", avgPx, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":pos", pos, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":upl", upl, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":imr", imr, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":mgnRatio", mgnRatio, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":markPx", markPx, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":bePx", bePx, 0)
- && redisUtils.set(REDIS_KEY_PREFIX + ":realizedPnl", realizedPnl, 0);
- }
-
- private static void calculateAndSaveBuyCount(RedisUtils redisUtils) {
- try {
- String ctValStr = (String) redisUtils.get(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":ctVal");
- String markPxStr = (String) redisUtils.get(REDIS_KEY_PREFIX + ":markPx");
- String minSzStr = (String) redisUtils.get(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":minSz");
- String everyTimeUsdt = (String) redisUtils.get(AccountWs.ACCOUNTWS_CHANNEL + ":" + CoinEnums.USDT.getCode() + ":everyTimeUsdt");
-
- BigDecimal margin = parseBigDecimal(everyTimeUsdt, "0");
- BigDecimal leverage = parseBigDecimal(OrderParamEnums.LEVERAGE.getValue(), "1");
- BigDecimal faceValue = parseBigDecimal(ctValStr, "0");
- BigDecimal markPrice = parseBigDecimal(markPxStr, "0"); // 默认值需谨慎对待
- int minLotSz = parseInt(minSzStr, 0);
-
- BigDecimal buyCnt = buyCnt(margin, leverage, faceValue, markPrice, minLotSz);
- redisUtils.set(REDIS_KEY_PREFIX + ":buyCnt", buyCnt.toString(), 0);
- } catch (NumberFormatException | ArithmeticException e) {
- log.error("计算购买数量时发生数字转换错误", e);
- }
- }
-
- private static String safeGetString(JSONObject obj, String key) {
- return Optional.ofNullable(obj.getString(key)).orElse("0");
- }
-
- private static BigDecimal parseBigDecimal(String value, String defaultValue) {
- return new BigDecimal(Optional.ofNullable(value).filter(s -> !s.isEmpty()).orElse(defaultValue));
- }
-
- private static int parseInt(String value, int defaultValue) {
- try {
- return Integer.parseInt(value);
- } catch (NumberFormatException e) {
- return defaultValue;
- }
- }
-
- /**
- * 计算购买合约的数量
- *
- * USDT 币本位合约
- * 公式:张数 = 保证金 / (面值 * 标记价格 / 杠杆倍数)
- *
- * @param margin 用户的保证金金额
- * @param leverage 杠杆倍数
- * @param faceValue 合约面值
- * @param markPrice 标记价格
- * @param minLotSz 最小下单精度
- * @return 返回用户可以购买的合约数量
- */
- public static BigDecimal buyCnt(BigDecimal margin, BigDecimal leverage, BigDecimal faceValue, BigDecimal markPrice, int minLotSz) {
- if (margin.compareTo(BigDecimal.ZERO) <= 0 ||
- leverage.compareTo(BigDecimal.ZERO) <= 0 ||
- faceValue.compareTo(BigDecimal.ZERO) <= 0 ||
- markPrice.compareTo(BigDecimal.ZERO) <= 0) {
- return BigDecimal.ZERO;
- }
-
- BigDecimal divisor = markPrice.divide(leverage, 10, BigDecimal.ROUND_DOWN);
- BigDecimal denominator = faceValue.multiply(divisor);
- return margin.divide(denominator, minLotSz, BigDecimal.ROUND_DOWN);
}
}
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 f76d187..c2e5abc 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
@@ -5,13 +5,14 @@
import com.alibaba.fastjson.JSONObject;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.CoinEnums;
import com.xcong.excoin.modules.okxNewPrice.okxWs.enums.OrderParamEnums;
-import com.xcong.excoin.modules.okxNewPrice.okxpi.MallUtils;
+import com.xcong.excoin.modules.okxNewPrice.utils.WsMapBuild;
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 java.math.BigDecimal;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
/**
* 交易订单处理类,负责构建和发送订单请求到OKX WebSocket
@@ -21,60 +22,34 @@
@Slf4j
public class TradeOrderWs {
+ public static final Map<String,String> TRADEORDERWSMAP = new ConcurrentHashMap<>();
+
public static final String ORDERWS_CHANNEL = "order";
- public static void orderEvent(WebSocketClient webSocketClient, RedisUtils redisUtils, String side) {
+ public static void orderEvent(WebSocketClient webSocketClient, String side) {
log.info("开始执行TradeOrderWs......");
- if (StrUtil.isBlank( side)){
- log.warn("止损了,下次再战...");
- return;
- }
- String live = (String) redisUtils.getWithDelay(ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state");
- if (!CoinEnums.ORDER_LIVE.getCode().equals( live)){
- log.warn("正在下单中,等待下单结束...");
- return;
- }
-
- String buyCnt = null;
- String ctval = getRedisValue(redisUtils, InstrumentsWs.INSTRUMENTSWS_CHANNEL, ":ctVal");
- String buyCntNormal = getRedisValue(redisUtils, PositionsWs.POSITIONSWS_CHANNEL, ":buyCnt");
- String pos = getRedisValue(redisUtils, PositionsWs.POSITIONSWS_CHANNEL, ":pos");
- if (OrderParamEnums.ORDERING.getValue().equals(side)) {
- log.warn("正在下单中,等待下单结束...");
- return;
- } else if (OrderParamEnums.HOLDING.getValue().equals(side)) {
- return;
- } else if (OrderParamEnums.INIT.getValue().equals(side)) {
- side = OrderParamEnums.BUY.getValue();
- if (StrUtil.isNotBlank(buyCntNormal) && new BigDecimal(buyCntNormal).compareTo(BigDecimal.ZERO) > 0) {
- buyCnt = buyCntNormal;
- }else{
- buyCnt = ctval;
- }
- } else if (OrderParamEnums.OUT.getValue().equals(side)) {
- log.info(OrderParamEnums.getNameByValue(OrderParamEnums.OUT.getValue()));
- side = OrderParamEnums.SELL.getValue();
- buyCnt = pos;
- } else if (OrderParamEnums.BUY.getValue().equals(side)){
- side = OrderParamEnums.BUY.getValue();
- if (StrUtil.isNotBlank(buyCntNormal) && new BigDecimal(buyCntNormal).compareTo(BigDecimal.ZERO) > 0) {
- buyCnt = buyCntNormal;
- }else{
- buyCnt = ctval;
- }
- }else if (OrderParamEnums.SELL.getValue().equals(side)){
- side = OrderParamEnums.SELL.getValue();
- buyCnt = getRedisValue(redisUtils, PositionsWs.POSITIONSWS_CHANNEL, ":pos");
- }else{
- log.warn("操作信号异常,请检查下单操作...");
- return;
- }
-
// 校验必要参数
if (StrUtil.isBlank(side)) {
log.warn("下单参数 side 为空,取消发送");
return;
+ }
+ String buyCnt = "";
+ if (OrderParamEnums.HOLDING.getValue().equals(side)){
+ log.info("当前状态为持仓中,取消发送");
+ return;
+ }else if (OrderParamEnums.OUT.getValue().equals(side)){
+ log.info("当前状态为止损");
+ buyCnt = String.valueOf(PositionsWs.POSITIONSWSMAP.get("pos"));
+ }else if (OrderParamEnums.INIT.getValue().equals(side)){
+ log.info("当前状态为初始化");
+ buyCnt = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.BUY_CNT.name());
+ }else if (OrderParamEnums.BUY.getValue().equals(side)){
+ log.info("当前状态为加仓");
+ buyCnt = InstrumentsWs.INSTRUMENTSWSMAP.get(CoinEnums.BUY_CNT.name());
+ }else if (OrderParamEnums.SELL.getValue().equals(side)){
+ log.info("当前状态为减仓");
+ buyCnt = String.valueOf(PositionsWs.POSITIONSWSMAP.get("pos"));
}
if (StrUtil.isBlank(buyCnt)) {
@@ -83,7 +58,7 @@
}
try {
- String clOrdId = MallUtils.getOrderNum(side);
+ String clOrdId = WsParamBuild.getOrderNum(side);
JSONArray argsArray = new JSONArray();
JSONObject args = new JSONObject();
args.put("instId", CoinEnums.HE_YUE.getCode());
@@ -95,17 +70,16 @@
args.put("sz", buyCnt);
argsArray.add(args);
- String connId = MallUtils.getOrderNum(ORDERWS_CHANNEL);
+ String connId = WsParamBuild.getOrderNum(ORDERWS_CHANNEL);
JSONObject jsonObject = WsParamBuild.buildJsonObject(connId, ORDERWS_CHANNEL, argsArray);
webSocketClient.send(jsonObject.toJSONString());
log.info("发送下单频道:{},数量:{}", side, buyCnt);
- boolean setResult =
- redisUtils.set(ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":clOrdId", clOrdId, 0)
- && redisUtils.set(ORDERWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", CoinEnums.ORDER_FILLED.getCode(), 0)
- && redisUtils.set(InstrumentsWs.INSTRUMENTSWS_CHANNEL + ":" + CoinEnums.HE_YUE.getCode() + ":state", OrderParamEnums.STATE_4.getValue(), 0);
- if (!setResult) {
- log.warn("Redis set operation failed for key: order:{}", CoinEnums.HE_YUE.getCode());
- }
+
+ WsMapBuild.saveStringToMap(TRADEORDERWSMAP, "clOrdId", connId);
+ WsMapBuild.saveStringToMap(TRADEORDERWSMAP, "state", CoinEnums.ORDER_FILLED.getCode());
+
+ WsMapBuild.saveStringToMap(InstrumentsWs.INSTRUMENTSWSMAP, CoinEnums.STATE.name(), OrderParamEnums.STATE_4.getValue());
+
} catch (Exception e) {
log.error("下单构建失败", e);
}
@@ -139,17 +113,4 @@
return profit.setScale(minTickSz, BigDecimal.ROUND_DOWN);
}
- /**
- * 统一封装 Redis Key 构建逻辑
- *
- * @param redisUtils Redis 工具类实例
- * @param prefix 渠道前缀
- * @param suffix 字段后缀
- * @return Redis 中存储的值
- */
- private static String getRedisValue(RedisUtils redisUtils, String prefix, String suffix) {
- String key = prefix + ":" + CoinEnums.HE_YUE.getCode() + suffix;
- Object valueObj = redisUtils.get(key);
- return valueObj == null ? null : String.valueOf(valueObj);
- }
}
\ No newline at end of file
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 0b39edd..35d2dce 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
@@ -14,48 +14,43 @@
*
* 若不添加该字段或将其设置为上述合法值以外的其他值,数据将根据事件推送并大约每 5 秒定期推送一次
*/
- UPDATEINTERVAL("2000",
- "2000"),
+ UPDATEINTERVAL("2000","2000"),
+
+ ORDER_FILLED("filled","filled"),
+ ORDER_LIVE("live","live"),
+
+ INSTTYPE_SWAP("SWAP","SWAP"),
+
+ ORDTYPE_MARKET("market","market"),
+
+ POSSIDE_SHORT("short","short"),
+
+ POSSIDE_LONG("long","long"),
+
+ SIDE_SELL("sell","sell"),
+
+ SIDE_BUY("buy","buy"),
+
+ CROSS("cross","cross"),
+
+ USDT("USDT","USDT"),
- ORDER_FILLED("filled",
- "filled"),
- ORDER_LIVE("live",
- "live"),
-
-
- INSTTYPE_SWAP("SWAP",
- "SWAP"),
-
-
- ORDTYPE_MARKET("market",
- "market"),
-
-
- POSSIDE_SHORT("short",
- "short"),
-
-
- POSSIDE_LONG("long",
- "long"),
-
-
- SIDE_SELL("sell",
- "sell"),
-
- SIDE_BUY("buy",
- "buy"),
-
- CROSS("cross",
- "cross"),
-
-
- USDT("USDT",
- "USDT"),
-
-
- HE_YUE("BTC-USDT-SWAP",
- "BTC-USDT-SWAP");
+ PING_CANG_SHOUYI("平仓收益比例", "0.2"),
+ //下单的总保障金为账户总金额cashBal * TOTAL_ORDER_USDT用来做保证金
+ TOTAL_ORDER_USDTPECENT("总保证金比例total_order_usdtpecent","0.1"),
+ TOTAL_ORDER_USDT("总保证金totalOrderUsdt","0"),
+ KANG_CANG("抗压比例KANG_CANG","0.8"),
+ ZHI_SUN("止损比例ZHI_SUN","0.5"),
+ //每次下单的张数
+ BUY_CNT("每次开仓的张数buyCnt","0.2"),
+ OUT("是否允许下单out","操作中"),
+ STATE("初始下单状态不允许下单state","0"),
+ CTVAL("合约面值ctVal","0.01"),
+ TICKSZ("下单价格精度tickSz","2"),
+ MINSZ("最小下单数小数位minSz","2"),
+ LEVERAGE("合约杠杆leverage","100"),
+ HE_YUE("合约instId","BTC-USDT-SWAP");
private String name;
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/OrderParamEnums.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/OrderParamEnums.java
index 6a16600..710fc71 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/OrderParamEnums.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/okxWs/enums/OrderParamEnums.java
@@ -26,17 +26,6 @@
STATE_1("允许开仓", "1"),
STATE_0("不允许开仓", "0"),
- ZHI_SUN("止损......", "0.6"),
-
- KANG_CANG("抗压......", "0.8"),
-
- LEVERAGE("杠杆倍数", "100"),
-
- PING_CANG_SHOUYI("平仓收益比例", "0.2"),
-
- EVERY_TIME_USDT("总下单次数", "50"),
- //下单的总保障金为账户总金额cashBal * TOTAL_ORDER_USDT用来做保证金
- TOTAL_ORDER_USDT("下单的总金额比例", "0.1"),
;
private String name;
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsMapBuild.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsMapBuild.java
new file mode 100644
index 0000000..c17fce5
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsMapBuild.java
@@ -0,0 +1,45 @@
+package com.xcong.excoin.modules.okxNewPrice.utils;
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ */
+@Slf4j
+public class WsMapBuild {
+
+ public static void saveBigDecimalToMap(Map<String,BigDecimal> accountMap, String key, BigDecimal value) {
+ try {
+ accountMap.put(key, value);
+ } catch (Exception e) {
+ log.error("保存账户数据到MAP 失败", e);
+ }
+ }
+
+ public static void saveStringToMap(Map<String,String> accountMap, String key, String value) {
+ try {
+ accountMap.put(key, value);
+ } catch (Exception e) {
+ log.error("保存账户数据到MAP 失败", e);
+ }
+ }
+
+ /**
+ * 安全地将字符串解析为 BigDecimal 类型
+ *
+ * @param value 字符串数值
+ * @return 解析后的 BigDecimal 对象,若解析失败则返回 null
+ */
+ public static BigDecimal parseBigDecimalSafe(String value) {
+ if (value == null || value.isEmpty()) {
+ return new BigDecimal(0);
+ }
+ return new BigDecimal(value);
+ }
+}
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsParamBuild.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsParamBuild.java
index ed386d0..082e530 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsParamBuild.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/utils/WsParamBuild.java
@@ -4,10 +4,36 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+
/**
* @author Administrator
*/
public class WsParamBuild {
+
+ public static String getOrderNum(String prefix) {
+ SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
+ String dd=df.format(new Date());
+ if (StrUtil.isNotBlank(prefix)) {
+ return prefix+dd+getRandomNum(5);
+ }
+ return dd+getRandomNum(5);
+ }
+
+ public static String getRandomNum(int length) {
+ String str = "0123456789";
+ Random random = new Random();
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; ++i) {
+ int number = random.nextInt(str.length());
+ sb.append(str.charAt(number));
+ }
+
+ return sb.toString();
+ }
public static JSONObject buildJsonObject(String connId, String option, JSONArray argsArray) {
JSONObject jsonObject = new JSONObject();
@@ -18,4 +44,31 @@
jsonObject.put("args", argsArray);
return jsonObject;
}
+
+
+ /**
+ * 计算购买合约的数量
+ *
+ * USDT 币本位合约
+ * 公式:张数 = 保证金 / (面值 * 标记价格 / 杠杆倍数)
+ *
+ * @param margin 用户的保证金金额
+ * @param leverage 杠杆倍数
+ * @param faceValue 合约面值
+ * @param markPrice 标记价格
+ * @param minLotSz 最小下单精度
+ * @return 返回用户可以购买的合约数量
+ */
+ public static BigDecimal buyCnt(BigDecimal margin, BigDecimal leverage, BigDecimal faceValue, BigDecimal markPrice, int minLotSz) {
+ if (margin.compareTo(BigDecimal.ZERO) <= 0 ||
+ leverage.compareTo(BigDecimal.ZERO) <= 0 ||
+ faceValue.compareTo(BigDecimal.ZERO) <= 0 ||
+ markPrice.compareTo(BigDecimal.ZERO) <= 0) {
+ return BigDecimal.ZERO;
+ }
+
+ BigDecimal divisor = markPrice.divide(leverage, 10, BigDecimal.ROUND_DOWN);
+ BigDecimal denominator = faceValue.multiply(divisor);
+ return margin.divide(denominator, minLotSz, BigDecimal.ROUND_DOWN);
+ }
}
--
Gitblit v1.9.1