Administrator
5 days ago ed38f71a22ffbdad4b17a03a4a30b6f9a1d93d71
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,67 @@
        } 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");
        longSlOrderId = placePriceTriggeredOrder(slPrice, FuturesPriceTrigger.RuleEnum.NUMBER_2, "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");
        shortSlOrderId = placePriceTriggeredOrder(slPrice, FuturesPriceTrigger.RuleEnum.NUMBER_1, "close_short");
        log.info("[GateGrid] 空头TP/SL已设置, TP:{}, SL:{}, tpId:{}, slId:{}", tpPrice, slPrice, shortTpOrderId, shortSlOrderId);
    }
    private Long placePriceTriggeredOrder(BigDecimal triggerPrice,
                                           FuturesPriceTrigger.RuleEnum rule,
                                           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.setAutoSize(autoSize);
            FuturesPriceTriggeredOrder order = new FuturesPriceTriggeredOrder();
            order.setTrigger(trigger);
            order.setInitial(initial);
            TriggerOrderResponse response = futuresApi.createPriceTriggeredOrder(SETTLE, order);
            log.info("[GateGrid] 条件单已创建, triggerPrice:{}, rule:{}, autoSize:{}, id:{}",
                    triggerPrice, rule, autoSize, response.getId());
            return response.getId();
        } catch (Exception e) {
            log.error("[GateGrid] 创建条件单失败, triggerPrice:{}, rule:{}, autoSize:{}",
                    triggerPrice, rule, 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 +339,9 @@
    }
    private void closeLongPosition() {
        if (longEntryPrice == null) return;
        if (longEntryPrice == null) {
            return;
        }
        try {
            FuturesOrder closeOrder = new FuturesOrder();
            closeOrder.setContract(contract);
@@ -274,10 +357,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 +382,10 @@
        }
        shortEntryPrice = null;
        shortOrderId = null;
        cancelTpSl(shortTpOrderId);
        cancelTpSl(shortSlOrderId);
        shortTpOrderId = null;
        shortSlOrderId = null;
    }
    private void closeAllPositions() {
@@ -301,10 +394,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");