From f4d1d77b2ea56e01ca57306f3a4b522037df7ae2 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Thu, 07 May 2026 14:55:42 +0800
Subject: [PATCH] fix(gateApi): 设置初始订单为仅减仓模式
---
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java | 128 +++++++++++++++++++++++++++++++++++++++---
1 files changed, 118 insertions(+), 10 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 13b72e4..3074c07 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -5,7 +5,11 @@
import io.gate.gateapi.GateApiException;
import io.gate.gateapi.api.FuturesApi;
import io.gate.gateapi.models.FuturesAccount;
+import io.gate.gateapi.models.FuturesInitialOrder;
import io.gate.gateapi.models.FuturesOrder;
+import io.gate.gateapi.models.FuturesPriceTrigger;
+import io.gate.gateapi.models.FuturesPriceTriggeredOrder;
+import io.gate.gateapi.models.TriggerOrderResponse;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
@@ -42,6 +46,7 @@
private final int maxCycles;
private final BigDecimal maxLoss;
private final String quantity;
+ private final String positionMode;
private volatile boolean strategyActive = false;
private int currentCycle = 0;
@@ -50,13 +55,19 @@
private BigDecimal shortEntryPrice;
private Long longOrderId;
private Long shortOrderId;
+ private Long longTpOrderId;
+ private Long longSlOrderId;
+ private Long shortTpOrderId;
+ private Long shortSlOrderId;
private volatile BigDecimal lastClosePrice;
public GateGridTradeService(String apiKey, String apiSecret,
- String contract, String leverage, String marginMode,
+ String contract, String leverage,
+ String marginMode,String positionMode,
BigDecimal gridRate, BigDecimal overallTp,
- int maxCycles, BigDecimal maxLoss, String quantity) {
+ int maxCycles, BigDecimal maxLoss,
+ String quantity) {
this.contract = contract;
this.leverage = leverage;
this.marginMode = marginMode;
@@ -65,6 +76,7 @@
this.maxCycles = maxCycles;
this.maxLoss = maxLoss;
this.quantity = quantity;
+ this.positionMode = positionMode;
this.apiClient = new ApiClient();
this.apiClient.setBasePath("https://api-testnet.gateapi.io/api/v4");
@@ -77,16 +89,18 @@
*/
public void init() {
try {
- futuresApi.setPositionMode(SETTLE, "dual");
- log.info("[GateGrid] 已设置双向持仓模式");
-
futuresApi.updateContractPositionLeverageCall(
- SETTLE, contract, leverage, marginMode, "dual", null);
+ SETTLE, contract, leverage, marginMode, positionMode, null);
log.info("[GateGrid] 已设置杠杆: {}x, 保证金模式: {}", leverage, marginMode);
FuturesAccount account = futuresApi.listFuturesAccounts(SETTLE);
log.info("[GateGrid] 账户可用余额: {}, 总资产: {}",
account.getAvailable(), account.getTotal());
+ String positionModeSet = account.getPositionMode();
+ if (!positionMode.equals(positionModeSet)){
+ futuresApi.setPositionMode(SETTLE, positionMode);
+ }
+ log.info("[GateGrid] 已设置双向持仓模式");
} catch (GateApiException e) {
log.error("[GateGrid] 初始化失败, label: {}, msg: {}", e.getErrorLabel(), e.getMessage());
} catch (ApiException e) {
@@ -114,6 +128,10 @@
*/
public void stopGrid() {
strategyActive = false;
+ cancelTpSl(longTpOrderId);
+ cancelTpSl(longSlOrderId);
+ cancelTpSl(shortTpOrderId);
+ cancelTpSl(shortSlOrderId);
closeAllPositions();
log.info("[GateGrid] 网格策略已停止, 总盈亏: {}, 循环: {}", totalProfit, currentCycle);
}
@@ -144,6 +162,7 @@
longOrderId = longResult.getId();
longEntryPrice = safeDecimal(longResult.getFillPrice());
log.info("[GateGrid] 开多成功, price: {}, id: {}", longEntryPrice, longOrderId);
+ placeLongTpSl(longEntryPrice);
FuturesOrder shortOrder = new FuturesOrder();
shortOrder.setContract(contract);
@@ -155,6 +174,7 @@
shortOrderId = shortResult.getId();
shortEntryPrice = safeDecimal(shortResult.getFillPrice());
log.info("[GateGrid] 开空成功, price: {}, id: {}", shortEntryPrice, shortOrderId);
+ placeShortTpSl(shortEntryPrice);
printGridInfo();
} catch (GateApiException e) {
@@ -163,6 +183,70 @@
} catch (Exception e) {
log.error("[GateGrid] 双开异常", e);
strategyActive = false;
+ }
+ }
+
+ private void placeLongTpSl(BigDecimal entryPrice) {
+ BigDecimal tpPrice = entryPrice.multiply(BigDecimal.ONE.add(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ BigDecimal slPrice = entryPrice.multiply(BigDecimal.ONE.subtract(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ longTpOrderId = placePriceTriggeredOrder(tpPrice, FuturesPriceTrigger.RuleEnum.NUMBER_1, "close-long-position", "close_long");
+ longSlOrderId = placePriceTriggeredOrder(slPrice, FuturesPriceTrigger.RuleEnum.NUMBER_2, "close-long-position", "close_long");
+ log.info("[GateGrid] 多头TP/SL已设置, TP:{}, SL:{}, tpId:{}, slId:{}", tpPrice, slPrice, longTpOrderId, longSlOrderId);
+ }
+
+ private void placeShortTpSl(BigDecimal entryPrice) {
+ BigDecimal tpPrice = entryPrice.multiply(BigDecimal.ONE.subtract(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ BigDecimal slPrice = entryPrice.multiply(BigDecimal.ONE.add(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ shortTpOrderId = placePriceTriggeredOrder(tpPrice, FuturesPriceTrigger.RuleEnum.NUMBER_2, "close-short-position", "close_short");
+ shortSlOrderId = placePriceTriggeredOrder(slPrice, FuturesPriceTrigger.RuleEnum.NUMBER_1, "close-short-position", "close_short");
+ log.info("[GateGrid] 空头TP/SL已设置, TP:{}, SL:{}, tpId:{}, slId:{}", tpPrice, slPrice, shortTpOrderId, shortSlOrderId);
+ }
+
+ private Long placePriceTriggeredOrder(BigDecimal triggerPrice,
+ FuturesPriceTrigger.RuleEnum rule,
+ String orderType,
+ String autoSize) {
+ try {
+ FuturesPriceTrigger trigger = new FuturesPriceTrigger();
+ trigger.setStrategyType(FuturesPriceTrigger.StrategyTypeEnum.NUMBER_0);
+ trigger.setPriceType(FuturesPriceTrigger.PriceTypeEnum.NUMBER_0);
+ trigger.setPrice(triggerPrice.toString());
+ trigger.setRule(rule);
+ trigger.setExpiration(0);
+
+ FuturesInitialOrder initial = new FuturesInitialOrder();
+ initial.setContract(contract);
+ initial.setSize(0L);
+ initial.setPrice("0");
+ initial.setTif(FuturesInitialOrder.TifEnum.IOC);
+ initial.setReduceOnly(true);
+ initial.setAutoSize(autoSize);
+
+ FuturesPriceTriggeredOrder order = new FuturesPriceTriggeredOrder();
+ order.setTrigger(trigger);
+ order.setInitial(initial);
+ order.setOrderType(orderType);
+
+ TriggerOrderResponse response = futuresApi.createPriceTriggeredOrder(SETTLE, order);
+ log.info("[GateGrid] 条件单已创建, triggerPrice:{}, rule:{}, orderType:{}, autoSize:{}, id:{}",
+ triggerPrice, rule, orderType, autoSize, response.getId());
+ return response.getId();
+ } catch (Exception e) {
+ log.error("[GateGrid] 创建条件单失败, triggerPrice:{}, rule:{}, orderType:{}, autoSize:{}",
+ triggerPrice, rule, orderType, autoSize, e);
+ return null;
+ }
+ }
+
+ private void cancelTpSl(Long orderId) {
+ if (orderId == null) {
+ return;
+ }
+ try {
+ futuresApi.cancelPriceTriggeredOrder(SETTLE, orderId);
+ log.info("[GateGrid] 已取消条件单, id:{}", orderId);
+ } catch (Exception e) {
+ log.warn("[GateGrid] 取消条件单失败, id:{}", orderId, e);
}
}
@@ -258,7 +342,9 @@
}
private void closeLongPosition() {
- if (longEntryPrice == null) return;
+ if (longEntryPrice == null) {
+ return;
+ }
try {
FuturesOrder closeOrder = new FuturesOrder();
closeOrder.setContract(contract);
@@ -274,10 +360,16 @@
}
longEntryPrice = null;
longOrderId = null;
+ cancelTpSl(longTpOrderId);
+ cancelTpSl(longSlOrderId);
+ longTpOrderId = null;
+ longSlOrderId = null;
}
private void closeShortPosition() {
- if (shortEntryPrice == null) return;
+ if (shortEntryPrice == null) {
+ return;
+ }
try {
FuturesOrder closeOrder = new FuturesOrder();
closeOrder.setContract(contract);
@@ -293,6 +385,10 @@
}
shortEntryPrice = null;
shortOrderId = null;
+ cancelTpSl(shortTpOrderId);
+ cancelTpSl(shortSlOrderId);
+ shortTpOrderId = null;
+ shortSlOrderId = null;
}
private void closeAllPositions() {
@@ -301,10 +397,22 @@
}
private void printGridInfo() {
+ BigDecimal longTp = BigDecimal.ZERO;
+ BigDecimal longSl = BigDecimal.ZERO;
+ BigDecimal shortTp = BigDecimal.ZERO;
+ BigDecimal shortSl = BigDecimal.ZERO;
+ if (longEntryPrice != null) {
+ longTp = longEntryPrice.multiply(BigDecimal.ONE.add(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ longSl = longEntryPrice.multiply(BigDecimal.ONE.subtract(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ }
+ if (shortEntryPrice != null) {
+ shortTp = shortEntryPrice.multiply(BigDecimal.ONE.subtract(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ shortSl = shortEntryPrice.multiply(BigDecimal.ONE.add(gridRate)).setScale(1, RoundingMode.HALF_UP);
+ }
System.out.println("========== Gate 网格开仓 ==========");
System.out.println("合约: " + contract + " 杠杆: " + leverage + "x " + marginMode);
- System.out.println("多头入场: " + longEntryPrice);
- System.out.println("空头入场: " + shortEntryPrice);
+ System.out.println("多头入场: " + longEntryPrice + " TP: " + longTp + " SL: " + longSl);
+ System.out.println("空头入场: " + shortEntryPrice + " TP: " + shortTp + " SL: " + shortSl);
System.out.println("数量: " + quantity + " 网格间距: " + gridRate.multiply(new BigDecimal("100")) + "%");
System.out.println("整体止盈: " + overallTp + " USDT 最大循环: " + maxCycles);
System.out.println("最大亏损: " + maxLoss + " USDT");
--
Gitblit v1.9.1