From f87f6265a05c720fcf0628f71aa3ca91e2a55377 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Mon, 22 Jun 2026 13:32:52 +0800
Subject: [PATCH] refactor(gateApi): 优化网格交易持仓查询逻辑
---
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java | 143 +++++++++++++----------------------------------
1 files changed, 41 insertions(+), 102 deletions(-)
diff --git a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
index 01bea3a..3bf8290 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -309,6 +309,8 @@
accumulatedShortLossCount = 0;
shortPriceQueue.clear();
longPriceQueue.clear();
+ totalShortPriceQueue.clear();
+ totalLongPriceQueue.clear();
currentLongOrderIds.clear();
currentShortOrderIds.clear();
// 每次重启重新获取当前本金
@@ -632,17 +634,18 @@
if (shortGridElement.isHasShortOrder() && StrUtil.isNotEmpty(tradeId) && !tradeId.equals("0") ){
int filledQty = Integer.parseInt(shortGridElement.getShortTraderParam().getQuantity());
shortEntryTraderIdParam(shortGridElement, null, false);
- // [Gate-需求2] 加仓后先撤空仓所有止盈+止损,再重挂
+ // [Gate-需求2] 加仓后先撤空仓所有止盈+止损,再查交易所持仓后重挂
cancelAllShortTakeProfitsAndStopLosses();
- extendShortStopLoss(filledQty,shortGridElement.getId());
+ int posSize = queryPositionSize(Position.ModeEnum.DUAL_SHORT);
+ extendShortStopLoss(posSize, shortGridElement.getId());
accumulatedShortLossCount = 0; // 加仓订单成交,重置止损累计
- log.info("[Gate] 空单成交 gridId:{}", filledQty);
+ log.info("[Gate] 空单成交 gridId:{}, 当前持仓:{}张", filledQty, posSize);
// 空仓持仓超过baseQuantity时,从gridId-2开始向外追挂止盈
BigDecimal shortBaseQty = new BigDecimal(config.getBaseQuantity());
BigDecimal shortGridQty = new BigDecimal(config.getQuantity());
- if (shortPositionSize.compareTo(shortBaseQty) > 0) {
- BigDecimal shortExcess = shortPositionSize.subtract(shortBaseQty);
+ if (BigDecimal.valueOf(posSize).compareTo(shortBaseQty) > 0) {
+ BigDecimal shortExcess = BigDecimal.valueOf(posSize).subtract(shortBaseQty);
int shortExcessCount = shortExcess.divide(shortGridQty, 0, RoundingMode.DOWN).intValue();
for (int i = 0; i < shortExcessCount; i++) {
int tpGridId = shortGridElement.getId() - 2 - i;
@@ -673,17 +676,18 @@
int filledQty = Integer.parseInt(longGridElement.getLongTraderParam().getQuantity());
longEntryTraderIdParam(longGridElement, null, false);
- // [Gate-需求2] 加仓后先撤多仓所有止盈+止损,再重挂
+ // [Gate-需求2] 加仓后先撤多仓所有止盈+止损,再查交易所持仓后重挂
cancelAllLongTakeProfitsAndStopLosses();
- extendLongStopLoss(filledQty,longGridElement.getId());
+ int posSize = queryPositionSize(Position.ModeEnum.DUAL_LONG);
+ extendLongStopLoss(posSize, longGridElement.getId());
accumulatedLongLossCount = 0; // 加仓订单成交,重置止损累计
- log.info("[Gate] 多单成交 gridId:{}", filledQty);
+ log.info("[Gate] 多单成交 gridId:{}, 当前持仓:{}张", filledQty, posSize);
// 多仓持仓超过baseQuantity时,从gridId+2开始向外追挂止盈
BigDecimal longBaseQty = new BigDecimal(config.getBaseQuantity());
BigDecimal longGridQty = new BigDecimal(config.getQuantity());
- if (longPositionSize.compareTo(longBaseQty) > 0) {
- BigDecimal longExcess = longPositionSize.subtract(longBaseQty);
+ if (BigDecimal.valueOf(posSize).compareTo(longBaseQty) > 0) {
+ BigDecimal longExcess = BigDecimal.valueOf(posSize).subtract(longBaseQty);
int longExcessCount = longExcess.divide(longGridQty, 0, RoundingMode.DOWN).intValue();
for (int i = 0; i < longExcessCount; i++) {
int tpGridId = longGridElement.getId() + 2 + i;
@@ -710,6 +714,29 @@
}
}
+
+ /**
+ * 查询交易所当前持仓张数(绝对值)。加仓/开仓后重挂止盈止损时调用,
+ * 绕过本地 WS 推送缓存避免时序竞态,直接拿到交易所权威数据。
+ *
+ * @param mode 持仓模式(DUAL_LONG / DUAL_SHORT)
+ * @return 持仓张数(绝对值),查询失败返回 0
+ */
+ private int queryPositionSize(Position.ModeEnum mode) {
+ try {
+ List<Position> positions = futuresApi.listPositions(SETTLE).execute();
+ if (positions != null) {
+ for (Position p : positions) {
+ if (mode == p.getMode() && config.getContract().equals(p.getContract())) {
+ return new BigDecimal(p.getSize()).abs().intValue();
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.warn("[Gate] 查询{}持仓失败", mode, e);
+ }
+ return 0;
+ }
// ---- 网格队列处理 ----
@@ -878,6 +905,8 @@
*/
private void generateShortQueue() {
shortPriceQueue.clear();
+ totalShortPriceQueue.clear();
+ totalLongPriceQueue.clear();
int prec = config.getPriceScale();
BigDecimal step = shortBaseEntryPrice.multiply(config.getGridRate()).setScale(prec, RoundingMode.HALF_UP);
config.setStep(step);
@@ -990,8 +1019,8 @@
elements.add(GridElement.builder()
.id(0)
.gridPrice(price)
- .upId(shortSize > 0 ? 1 : null)
- .downId(longSize > 0 ? -1 : null)
+ .upId(longSize > 0 ? 1 : null)
+ .downId(shortSize > 0 ? -1 : null)
.longTraderParam(longParam)
.shortTraderParam(shortParam)
.build());
@@ -1253,96 +1282,6 @@
});
}
}
-
- // ========== 止盈/止损取消辅助方法 ==========
-
- /**
- * 取消最远的多仓止损订单。
- * 多仓止损在 gridId 负方向,最远 = id 最小。
- */
- private void cancelFarthestLongStopLoss() {
- GridElement farthest = null;
- for (GridElement e : config.getGridElements()) {
- if (e.getLongStopLossOrderId() != null) {
- if (farthest == null || e.getId() < farthest.getId()) {
- farthest = e;
- }
- }
- }
- if (farthest != null) {
- String slId = farthest.getLongStopLossOrderId();
- farthest.setLongStopLossOrderId(null);
- GridElement.refreshIndices();
- GridElement finalFarthest = farthest;
- executor.cancelConditionalOrder(slId, oid ->
- log.info("[Gate] 止盈触发, 取消最远多仓止损 gridId:{}, orderId:{}", finalFarthest.getId(), slId));
- }
- }
-
- /**
- * 取消最远的空仓止损订单。
- * 空仓止损在 gridId 正方向,最远 = id 最大。
- */
- private void cancelFarthestShortStopLoss() {
- GridElement farthest = null;
- for (GridElement e : config.getGridElements()) {
- if (e.getShortStopLossOrderId() != null) {
- if (farthest == null || e.getId() > farthest.getId()) {
- farthest = e;
- }
- }
- }
- if (farthest != null) {
- String slId = farthest.getShortStopLossOrderId();
- farthest.setShortStopLossOrderId(null);
- GridElement.refreshIndices();
- GridElement finalFarthest = farthest;
- executor.cancelConditionalOrder(slId, oid ->
- log.info("[Gate] 止盈触发, 取消最远空仓止损 gridId:{}, orderId:{}", finalFarthest.getId(), slId));
- }
- }
-
- /**
- * 取消所有多仓止盈 + 多仓止损订单(加仓后重建前清场)。
- */
- private void cancelAllLongTakeProfitsAndStopLosses() {
- for (GridElement e : config.getGridElements()) {
- String tpId = e.getLongTakeProfitOrderId();
- if (tpId != null) {
- e.setLongTakeProfitOrderId(null);
- executor.cancelConditionalOrder(tpId, oid -> {});
- }
- String slId = e.getLongStopLossOrderId();
- if (slId != null) {
- e.setLongStopLossOrderId(null);
- executor.cancelConditionalOrder(slId, oid -> {});
- }
- }
- GridElement.refreshIndices();
- log.info("[Gate] 已提交取消所有多仓止盈+止损");
- }
-
- /**
- * 取消所有空仓止盈 + 空仓止损订单(加仓后重建前清场)。
- */
- private void cancelAllShortTakeProfitsAndStopLosses() {
- for (GridElement e : config.getGridElements()) {
- String tpId = e.getShortTakeProfitOrderId();
- if (tpId != null) {
- e.setShortTakeProfitOrderId(null);
- executor.cancelConditionalOrder(tpId, oid -> {});
- }
- String slId = e.getShortStopLossOrderId();
- if (slId != null) {
- e.setShortStopLossOrderId(null);
- executor.cancelConditionalOrder(slId, oid -> {});
- }
- }
- GridElement.refreshIndices();
- log.info("[Gate] 已提交取消所有空仓止盈+止损");
- }
-
- // ========== 止损追单 ==========
private void extendLongStopLoss(int filledQty,int gridId) {
int furthestSlId = 0;
--
Gitblit v1.9.1