6 "github.com/bytom/vapor/application/mov/common"
7 "github.com/bytom/vapor/application/mov/database"
8 "github.com/bytom/vapor/errors"
11 // OrderBook is used to handle the mov orders in memory like stack
12 type OrderBook struct {
13 movStore database.MovStore
14 // key of tradePair -> []order
15 dbOrders map[string][]*common.Order
16 // key of tradePair -> iterator
17 orderIterators map[string]*database.OrderIterator
19 // key of tradePair -> []order
20 arrivalAddOrders map[string][]*common.Order
21 // key of order -> order
22 arrivalDelOrders map[string]*common.Order
25 // NewOrderBook create a new OrderBook object
26 func NewOrderBook(movStore database.MovStore, arrivalAddOrders, arrivalDelOrders []*common.Order) *OrderBook {
29 dbOrders: make(map[string][]*common.Order),
30 orderIterators: make(map[string]*database.OrderIterator),
32 arrivalAddOrders: arrangeArrivalAddOrders(arrivalAddOrders),
33 arrivalDelOrders: arrangeArrivalDelOrders(arrivalDelOrders),
37 // AddOrder add the in memory temp order to order table
38 func (o *OrderBook) AddOrder(order *common.Order) error {
39 tradePairKey := order.TradePair().Key()
40 orders := o.arrivalAddOrders[tradePairKey]
41 if len(orders) > 0 && order.Rate() > orders[len(orders)-1].Rate() {
42 return errors.New("rate of order must less than the min order in order table")
45 o.arrivalAddOrders[tradePairKey] = append(orders, order)
49 // PeekOrder return the next lowest order of given trade pair
50 func (o *OrderBook) PeekOrder(tradePair *common.TradePair) *common.Order {
51 if len(o.dbOrders[tradePair.Key()]) == 0 {
52 o.extendDBOrders(tradePair)
55 var nextOrder *common.Order
56 orders := o.dbOrders[tradePair.Key()]
58 nextOrder = orders[len(orders)-1]
61 if nextOrder != nil && o.arrivalDelOrders[nextOrder.Key()] != nil {
62 o.dbOrders[tradePair.Key()] = orders[0 : len(orders)-1]
63 return o.PeekOrder(tradePair)
66 arrivalOrder := o.peekArrivalOrder(tradePair)
67 if nextOrder == nil || (arrivalOrder != nil && arrivalOrder.Rate() < nextOrder.Rate()) {
68 nextOrder = arrivalOrder
73 // PeekOrders return the next lowest orders by given array of trade pairs
74 func (o *OrderBook) PeekOrders(tradePairs []*common.TradePair) []*common.Order {
75 var orders []*common.Order
76 for _, tradePair := range tradePairs {
77 order := o.PeekOrder(tradePair)
82 orders = append(orders, order)
87 // PopOrder delete the next lowest order of given trade pair
88 func (o *OrderBook) PopOrder(tradePair *common.TradePair) {
89 order := o.PeekOrder(tradePair)
94 orders := o.dbOrders[tradePair.Key()]
95 if len(orders) != 0 && orders[len(orders)-1].Key() == order.Key() {
96 o.dbOrders[tradePair.Key()] = orders[0 : len(orders)-1]
99 arrivalOrders := o.arrivalAddOrders[tradePair.Key()]
100 if len(arrivalOrders) != 0 && arrivalOrders[len(arrivalOrders)-1].Key() == order.Key() {
101 o.arrivalAddOrders[tradePair.Key()] = arrivalOrders[0 : len(arrivalOrders)-1]
105 // PopOrders delete the next lowest orders by given trade pairs
106 func (o *OrderBook) PopOrders(tradePairs []*common.TradePair) []*common.Order {
107 var orders []*common.Order
108 for _, tradePair := range tradePairs {
109 o.PopOrder(tradePair)
114 func arrangeArrivalAddOrders(orders []*common.Order) map[string][]*common.Order {
115 arrivalAddOrderMap := make(map[string][]*common.Order)
116 for _, order := range orders {
117 arrivalAddOrderMap[order.TradePair().Key()] = append(arrivalAddOrderMap[order.TradePair().Key()], order)
120 for _, orders := range arrivalAddOrderMap {
121 sort.Sort(sort.Reverse(common.OrderSlice(orders)))
123 return arrivalAddOrderMap
126 func arrangeArrivalDelOrders(orders []*common.Order) map[string]*common.Order {
127 arrivalDelOrderMap := make(map[string]*common.Order)
128 for _, order := range orders {
129 arrivalDelOrderMap[order.Key()] = order
131 return arrivalDelOrderMap
134 func (o *OrderBook) extendDBOrders(tradePair *common.TradePair) {
135 iterator, ok := o.orderIterators[tradePair.Key()]
137 iterator = database.NewOrderIterator(o.movStore, tradePair)
138 o.orderIterators[tradePair.Key()] = iterator
141 nextOrders := iterator.NextBatch()
142 for i := len(nextOrders) - 1; i >= 0; i-- {
143 o.dbOrders[tradePair.Key()] = append(o.dbOrders[tradePair.Key()], nextOrders[i])
147 func (o *OrderBook) peekArrivalOrder(tradePair *common.TradePair) *common.Order {
148 if arrivalAddOrders := o.arrivalAddOrders[tradePair.Key()]; len(arrivalAddOrders) > 0 {
149 return arrivalAddOrders[len(arrivalAddOrders)-1]