From 1b55621d4dcf3b4ee6b9c4beb81ad69e5b7a5856 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Fri, 05 Jun 2026 17:58:08 +0800
Subject: [PATCH] refactor(okxNewPrice): 优化止损管理器的挂单数量计算逻辑

---
 src/main/java/com/xcong/excoin/modules/okxNewPrice/GridQueueBuilder.java |  152 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 152 insertions(+), 0 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxNewPrice/GridQueueBuilder.java b/src/main/java/com/xcong/excoin/modules/okxNewPrice/GridQueueBuilder.java
new file mode 100644
index 0000000..a2d03e4
--- /dev/null
+++ b/src/main/java/com/xcong/excoin/modules/okxNewPrice/GridQueueBuilder.java
@@ -0,0 +1,152 @@
+package com.xcong.excoin.modules.okxNewPrice;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 网格价格队列构建器 — 从基底入场价生成双向价格队列和 OkxGridElement 列表。
+ *
+ * <h3>职责</h3>
+ * <ul>
+ *   <li>根据基底空头入场价,向下递减排空仓队列</li>
+ *   <li>向上递增排多仓队列</li>
+ *   <li>整合两队列为 OkxGridElement 列表并注入 {@link OkxConfig}</li>
+ * </ul>
+ *
+ * <h3>线程安全</h3>
+ * 本类为纯函数式(除 config.setStep / config.setGridElements 副作用外),
+ * 每次调用返回新构建的对象,不持有可变状态。
+ *
+ * @author Administrator
+ */
+@Slf4j
+public final class GridQueueBuilder {
+
+    private GridQueueBuilder() { /* utility class */ }
+
+    /**
+     * 从基底入场价向下递减生成空仓价格队列,降序排列(大→小)。
+     *
+     * @param config   全局配置(step 会被计算并写入)
+     * @param basePrice 空仓基底入场价
+     * @return 空仓价格队列,按降序排列
+     */
+    public static List<BigDecimal> buildShortQueue(OkxConfig config, BigDecimal basePrice) {
+        int prec = config.getPriceScale();
+        BigDecimal step = basePrice.multiply(config.getGridRate()).setScale(prec, RoundingMode.HALF_UP);
+        config.setStep(step); // 其它方法依赖此 step
+
+        List<BigDecimal> queue = new ArrayList<>();
+        BigDecimal elem = basePrice.subtract(step).setScale(prec, RoundingMode.HALF_UP);
+        for (int i = 0; i < config.getGridQueueSize(); i++) {
+            queue.add(elem);
+            elem = elem.subtract(step).setScale(prec, RoundingMode.HALF_UP);
+            if (elem.compareTo(BigDecimal.ZERO) <= 0) break;
+        }
+        queue.sort((a, b) -> b.compareTo(a)); // 降序
+        log.info("[OKX] 空队列:{}", queue);
+        return queue;
+    }
+
+    /**
+     * 从基底入场价向上递增生成多仓价格队列,升序排列(小→大)。
+     *
+     * @param config   全局配置(使用已设置的 step)
+     * @param basePrice 空仓基底入场价(对齐 Gate 版本,多仓队列也以此为基准)
+     * @return 多仓价格队列,按升序排列
+     */
+    public static List<BigDecimal> buildLongQueue(OkxConfig config, BigDecimal basePrice) {
+        int prec = config.getPriceScale();
+        BigDecimal step = config.getStep();
+        List<BigDecimal> queue = new ArrayList<>();
+        BigDecimal elem = basePrice.add(step).setScale(prec, RoundingMode.HALF_UP);
+        for (int i = 0; i < config.getGridQueueSize(); i++) {
+            queue.add(elem);
+            elem = elem.add(step).setScale(prec, RoundingMode.HALF_UP);
+        }
+        queue.sort(BigDecimal::compareTo); // 升序
+        log.info("[OKX] 多队列:{}", queue);
+        return queue;
+    }
+
+    /**
+     * 将空/多仓队列整合为 OkxGridElement 列表。
+     * <ul>
+     *   <li>空仓网格: id = -1, -2, -3 …</li>
+     *   <li>基底网格: id = 0(短仓入场价位置)</li>
+     *   <li>多仓网格: id = +1, +2, +3 …</li>
+     * </ul>
+     * 每个网格元素包含两个方向的 {@link OkxTraderParam}(入场价 / 止盈价 / 数量)。
+     *
+     * @param config     全局配置
+     * @param shortQueue 空仓价格队列
+     * @param longQueue  多仓价格队列
+     * @param basePrice  空仓基底入场价
+     * @return 构建好的网格元素列表(已注入 config)
+     */
+    public static List<OkxGridElement> buildGridElements(OkxConfig config,
+                                                          List<BigDecimal> shortQueue,
+                                                          List<BigDecimal> longQueue,
+                                                          BigDecimal basePrice) {
+        List<OkxGridElement> elements = new ArrayList<>();
+        int shortSize = shortQueue.size();
+        int longSize = longQueue.size();
+        int prec = config.getPriceScale();
+        BigDecimal step = config.getStep();
+        String qty = config.getQuantity();
+
+        // ---- 空仓网格: id = -1, -2, … ----
+        for (int i = 0; i < shortSize; i++) {
+            int id = -(i + 1);
+            Integer upId = (i == 0) ? 0 : id + 1;
+            Integer downId = (i == shortSize - 1) ? null : id - 1;
+            BigDecimal price = shortQueue.get(i);
+            OkxTraderParam longParam = OkxTraderParam.builder()
+                    .direction(OkxTraderParam.Direction.LONG)
+                    .entryPrice(price).takeProfitPrice(price.add(step).setScale(prec, RoundingMode.HALF_UP)).quantity(qty).build();
+            OkxTraderParam shortParam = OkxTraderParam.builder()
+                    .direction(OkxTraderParam.Direction.SHORT)
+                    .entryPrice(price).takeProfitPrice(price.subtract(step).setScale(prec, RoundingMode.HALF_UP)).quantity(qty).build();
+            elements.add(OkxGridElement.builder().id(id).gridPrice(price).upId(upId).downId(downId)
+                    .longTraderParam(longParam).shortTraderParam(shortParam).build());
+        }
+
+        // ---- 基底网格: id = 0 ----
+        {
+            BigDecimal price = basePrice;
+            OkxTraderParam longParam = OkxTraderParam.builder()
+                    .direction(OkxTraderParam.Direction.LONG)
+                    .entryPrice(price).takeProfitPrice(price.add(step).setScale(prec, RoundingMode.HALF_UP)).quantity(qty).build();
+            OkxTraderParam shortParam = OkxTraderParam.builder()
+                    .direction(OkxTraderParam.Direction.SHORT)
+                    .entryPrice(price).takeProfitPrice(price.subtract(step).setScale(prec, RoundingMode.HALF_UP)).quantity(qty).build();
+            elements.add(OkxGridElement.builder().id(0).gridPrice(price)
+                    .upId(shortSize > 0 ? 1 : null).downId(longSize > 0 ? -1 : null)
+                    .longTraderParam(longParam).shortTraderParam(shortParam).build());
+        }
+
+        // ---- 多仓网格: id = 1, 2, … ----
+        for (int i = 0; i < longSize; i++) {
+            int id = i + 1;
+            Integer downId = (i == 0) ? 0 : id - 1;
+            Integer upId = (i == longSize - 1) ? null : id + 1;
+            BigDecimal price = longQueue.get(i);
+            OkxTraderParam longParam = OkxTraderParam.builder()
+                    .direction(OkxTraderParam.Direction.LONG)
+                    .entryPrice(price).takeProfitPrice(price.add(step).setScale(prec, RoundingMode.HALF_UP)).quantity(qty).build();
+            OkxTraderParam shortParam = OkxTraderParam.builder()
+                    .direction(OkxTraderParam.Direction.SHORT)
+                    .entryPrice(price).takeProfitPrice(price.subtract(step).setScale(prec, RoundingMode.HALF_UP)).quantity(qty).build();
+            elements.add(OkxGridElement.builder().id(id).gridPrice(price).upId(upId).downId(downId)
+                    .longTraderParam(longParam).shortTraderParam(shortParam).build());
+        }
+
+        config.setGridElements(elements);
+        log.info("[OKX] 网格元素列表已构建, 共{}个元素", elements.size());
+        return elements;
+    }
+}

--
Gitblit v1.9.1