github.com/frankrap/okex-api@v1.0.4/orderbook.go (about) 1 package okex 2 3 import ( 4 "fmt" 5 "github.com/MauriceGit/skiplist" 6 "strconv" 7 "time" 8 ) 9 10 const ( 11 ActionDepthL2Partial = "partial" 12 ActionDepthL2Update = "update" 13 ) 14 15 type Item struct { 16 Price float64 17 Amount float64 18 } 19 20 func (e Item) ExtractKey() float64 { 21 return e.Price 22 } 23 24 func (e Item) String() string { 25 return fmt.Sprintf("%.8f", e.Price) 26 } 27 28 type OrderBook struct { 29 InstrumentID string `json:"instrument_id"` 30 Asks []Item `json:"asks"` 31 Bids []Item `json:"bids"` 32 } 33 34 type DepthOrderBook struct { 35 instrumentID string // BTC-USD-SWAP 36 asks skiplist.SkipList 37 bids skiplist.SkipList 38 } 39 40 func (d *DepthOrderBook) GetInstrumentID() string { 41 return d.instrumentID 42 } 43 44 func (d *DepthOrderBook) Update(action string, data *WSDepthL2Tbt) { 45 if action == ActionDepthL2Partial { 46 d.asks = skiplist.NewSeedEps(time.Now().UTC().UnixNano(), 0.00000001) 47 d.bids = skiplist.NewSeedEps(time.Now().UTC().UnixNano(), 0.00000001) 48 //d.asks = skiplist.New() 49 //d.bids = skiplist.New() 50 // 举例: ["411.8", "10", "1", "4"] 51 // 411.8为深度价格,10为此价格的合约张数,1为此价格的强平单个数,4为此价格的订单个数。 52 for _, ask := range data.Asks { 53 price, _ := strconv.ParseFloat(ask[0], 64) 54 amount, _ := strconv.ParseFloat(ask[1], 64) 55 d.asks.Insert(Item{ 56 Price: price, 57 Amount: amount, 58 }) 59 } 60 for _, bid := range data.Bids { 61 price, _ := strconv.ParseFloat(bid[0], 64) 62 amount, _ := strconv.ParseFloat(bid[1], 64) 63 d.bids.Insert(Item{ 64 Price: price, 65 Amount: amount, 66 }) 67 } 68 return 69 } 70 71 if action == ActionDepthL2Update { 72 for _, ask := range data.Asks { 73 price, _ := strconv.ParseFloat(ask[0], 64) 74 amount, _ := strconv.ParseFloat(ask[1], 64) 75 if amount == 0 { 76 d.asks.Delete(Item{ 77 Price: price, 78 Amount: amount, 79 }) 80 } else { 81 item := Item{ 82 Price: price, 83 Amount: amount, 84 } 85 elem, ok := d.asks.Find(item) 86 if ok { 87 d.asks.ChangeValue(elem, item) 88 } else { 89 d.asks.Insert(item) 90 } 91 } 92 } 93 for _, bid := range data.Bids { 94 price, _ := strconv.ParseFloat(bid[0], 64) 95 amount, _ := strconv.ParseFloat(bid[1], 64) 96 if amount == 0 { 97 d.bids.Delete(Item{ 98 Price: price, 99 Amount: amount, 100 }) 101 } else { 102 item := Item{ 103 Price: price, 104 Amount: amount, 105 } 106 elem, ok := d.bids.Find(item) 107 if ok { 108 d.bids.ChangeValue(elem, item) 109 } else { 110 d.bids.Insert(item) 111 } 112 } 113 } 114 } 115 } 116 117 func (d *DepthOrderBook) GetOrderBook(depth int) (result OrderBook) { 118 result.InstrumentID = d.instrumentID 119 smallest := d.asks.GetSmallestNode() 120 if smallest != nil { 121 result.Asks = append(result.Asks, smallest.GetValue().(Item)) 122 count := 1 123 node := smallest 124 for count < depth { 125 node = d.asks.Next(node) 126 if node == nil { 127 break 128 } 129 result.Asks = append(result.Asks, node.GetValue().(Item)) 130 count++ 131 } 132 } 133 134 largest := d.bids.GetLargestNode() 135 if largest != nil { 136 result.Bids = append(result.Bids, largest.GetValue().(Item)) 137 count := 1 138 node := largest 139 for count < depth { 140 node = d.bids.Prev(node) 141 if node == nil { 142 break 143 } 144 result.Bids = append(result.Bids, node.GetValue().(Item)) 145 count++ 146 } 147 } 148 return 149 } 150 151 func NewDepthOrderBook(instrumentID string) *DepthOrderBook { 152 return &DepthOrderBook{ 153 instrumentID: instrumentID, 154 asks: skiplist.New(), 155 bids: skiplist.New(), 156 } 157 }