func (m *M) addBuy(b *pqueue.OrderNode) { if b.Price() == msg.MARKET_PRICE { panic("It is illegal to send a buy at market price") } q := m.getMatchQueues(b.StockId()) if !m.fillableBuy(b, q) { q.PushBuy(b) } }
func (m *M) cancel(o *pqueue.OrderNode) { q := m.getMatchQueues(o.StockId()) ro := q.Cancel(o) if ro != nil { m.completeCancelled(ro) m.slab.Free(ro) } else { m.completeNotCancelled(o) } m.slab.Free(o) }
func (rm *refmatcher) push(o *pqueue.OrderNode) { if o.Kind() == msg.BUY { rm.matchQueues.PushBuy(o) return } if o.Kind() == msg.SELL { rm.matchQueues.PushSell(o) return } panic("Unsupported trade kind pushed") }
func (m *M) fillableBuy(b *pqueue.OrderNode, q *pqueue.MatchQueues) bool { for { s := q.PeekSell() if s == nil { return false } if b.Price() >= s.Price() { if b.Amount() > s.Amount() { amount := s.Amount() price := price(b.Price(), s.Price()) s.Remove() m.slab.Free(s) b.ReduceAmount(amount) m.completeTrade(msg.PARTIAL, msg.FULL, b, s, price, amount) continue // The sell has been used up } if s.Amount() > b.Amount() { amount := b.Amount() price := price(b.Price(), s.Price()) s.ReduceAmount(amount) m.completeTrade(msg.FULL, msg.PARTIAL, b, s, price, amount) m.slab.Free(b) return true // The buy has been used up } if s.Amount() == b.Amount() { amount := b.Amount() price := price(b.Price(), s.Price()) m.completeTrade(msg.FULL, msg.FULL, b, s, price, amount) s.Remove() m.slab.Free(s) m.slab.Free(b) return true // The buy and sell have been used up } } else { return false } } }
func (m *M) addSell(s *pqueue.OrderNode) { q := m.getMatchQueues(s.StockId()) if !m.fillableSell(s, q) { q.PushSell(s) } }
func (m *M) completeNotCancelled(nc *pqueue.OrderNode) { ncm := msg.Message{} nc.CopyTo(&ncm) ncm.Kind = msg.NOT_CANCELLED m.Out.Write(ncm) }
func (m *M) completeCancelled(c *pqueue.OrderNode) { cm := msg.Message{} c.CopyTo(&cm) cm.Kind = msg.CANCELLED m.Out.Write(cm) }
func (m *M) completeTrade(brk, srk msg.MsgKind, b, s *pqueue.OrderNode, price, amount uint64) { m.Out.Write(msg.Message{Kind: brk, Price: price, Amount: amount, TraderId: b.TraderId(), TradeId: b.TradeId(), StockId: b.StockId()}) m.Out.Write(msg.Message{Kind: srk, Price: price, Amount: amount, TraderId: s.TraderId(), TradeId: s.TradeId(), StockId: s.StockId()}) }
func completeNotCancelled(out chan<- *msg.Message, nc *pqueue.OrderNode) { ncm := &msg.Message{} nc.CopyTo(ncm) ncm.Kind = msg.NOT_CANCELLED out <- ncm }
func completeCancelled(out chan<- *msg.Message, c *pqueue.OrderNode) { cm := &msg.Message{} c.CopyTo(cm) cm.Kind = msg.CANCELLED out <- cm }
func completeTrade(out chan<- *msg.Message, brk, srk msg.MsgKind, b, s *pqueue.OrderNode, price uint64, amount uint32) { br := &msg.Message{Kind: brk, Price: price, Amount: amount, TraderId: b.TraderId(), TradeId: b.TradeId(), StockId: b.StockId()} sr := &msg.Message{Kind: srk, Price: price, Amount: amount, TraderId: s.TraderId(), TradeId: s.TradeId(), StockId: s.StockId()} out <- br out <- sr }
func (m *M) fillableSell(s *pqueue.OrderNode, q *pqueue.MatchQueues) bool { for { b := q.PeekBuy() if b == nil { return false } if b.Price() >= s.Price() { if b.Amount() > s.Amount() { amount := s.Amount() price := price(b.Price(), s.Price()) b.ReduceAmount(amount) completeTrade(m.Out, msg.PARTIAL, msg.FULL, b, s, price, amount) m.slab.Free(s) return true // The sell has been used up } if s.Amount() > b.Amount() { amount := b.Amount() price := price(b.Price(), s.Price()) s.ReduceAmount(amount) completeTrade(m.Out, msg.FULL, msg.PARTIAL, b, s, price, amount) m.slab.Free(q.PopBuy()) continue } if s.Amount() == b.Amount() { amount := b.Amount() price := price(b.Price(), s.Price()) completeTrade(m.Out, msg.FULL, msg.FULL, b, s, price, amount) m.slab.Free(q.PopBuy()) m.slab.Free(s) return true // The sell has been used up } } else { return false } } panic("Unreachable") }