| | |
| | | public void init() { |
| | | try { |
| | | JSONObject account = executorGet("/api/v5/account/balance"); |
| | | JSONArray details = account.getJSONArray("data"); |
| | | if (details != null && !details.isEmpty()) { |
| | | JSONObject total = details.getJSONObject(0); |
| | | this.initialPrincipal = total.getBigDecimal("totalEq"); |
| | | log.info("[OKX] 初始本金: {} USDT", initialPrincipal); |
| | | JSONArray dataArr = account.getJSONArray("data"); |
| | | if (dataArr != null && !dataArr.isEmpty()) { |
| | | JSONArray details = dataArr.getJSONObject(0).getJSONArray("details"); |
| | | if (details != null) { |
| | | for (int i = 0; i < details.size(); i++) { |
| | | JSONObject currency = details.getJSONObject(i); |
| | | if ("USDT".equals(currency.getString("ccy"))) { |
| | | this.initialPrincipal = currency.getBigDecimal("eq"); |
| | | log.info("[OKX] 初始本金(USDT余额): {}", initialPrincipal); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 设置双向持仓模式 |
| | |
| | | private void refreshInitialPrincipal() { |
| | | try { |
| | | JSONObject account = executorGet("/api/v5/account/balance"); |
| | | JSONArray details = account.getJSONArray("data"); |
| | | if (details != null && !details.isEmpty()) { |
| | | this.initialPrincipal = details.getJSONObject(0).getBigDecimal("totalEq"); |
| | | JSONArray dataArr = account.getJSONArray("data"); |
| | | if (dataArr != null && !dataArr.isEmpty()) { |
| | | JSONArray details = dataArr.getJSONObject(0).getJSONArray("details"); |
| | | if (details != null) { |
| | | for (int i = 0; i < details.size(); i++) { |
| | | JSONObject currency = details.getJSONObject(i); |
| | | if ("USDT".equals(currency.getString("ccy"))) { |
| | | this.initialPrincipal = currency.getBigDecimal("eq"); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception e) { |
| | | log.warn("[OKX] 获取初始化本金失败,使用旧值: {}", initialPrincipal); |
| | |
| | | config.setBaseShortTraderParam(baseShortTp); |
| | | }, null); |
| | | return; |
| | | } |
| | | |
| | | // OPENING 状态下若 WS 仓位已确认但 REST 回调尚未完成,等标记价格推送时重试队列生成 |
| | | if (state == StrategyState.OPENING && |
| | | baseLongOpened && baseShortOpened) { |
| | | tryGenerateQueues(); |
| | | } |
| | | |
| | | if (state == StrategyState.ACTIVE && |
| | |
| | | |
| | | private void tryGenerateQueues() { |
| | | if (baseLongOpened && baseShortOpened) { |
| | | // 确保 openLong/openShort 的 REST 回调已完成(WS 推送可能比回调更快到达) |
| | | if (config.getBaseLongTraderParam() == null || config.getBaseShortTraderParam() == null) { |
| | | log.warn("[OKX] 基底REST回调尚未完成, 延后队列生成"); |
| | | return; |
| | | } |
| | | |
| | | generateShortQueue(); |
| | | generateLongQueue(); |
| | | updateGridElements(); |
| | |
| | | baseGridElement.setShortOrderId(baseShortTraderParam.getEntryOrderId()); |
| | | baseGridElement.setHasShortOrder(true); |
| | | |
| | | // 挂基座止盈 |
| | | { |
| | | BigDecimal tpPrice = baseGridElement.getGridPrice().add(config.getStep()); |
| | | executor.placeTakeProfit(tpPrice, "close_long", config.getBaseQuantity(), |
| | | profitId -> { |
| | | longTakeProfitTraderIdParam(baseGridElement, profitId, true); |
| | | log.info("[OKX] 基座多仓止盈已挂, gridId:0, 触发价:{}, tpId:{}", tpPrice, profitId); |
| | | }); |
| | | } |
| | | { |
| | | BigDecimal tpPrice = baseGridElement.getGridPrice().subtract(config.getStep()); |
| | | executor.placeTakeProfit(tpPrice, "close_short", config.getBaseQuantity(), |
| | | profitId -> { |
| | | shortTakeProfitTraderIdParam(baseGridElement, profitId, true); |
| | | log.info("[OKX] 基座空仓止盈已挂, gridId:0, 触发价:{}, tpId:{}", tpPrice, profitId); |
| | | }); |
| | | } |
| | | |
| | | // 挂初始止损 |
| | | int stopCount = Integer.parseInt(config.getBaseQuantity()) / Integer.parseInt(config.getQuantity()) + 1; |
| | | for (int id = 2; id <= stopCount; id++) { |
| | |
| | | } |
| | | BigDecimal triggerPrice = elem.getGridPrice(); |
| | | int finalId = id; |
| | | executor.placeTakeProfit(triggerPrice, "close_short", config.getQuantity(), |
| | | executor.placeStopLoss(triggerPrice, "close_short", config.getQuantity(), |
| | | profitId -> { |
| | | elem.setShortStopLossOrderId(profitId); |
| | | GridElement.refreshIndices(); |
| | |
| | | } |
| | | BigDecimal triggerPrice = elem.getGridPrice(); |
| | | int finalId = id; |
| | | executor.placeTakeProfit(triggerPrice, "close_long", config.getQuantity(), |
| | | executor.placeStopLoss(triggerPrice, "close_long", config.getQuantity(), |
| | | profitId -> { |
| | | elem.setLongStopLossOrderId(profitId); |
| | | GridElement.refreshIndices(); |
| | |
| | | } |
| | | BigDecimal triggerPrice = elem.getGridPrice(); |
| | | int finalSlId = newSlId; |
| | | executor.placeTakeProfit(triggerPrice, "close_long", config.getQuantity(), |
| | | executor.placeStopLoss(triggerPrice, "close_long", config.getQuantity(), |
| | | profitId -> { |
| | | elem.setLongStopLossOrderId(profitId); |
| | | GridElement.refreshIndices(); |
| | |
| | | } |
| | | BigDecimal triggerPrice = elem.getGridPrice(); |
| | | int finalSlId = newSlId; |
| | | executor.placeTakeProfit(triggerPrice, "close_short", config.getQuantity(), |
| | | executor.placeStopLoss(triggerPrice, "close_short", config.getQuantity(), |
| | | profitId -> { |
| | | elem.setShortStopLossOrderId(profitId); |
| | | GridElement.refreshIndices(); |