| | |
| | | } |
| | | shortGridElement.setExtendStopLossInProgress(true); |
| | | |
| | | accumulatedShortLossCount = 0; |
| | | lastShortStopLossGridId = Integer.MAX_VALUE; |
| | | // [Gate-需求2] 加仓后先撤空仓所有止盈+止损,再查交易所持仓后重挂 |
| | | cancelAllShortTakeProfitsAndStopLosses(); |
| | |
| | | // [Gate] 止盈挂单:超出基础仓位的部分,挂在多仓第一止损位 |
| | | // placeExcessTakeProfit(posSize, false); |
| | | log.info("[Gate] 空单成交 gridId:{}, 当前持仓:{}张", filledQty, posSize); |
| | | |
| | | |
| | | |
| | | checkShortStopLongProfit(accumulatedShortLossCount, shortGridElement.getId() + 2); |
| | |
| | | // [Gate] 止盈挂单:超出基础仓位的部分,挂在空仓第一止损位 |
| | | // placeExcessTakeProfit(posSize, true); |
| | | log.info("[Gate] 多单成交 gridId:{}, 当前持仓:{}张", filledQty, posSize); |
| | | |
| | | |
| | | checkLongStopShortProfit(accumulatedLongLossCount, longGridElement.getId() -2); |
| | | |
| | |
| | | |
| | | if (newEntryGrid != null) { |
| | | |
| | | String quantity = String.valueOf(Math.max(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue()) + Integer.parseInt(config.getQuantity())); |
| | | |
| | | // String quantity = String.valueOf(Math.max(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue()) + Integer.parseInt(config.getQuantity())); |
| | | String quantity = String.valueOf(config.getBaseQuantity()); |
| | | // 向下检查是否已有多单挂在更低价格网格,有则跳过(防止价格回升后重复挂单) |
| | | boolean hasLongOrderBelow = false; |
| | | GridElement checkDownCursor = GridElement.findById(newEntryGrid.getDownId()); |
| | |
| | | if (newEntryGrid != null) { |
| | | |
| | | // String quantity = String.valueOf((accumulatedShortLossCount + 1) * Integer.parseInt(config.getQuantity())); |
| | | String quantity = String.valueOf(Math.max(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue()) + Integer.parseInt(config.getQuantity())); |
| | | |
| | | // String quantity = String.valueOf(Math.max(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue()) + Integer.parseInt(config.getQuantity())); |
| | | String quantity = String.valueOf(config.getBaseQuantity()); |
| | | // 向上检查是否已有空单挂在更高价格网格,有则跳过(防止价格回落后重复挂单) |
| | | boolean hasShortOrderAbove = false; |
| | | GridElement checkUpCursor = GridElement.findById(newEntryGrid.getUpId()); |
| | |
| | | } |
| | | |
| | | lastLongStopLossGridId = gridId; |
| | | |
| | | accumulatedLongLossCount++; |
| | | log.info("[Gate] 多仓止损触发 gridId:{}, 止损次数:{}{}, 开始追单", |
| | | gridId, accumulatedLongLossCount, sameGrid ? "(同网格)" : ""); |
| | |
| | | * </ul> |
| | | */ |
| | | private static final Map<Integer, int[]> STOP_LOSS_RULES = new LinkedHashMap<>(); |
| | | private static final int DEFAULT_STOP_LOSS_PERCENT = 5; |
| | | |
| | | static { |
| | | // times {满仓%, 阈值%} |
| | |
| | | */ |
| | | private void checkLongStopShortProfit(int times, int gridId) { |
| | | int[] r = ruleOf(times); |
| | | int maxPos = config.getMaxPositionSize(); |
| | | int maxPos = Integer.parseInt(config.getBaseQuantity()); |
| | | if (maxPos <= 0) { |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | // ---------- 己方(多仓)盈止(≥6次) ---------- |
| | | if (times >= 6 && thresholdPct > 0) { |
| | | int selfPos = Math.max(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue()); |
| | | int excess = selfPos - thresholdPosNum; |
| | | if (excess > 0) { |
| | | int perOrderQty = maxPos * 5 / 100; |
| | | if (perOrderQty <= 0) { |
| | | perOrderQty = 1; |
| | | } |
| | | int totalOrders = excess / perOrderQty; |
| | | if (totalOrders <= 0) { |
| | | totalOrders = 1; |
| | | } |
| | | int entryGridId = 0; // 多仓建仓格 |
| | | for (int i = 0; i < totalOrders; i++) { |
| | | int tpGridId = entryGridId + 2 * (i + 1); // 朝盈利方向(向上)间隔2格 |
| | | GridElement tpElem = GridElement.findById(tpGridId); |
| | | if (tpElem == null) { |
| | | break; |
| | | } |
| | | placeTakeProfitAtGrid(tpElem, true, perOrderQty, times); |
| | | } |
| | | log.info("[Gate] 止损{}→己方多仓止盈, excess:{}, 挂{}单, 每单{}张", |
| | | times, excess, totalOrders, perOrderQty); |
| | | } |
| | | } |
| | | // if (times >= 6 && thresholdPct > 0) { |
| | | // int selfPos = Math.max(queryPositionSize(Position.ModeEnum.DUAL_LONG), longPositionSize.intValue()); |
| | | // int excess = selfPos - thresholdPosNum; |
| | | // if (excess > 0) { |
| | | // int perOrderQty = maxPos * DEFAULT_STOP_LOSS_PERCENT / 100; |
| | | // if (perOrderQty <= 0) { |
| | | // perOrderQty = 1; |
| | | // } |
| | | // int totalOrders = excess / perOrderQty; |
| | | // if (totalOrders <= 0) { |
| | | // totalOrders = 1; |
| | | // } |
| | | // int entryGridId = 0; // 多仓建仓格 |
| | | // for (int i = 0; i < totalOrders; i++) { |
| | | // int tpGridId = entryGridId + 2 * (i + 1); // 朝盈利方向(向上)间隔2格 |
| | | // GridElement tpElem = GridElement.findById(tpGridId); |
| | | // if (tpElem == null) { |
| | | // break; |
| | | // } |
| | | // placeTakeProfitAtGrid(tpElem, true, perOrderQty, times); |
| | | // } |
| | | // log.info("[Gate] 止损{}→己方多仓止盈, excess:{}, 挂{}单, 每单{}张", |
| | | // times, excess, totalOrders, perOrderQty); |
| | | // } |
| | | // } |
| | | |
| | | } |
| | | |
| | |
| | | */ |
| | | private void checkShortStopLongProfit(int times, int gridId) { |
| | | int[] r = ruleOf(times); |
| | | int maxPos = config.getMaxPositionSize(); |
| | | int maxPos = Integer.parseInt(config.getBaseQuantity()); |
| | | if (maxPos <= 0) { |
| | | return; |
| | | } |
| | |
| | | } |
| | | |
| | | // ---------- 己方(空仓)盈止(≥6次) ---------- |
| | | if (times >= 6 && thresholdPct > 0) { |
| | | int selfPos = Math.max(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue()); |
| | | int excess = selfPos - thresholdPosNum; |
| | | if (excess > 0) { |
| | | int perOrderQty = maxPos * 5 / 100; |
| | | if (perOrderQty <= 0) { |
| | | perOrderQty = 1; |
| | | } |
| | | int totalOrders = excess / perOrderQty; |
| | | if (totalOrders <= 0) { |
| | | totalOrders = 1; |
| | | } |
| | | int entryGridId = 0; // 空仓建仓格 |
| | | for (int i = 0; i < totalOrders; i++) { |
| | | int tpGridId = entryGridId - 2 * (i + 1); // 朝盈利方向(向下)间隔2格 |
| | | GridElement tpElem = GridElement.findById(tpGridId); |
| | | if (tpElem == null) { |
| | | break; |
| | | } |
| | | placeTakeProfitAtGrid(tpElem, false, perOrderQty, times); |
| | | } |
| | | log.info("[Gate] 止损{}→己方空仓止盈, excess:{}, 挂{}单, 每单{}张", |
| | | times, excess, totalOrders, perOrderQty); |
| | | } |
| | | } |
| | | // if (times >= 6 && thresholdPct > 0) { |
| | | // int selfPos = Math.max(queryPositionSize(Position.ModeEnum.DUAL_SHORT), shortPositionSize.intValue()); |
| | | // int excess = selfPos - thresholdPosNum; |
| | | // if (excess > 0) { |
| | | // int perOrderQty = maxPos * DEFAULT_STOP_LOSS_PERCENT / 100; |
| | | // if (perOrderQty <= 0) { |
| | | // perOrderQty = 1; |
| | | // } |
| | | // int totalOrders = excess / perOrderQty; |
| | | // if (totalOrders <= 0) { |
| | | // totalOrders = 1; |
| | | // } |
| | | // int entryGridId = 0; // 空仓建仓格 |
| | | // for (int i = 0; i < totalOrders; i++) { |
| | | // int tpGridId = entryGridId - 2 * (i + 1); // 朝盈利方向(向下)间隔2格 |
| | | // GridElement tpElem = GridElement.findById(tpGridId); |
| | | // if (tpElem == null) { |
| | | // break; |
| | | // } |
| | | // placeTakeProfitAtGrid(tpElem, false, perOrderQty, times); |
| | | // } |
| | | // log.info("[Gate] 止损{}→己方空仓止盈, excess:{}, 挂{}单, 每单{}张", |
| | | // times, excess, totalOrders, perOrderQty); |
| | | // } |
| | | // } |
| | | |
| | | } |
| | | |