如何建立回测系统(二)

如何建立回测系统(二)

一个简单的回放市场实现

public class MarketPlace {

    private Map<String, List<Order>> orderChannel;
    private Map<String, Long> lastComplete;

    public MarketPlace() {
        orderChannel = new ConcurrentHashMap<>();
        lastComplete = new ConcurrentHashMap<>();
    }

    public void order(Order order) {
        List<Order> list = orderChannel.get(order.getTradeCode());
        if (Objects.isNull(list)) {
            list = new ArrayList<>();
            orderChannel.put(order.getTradeCode(), list);
        }
        synchronized (list) {
            List<Order> targetPriceOrder;
            List<Order> sellOrder = list.stream()
                .filter(order1 -> !order1.isComplete())
                .filter(Order::sell)
                .sorted(Comparator.comparing(Order::getPrice)
                    .thenComparing(Order::getTimestamp))
                .collect(Collectors.toList());
            List<Order> buyOrder = list.stream()
                .filter(order1 -> !order1.isComplete())
                .filter(order1 -> !order1.sell())
                .sorted(Comparator.comparing(Order::getPrice, Comparator.reverseOrder())
                    .thenComparing(Order::getTimestamp))
                .collect(Collectors.toList());
            //进来的是买单
            if (!order.sell()) {
                if (!buyOrder.isEmpty() && buyOrder.get(0).getPrice() > order.getPrice()) {
                    list.add(order);
                    return;
                }
                //处理好后,是按照价格小,时间先排列
                targetPriceOrder = sellOrder.stream()
                    //需要找到挂单中比当前订单要价低或者相等的
                    .filter(order1 -> order.getPrice() <= order1.getPrice())
                    .collect(Collectors.toList());
            } else {
                if (!sellOrder.isEmpty() && sellOrder.get(0).getPrice() < order.getPrice()) {
                    list.add(order);
                    return;
                }
                //进来的是卖单,找买单 , 卖单进来,先开始撮合最高价的买单
                targetPriceOrder = buyOrder.stream()
                    //需要找到买单中比当前订单要价高的
                    .filter(order1 -> order.getPrice() <= order1.getPrice())
                    .collect(Collectors.toList());
                //新入订单需要撮合的数量
            }
            //新入订单需要撮合的数量
            long count = order.getRemainCount();
            //连续竞价,买单进来,开始先撮合最低价的卖单
            for (Order order1 : targetPriceOrder) {
                count = count - order1.getRemainCount();
                if (count < 0) {
                    //说明当前订单已经满足,order不需要进入队列排队,order1更新成交数,中断循环
                    order1.addCompleteCount(order1.getCount() - Math.abs(count));
                    order.addCompleteCount(order.getCount());
                    order.complete();
                    this.lastComplete.put(order.getTradeCode(), order.getPrice());
                    break;
                } else if (count == 0) {
                    //说明订单恰好满足,中断循环,将order1添加移除队列
                    order.addCompleteCount(order.getCount());
                    order1.addCompleteCount(order1.getCount());
                    order1.complete();
                    order.complete();
                    this.lastComplete.put(order.getTradeCode(), order.getPrice());
                } else {
                    //说明订单未满足,将order1添加移除队列,并继续循环
                    order1.complete();
                    order.addCompleteCount(order1.getRemainCount());
                }
                count = order.getRemainCount();
            }
            if (!order.isComplete()) {
                list.add(order);
            }
        }
    }

    public Long getLastPrice(String security) {
        return this.lastComplete.get(security);
    }

性能分析

最高对单个标的物单线程,且订单越多,处理速度越慢

T = f(m*n)

可能的优化点

  1. 减少每次对全部订单进行筛选排序,分出买卖单
  2. 针对国内涨跌幅限制,对价格进行分级,每个价格中订单按照实践排序
  3. 尽可能用基础类型