Administrator
13 hours ago a986f3571c7e18ade4665fe5999b445b5762264d
src/main/java/com/xcong/excoin/modules/gateApi/GateGridTradeService.java
@@ -479,32 +479,35 @@
    /**
     * 生成空仓价格队列。
     * 以空头基底入场价 shortBaseEntryPrice 为基准,按 gridRate 递减生成 gridQueueSize 个价格元素:
     * <pre>shortBaseEntryPrice × (1 − gridRate × i), i=1..gridQueueSize</pre>
     * 以 shortBaseEntryPrice × gridRate 作为绝对步长 step,存到 config。
     * 第1个元素 = shortBaseEntryPrice − step,后续依次递减 step,共 gridQueueSize 个。
     * 队列降序排列(大→小),方便 processShortGrid 中从头遍历。
     */
    private void generateShortQueue() {
        shortPriceQueue.clear();
        BigDecimal step = config.getGridRate();
        for (int i = 1; i <= config.getGridQueueSize(); i++) {
            shortPriceQueue.add(shortBaseEntryPrice.multiply(BigDecimal.ONE.subtract(step.multiply(BigDecimal.valueOf(i)))).setScale(1, RoundingMode.HALF_UP));
        BigDecimal step = shortBaseEntryPrice.multiply(config.getGridRate()).setScale(1, RoundingMode.HALF_UP);
        config.setStep(step);
        BigDecimal elem = shortBaseEntryPrice.subtract(step).setScale(1, RoundingMode.HALF_UP);
        for (int i = 0; i < config.getGridQueueSize(); i++) {
            shortPriceQueue.add(elem);
            elem = elem.subtract(step).setScale(1, RoundingMode.HALF_UP);
        }
        shortPriceQueue.sort((a, b) -> b.compareTo(a));
        //输出队列:shortPriceQueue;
        log.info("[Gate] 空队列:{}", shortPriceQueue);
    }
    /**
     * 生成多仓价格队列。
     * 以多头基底入场价 longBaseEntryPrice 为基准,按 gridRate 递增生成 gridQueueSize 个价格元素:
     * <pre>longBaseEntryPrice × (1 + gridRate × i), i=1..gridQueueSize</pre>
     * 以 shortBaseEntryPrice + step 为首元素,后续依次递增 step,共 gridQueueSize 个。
     * 队列升序排列(小→大),方便 processLongGrid 中从头遍历。
     */
    private void generateLongQueue() {
        longPriceQueue.clear();
        BigDecimal step = config.getGridRate();
        for (int i = 1; i <= config.getGridQueueSize(); i++) {
            longPriceQueue.add(longBaseEntryPrice.multiply(BigDecimal.ONE.add(step.multiply(BigDecimal.valueOf(i)))).setScale(1, RoundingMode.HALF_UP));
        BigDecimal step = config.getStep();
        BigDecimal elem = shortBaseEntryPrice.add(step).setScale(1, RoundingMode.HALF_UP);
        for (int i = 0; i < config.getGridQueueSize(); i++) {
            longPriceQueue.add(elem);
            elem = elem.add(step).setScale(1, RoundingMode.HALF_UP);
        }
        longPriceQueue.sort(BigDecimal::compareTo);
        log.info("[Gate] 多队列:{}", longPriceQueue);
@@ -520,8 +523,8 @@
     * <h3>执行流程</h3>
     * <ol>
     *   <li>匹配队列元素 → 为空则直接返回</li>
     *   <li>空仓队列:移除 matched 元素,尾部补充新元素(尾价 × (1 − gridRate) 循环递减)</li>
     *   <li>多仓队列:以多仓队列首元素(最小价)为种子,生成 matched.size() 个递减元素加入</li>
     *   <li>空仓队列:移除 matched 元素,尾部补充新元素(尾价 − step 循环递减)</li>
     *   <li>多仓队列:以多仓队列首元素(最小价)为种子,递减 step 生成 matched.size() 个元素加入</li>
     *   <li>保证金检查 → 安全则开空一次</li>
     *   <li>额外反向开多:若多仓均价 > 空仓均价 且 当前价夹在中间且远离多仓均价</li>
     * </ol>
@@ -550,9 +553,9 @@
        synchronized (shortPriceQueue) {
            shortPriceQueue.removeAll(matched);
            BigDecimal min = shortPriceQueue.isEmpty() ? matched.get(matched.size() - 1) : shortPriceQueue.get(shortPriceQueue.size() - 1);
            BigDecimal step = config.getGridRate();
            BigDecimal gridStep = config.getStep();
            for (int i = 0; i < matched.size(); i++) {
                min = min.multiply(BigDecimal.ONE.subtract(step)).setScale(1, RoundingMode.HALF_UP);
                min = min.subtract(gridStep).setScale(1, RoundingMode.HALF_UP);
                shortPriceQueue.add(min);
                log.info("[Gate] 空队列增加:{}", min);
            }
@@ -564,14 +567,14 @@
        synchronized (longPriceQueue) {
            BigDecimal first = longPriceQueue.isEmpty() ? matched.get(matched.size() - 1) : longPriceQueue.get(0);
            BigDecimal step = config.getGridRate();
            BigDecimal gridStep = config.getStep();
            for (int i = 1; i <= matched.size(); i++) {
                BigDecimal elem = first.multiply(BigDecimal.ONE.subtract(step.multiply(BigDecimal.valueOf(i)))).setScale(1, RoundingMode.HALF_UP);
                if (longEntryPrice.compareTo(BigDecimal.ZERO) > 0
                        && currentPrice.subtract(longEntryPrice).abs().compareTo(longEntryPrice.multiply(step)) < 0) {
                    log.info("[Gate] 多队列跳过(price≈longEntry):{}", elem);
                    continue;
                }
                BigDecimal elem = first.subtract(gridStep.multiply(BigDecimal.valueOf(i))).setScale(1, RoundingMode.HALF_UP);
//                if (longEntryPrice.compareTo(BigDecimal.ZERO) > 0
//                        && currentPrice.subtract(longEntryPrice).abs().compareTo(longEntryPrice.multiply(config.getGridRate())) < 0) {
//                    log.info("[Gate] 多队列跳过(price≈longEntry):{}", elem);
//                    continue;
//                }
                longPriceQueue.add(elem);
                log.info("[Gate] 多队列增加:{}", elem);
            }
@@ -607,8 +610,8 @@
     * <h3>执行流程</h3>
     * <ol>
     *   <li>匹配队列元素 → 为空则直接返回</li>
     *   <li>多仓队列:移除 matched 元素,尾部补充新元素(尾价 × (1 + gridRate) 循环递增)</li>
     *   <li>空仓队列:以空仓队列首元素(最高价)为种子,生成 matched.size() 个递增元素加入</li>
     *   <li>多仓队列:移除 matched 元素,尾部补充新元素(尾价 + step 循环递增)</li>
     *   <li>空仓队列:以空仓队列首元素(最高价)为种子,递增 step 生成 matched.size() 个元素加入</li>
     *   <li>保证金检查 → 安全则开多一次</li>
     *   <li>额外反向开空:若多仓均价 > 空仓均价 且 当前价夹在中间且远离空仓均价</li>
     * </ol>
@@ -638,9 +641,9 @@
        synchronized (longPriceQueue) {
            longPriceQueue.removeAll(matched);
            BigDecimal max = longPriceQueue.isEmpty() ? matched.get(matched.size() - 1) : longPriceQueue.get(longPriceQueue.size() - 1);
            BigDecimal step = config.getGridRate();
            BigDecimal gridStep = config.getStep();
            for (int i = 0; i < matched.size(); i++) {
                max = max.multiply(BigDecimal.ONE.add(step)).setScale(1, RoundingMode.HALF_UP);
                max = max.add(gridStep).setScale(1, RoundingMode.HALF_UP);
                longPriceQueue.add(max);
                log.info("[Gate] 多队列增加:{}", max);
@@ -652,14 +655,14 @@
        synchronized (shortPriceQueue) {
            BigDecimal first = shortPriceQueue.isEmpty() ? matched.get(0) : shortPriceQueue.get(0);
            BigDecimal step = config.getGridRate();
            BigDecimal gridStep = config.getStep();
            for (int i = 1; i <= matched.size(); i++) {
                BigDecimal elem = first.multiply(BigDecimal.ONE.add(step.multiply(BigDecimal.valueOf(i)))).setScale(1, RoundingMode.HALF_UP);
                if (shortEntryPrice.compareTo(BigDecimal.ZERO) > 0
                        && currentPrice.subtract(shortEntryPrice).abs().compareTo(shortEntryPrice.multiply(step)) < 0) {
                    log.info("[Gate] 空队列跳过(price≈shortEntry):{}", elem);
                    continue;
                }
                BigDecimal elem = first.add(gridStep.multiply(BigDecimal.valueOf(i))).setScale(1, RoundingMode.HALF_UP);
//                if (shortEntryPrice.compareTo(BigDecimal.ZERO) > 0
//                        && currentPrice.subtract(shortEntryPrice).abs().compareTo(shortEntryPrice.multiply(config.getGridRate())) < 0) {
//                    log.info("[Gate] 空队列跳过(price≈shortEntry):{}", elem);
//                    continue;
//                }
                shortPriceQueue.add(elem);
                log.info("[Gate] 空队列增加:{}", elem);
            }