From da014bcdd947e917181c757e7046e8dc1263f881 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 22 Sep 2026 17:56:33 +0800
Subject: [PATCH] fix(gateApi): 修复网格交易中长短仓逻辑错误
---
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java | 46 +++++++++++++++++++++++++++-------------------
1 files changed, 27 insertions(+), 19 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 6612d63..3a2bb2a 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -188,13 +188,19 @@
}
/**
- * 构建容错的 JSON 序列化器,跳过 {@code finishAs} 字段的反序列化。
+ * 构建容错的 JSON 序列化器,跳过部分枚举不完整字段的反序列化。
*
- * <p>gate-api SDK 的 {@code FuturesOrder.FinishAsEnum} 枚举不完整,缺少
- * {@code price_rate_proteced}(价格保护)等 Gate 实际会返回的值。反序列化未知
- * 枚举值时 {@code fromValue} 会抛 {@link IllegalArgumentException},导致已成功
- * 提交的订单被误判为失败(如日志 {@code Unexpected value 'price_rate_proteced'})。
- * 业务不使用 finishAs 字段,因此通过 Gson 排除策略直接跳过其解析。
+ * <p>gate-api SDK 的枚举定义滞后于交易所实际返回值,反序列化未知枚举值时
+ * {@code fromValue} 会抛 {@link IllegalArgumentException},导致接口被误判为失败。
+ * 已确认业务不使用以下字段,因此通过 Gson 排除策略直接跳过其解析:
+ * <ul>
+ * <li>{@code finishAs}:{@code FuturesOrder.FinishAsEnum} 缺少
+ * {@code price_rate_protected}(价格保护)等值(如日志
+ * {@code Unexpected value 'price_rate_proteced'});</li>
+ * <li>{@code posMarginMode}:{@code FuturesPriceTriggeredOrder.PosMarginModeEnum}
+ * 只定义 {@code cross}/{@code dual},而 {@code cancelPriceTriggeredOrderList}
+ * 会返回组合值 {@code cross|dual}(如日志 {@code Unexpected value 'cross|dual'})。</li>
+ * </ul>
*/
private static JSON buildLenientJson() {
JSON json = new JSON();
@@ -202,7 +208,13 @@
.setExclusionStrategies(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
- return "finishAs".equals(f.getName());
+ if ("finishAs".equals(f.getName())) {
+ return true;
+ }
+ // 仅跳过 FuturesPriceTriggeredOrder 的 posMarginMode,避免误伤
+ // FuturesOrder / Position 的同名字段(二者语义为 isolated/cross)
+ return "posMarginMode".equals(f.getName())
+ && FuturesPriceTriggeredOrder.class.equals(f.getDeclaringClass());
}
@Override
@@ -517,7 +529,7 @@
config.isPriceDriveEnabled() &&
longActive == false &&
longPositionSize.compareTo(BigDecimal.ZERO) == 0){
- processShortGrid(closePrice);
+ processLongGrid(closePrice);
}
@@ -525,7 +537,7 @@
config.isPriceDriveEnabled() &&
shortActive == false &&
shortPositionSize.compareTo(BigDecimal.ZERO) == 0){
- processLongGrid(closePrice);
+ processShortGrid(closePrice);
}
}
@@ -936,12 +948,6 @@
generateShortQueue();
generateLongQueue();
updateGridElements();
-
- GridElement baseGridElement = GridElement.findById(0);
- baseGridElement.setLongOrderId(baseLongTraderParam.getEntryOrderId());
- baseGridElement.setHasLongOrder(true);
- baseGridElement.setShortOrderId(baseShortTraderParam.getEntryOrderId());
- baseGridElement.setHasShortOrder(true);
// // 空仓止损对应的多仓止盈:多仓止盈挂在ID=3
// int tpGridIdLong = 3;
@@ -1437,7 +1443,8 @@
}
- private void processShortGrid(BigDecimal currentPrice) {
+ /** 多仓仓位归零后,在当前价上方最近网格重新挂多单(遍历 totalLongPriceQueue 升序)。 */
+ private void processLongGrid(BigDecimal currentPrice) {
BigDecimal matched = BigDecimal.ZERO;
synchronized (totalLongPriceQueue) {
for (BigDecimal p : totalLongPriceQueue) {
@@ -1510,7 +1517,8 @@
}
- private void processLongGrid(BigDecimal currentPrice) {
+ /** 空仓仓位归零后,在当前价下方最近网格重新挂空单(遍历 totalShortPriceQueue 降序)。 */
+ private void processShortGrid(BigDecimal currentPrice) {
BigDecimal matched = BigDecimal.ZERO;
synchronized (totalShortPriceQueue) {
for (BigDecimal p : totalShortPriceQueue) {
@@ -1559,7 +1567,7 @@
GridElement finalCancelCursor = cancelCursor;
executor.cancelConditionalOrder(shortOrderId, oid -> {
shortEntryTraderIdParam(finalCancelCursor, shortOrderId, false);
- log.info("[Gate] 空仓仓位归零, 取消gridId:{}的多单{}", finalCancelCursor.getId(), shortOrderId);
+ log.info("[Gate] 空仓仓位归零, 取消gridId:{}的空单{}", finalCancelCursor.getId(), shortOrderId);
});
}
}
@@ -1570,7 +1578,7 @@
if (!newEntryGrid.isHasShortOrder() && !hasShortOrderAbove){
BigDecimal triggerPrice = newEntryGrid.getGridPrice();
String size = quantity;
- log.info("[Gate] 空仓仓位归零 gridId:{}, 挂{}基础张多单",
+ log.info("[Gate] 空仓仓位归零 gridId:{}, 挂{}基础张空单",
newEntryGrid.getId(), size);
newEntryGrid.getShortTraderParam().setQuantity(size);
placeEntryOrderWithPreFlag(newEntryGrid, false, triggerPrice,
--
Gitblit v1.9.1