package com.xcong.excoin.modules.okxNewPrice; import java.math.BigDecimal; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 网格价格层级,策略的最小操作单元。 * *

定位

* 每个 OkxGridElement 对应网格中的一个价格点,同时持有该点的多仓和空仓挂单状态。 * 维护全局静态 HashMap 索引实现 O(1) 双向查询。 * *

ID 体系与链表

*
 *   ID ≦ -1:  空仓队列区域(降序),ID 自减,gridPrice 递减
 *   ID  =  0:  基座位置,gridPrice = shortBaseEntryPrice
 *   ID ≧  1:  多仓队列区域(升序),ID 自增,gridPrice 递增
 *
 *   链表: ... ← -3 ← -2 ← -1 ← 0 → 1 → 2 → 3 → ...
 * 
* *

8 个全局 O(1) 索引

*
 *   INDEX                 → findById(int)               ID → 元素
 *   PRICE_INDEX           → findByPrice(BigDecimal)     价格 → 元素
 *   LONG_ORDER_ID_INDEX   → findByLongOrderId(String)   多仓挂单ID → 元素
 *   SHORT_ORDER_ID_INDEX  → findByShortOrderId(String)  空仓挂单ID → 元素
 *   LONG_TP_ORDER_ID_INDEX→ findByLongTakeProfitOrderId(String)  多止盈ID → 元素
 *   SHORT_TP_ORDER_ID_INDEX→ findByShortTakeProfitOrderId(String) 空止盈ID → 元素
 *   LONG_SL_ORDER_ID_INDEX→ findByLongStopLossOrderId(String)    多止损ID → 元素
 *   SHORT_SL_ORDER_ID_INDEX→ findByShortStopLossOrderId(String)  空止损ID → 元素
 * 
* * @author Administrator */ public class OkxGridElement { private int id; private BigDecimal gridPrice; private boolean hasLongOrder; private boolean hasShortOrder; private OkxTraderParam longTraderParam; private OkxTraderParam shortTraderParam; private Integer upId; private Integer downId; private String longOrderId; private String shortOrderId; private String longTakeProfitOrderId; private String shortTakeProfitOrderId; private String longStopLossOrderId; private String shortStopLossOrderId; // ==================== 全局索引 ==================== private static final Map INDEX = new ConcurrentHashMap<>(); private static final Map PRICE_INDEX = new ConcurrentHashMap<>(); private static final Map LONG_ORDER_ID_INDEX = new ConcurrentHashMap<>(); private static final Map SHORT_ORDER_ID_INDEX = new ConcurrentHashMap<>(); private static final Map LONG_TP_ORDER_ID_INDEX = new ConcurrentHashMap<>(); private static final Map SHORT_TP_ORDER_ID_INDEX = new ConcurrentHashMap<>(); private static final Map LONG_SL_ORDER_ID_INDEX = new ConcurrentHashMap<>(); private static final Map SHORT_SL_ORDER_ID_INDEX = new ConcurrentHashMap<>(); // ==================== 静态查找方法 ==================== public static OkxGridElement findById(int id) { return INDEX.get(id); } public static OkxGridElement findByPrice(BigDecimal price) { return PRICE_INDEX.get(price); } public static OkxGridElement findByLongOrderId(String orderId) { return LONG_ORDER_ID_INDEX.get(orderId); } public static OkxGridElement findByShortOrderId(String orderId) { return SHORT_ORDER_ID_INDEX.get(orderId); } public static OkxGridElement findByLongTakeProfitOrderId(String orderId) { return LONG_TP_ORDER_ID_INDEX.get(orderId); } public static OkxGridElement findByShortTakeProfitOrderId(String orderId) { return SHORT_TP_ORDER_ID_INDEX.get(orderId); } public static OkxGridElement findByLongStopLossOrderId(String orderId) { return LONG_SL_ORDER_ID_INDEX.get(orderId); } public static OkxGridElement findByShortStopLossOrderId(String orderId) { return SHORT_SL_ORDER_ID_INDEX.get(orderId); } /** * 全量重建全局索引。由 OkxConfig.setGridElements() 调用。 */ public static void rebuildIndex(List elements) { INDEX.clear(); PRICE_INDEX.clear(); LONG_ORDER_ID_INDEX.clear(); SHORT_ORDER_ID_INDEX.clear(); LONG_TP_ORDER_ID_INDEX.clear(); SHORT_TP_ORDER_ID_INDEX.clear(); LONG_SL_ORDER_ID_INDEX.clear(); SHORT_SL_ORDER_ID_INDEX.clear(); for (OkxGridElement e : elements) { INDEX.put(e.getId(), e); putDynamicIndices(e); } logAll(); } /** * 增量刷新动态索引。每次修改订单状态后调用。 */ public static void refreshIndices() { PRICE_INDEX.clear(); LONG_ORDER_ID_INDEX.clear(); SHORT_ORDER_ID_INDEX.clear(); LONG_TP_ORDER_ID_INDEX.clear(); SHORT_TP_ORDER_ID_INDEX.clear(); LONG_SL_ORDER_ID_INDEX.clear(); SHORT_SL_ORDER_ID_INDEX.clear(); for (OkxGridElement e : INDEX.values()) { putDynamicIndices(e); } logAll(); } /** * 获取所有已挂空仓条件单且当前价高于其价格、无止盈单的网格元素。 */ public static List findAllLongOrders(BigDecimal currentPrice) { List result = new ArrayList<>(); for (OkxGridElement e : INDEX.values()) { if (e.isHasLongOrder() && e.getGridPrice().compareTo(currentPrice) > 0 && e.getLongTakeProfitOrderId() == null) { result.add(e); } } return result; } /** * 获取所有已挂多仓条件单且当前价低于其价格、无止盈单的网格元素。 */ public static List findAllShortOrders(BigDecimal currentPrice) { List result = new ArrayList<>(); for (OkxGridElement e : INDEX.values()) { if (e.isHasShortOrder() && e.getGridPrice().compareTo(currentPrice) < 0 && e.getShortTakeProfitOrderId() == null) { result.add(e); } } return result; } private static void putDynamicIndices(OkxGridElement e) { PRICE_INDEX.put(e.getGridPrice(), e); if (e.getLongOrderId() != null) LONG_ORDER_ID_INDEX.put(e.getLongOrderId(), e); if (e.getShortOrderId() != null) SHORT_ORDER_ID_INDEX.put(e.getShortOrderId(), e); if (e.getLongTakeProfitOrderId() != null) LONG_TP_ORDER_ID_INDEX.put(e.getLongTakeProfitOrderId(), e); if (e.getShortTakeProfitOrderId() != null) SHORT_TP_ORDER_ID_INDEX.put(e.getShortTakeProfitOrderId(), e); if (e.getLongStopLossOrderId() != null) LONG_SL_ORDER_ID_INDEX.put(e.getLongStopLossOrderId(), e); if (e.getShortStopLossOrderId() != null) SHORT_SL_ORDER_ID_INDEX.put(e.getShortStopLossOrderId(), e); } public static void logAll() { List sorted = new ArrayList<>(INDEX.values()); sorted.sort((a, b) -> Integer.compare(a.getId(), b.getId())); StringBuilder sb = new StringBuilder("\n========== OKX 网格数据 ==========\n"); for (OkxGridElement e : sorted) { if (e.isHasLongOrder() || e.isHasShortOrder() || e.getLongStopLossOrderId() != null || e.getShortStopLossOrderId() != null) { sb.append(String.format( " ID=%4d 价格=%s up=%s down=%s 多仓=%s(%s) 空仓=%s(%s) 多止盈=%s 空止盈=%s 多止损=%s 空止损=%s\n", e.getId(), e.getGridPrice(), e.getUpId(), e.getDownId(), e.isHasLongOrder() ? "有" : "无", e.getLongOrderId() != null ? e.getLongOrderId() : "-", e.isHasShortOrder() ? "有" : "无", e.getShortOrderId() != null ? e.getShortOrderId() : "-", e.getLongTakeProfitOrderId() != null ? e.getLongTakeProfitOrderId() : "-", e.getShortTakeProfitOrderId() != null ? e.getShortTakeProfitOrderId() : "-", e.getLongStopLossOrderId() != null ? e.getLongStopLossOrderId() : "-", e.getShortStopLossOrderId() != null ? e.getShortStopLossOrderId() : "-")); } } sb.append(String.format( " 索引统计: ID=%d 价格=%d 多仓订单ID=%d 空仓订单ID=%d 多止盈ID=%d 空止盈ID=%d 多止损ID=%d 空止损ID=%d\n", INDEX.size(), PRICE_INDEX.size(), LONG_ORDER_ID_INDEX.size(), SHORT_ORDER_ID_INDEX.size(), LONG_TP_ORDER_ID_INDEX.size(), SHORT_TP_ORDER_ID_INDEX.size(), LONG_SL_ORDER_ID_INDEX.size(), SHORT_SL_ORDER_ID_INDEX.size())); sb.append("================================\n"); System.out.println(sb); } public OkxGridElement getUp() { return upId != null ? INDEX.get(upId) : null; } public OkxGridElement getDown() { return downId != null ? INDEX.get(downId) : null; } private OkxGridElement(Builder builder) { this.id = builder.id; this.gridPrice = builder.gridPrice; this.hasLongOrder = builder.hasLongOrder; this.hasShortOrder = builder.hasShortOrder; this.longTraderParam = builder.longTraderParam; this.shortTraderParam = builder.shortTraderParam; this.upId = builder.upId; this.downId = builder.downId; this.longOrderId = builder.longOrderId; this.shortOrderId = builder.shortOrderId; this.longTakeProfitOrderId = builder.longTakeProfitOrderId; this.shortTakeProfitOrderId = builder.shortTakeProfitOrderId; this.longStopLossOrderId = builder.longStopLossOrderId; this.shortStopLossOrderId = builder.shortStopLossOrderId; } // ==================== getters/setters ==================== public int getId() { return id; } public void setId(int id) { this.id = id; } public BigDecimal getGridPrice() { return gridPrice; } public void setGridPrice(BigDecimal gridPrice) { this.gridPrice = gridPrice; } public boolean isHasLongOrder() { return hasLongOrder; } public void setHasLongOrder(boolean hasLongOrder) { this.hasLongOrder = hasLongOrder; } public boolean isHasShortOrder() { return hasShortOrder; } public void setHasShortOrder(boolean hasShortOrder) { this.hasShortOrder = hasShortOrder; } public OkxTraderParam getLongTraderParam() { return longTraderParam; } public void setLongTraderParam(OkxTraderParam longTraderParam) { this.longTraderParam = longTraderParam; } public OkxTraderParam getShortTraderParam() { return shortTraderParam; } public void setShortTraderParam(OkxTraderParam shortTraderParam) { this.shortTraderParam = shortTraderParam; } public Integer getUpId() { return upId; } public void setUpId(Integer upId) { this.upId = upId; } public Integer getDownId() { return downId; } public void setDownId(Integer downId) { this.downId = downId; } public String getLongOrderId() { return longOrderId; } public void setLongOrderId(String longOrderId) { this.longOrderId = longOrderId; } public String getShortOrderId() { return shortOrderId; } public void setShortOrderId(String shortOrderId) { this.shortOrderId = shortOrderId; } public String getLongTakeProfitOrderId() { return longTakeProfitOrderId; } public void setLongTakeProfitOrderId(String longTakeProfitOrderId) { this.longTakeProfitOrderId = longTakeProfitOrderId; } public String getShortTakeProfitOrderId() { return shortTakeProfitOrderId; } public void setShortTakeProfitOrderId(String shortTakeProfitOrderId) { this.shortTakeProfitOrderId = shortTakeProfitOrderId; } public String getLongStopLossOrderId() { return longStopLossOrderId; } public void setLongStopLossOrderId(String longStopLossOrderId) { this.longStopLossOrderId = longStopLossOrderId; } public String getShortStopLossOrderId() { return shortStopLossOrderId; } public void setShortStopLossOrderId(String shortStopLossOrderId) { this.shortStopLossOrderId = shortStopLossOrderId; } public static Builder builder() { return new Builder(); } public static class Builder { private int id; private BigDecimal gridPrice; private boolean hasLongOrder = false; private boolean hasShortOrder = false; private OkxTraderParam longTraderParam; private OkxTraderParam shortTraderParam; private Integer upId; private Integer downId; private String longOrderId; private String shortOrderId; private String longTakeProfitOrderId; private String shortTakeProfitOrderId; private String longStopLossOrderId; private String shortStopLossOrderId; public Builder id(int id) { this.id = id; return this; } public Builder gridPrice(BigDecimal gridPrice) { this.gridPrice = gridPrice; return this; } public Builder hasLongOrder(boolean hasLongOrder) { this.hasLongOrder = hasLongOrder; return this; } public Builder hasShortOrder(boolean hasShortOrder) { this.hasShortOrder = hasShortOrder; return this; } public Builder longTraderParam(OkxTraderParam longTraderParam) { this.longTraderParam = longTraderParam; return this; } public Builder shortTraderParam(OkxTraderParam shortTraderParam) { this.shortTraderParam = shortTraderParam; return this; } public Builder upId(Integer upId) { this.upId = upId; return this; } public Builder downId(Integer downId) { this.downId = downId; return this; } public Builder longOrderId(String longOrderId) { this.longOrderId = longOrderId; return this; } public Builder shortOrderId(String shortOrderId) { this.shortOrderId = shortOrderId; return this; } public Builder longTakeProfitOrderId(String longTakeProfitOrderId) { this.longTakeProfitOrderId = longTakeProfitOrderId; return this; } public Builder shortTakeProfitOrderId(String shortTakeProfitOrderId) { this.shortTakeProfitOrderId = shortTakeProfitOrderId; return this; } public Builder longStopLossOrderId(String longStopLossOrderId) { this.longStopLossOrderId = longStopLossOrderId; return this; } public Builder shortStopLossOrderId(String shortStopLossOrderId) { this.shortStopLossOrderId = shortStopLossOrderId; return this; } public OkxGridElement build() { return new OkxGridElement(this); } } }