From 5516e36f3ec2fa09803c427051e3887701032843 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Wed, 13 May 2026 16:46:14 +0800
Subject: [PATCH] refactor(okxNewPrice): 账户配置

---
 src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java |  292 ++++++++++++++++++++++++++++++----------------------------
 1 files changed, 151 insertions(+), 141 deletions(-)

diff --git a/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java b/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java
index 75b1296..9655c89 100644
--- a/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java
+++ b/src/main/java/com/xcong/excoin/modules/okxApi/OkxGridTradeService.java
@@ -8,6 +8,7 @@
 import java.math.RoundingMode;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 @Slf4j
@@ -17,9 +18,7 @@
         WAITING_KLINE, OPENING, ACTIVE, STOPPED
     }
 
-    private static final String ORDER_TYPE_CLOSE_LONG = "plan-close-long-position";
-    private static final String ORDER_TYPE_CLOSE_SHORT = "plan-close-short-position";
-
+    private final String accountName;
     private final OkxConfig config;
     private final OkxTradeExecutor executor;
 
@@ -38,6 +37,8 @@
     private volatile BigDecimal lastKlinePrice;
     private volatile BigDecimal cumulativePnl = BigDecimal.ZERO;
     private volatile BigDecimal unrealizedPnl = BigDecimal.ZERO;
+    private volatile BigDecimal longRealizedPnl = BigDecimal.ZERO;
+    private volatile BigDecimal shortRealizedPnl = BigDecimal.ZERO;
     private volatile BigDecimal longEntryPrice = BigDecimal.ZERO;
     private volatile BigDecimal shortEntryPrice = BigDecimal.ZERO;
     private volatile BigDecimal longPositionSize = BigDecimal.ZERO;
@@ -45,6 +46,7 @@
 
     public OkxGridTradeService(OkxConfig config, String accountName) {
         this.config = config;
+        this.accountName = accountName;
         this.executor = new OkxTradeExecutor(config.getContract(), config.getMarginMode(), accountName);
     }
 
@@ -60,6 +62,8 @@
         state = StrategyState.WAITING_KLINE;
         cumulativePnl = BigDecimal.ZERO;
         unrealizedPnl = BigDecimal.ZERO;
+        longRealizedPnl = BigDecimal.ZERO;
+        shortRealizedPnl = BigDecimal.ZERO;
         longEntryPrice = BigDecimal.ZERO;
         shortEntryPrice = BigDecimal.ZERO;
         longPositionSize = BigDecimal.ZERO;
@@ -70,6 +74,7 @@
         shortActive = false;
         shortPriceQueue.clear();
         longPriceQueue.clear();
+        config.setStep(null);
         log.info("[{}] 网格策略已启动", config.getContract());
     }
 
@@ -106,74 +111,44 @@
         processLongGrid(closePrice);
     }
 
-    public void onPositionUpdate(String posSide, BigDecimal size, BigDecimal entryPrice) {
-        if (state == StrategyState.STOPPED || state == StrategyState.WAITING_KLINE) {
+    public void onPositionUpdate(String posSide, BigDecimal size, BigDecimal entryPrice, BigDecimal realizedPnl) {
+        if (state == StrategyState.STOPPED) {
             return;
         }
 
         boolean hasPosition = size.compareTo(BigDecimal.ZERO) > 0;
 
         if (OkxEnums.POSSIDE_LONG.equals(posSide)) {
+            longRealizedPnl = realizedPnl;
             if (hasPosition) {
                 longActive = true;
                 longEntryPrice = entryPrice;
-                if (!baseLongOpened) {
-                    longPositionSize = size;
-                    longBaseEntryPrice = entryPrice;
-                    baseLongOpened = true;
-                    log.info("[{}] 基底多成交价: {}", config.getContract(), longBaseEntryPrice);
-                    tryGenerateQueues();
-                } else if (size.compareTo(longPositionSize) > 0) {
-                    longPositionSize = size;
-                    if (longPriceQueue.isEmpty()) {
-                        log.warn("[{}] 多仓队列为空,无法设止盈", config.getContract());
-                    } else {
-                        BigDecimal tpPrice = longPriceQueue.get(0);
-                        executor.placeTakeProfit(tpPrice, ORDER_TYPE_CLOSE_LONG, config.getQuantity());
-                        log.info("[{}] 多单止盈已设, entry:{}, tp:{}, size:{}", config.getContract(), entryPrice, tpPrice, config.getQuantity());
-                    }
-                } else {
-                    longPositionSize = size;
-                }
+                longPositionSize = size;
             } else {
                 longActive = false;
                 longPositionSize = BigDecimal.ZERO;
+                longRealizedPnl = BigDecimal.ZERO;
             }
         } else if (OkxEnums.POSSIDE_SHORT.equals(posSide)) {
+            shortRealizedPnl = realizedPnl;
             if (hasPosition) {
                 shortActive = true;
                 shortEntryPrice = entryPrice;
-                if (!baseShortOpened) {
-                    shortPositionSize = size;
-                    shortBaseEntryPrice = entryPrice;
-                    baseShortOpened = true;
-                    log.info("[{}] 基底空成交价: {}", config.getContract(), shortBaseEntryPrice);
-                    tryGenerateQueues();
-                } else if (size.compareTo(shortPositionSize) > 0) {
-                    shortPositionSize = size;
-                    if (shortPriceQueue.isEmpty()) {
-                        log.warn("[{}] 空仓队列为空,无法设止盈", config.getContract());
-                    } else {
-                        BigDecimal tpPrice = shortPriceQueue.get(0);
-                        executor.placeTakeProfit(tpPrice, ORDER_TYPE_CLOSE_SHORT, config.getQuantity());
-                        log.info("[{}] 空单止盈已设, entry:{}, tp:{}, size:{}", config.getContract(), entryPrice, tpPrice, config.getQuantity());
-                    }
-                } else {
-                    shortPositionSize = size;
-                }
+                shortPositionSize = size;
             } else {
                 shortActive = false;
                 shortPositionSize = BigDecimal.ZERO;
+                shortRealizedPnl = BigDecimal.ZERO;
             }
         }
-    }
 
-    public void onOrderFilled(String posSide, BigDecimal fillSz, BigDecimal pnl) {
-        if (state == StrategyState.STOPPED) {
+        cumulativePnl = longRealizedPnl.add(shortRealizedPnl);
+        log.info("[{}] 持仓更新, 多已实现盈亏:{}, 空已实现盈亏:{}, 累计:{}",
+                config.getContract(), longRealizedPnl, shortRealizedPnl, cumulativePnl);
+
+        if (state == StrategyState.WAITING_KLINE) {
             return;
         }
-        cumulativePnl = cumulativePnl.add(pnl);
-        log.info("[{}] 订单成交盈亏: {}, 方向:{}, 累计:{}", config.getContract(), pnl, posSide, cumulativePnl);
 
         if (cumulativePnl.compareTo(config.getOverallTp()) >= 0) {
             log.info("[{}] 已达止盈目标 {}→已停止", config.getContract(), cumulativePnl);
@@ -184,13 +159,58 @@
         }
     }
 
+    public void onOrderFilled(String posSide, BigDecimal fillSz, BigDecimal avgPx, BigDecimal pnl) {
+        if (state == StrategyState.STOPPED || state == StrategyState.WAITING_KLINE) {
+            return;
+        }
+
+        log.info("[{}] 订单成交, 方向:{}, 数量:{}, 成交价:{}, 盈亏:{}",
+                config.getContract(), posSide, fillSz, avgPx, pnl);
+
+        if (OkxEnums.POSSIDE_LONG.equals(posSide)) {
+            if (!baseLongOpened) {
+                longBaseEntryPrice = avgPx;
+                baseLongOpened = true;
+                log.info("[{}] 基底多成交价: {}", config.getContract(), longBaseEntryPrice);
+                tryGenerateQueues();
+            } else if (fillSz.compareTo(BigDecimal.ZERO) > 0) {
+                if (longPriceQueue.isEmpty()) {
+                    log.warn("[{}] 多仓队列为空,无法设止盈", config.getContract());
+                } else {
+                    BigDecimal tpPrice = longPriceQueue.get(0);
+                    executor.placeTakeProfit(tpPrice, OkxEnums.ORDER_TYPE_CLOSE_LONG, config.getQuantity());
+                    log.info("[{}] 多单止盈已设, 成交价:{}, tp:{}, size:{}",
+                            config.getContract(), avgPx, tpPrice, config.getQuantity());
+                }
+            }
+        } else if (OkxEnums.POSSIDE_SHORT.equals(posSide)) {
+            if (!baseShortOpened) {
+                shortBaseEntryPrice = avgPx;
+                baseShortOpened = true;
+                log.info("[{}] 基底空成交价: {}", config.getContract(), shortBaseEntryPrice);
+                tryGenerateQueues();
+            } else if (fillSz.compareTo(BigDecimal.ZERO) > 0) {
+                if (shortPriceQueue.isEmpty()) {
+                    log.warn("[{}] 空仓队列为空,无法设止盈", config.getContract());
+                } else {
+                    BigDecimal tpPrice = shortPriceQueue.get(0);
+                    executor.placeTakeProfit(tpPrice, OkxEnums.ORDER_TYPE_CLOSE_SHORT, config.getQuantity());
+                    log.info("[{}] 空单止盈已设, 成交价:{}, tp:{}, size:{}",
+                            config.getContract(), avgPx, tpPrice, config.getQuantity());
+                }
+            }
+        }
+    }
+
     private void tryGenerateQueues() {
         if (baseLongOpened && baseShortOpened) {
+            BigDecimal step = shortBaseEntryPrice.multiply(config.getGridRate()).setScale(1, RoundingMode.HALF_UP);
+            config.setStep(step);
             generateShortQueue();
             generateLongQueue();
             state = StrategyState.ACTIVE;
-            log.info("[{}] 网格队列已生成, 空队首:{} → 尾:{}, 多队首:{} → 尾:{}, 已激活",
-                    config.getContract(),
+            log.info("[{}] 网格队列已生成, 步长:{}, 空队首:{} → 尾:{}, 多队首:{} → 尾:{}, 已激活",
+                    config.getContract(), step,
                     shortPriceQueue.isEmpty() ? "N/A" : shortPriceQueue.get(0),
                     shortPriceQueue.isEmpty() ? "N/A" : shortPriceQueue.get(shortPriceQueue.size() - 1),
                     longPriceQueue.isEmpty() ? "N/A" : longPriceQueue.get(0),
@@ -200,22 +220,26 @@
 
     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 = config.getStep();
+        BigDecimal prev = shortBaseEntryPrice;
+        for (int i = 0; i < config.getGridQueueSize(); i++) {
+            prev = prev.subtract(step).setScale(1, RoundingMode.HALF_UP);
+            shortPriceQueue.add(prev);
         }
         shortPriceQueue.sort((a, b) -> b.compareTo(a));
-        log.info("[{}] 空队列:{}", config.getContract(), shortPriceQueue);
+        log.info("[{}] 空队列:{} 步长:{}", config.getContract(), shortPriceQueue, step);
     }
 
     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 prev = longBaseEntryPrice;
+        for (int i = 0; i < config.getGridQueueSize(); i++) {
+            prev = prev.add(step).setScale(1, RoundingMode.HALF_UP);
+            longPriceQueue.add(prev);
         }
-        longPriceQueue.sort(BigDecimal::compareTo);
-        log.info("[{}] 多队列:{}", config.getContract(), longPriceQueue);
+        Collections.sort(longPriceQueue);
+        log.info("[{}] 多队列:{} 步长:{}", config.getContract(), longPriceQueue, step);
     }
 
     /**
@@ -228,8 +252,8 @@
      * <h3>执行流程</h3>
      * <ol>
      *   <li>匹配队列元素 → 为空则直接返回</li>
-     *   <li>空仓队列:移除 matched 元素,尾部补充新元素(尾价 × (1 − gridRate) 循环递减)</li>
-     *   <li>多仓队列:以多仓队列首元素(最小价)为种子,生成 matched.size() 个递减元素加入</li>
+     *   <li>空仓队列:移除 matched 元素,尾部以固定步长(shortBasePrice × gridRate)递减补充新元素</li>
+     *   <li>多仓队列:以多仓队列首元素(最小价)为种子,以多仓固定步长递减加入新元素</li>
      *   <li>保证金检查 → 安全则开空一次</li>
      *   <li>额外反向开多:若多仓均价 > 空仓均价 且 当前价夹在中间且远离多仓均价</li>
      * </ol>
@@ -255,48 +279,21 @@
         }
         log.info("[{}] 空仓队列触发, 匹配{}个元素, 当前价:{}", config.getContract(), matched.size(), currentPrice);
 
-        synchronized (shortPriceQueue) {
-            shortPriceQueue.removeAll(matched);
-            BigDecimal min = shortPriceQueue.isEmpty() ? matched.get(matched.size() - 1) : shortPriceQueue.get(shortPriceQueue.size() - 1);
-            BigDecimal step = config.getGridRate();
-            for (int i = 0; i < matched.size(); i++) {
-                min = min.multiply(BigDecimal.ONE.subtract(step)).setScale(1, RoundingMode.HALF_UP);
-                shortPriceQueue.add(min);
-                log.info("[{}] 空队列增加:{}", config.getContract(), min);
-            }
-            shortPriceQueue.sort((a, b) -> b.compareTo(a));
-            log.info("[{}] 现空队列:{}", config.getContract(), shortPriceQueue);
-        }
+        BigDecimal step = config.getStep();
+        replenishOwnQueue(shortPriceQueue, matched, step, true, "空");
 
-        synchronized (longPriceQueue) {
-            BigDecimal first = longPriceQueue.isEmpty() ? matched.get(matched.size() - 1) : longPriceQueue.get(0);
-            BigDecimal step = config.getGridRate();
-            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("[{}] 多队列跳过(price≈longEntry):{}", config.getContract(), elem);
-                    continue;
-                }
-                longPriceQueue.add(elem);
-                log.info("[{}] 多队列增加:{}", config.getContract(), elem);
-            }
-            longPriceQueue.sort(BigDecimal::compareTo);
-            while (longPriceQueue.size() > config.getGridQueueSize()) {
-                longPriceQueue.remove(longPriceQueue.size() - 1);
-            }
-            log.info("[{}] 现多队列:{}", config.getContract(), longPriceQueue);
-        }
+        transferBetweenQueues(longPriceQueue, matched, matched.get(matched.size() - 1),
+                step, false, longEntryPrice, BigDecimal::compareTo, "多", currentPrice);
 
         if (!isMarginSafe()) {
             log.warn("[{}] 保证金超限,跳过空单开仓", config.getContract());
         } else {
-            executor.openShort(config.getQuantity(), null, null);
-            if (shortEntryPrice.compareTo(BigDecimal.ZERO) > 0
-                    && longEntryPrice.compareTo(BigDecimal.ZERO) > 0
-                    && longEntryPrice.compareTo(shortEntryPrice) > 0
-                    && currentPrice.compareTo(shortEntryPrice) > 0
-                    && currentPrice.compareTo(longEntryPrice.multiply(BigDecimal.ONE.subtract(config.getGridRate()))) < 0) {
+            if (shortPositionSize.compareTo(config.getMaxPosSize()) < 0){
+                executor.openShort(config.getQuantity(), null, null);
+            }
+            if (currentPrice.compareTo(shortEntryPrice) > 0
+                    && currentPrice.compareTo(longEntryPrice) < 0
+            && shortPositionSize.compareTo(config.getMaxPosSize()) < 0) {
                 executor.openLong(config.getQuantity(), null, null);
                 log.info("[{}] 触发价在多/空持仓价之间且多>空且远离多仓均价, 额外开多一次, 当前价:{}", config.getContract(), currentPrice);
             }
@@ -313,8 +310,8 @@
      * <h3>执行流程</h3>
      * <ol>
      *   <li>匹配队列元素 → 为空则直接返回</li>
-     *   <li>多仓队列:移除 matched 元素,尾部补充新元素(尾价 × (1 + gridRate) 循环递增)</li>
-     *   <li>空仓队列:以空仓队列首元素(最高价)为种子,生成 matched.size() 个递增元素加入</li>
+     *   <li>多仓队列:移除 matched 元素,尾部以固定步长(longBasePrice × gridRate)递增补充新元素</li>
+     *   <li>空仓队列:以空仓队列首元素(最高价)为种子,以空仓固定步长递增加入新元素</li>
      *   <li>保证金检查 → 安全则开多一次</li>
      *   <li>额外反向开空:若多仓均价 > 空仓均价 且 当前价夹在中间且远离空仓均价</li>
      * </ol>
@@ -340,62 +337,75 @@
         }
         log.info("[{}] 多仓队列触发, 匹配{}个元素, 当前价:{}", config.getContract(), matched.size(), currentPrice);
 
-        synchronized (longPriceQueue) {
-            longPriceQueue.removeAll(matched);
-            BigDecimal max = longPriceQueue.isEmpty() ? matched.get(matched.size() - 1) : longPriceQueue.get(longPriceQueue.size() - 1);
-            BigDecimal step = config.getGridRate();
-            for (int i = 0; i < matched.size(); i++) {
-                max = max.multiply(BigDecimal.ONE.add(step)).setScale(1, RoundingMode.HALF_UP);
-                longPriceQueue.add(max);
-                log.info("[{}] 多队列增加:{}", config.getContract(), max);
-            }
-            longPriceQueue.sort(BigDecimal::compareTo);
-            log.info("[{}] 现多队列:{}", config.getContract(), longPriceQueue);
-        }
+        BigDecimal step = config.getStep();
+        replenishOwnQueue(longPriceQueue, matched, step, false, "多");
 
-        synchronized (shortPriceQueue) {
-            BigDecimal first = shortPriceQueue.isEmpty() ? matched.get(0) : shortPriceQueue.get(0);
-            BigDecimal step = config.getGridRate();
-            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("[{}] 空队列跳过(price≈shortEntry):{}", config.getContract(), elem);
-                    continue;
-                }
-                shortPriceQueue.add(elem);
-                log.info("[{}] 空队列增加:{}", config.getContract(), elem);
-            }
-            shortPriceQueue.sort((a, b) -> b.compareTo(a));
-            while (shortPriceQueue.size() > config.getGridQueueSize()) {
-                shortPriceQueue.remove(shortPriceQueue.size() - 1);
-            }
-            log.info("[{}] 现空队列:{}", config.getContract(), shortPriceQueue);
-        }
+        transferBetweenQueues(shortPriceQueue, matched, matched.get(0),
+                step, true, shortEntryPrice, (a, b) -> b.compareTo(a), "空", currentPrice);
 
         if (!isMarginSafe()) {
             log.warn("[{}] 保证金超限,跳过多单开仓", config.getContract());
         } else {
-            executor.openLong(config.getQuantity(), null, null);
+            if (longPositionSize.compareTo(config.getMaxPosSize()) < 0) {
+                executor.openLong(config.getQuantity(), null, null);
+            }
             if (shortEntryPrice.compareTo(BigDecimal.ZERO) > 0
                     && longEntryPrice.compareTo(BigDecimal.ZERO) > 0
                     && longEntryPrice.compareTo(shortEntryPrice) > 0
-                    && currentPrice.compareTo(shortEntryPrice.multiply(BigDecimal.ONE.add(config.getGridRate()))) > 0
-                    && currentPrice.compareTo(longEntryPrice) < 0) {
+                    && currentPrice.compareTo(shortEntryPrice.add(step)) > 0
+                    && currentPrice.compareTo(longEntryPrice) < 0
+                    && shortPositionSize.compareTo(config.getMaxPosSize()) < 0) {
                 executor.openShort(config.getQuantity(), null, null);
                 log.info("[{}] 触发价在多/空持仓价之间且多>空且远离空仓均价, 额外开空一次, 当前价:{}", config.getContract(), currentPrice);
             }
         }
     }
 
-    /**
-     * 保证金安全阀检查。
-     *
-     * <p>当前版本通过 wsHandler 推送的账户/持仓数据间接判断保证金状态。
-     * 后续可通过 OKX REST API 实时查询保证金占用比例,超 marginRatioLimit 时拒绝开仓。
-     *
-     * @return true=安全可开仓 / false=保证金超限跳过开仓
-     */
+    private void replenishOwnQueue(List<BigDecimal> queue, List<BigDecimal> matched, BigDecimal fixedStep,
+                                    boolean isShort, String label) {
+        synchronized (queue) {
+            queue.removeAll(matched);
+            BigDecimal tail = queue.isEmpty() ? matched.get(matched.size() - 1) : queue.get(queue.size() - 1);
+            Comparator<BigDecimal> comparator = isShort ? (a, b) -> b.compareTo(a) : BigDecimal::compareTo;
+            for (int i = 0; i < matched.size(); i++) {
+                tail = isShort
+                        ? tail.subtract(fixedStep).setScale(1, RoundingMode.HALF_UP)
+                        : tail.add(fixedStep).setScale(1, RoundingMode.HALF_UP);
+                queue.add(tail);
+                log.info("[{}] {}队列增加:{}", config.getContract(), label, tail);
+            }
+            queue.sort(comparator);
+            log.info("[{}] 现{}队列:{}", config.getContract(), label, queue);
+        }
+    }
+
+    private void transferBetweenQueues(List<BigDecimal> targetQueue, List<BigDecimal> matched,
+                                        BigDecimal firstFallback, BigDecimal fixedStep, boolean isShort,
+                                        BigDecimal filterEntryPrice, Comparator<BigDecimal> comparator,
+                                        String label, BigDecimal currentPrice) {
+        synchronized (targetQueue) {
+            BigDecimal first = targetQueue.isEmpty() ? firstFallback : targetQueue.get(0);
+            for (int i = 1; i <= matched.size(); i++) {
+                BigDecimal offset = fixedStep.multiply(BigDecimal.valueOf(i));
+                BigDecimal elem = isShort
+                        ? first.add(offset).setScale(1, RoundingMode.HALF_UP)
+                        : first.subtract(offset).setScale(1, RoundingMode.HALF_UP);
+                if (filterEntryPrice.compareTo(BigDecimal.ZERO) > 0
+                        && currentPrice.subtract(filterEntryPrice).abs().compareTo(filterEntryPrice.multiply(config.getGridRate())) < 0) {
+                    log.info("[{}] {}队列跳过(price≈entry):{}", config.getContract(), label, elem);
+                    continue;
+                }
+                targetQueue.add(elem);
+                log.info("[{}] {}队列增加:{}", config.getContract(), label, elem);
+            }
+            targetQueue.sort(comparator);
+            while (targetQueue.size() > config.getGridQueueSize()) {
+                targetQueue.remove(targetQueue.size() - 1);
+            }
+            log.info("[{}] 现{}队列:{}", config.getContract(), label, targetQueue);
+        }
+    }
+
     private boolean isMarginSafe() {
         return true;
     }
@@ -423,5 +433,5 @@
     public BigDecimal getCumulativePnl() { return cumulativePnl; }
     public BigDecimal getUnrealizedPnl() { return unrealizedPnl; }
     public StrategyState getState() { return state; }
-    public String getAccountName() { return config.getContract(); }
+    public String getAccountName() { return accountName; }
 }

--
Gitblit v1.9.1