func CreateMarket(basisCoin, coin string) *Market { marketName := coin + "/" + basisCoin numMemPool := (MIN_MEMPOOL + MAX_MEMPOOL) / 2 // First, get the maximum executed (completed) order number. // Any pending orders greater than this need to get re-executed. // NOTE: this is only an estimate. It's possible that a later order // was successfully processed as a new limit order, // but it doesn't hurt to re-process them since they have no further side effects. lastOrderId := LastCompletedOrderId(basisCoin, coin) // Load limit orders. bidsSlice, hasMoreBids := LoadLimitBids(basisCoin, coin, numMemPool+1, math.MaxInt64, 0, lastOrderId) asksSlice, hasMoreAsks := LoadLimitAsks(basisCoin, coin, numMemPool+1, 0, 0, lastOrderId) bids, asks := llrb.New(), llrb.New() for _, bid := range bidsSlice { bids.InsertNoReplace(llrb.Item(bid)) } for _, ask := range asksSlice { asks.InsertNoReplace(llrb.Item(ask)) } market := &Market{ Coin: coin, BasisCoin: basisCoin, Bids: bids, Asks: asks, HasMoreBids: hasMoreBids, HasMoreAsks: hasMoreAsks, PriceLogger: &PriceLogger{Market: marketName}, } // TODO: graceful continuing after server restart. // currently the PriceLogger is at the BasisInterval scale. market.PriceLogger.Initialize() // Process pending orders from last app shutdown. pendingOrders := LoadPendingOrdersSince(basisCoin, coin, lastOrderId+1) if len(pendingOrders) > 0 { Info("[%v/%v] Processing %v orders from last shutdown...", coin, basisCoin, len(pendingOrders)) for _, order := range pendingOrders { market.ProcessOrder(order) } Info("[%v/%v] Done processing.", coin, basisCoin) } return market }
// Loads more bids or orders, updating .Asks/.HasMoreAsks or .Bids/.HasMoreBids. // lastOrderId: We need this for the 'maxId' parameter of loadLimitBids/loadLimitAsks. // It must be the same as the result of LastCompletedOrderId() func (market *Market) LoadMore(orderType string, lastOrderId int64) { if orderType == ORDER_TYPE_BID { // Maybe we need to load more asks. if market.HasMoreAsks && market.Asks.Len() < MIN_MEMPOOL { if market.Asks.Len() == 0 { panic("market.HasMoreAsks but no asks in mempool?") } moreAsks, hasMoreAsks := LoadLimitAsks( market.BasisCoin, market.Coin, (MAX_MEMPOOL-MIN_MEMPOOL)/2, market.Asks.Max().(*Order).Price, market.Asks.Max().(*Order).Id, lastOrderId, ) for _, ask := range moreAsks { market.Asks.InsertNoReplace(llrb.Item(ask)) } market.HasMoreAsks = hasMoreAsks } } else { // Maybe we need to load more bids. if market.HasMoreBids && market.Bids.Len() < MIN_MEMPOOL { if market.Bids.Len() == 0 { panic("market.HasMoreBids but no bids in mempool?") } moreBids, hasMoreBids := LoadLimitBids( market.BasisCoin, market.Coin, (MAX_MEMPOOL-MIN_MEMPOOL)/2, market.Bids.Max().(*Order).Price, market.Bids.Max().(*Order).Id, lastOrderId, ) for _, bid := range moreBids { market.Bids.InsertNoReplace(llrb.Item(bid)) } market.HasMoreBids = hasMoreBids } } }