Administrator
2026-09-30 c3e27beb584c9252f33b90729817bc2546b1297c
src/main/java/com/xcong/excoin/modules/gateApi/GateConfigDTO.java
@@ -6,6 +6,8 @@
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.Map;
/**
 * Gate 策略配置 DTO,用于 Web 控制面板参数传递。
@@ -55,6 +57,34 @@
    private boolean isProduction;
    /** 价格驱动开关:true=启用K线推送中的价格驱动逻辑,false=禁用。null=未设置(默认true) */
    private Boolean priceDriveEnabled;
    /** 策略运行轮数上限:达到盈利后重启计数,达到此值后不再重启。0=不限 */
    private int rounds;
    /** 止损次数统计方式:"single"=单向分别统计 / "dual"=双向统一统计,默认 "dual" */
    private String stopLossCountMode;
    /** 加仓间隔:每隔多少次止损触发一次加仓,默认 3 */
    private int addPositionInterval;
    /** 加仓数量:每次加仓追加的张数,默认 1 */
    private int addPositionQuantity;
    /** 单边最大仓位量:单向持仓张数上限,超出则按上限挂单,0=不限制 */
    private int maxPositionPerSide;
    /** 加仓启动阈值:前N次止损不触发加仓,默认 1 */
    private int addPositionStartThreshold;
    /** 止盈挂单模式:off=关闭 / concentrated=集中止盈 / dispersed=分散止盈,默认 off */
    private String placeExcessTakeProfit;
    /** 自定义止损开关:true=启用自定义止损触发价,false=使用默认阶梯止损。null=未设置(默认false) */
    private Boolean dualStopLossEnabled;
    /** 多仓自定义止损触发价(价格跌至该值触发平多),null=未设置 */
    private BigDecimal longStopLossPrice;
    /** 空仓自定义止损触发价(价格涨至该值触发平空),null=未设置 */
    private BigDecimal shortStopLossPrice;
    /** 止盈成交触发对向加仓开关:true=启用,false=禁用。null=未设置(默认false) */
    private Boolean tpTriggerOppositeAddEnabled;
    /** 对向加仓挂单数量:止盈成交后在对向挂出的开仓张数,0=不启用 */
    private Integer tpTriggerOppositeAddQuantity;
    /** 单格止盈张数:基础仓位止盈挂单时每个网格挂的止盈张数,支持小数,0=不启用 */
    private BigDecimal baseTakeProfitPerGrid;
    /** 止盈网格数量:基础仓位止盈挂单的网格数量,0=不启用 */
    private Integer baseTakeProfitGridCount;
    /**
     * 从 GateConfig 构建 DTO(不暴露 apiSecret)。
@@ -81,6 +111,95 @@
                        ? config.getUnrealizedPnlPriceMode().name() : "LAST_PRICE")
                .isProduction(config.isProduction())
                .priceDriveEnabled(config.isPriceDriveEnabled())
                .rounds(config.getRounds())
                .stopLossCountMode(config.getStopLossCountMode())
                .addPositionInterval(config.getAddPositionInterval())
                .addPositionQuantity(config.getAddPositionQuantity())
                .maxPositionPerSide(config.getMaxPositionPerSide())
                .addPositionStartThreshold(config.getAddPositionStartThreshold())
                .placeExcessTakeProfit(config.getPlaceExcessTakeProfit())
                .dualStopLossEnabled(config.isDualStopLossEnabled())
                .longStopLossPrice(config.getLongStopLossPrice())
                .shortStopLossPrice(config.getShortStopLossPrice())
                .tpTriggerOppositeAddEnabled(config.isTpTriggerOppositeAddEnabled())
                .tpTriggerOppositeAddQuantity(config.getTpTriggerOppositeAddQuantity())
                .baseTakeProfitPerGrid(config.getBaseTakeProfitPerGrid())
                .baseTakeProfitGridCount(config.getBaseTakeProfitGridCount())
                .build();
    }
    /**
     * 所有可调参数的扁平快照 — stats 埋点 + STRATEGY_START payload 用。
     * 新增参数只需在此方法加一行,无需修改 stats 消费者。
     */
    public Map<String, Object> toParamsMap() {
        Map<String, Object> m = new LinkedHashMap<>();
        m.put("contract", contract);
        m.put("leverage", leverage);
        m.put("gridRate", gridRate);
        m.put("expectedProfit", expectedProfit);
        m.put("maxLoss", maxLoss);
        m.put("baseQuantity", baseQuantity);
        m.put("quantity", quantity);
        m.put("maxPositionSize", maxPositionSize);
        m.put("stopLossCount", stopLossCount);
        m.put("takeProfitGridSpan", takeProfitGridSpan);
        m.put("priceDriveEnabled", priceDriveEnabled);
        m.put("rounds", rounds);
        m.put("stopLossCountMode", stopLossCountMode);
        m.put("addPositionInterval", addPositionInterval);
        m.put("addPositionQuantity", addPositionQuantity);
        m.put("maxPositionPerSide", maxPositionPerSide);
        m.put("addPositionStartThreshold", addPositionStartThreshold);
        m.put("placeExcessTakeProfit", placeExcessTakeProfit);
        m.put("dualStopLossEnabled", dualStopLossEnabled);
        m.put("longStopLossPrice", longStopLossPrice);
        m.put("shortStopLossPrice", shortStopLossPrice);
        m.put("tpTriggerOppositeAddEnabled", tpTriggerOppositeAddEnabled);
        m.put("tpTriggerOppositeAddQuantity", tpTriggerOppositeAddQuantity);
        m.put("baseTakeProfitPerGrid", baseTakeProfitPerGrid);
        m.put("baseTakeProfitGridCount", baseTakeProfitGridCount);
        return m;
    }
    /**
     * 带默认值的工厂方法 — 统一 Manager 和 HTML 的默认值入口。
     */
    public static GateConfigDTO defaultsFor(String apiKey) {
        return GateConfigDTO.builder()
                .apiKey(apiKey)
                .contract("ETH_USDT")
                .leverage("100")
                .marginMode("cross")
                .positionMode("dual")
                .gridRate(new BigDecimal("0.005"))
                .expectedProfit(new BigDecimal("0.15"))
                .maxLoss(new BigDecimal("1.5"))
                .baseQuantity("2")
                .quantity("2")
                .maxPositionSize(4)
                .stopLossCount(0)
                .takeProfitGridSpan(2)
                .restartGridSpan(0)
                .priceScale(1)
                .contractMultiplier(new BigDecimal("0.001"))
                .unrealizedPnlPriceMode("LAST_PRICE")
                .isProduction(true)
                .priceDriveEnabled(true)
                .rounds(0)
                .stopLossCountMode("dual")
                .addPositionInterval(3)
                .addPositionQuantity(1)
                .maxPositionPerSide(0)
                .addPositionStartThreshold(1)
                .placeExcessTakeProfit("off")
                .dualStopLossEnabled(false)
                .longStopLossPrice(null)
                .shortStopLossPrice(null)
                .tpTriggerOppositeAddEnabled(false)
                .tpTriggerOppositeAddQuantity(0)
                .baseTakeProfitPerGrid(BigDecimal.ZERO)
                .baseTakeProfitGridCount(0)
                .build();
    }
}