From e9a397babbbfa9cff8a5ed026447d585e739c37f Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Tue, 12 May 2026 21:47:21 +0800
Subject: [PATCH] refactor(gateApi): 将网格交易策略从限价单改为条件单
---
src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java | 148 ++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 145 insertions(+), 3 deletions(-)
diff --git a/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java b/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java
index 6de0e63..9f155e6 100644
--- a/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java
+++ b/src/main/java/com/xcong/excoin/modules/gateApi/GateTradeExecutor.java
@@ -14,6 +14,7 @@
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
/**
* Gate REST API 执行器。
@@ -37,19 +38,33 @@
*
* <h3>调用链</h3>
* <pre>
- * GateGridTradeService.onKline → executor.openLong/openShort (基底双开 + 网格触发)
- * GateGridTradeService.onPositionUpdate → executor.placeTakeProfit (开仓成交后设止盈)
+ * // 基底双开
+ * GateGridTradeService.init → executor.openLong / executor.openShort
+ *
+ * // 网格条件开仓
+ * GateGridTradeService.tryGenerateQueues / processShortGrid / processLongGrid
+ * → executor.placeConditionalEntryOrder(价格触发后市价 IOC 开仓)
+ * → executor.cancelConditionalOrder(取消对方方向旧条件单)
+ *
+ * // 止盈
+ * GateGridTradeService.onPositionUpdate → executor.placeTakeProfit(开仓后设止盈条件单)
+ *
+ * // 停止
* GateGridTradeService.stopGrid → executor.cancelAllPriceTriggeredOrders
* </pre>
*
- * @author Administrator
+ * <h3>遗留方法(当前策略未使用)</h3>
+ * {@link #placeGridLimitOrder(BigDecimal, String, Consumer, Runnable)} 和
+ * {@link #cancelOrder(String)} 为旧版限价单策略的遗留方法,保留以备后续使用。
*/
@Slf4j
public class GateTradeExecutor {
private static final String SETTLE = "usdt";
+ /** Gate U 本位合约 REST API */
private final FuturesApi futuresApi;
+ /** 合约名称(如 ETH_USDT) */
private final String contract;
/** 交易线程池:单线程 + 有界队列 + 背压策略 */
@@ -209,6 +224,133 @@
}
/**
+ * <b>遗留方法 — 当前条件单策略未使用</b>
+ *
+ * <p>异步挂限价单(GTC),用于旧版网格限价开仓。当前策略改用
+ * {@link #placeConditionalEntryOrder(BigDecimal, FuturesPriceTrigger.RuleEnum, String, Consumer, Runnable)}。
+ *
+ * @param price 限价价格
+ * @param size 下单张数(正=多 / 负=空)
+ * @param onSuccess 成功回调,接收 orderId(可为 null)
+ * @param onFailure 失败回调(可为 null)
+ */
+ public void placeGridLimitOrder(BigDecimal price, String size, Consumer<String> onSuccess, Runnable onFailure) {
+ executor.execute(() -> {
+ try {
+ FuturesOrder order = new FuturesOrder();
+ order.setContract(contract);
+ order.setSize(size);
+ order.setPrice(price.toString());
+ order.setTif(FuturesOrder.TifEnum.GTC);
+ order.setText(size.startsWith("-") ? "t-grid-limit-short" : "t-grid-limit-long");
+ FuturesOrder result = futuresApi.createFuturesOrder(SETTLE, order, null);
+ log.info("[TradeExec] 限价单已挂, price:{}, size:{}, id:{}, status:{}", price, size, result.getId(), result.getStatus());
+ if (onSuccess != null) {
+ onSuccess.accept(String.valueOf(result.getId()));
+ }
+ } catch (Exception e) {
+ log.error("[TradeExec] 限价单挂单失败, price:{}, size:{}", price, size, e);
+ if (onFailure != null) {
+ onFailure.run();
+ }
+ }
+ });
+ }
+
+ /**
+ * <b>遗留方法 — 当前条件单策略未使用</b>
+ *
+ * <p>异步取消指定限价单。当前策略改用 {@link #cancelConditionalOrder(String)}。
+ *
+ * @param orderId 订单 ID,为 null 时跳过
+ */
+ public void cancelOrder(String orderId) {
+ if (orderId == null) {
+ return;
+ }
+ executor.execute(() -> {
+ try {
+ FuturesOrder cancelled = futuresApi.cancelFuturesOrder(SETTLE, orderId, null);
+ log.info("[TradeExec] 订单已取消, id:{}, status:{}", orderId, cancelled.getStatus());
+ } catch (Exception e) {
+ log.warn("[TradeExec] 取消订单失败(可能已成交), id:{}", orderId);
+ }
+ });
+ }
+
+ /**
+ * 异步创建条件开仓单(价格触发后市价开仓)。
+ *
+ * <p>服务器监控价格,达到触发价后以市价 IOC 开仓。与止盈单不同,不设 order_type(默认开仓),
+ * reduce_only=false。
+ *
+ * @param triggerPrice 触发价格
+ * @param rule 触发规则(NUMBER_1: 最新价≥触发价时执行;NUMBER_2: 最新价≤触发价时执行)
+ * @param size 开仓张数(正=开多,负=开空)
+ * @param onSuccess 成功回调,接收 conditionOrderId
+ * @param onFailure 失败回调
+ */
+ public void placeConditionalEntryOrder(BigDecimal triggerPrice,
+ FuturesPriceTrigger.RuleEnum rule,
+ String size,
+ Consumer<String> onSuccess,
+ Runnable onFailure) {
+ executor.execute(() -> {
+ 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(Long.parseLong(size));
+ initial.setPrice("0");
+ initial.setTif(FuturesInitialOrder.TifEnum.IOC);
+ initial.setReduceOnly(false);
+
+ FuturesPriceTriggeredOrder order = new FuturesPriceTriggeredOrder();
+ order.setTrigger(trigger);
+ order.setInitial(initial);
+
+ TriggerOrderResponse response = futuresApi.createPriceTriggeredOrder(SETTLE, order);
+ String orderId = String.valueOf(response.getId());
+ log.info("[TradeExec] 条件开仓单已创建, trigger:{}, rule:{}, size:{}, id:{}",
+ triggerPrice, rule, size, orderId);
+ if (onSuccess != null) {
+ onSuccess.accept(orderId);
+ }
+ } catch (Exception e) {
+ log.error("[TradeExec] 条件开仓单创建失败, trigger:{}, size:{}", triggerPrice, size, e);
+ if (onFailure != null) {
+ onFailure.run();
+ }
+ }
+ });
+ }
+
+ /**
+ * 异步取消单个条件单。
+ *
+ * @param orderId 条件单 ID,为 null 时跳过
+ */
+ public void cancelConditionalOrder(String orderId) {
+ if (orderId == null) {
+ return;
+ }
+ executor.execute(() -> {
+ try {
+ futuresApi.cancelPriceTriggeredOrder(SETTLE, Long.parseLong(orderId));
+ log.info("[TradeExec] 条件单已取消, id:{}", orderId);
+ } catch (Exception e) {
+ log.warn("[TradeExec] 取消条件单失败(可能已触发), id:{}", orderId);
+ }
+ });
+ }
+
+ /**
* 构建 FuturesPriceTriggeredOrder 对象。
*
* <p>策略=0(价格触发),price_type=0(最新价),expiration=0(永不过期),
--
Gitblit v1.9.1