| | |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.*; |
| | | |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.handler.CandlestickChannelHandler; |
| | | import com.xcong.excoin.modules.gateApi.wsHandler.handler.PositionClosesChannelHandler; |
| | |
| | | private final List<BigDecimal> shortPriceQueue = Collections.synchronizedList(new ArrayList<>()); |
| | | /** 多仓价格队列,升序排列(小→大),容量 gridQueueSize */ |
| | | private final List<BigDecimal> longPriceQueue = Collections.synchronizedList(new ArrayList<>()); |
| | | private final List<BigDecimal> totalLongPriceQueue = Collections.synchronizedList(new ArrayList<>()); |
| | | private final List<BigDecimal> totalShortPriceQueue = Collections.synchronizedList(new ArrayList<>()); |
| | | |
| | | /** 当前多仓条件单映射:订单ID → 止盈价格,订单成交后通过订单订阅推送匹配止盈 */ |
| | | private final Map<String, BigDecimal> currentLongOrderIds = Collections.synchronizedMap(new LinkedHashMap<>()); |
| | |
| | | longPositionSize = size; |
| | | longEntryPrice = entryPrice; |
| | | } else { |
| | | |
| | | log.info("[Gate-0]多仓: {}", shortBaseEntryPrice); |
| | | longActive = false; |
| | | longPositionSize = BigDecimal.ZERO; |
| | | longEntryPrice = BigDecimal.ZERO; |
| | |
| | | shortPositionSize = size.abs(); |
| | | shortEntryPrice = entryPrice; |
| | | } else { |
| | | |
| | | log.info("[Gate-0]空仓: {}", shortBaseEntryPrice); |
| | | shortActive = false; |
| | | shortPositionSize = BigDecimal.ZERO; |
| | | shortEntryPrice = BigDecimal.ZERO; |
| | |
| | | BigDecimal elem = shortBaseEntryPrice.subtract(step).setScale(prec, RoundingMode.HALF_UP); |
| | | for (int i = 0; i < config.getGridQueueSize(); i++) { |
| | | shortPriceQueue.add(elem); |
| | | totalLongPriceQueue.add( elem); |
| | | totalShortPriceQueue.add( elem); |
| | | |
| | | elem = elem.subtract(step).setScale(prec, RoundingMode.HALF_UP); |
| | | if (elem.compareTo(BigDecimal.ZERO) <= 0) { |
| | | break; |
| | |
| | | BigDecimal elem = shortBaseEntryPrice.add(step).setScale(prec, RoundingMode.HALF_UP); |
| | | for (int i = 0; i < config.getGridQueueSize(); i++) { |
| | | longPriceQueue.add(elem); |
| | | totalLongPriceQueue.add( elem); |
| | | totalShortPriceQueue.add( elem); |
| | | elem = elem.add(step).setScale(prec, RoundingMode.HALF_UP); |
| | | } |
| | | longPriceQueue.sort(BigDecimal::compareTo); |
| | | log.info("[Gate] 多队列:{}", longPriceQueue); |
| | | totalShortPriceQueue.sort((a, b) -> b.compareTo(a)); |
| | | log.info("[Gate] 队列从大到小:{}", totalShortPriceQueue); |
| | | totalLongPriceQueue.sort(BigDecimal::compareTo); |
| | | log.info("[Gate] 队列从小到大:{}", totalLongPriceQueue); |
| | | } |
| | | |
| | | /** |
| | |
| | | log.info("[Gate] 网格元素列表已构建, 共{}个元素 (空仓:{} 位置:0 多仓:{})", elements.size(), shortSize, longSize); |
| | | } |
| | | |
| | | |
| | | private void processShortGrid(BigDecimal currentPrice) { |
| | | BigDecimal matched = BigDecimal.ZERO; |
| | | synchronized (shortPriceQueue) { |
| | | for (BigDecimal p : shortPriceQueue) { |
| | | synchronized (totalLongPriceQueue) { |
| | | for (BigDecimal p : totalLongPriceQueue) { |
| | | if (p.compareTo(currentPrice) >= 0) { |
| | | matched = p; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | log.info("[Gate-1] 多仓仓位归零 空仓队列触发, 匹配:{},当前价:{}", matched, currentPrice); |
| | | if (BigDecimal.ZERO.compareTo( matched) == 0) { |
| | | return; |
| | | } |
| | |
| | | GridElement newEntryGrid = GridElement.findById(upId); |
| | | |
| | | if (newEntryGrid != null) { |
| | | log.info("[Gate] 多仓仓位归零 空仓队列触发, 匹配:{},当前价:{}", matched, currentPrice); |
| | | log.info("[Gate-2] 多仓仓位归零 空仓队列触发, 匹配:{},当前价:{}", matched, currentPrice); |
| | | if (!newEntryGrid.isHasLongOrder()) { |
| | | BigDecimal triggerPrice = newEntryGrid.getGridPrice(); |
| | | String size = config.getBaseQuantity(); |
| | |
| | | |
| | | GridElement cancelGridElement = GridElement.findById(newEntryGrid.getUpId()); |
| | | if (cancelGridElement != null && cancelGridElement.isHasLongOrder()) { |
| | | String longOrderId = cancelGridElement.getLongOrderId(); |
| | | longEntryTraderIdParam(cancelGridElement, null, false); |
| | | executor.cancelConditionalOrder(cancelGridElement.getLongOrderId(), oid -> { |
| | | log.info("[Gate] 多仓仓位归零, 取消gridId:{}的多单", cancelGridElement.getId()); |
| | | executor.cancelConditionalOrder(longOrderId, oid -> { |
| | | log.info("[Gate] 多仓仓位归零, 取消gridId:{}的多单,{}", cancelGridElement.getId(),longOrderId); |
| | | }); |
| | | } |
| | | } |
| | |
| | | |
| | | private void processLongGrid(BigDecimal currentPrice) { |
| | | BigDecimal matched = BigDecimal.ZERO; |
| | | synchronized (longPriceQueue) { |
| | | for (BigDecimal p : longPriceQueue) { |
| | | synchronized (totalShortPriceQueue) { |
| | | for (BigDecimal p : totalShortPriceQueue) { |
| | | if (p.compareTo(currentPrice) <= 0) { |
| | | matched = p; |
| | | } else { |
| | | break; |
| | | } |
| | | } |
| | | log.info("[Gate-3] 空仓仓位归零 多仓队列触发, 匹配:{},当前价:{}", matched, currentPrice); |
| | | if (BigDecimal.ZERO.compareTo( matched) == 0) { |
| | | return; |
| | | } |
| | |
| | | GridElement newEntryGrid = GridElement.findById(downId); |
| | | |
| | | if (newEntryGrid != null) { |
| | | log.info("[Gate] 空仓仓位归零 多仓队列触发, 匹配:{},当前价:{}", matched, currentPrice); |
| | | log.info("[Gate-4] 空仓仓位归零 多仓队列触发, 匹配:{},当前价:{}", matched, currentPrice); |
| | | if (!newEntryGrid.isHasShortOrder()){ |
| | | BigDecimal triggerPrice = newEntryGrid.getGridPrice(); |
| | | String size = config.getBaseQuantity(); |
| | |
| | | * 看是否有空仓挂单,有就取消 |
| | | */ |
| | | if (cancelGridElement != null && cancelGridElement.isHasShortOrder()) { |
| | | String shortOrderId = cancelGridElement.getShortOrderId(); |
| | | shortEntryTraderIdParam(cancelGridElement, null, false); |
| | | executor.cancelConditionalOrder(cancelGridElement.getShortOrderId(), oid -> { |
| | | log.info("[Gate] 空仓仓位归零, 取消gridId:{}的多单", cancelGridElement.getId()); |
| | | executor.cancelConditionalOrder(shortOrderId, oid -> { |
| | | log.info("[Gate] 空仓仓位归零, 取消gridId:{}的多单{}", cancelGridElement.getId(),shortOrderId); |
| | | }); |
| | | } |
| | | |