coinex03 // level2数据展示
目录
1. 委托账本的设计
1.0 课程视频
1.1 数据库表设计
2. 构建数据处理方法
2.1 数据初始化方法
2.2 获取当前的交易的队列方法
2.3 添加 删除使用的迭代器方法
2.4 添加订单到队列的方法
2.5 取消订单 -> 使用迭代器
2.6 获取队列第一个数据
2.7 OrderBooks构造器方法-> 初始化时数据构造 实时使用时数据构造
3. 撮合引擎
3.0 课程视频
1. 委托账本的设计
1.0 课程视频
https://www.bilibili.com/video/BV13v4y1A7qH?p=51&spm_id_from=pageDriver&vd_source=ff8b7f852278821525f11666b36f180a
1.1 数据库表设计
1. model-> OrderBooks // 不同价格的数据库表
2. model-> MergeOrder // 相同价格的不同时间的数据库表
3. 枚举类的使用
2. 构建数据处理方法
2.1 数据初始化方法
public void initialize() {log.info("init CoinTrader for symbol {}", symbol);// 载入比较器buyLimitPrice = new TreeMap<>(Comparator.reverseOrder()); //价格从大到小 Comparator 比较器sellLimitPrice = new TreeMap<>(Comparator.naturalOrder()); // 价格从小到大buyTradePlate = new TradePlate(symbol, OrderDirection.BUY);sellTradePlate = new TradePlate(symbol, OrderDirection.SELL);dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");}
2.2 获取当前的交易的队列方法
public TreeMap<BigDecimal, MergeOrder> getCurrentLimitPrices(OrderDirection direction) {return direction == OrderDirection.BUY ? buyLimitPrice : sellLimitPrice;}
2.3 添加 删除使用的迭代器方法
public Iterator<Map.Entry<BigDecimal, MergeOrder>> getCurrentLimitPriceIterator(OrderDirection direction) { // 之后 删除 添加 操作使用的return getCurrentLimitPrices(direction).entrySet().iterator();}
2.4 添加订单到队列的方法
// 原理:横向mergeOrder数据库表, 通过价格不同 判断是否存在mergeOrder 不存在就添加mergerOrder 再添加数据, 存在就直接在里面添加数据
public void addOrder(Order order) {TreeMap<BigDecimal, MergeOrder> currentLimitPrices = getCurrentLimitPrices(order.getOrderDirection());MergeOrder mergeOrder = currentLimitPrices.get(order.getPrice());//if (mergeOrder == null) { // 之前在红黑树里面没有这个价格的keymergeOrder = new MergeOrder();currentLimitPrices.put(order.getPrice(), mergeOrder);}//mergeOrder.add(order);// 将新的订单添加到盘口里面if(order.getOrderDirection()==OrderDirection.BUY){buyTradePlate.add(order);}else{sellTradePlate.add(order);}}
2.5 取消订单 -> 使用迭代器
// 原理: 取消订单 并判断 取消后 mergeOrder表中这个价格 是否还有其他订单,有则删取消的订单,无 则删除此价格的mergeOrder
public void cancelOrder(Order order) {TreeMap<BigDecimal, MergeOrder> currentLimitPrices = getCurrentLimitPrices(order.getOrderDirection());MergeOrder mergeOrder = currentLimitPrices.get(order);if (mergeOrder == null) {return;}Iterator<Order> iterator = mergeOrder.iterator();while (iterator.hasNext()) {Order next = iterator.next();// 找到之前的我们的订单记录if (next.getOrderId().equals(order.getOrderId())) {iterator.remove(); // 使用迭代器}}int size = mergeOrder.size(); // 删除之前,我们看合并订单的大小if (size == 0) { // 若我们的红黑树里面的合并订单的数据为空,我们摘除currentLimitPrices.remove(order.getPrice());}if(order.getOrderDirection()==OrderDirection.BUY){buyTradePlate.remove(order);}else{sellTradePlate.remove(order);}}
2.6 获取队列第一个数据
public Map.Entry<BigDecimal, MergeOrder> getBestSuitOrder(OrderDirection orderDirection) {return getCurrentLimitPrices(orderDirection).firstEntry();}
2.7 OrderBooks构造器方法-> 初始化时数据构造 实时使用时数据构造
public OrderBooks(String symbol) {this(symbol, 4, 4);} // 小数点后4位// 构造器public OrderBooks(String symbol, int coinScale, int baseCoinScale) { // MatchEngineProperties 在这里面定义的方法类this.symbol = symbol;this.coinScale = coinScale; // 交易币种的精度this.baseCoinScale = baseCoinScale; //基币的精度this.initialize(); // 初始化方法}
3. 撮合引擎
3.0 课程视频
https://www.bilibili.com/video/BV13v4y1A7qH?p=52&spm_id_from=pageDriver&vd_source=ff8b7f852278821525f11666b36f180a
0. 课程视频
https://www.bilibili.com/video/BV13v4y1A7qH/?p=45&spm_id_from=pageDriver&vd_source=ff8b7f852278821525f11666b36f180a
1. 实体类DepthsVo 选出属性 解耦
import org.example.domain.DepthItemVo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;@Data
@ApiModel(value = "深度盘口数据")
public class DepthsVo {/* 委托买单*/@ApiModelProperty(value = "委托买单")private List<DepthItemVo> bids = Collections.emptyList() ;/* 委托卖单*/@ApiModelProperty(value = "委托卖单")private List<DepthItemVo> asks = Collections.emptyList() ;/* 当前成交价(GCN)*/@ApiModelProperty(value = "当前成交价GCN")private BigDecimal price = BigDecimal.ZERO;/* 当前成交价对应CNY价格*/@ApiModelProperty(value = "当前成交价CNY")private BigDecimal cnyPrice = BigDecimal.ZERO;
}
2. 前端确定 请求url
http://127.0.0.1/exchange/markets/depth/BTCGCN/DEFAULT
3. DepthItemVo
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;import java.math.BigDecimal;@ApiModel("明细")
@NoArgsConstructor
@AllArgsConstructor
@Data
public class DepthItemVo implements Comparable<DepthItemVo> {/* 价格*/@ApiModelProperty(value = "价格")private BigDecimal price = BigDecimal.ZERO;;/* 数量*/@ApiModelProperty(value = "数量")private BigDecimal volume = BigDecimal.ZERO;@Overridepublic int compareTo(DepthItemVo o) {return this.price.compareTo(o.getPrice());}
}
4. controller ->MarketController
public R<DepthsVo> findDeptVosSymbol(@PathVariable("symbol") String symbol, String dept) { // @PathVariable("symbol") 路径里的值// 交易市场Market market = marketService.getMarkerBySymbol(symbol);DepthsVo depthsVo = new DepthsVo();depthsVo.setCnyPrice(market.getOpenPrice()); // CNY的价格depthsVo.setPrice(market.getOpenPrice()); // GCN的价格Map<String, List<DepthItemVo>> depthMap = orderBooksFeignClient.querySymbolDepth(symbol);if (!CollectionUtils.isEmpty(depthMap)) {depthsVo.setAsks(depthMap.get("asks"));depthsVo.setBids(depthMap.get("bids"));}return R.ok(depthsVo);}