From 917000befa702ed94fa12c4bf7395b940080eb71 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 02 Jun 2026 11:35:23 +0800
Subject: [PATCH] fix(okx): 修复账户余额获取和API请求处理问题
---
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java | 49 +++++++++++++++---------
src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxAlgoOrdersChannelHandler.java | 6 ++
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxTradeExecutor.java | 8 ++--
src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxPositionsChannelHandler.java | 6 ++
4 files changed, 44 insertions(+), 25 deletions(-)
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java
index 7b700d8..d0bc3b9 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java
@@ -356,7 +356,7 @@
// ---- 订单/条件单推送回调 ----
public void onOrderUpdate(String algoId, String state, String ordType) {
- if (!"effective".equals(state) && !"canceled".equals(state)) {
+ if (!"filled".equals(state) && !"canceled".equals(state)) {
return;
}
@@ -408,31 +408,33 @@
baseGridElement.setShortOrderId(baseShortTp.getEntryOrderId());
baseGridElement.setHasShortOrder(true);
- // 挂多仓止损 (id=-2 到 -11)
+ // 挂多仓止损 (id=-2 到 -11),每格 quantity 张
for (int id = -2; id >= -11; id--) {
OkxGridElement elem = OkxGridElement.findById(id);
if (elem == null) continue;
BigDecimal triggerPrice = elem.getGridPrice();
int finalId = id;
- executor.placeTakeProfit(triggerPrice.toString(), "sell", "long", "1",
+ executor.placeTakeProfit(triggerPrice.toString(), "sell", "long", config.getQuantity(),
profitId -> {
elem.setLongStopLossOrderId(profitId);
OkxGridElement.refreshIndices();
- log.info("[OKX] 多仓止损已挂, gridId:{}, 触发价:{}, stopLossId:{}", finalId, triggerPrice, profitId);
+ log.info("[OKX] 多仓止损已挂, gridId:{}, 触发价:{}, qty:{}, stopLossId:{}",
+ finalId, triggerPrice, config.getQuantity(), profitId);
});
}
- // 挂空仓止损 (id=2 到 11)
+ // 挂空仓止损 (id=2 到 11),每格 quantity 张
for (int id = 2; id <= 11; id++) {
OkxGridElement elem = OkxGridElement.findById(id);
if (elem == null) continue;
BigDecimal triggerPrice = elem.getGridPrice();
int finalId = id;
- executor.placeTakeProfit(triggerPrice.toString(), "buy", "short", "1",
+ executor.placeTakeProfit(triggerPrice.toString(), "buy", "short", config.getQuantity(),
profitId -> {
elem.setShortStopLossOrderId(profitId);
OkxGridElement.refreshIndices();
- log.info("[OKX] 空仓止损已挂, gridId:{}, 触发价:{}, stopLossId:{}", finalId, triggerPrice, profitId);
+ log.info("[OKX] 空仓止损已挂, gridId:{}, 触发价:{}, qty:{}, stopLossId:{}",
+ finalId, triggerPrice, config.getQuantity(), profitId);
});
}
@@ -561,10 +563,12 @@
BigDecimal triggerPrice = newEntryGrid.getGridPrice();
BigDecimal priceDiff = longEntryPrice.subtract(triggerPrice).abs();
- int entryQty = priceDiff.divide(config.getStep(), 0, RoundingMode.DOWN).intValue();
- entryQty = Math.max(1, entryQty);
+ int count = priceDiff.divide(config.getStep(), 0, RoundingMode.DOWN).intValue();
+ count = Math.max(1, count);
+ int entryQty = count * Integer.parseInt(config.getQuantity());
String size = String.valueOf(entryQty);
- log.info("[OKX] 多仓止损触发 gridId:{}, 在gridId:{}挂{}张多单", gridId, newEntryGridId, entryQty);
+ log.info("[OKX] 多仓止损触发 gridId:{}, 在gridId:{}挂{}张多单(价差:{},步长:{},count:{},qty:{})",
+ gridId, newEntryGridId, entryQty, priceDiff, config.getStep(), count, config.getQuantity());
newEntryGrid.getLongTraderParam().setQuantity(size);
placeEntryOrderWithPreFlag(newEntryGrid, true, triggerPrice, size);
}
@@ -601,15 +605,20 @@
BigDecimal triggerPrice = newEntryGrid.getGridPrice();
BigDecimal priceDiff = shortEntryPrice.subtract(triggerPrice).abs();
- int entryQty = priceDiff.divide(config.getStep(), 0, RoundingMode.DOWN).intValue();
- entryQty = Math.max(1, entryQty);
+ int count = priceDiff.divide(config.getStep(), 0, RoundingMode.DOWN).intValue();
+ count = Math.max(1, count);
+ int entryQty = count * Integer.parseInt(config.getQuantity());
String size = String.valueOf(entryQty);
- log.info("[OKX] 空仓止损触发 gridId:{}, 在gridId:{}挂{}张空单", gridId, newEntryGridId, entryQty);
+ log.info("[OKX] 空仓止损触发 gridId:{}, 在gridId:{}挂{}张空单(价差:{},步长:{},count:{},qty:{})",
+ gridId, newEntryGridId, entryQty, priceDiff, config.getStep(), count, config.getQuantity());
newEntryGrid.getShortTraderParam().setQuantity(size);
placeEntryOrderWithPreFlag(newEntryGrid, false, triggerPrice, size);
}
private void extendLongStopLoss(int filledQty) {
+ // filledQty 为本次新增止损张数 = count * quantity, 需要按 quantity 为粒度拆分为 count 个止损单
+ int qty = Integer.parseInt(config.getQuantity());
+ int stopLossCount = filledQty / qty;
int furthestSlId = 0;
for (OkxGridElement e : config.getGridElements()) {
if (e.getLongStopLossOrderId() != null && e.getId() < furthestSlId) {
@@ -617,14 +626,14 @@
}
}
if (furthestSlId == 0) furthestSlId = -11;
- log.info("[OKX] 多仓追挂止损, 当前最远止损gridId:{}, 追加{}张", furthestSlId, filledQty);
- for (int i = 0; i < filledQty; i++) {
+ log.info("[OKX] 多仓追挂止损, 当前最远止损gridId:{}, 追加{}单, 每单{}张", furthestSlId, stopLossCount, qty);
+ for (int i = 0; i < stopLossCount; i++) {
int newSlId = furthestSlId - i - 1;
OkxGridElement elem = OkxGridElement.findById(newSlId);
if (elem == null) continue;
BigDecimal triggerPrice = elem.getGridPrice();
int finalSlId = newSlId;
- executor.placeTakeProfit(triggerPrice.toString(), "sell", "long", "1",
+ executor.placeTakeProfit(triggerPrice.toString(), "sell", "long", config.getQuantity(),
profitId -> {
elem.setLongStopLossOrderId(profitId);
OkxGridElement.refreshIndices();
@@ -634,6 +643,8 @@
}
private void extendShortStopLoss(int filledQty) {
+ int qty = Integer.parseInt(config.getQuantity());
+ int stopLossCount = filledQty / qty;
int furthestSlId = 0;
for (OkxGridElement e : config.getGridElements()) {
if (e.getShortStopLossOrderId() != null && e.getId() > furthestSlId) {
@@ -641,14 +652,14 @@
}
}
if (furthestSlId == 0) furthestSlId = 11;
- log.info("[OKX] 空仓追挂止损, 当前最远止损gridId:{}, 追加{}张", furthestSlId, filledQty);
- for (int i = 0; i < filledQty; i++) {
+ log.info("[OKX] 空仓追挂止损, 当前最远止损gridId:{}, 追加{}单, 每单{}张", furthestSlId, stopLossCount, qty);
+ for (int i = 0; i < stopLossCount; i++) {
int newSlId = furthestSlId + i + 1;
OkxGridElement elem = OkxGridElement.findById(newSlId);
if (elem == null) continue;
BigDecimal triggerPrice = elem.getGridPrice();
int finalSlId = newSlId;
- executor.placeTakeProfit(triggerPrice.toString(), "buy", "short", "1",
+ executor.placeTakeProfit(triggerPrice.toString(), "buy", "short", config.getQuantity(),
profitId -> {
elem.setShortStopLossOrderId(profitId);
OkxGridElement.refreshIndices();
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxTradeExecutor.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxTradeExecutor.java
index 5f8ca15..640424a 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxTradeExecutor.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxTradeExecutor.java
@@ -86,7 +86,7 @@
* @param onFailure 失败回调
*/
public void openLong(String quantity, Consumer<String> onSuccess, Runnable onFailure) {
- submitOrder("buy", "long", quantity, "market", null, false, "tGridLong", onSuccess, onFailure);
+ submitOrder("buy", "long", quantity, "market", null, false, null, onSuccess, onFailure);
}
/**
@@ -97,7 +97,7 @@
* @param onFailure 失败回调
*/
public void openShort(String quantity, Consumer<String> onSuccess, Runnable onFailure) {
- submitOrder("sell", "short", quantity, "market", null, false, "tGridShort", onSuccess, onFailure);
+ submitOrder("sell", "short", quantity, "market", null, false, null, onSuccess, onFailure);
}
/**
@@ -233,7 +233,7 @@
}
/**
- * 异步取消所有未完成的 algo 订单。
+ * 异步取消所有未完成的 algo 订单(best-effort,失败仅警告)。
*/
public void cancelAllAlgoOrders() {
executor.execute(() -> {
@@ -243,7 +243,7 @@
okxAccount.baseUrl, "/api/v5/trade/cancel-algos", body, HttpMethod.POST, okxAccount.isSimluate());
log.info("[OkxExec] 已尝试清除条件单, resp:{}", resp);
} catch (Exception e) {
- log.error("[OkxExec] 清除条件单失败", e);
+ log.warn("[OkxExec] 清除条件单失败(若无挂单可忽略), msg:{}", e.getMessage());
}
});
}
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxAlgoOrdersChannelHandler.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxAlgoOrdersChannelHandler.java
index 5410920..11114d6 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxAlgoOrdersChannelHandler.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxAlgoOrdersChannelHandler.java
@@ -18,10 +18,12 @@
private static final String CHANNEL_NAME = "orders-algo";
private final String instId;
+ private final String instFamily;
private final OkxGridTradeService gridTradeService;
public OkxAlgoOrdersChannelHandler(String instId, OkxGridTradeService gridTradeService) {
this.instId = instId;
+ this.instFamily = instId.contains("-") ? instId.substring(0, instId.lastIndexOf("-")) : instId;
this.gridTradeService = gridTradeService;
}
@@ -34,12 +36,13 @@
JSONObject arg = new JSONObject();
arg.put("channel", CHANNEL_NAME);
arg.put("instType", "SWAP");
+ arg.put("instFamily", instFamily);
msg.put("op", "subscribe");
JSONArray args = new JSONArray();
args.add(arg);
msg.put("args", args);
ws.send(msg.toJSONString());
- log.info("[OKX-WS] {} 订阅成功", CHANNEL_NAME);
+ log.info("[OKX-WS] {} 订阅成功, instFamily:{}", CHANNEL_NAME, instFamily);
}
@Override
@@ -48,6 +51,7 @@
JSONObject arg = new JSONObject();
arg.put("channel", CHANNEL_NAME);
arg.put("instType", "SWAP");
+ arg.put("instFamily", instFamily);
msg.put("op", "unsubscribe");
JSONArray args = new JSONArray();
args.add(arg);
diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxPositionsChannelHandler.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxPositionsChannelHandler.java
index 5749544..51ae155 100644
--- a/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxPositionsChannelHandler.java
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/gridWs/OkxPositionsChannelHandler.java
@@ -20,10 +20,12 @@
private static final String CHANNEL_NAME = "positions";
private final String instId;
+ private final String instFamily;
private final OkxGridTradeService gridTradeService;
public OkxPositionsChannelHandler(String instId, OkxGridTradeService gridTradeService) {
this.instId = instId;
+ this.instFamily = instId.contains("-") ? instId.substring(0, instId.lastIndexOf("-")) : instId;
this.gridTradeService = gridTradeService;
}
@@ -36,12 +38,13 @@
JSONObject arg = new JSONObject();
arg.put("channel", CHANNEL_NAME);
arg.put("instType", "SWAP");
+ arg.put("instFamily", instFamily);
msg.put("op", "subscribe");
JSONArray args = new JSONArray();
args.add(arg);
msg.put("args", args);
ws.send(msg.toJSONString());
- log.info("[OKX-WS] {} 订阅成功", CHANNEL_NAME);
+ log.info("[OKX-WS] {} 订阅成功, instFamily:{}", CHANNEL_NAME, instFamily);
}
@Override
@@ -50,6 +53,7 @@
JSONObject arg = new JSONObject();
arg.put("channel", CHANNEL_NAME);
arg.put("instType", "SWAP");
+ arg.put("instFamily", instFamily);
msg.put("op", "unsubscribe");
JSONArray args = new JSONArray();
args.add(arg);
--
Gitblit v1.9.1