Administrator
2026-06-05 b779f4884d55f8bcb24c0d13ca34795d1003c296
fix(okxNewPrice): 解决网格交易价格精度计算问题

- 在longEntryPrice计算中添加精度补偿epsilon值防止向下截断错误
- 在shortEntryPrice计算中添加精度补偿epsilon值防止向下截断错误
- 修复因BigDecimal精度丢失导致的网格数量计算错误
- 防止1.99998等浮点数被向下取整为1的问题
1 files modified
19 ■■■■ changed files
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java 19 ●●●● patch | view | raw | blame | history
src/main/java/com/xcong/excoin/modules/okxNewPrice/OkxGridTradeService.java
@@ -267,10 +267,12 @@
            executor.openLong(config.getBaseQuantity(), (orderId) -> {
                OkxTraderParam baseLongTp = OkxTraderParam.builder().entryOrderId(orderId).build();
                config.setBaseLongTraderParam(baseLongTp);
                tryGenerateQueues(); // 异步回调到达后重试,防止 WS 推送先到导致 NPE
            }, null);
            executor.openShort(config.getBaseQuantity(), (orderId) -> {
                OkxTraderParam baseShortTp = OkxTraderParam.builder().entryOrderId(orderId).build();
                config.setBaseShortTraderParam(baseShortTp);
                tryGenerateQueues(); // 异步回调到达后重试,防止 WS 推送先到导致 NPE
            }, null);
            return;
        }
@@ -302,6 +304,7 @@
                    tryGenerateQueues();
                } else {
                    longPositionSize = posSize;
                tryGenerateQueues(); // 后续 WS 推送触发重试,兜底此前 NPE 失败的情况
                }
            } else {
                if (longActive && state == StrategyState.ACTIVE) {
@@ -323,6 +326,7 @@
                    tryGenerateQueues();
                } else {
                    shortPositionSize = posSize;
                tryGenerateQueues(); // 后续 WS 推送触发重试,兜底此前 NPE 失败的情况
                }
            } else {
                if (shortActive && state == StrategyState.ACTIVE) {
@@ -394,17 +398,28 @@
    // ---- 网格队列处理 ----
    private void tryGenerateQueues() {
        // 防止重复执行:一旦已进入 ACTIVE 状态不再重复初始化
        if (state == StrategyState.ACTIVE) {
            return;
        }
        if (baseLongOpened && baseShortOpened) {
            // 防御异步竞态:openLong/openShort 的回调可能还未设置 trader param
            OkxTraderParam baseLongTp = config.getBaseLongTraderParam();
            OkxTraderParam baseShortTp = config.getBaseShortTraderParam();
            if (baseLongTp == null || baseShortTp == null) {
                log.warn("[OKX] tryGenerateQueues 等待异步回调: longTp={}, shortTp={}",
                        baseLongTp != null, baseShortTp != null);
                return;
            }
            generateShortQueue();
            generateLongQueue();
            updateGridElements();
            // 标记基座挂单
            OkxGridElement baseGridElement = OkxGridElement.findById(0);
            OkxTraderParam baseLongTp = config.getBaseLongTraderParam();
            baseGridElement.setLongOrderId(baseLongTp.getEntryOrderId());
            baseGridElement.setHasLongOrder(true);
            OkxTraderParam baseShortTp = config.getBaseShortTraderParam();
            baseGridElement.setShortOrderId(baseShortTp.getEntryOrderId());
            baseGridElement.setHasShortOrder(true);