diff --git a/pkg/backtest/exchange.go b/pkg/backtest/exchange.go index dfff47791..c5b850d4b 100644 --- a/pkg/backtest/exchange.go +++ b/pkg/backtest/exchange.go @@ -167,7 +167,7 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) { for _, order := range orders { symbol := order.Symbol - matching, ok := e.MatchingBook(symbol) + matching, ok := e.matchingBook(symbol) if !ok { return nil, fmt.Errorf("matching engine is not initialized for symbol %s", symbol) } @@ -192,7 +192,7 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder } func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) { - matching, ok := e.MatchingBook(symbol) + matching, ok := e.matchingBook(symbol) if !ok { return nil, fmt.Errorf("matching engine is not initialized for symbol %s", symbol) } @@ -211,7 +211,7 @@ func (e *Exchange) QueryClosedOrders(ctx context.Context, symbol string, since, func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) error { for _, order := range orders { - matching, ok := e.MatchingBook(order.Symbol) + matching, ok := e.matchingBook(order.Symbol) if !ok { return fmt.Errorf("matching engine is not initialized for symbol %s", order.Symbol) } @@ -250,7 +250,7 @@ func (e *Exchange) QueryTrades(ctx context.Context, symbol string, options *type } func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticker, error) { - matching, ok := e.MatchingBook(symbol) + matching, ok := e.matchingBook(symbol) if !ok { return nil, fmt.Errorf("matching engine is not initialized for symbol %s", symbol) } @@ -293,7 +293,7 @@ func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since return nil, nil } -func (e *Exchange) MatchingBook(symbol string) (*SimplePriceMatching, bool) { +func (e *Exchange) matchingBook(symbol string) (*SimplePriceMatching, bool) { e.matchingBooksMutex.Lock() m, ok := e.matchingBooks[symbol] e.matchingBooksMutex.Unlock() @@ -363,7 +363,7 @@ func (e *Exchange) SubscribeMarketData(startTime, endTime time.Time, extraInterv } func (e *Exchange) ConsumeKLine(k types.KLine, handlers []func(types.KLine, *ExchangeDataSource), src *ExchangeDataSource) { - matching, ok := e.MatchingBook(k.Symbol) + matching, ok := e.matchingBook(k.Symbol) if !ok { log.Errorf("matching book of %s is not initialized", k.Symbol) return @@ -381,16 +381,16 @@ func (e *Exchange) ConsumeKLine(k types.KLine, handlers []func(types.KLine, *Exc } // log.Errorf("kline %v, next %v", param.kline, matching.NextKLine) e.MarketDataStream.EmitKLineClosed(param.kline) - for _, h := range param.callback { + for _, h := range param.callbacks { h(param.kline, param.src) } } matching.ParamCache = make(map[types.Interval]Param) } matching.ParamCache[k.Interval] = Param{ - callback: handlers, - src: src, - kline: k, + callbacks: handlers, + src: src, + kline: k, } } diff --git a/pkg/backtest/matching.go b/pkg/backtest/matching.go index 99279980d..eae117cad 100644 --- a/pkg/backtest/matching.go +++ b/pkg/backtest/matching.go @@ -48,9 +48,9 @@ func init() { } type Param struct { - callback []func(types.KLine, *ExchangeDataSource) - kline types.KLine - src *ExchangeDataSource + callbacks []func(types.KLine, *ExchangeDataSource) + kline types.KLine + src *ExchangeDataSource } // SimplePriceMatching implements a simple kline data driven matching engine for backtest @@ -193,9 +193,9 @@ func (m *SimplePriceMatching) PlaceOrder(o types.SubmitOrder) (*types.Order, *ty order.Price = m.Market.TruncatePrice(m.LastPrice) price = order.Price } else if order.Type == types.OrderTypeLimit { - if m.NextKLine.High.Compare(order.Price) > 0 && order.Side == types.SideTypeBuy { + if m.NextKLine != nil && m.NextKLine.High.Compare(order.Price) > 0 && order.Side == types.SideTypeBuy { order.AveragePrice = order.Price - } else if m.NextKLine.Low.Compare(order.Price) < 0 && order.Side == types.SideTypeSell { + } else if m.NextKLine != nil && m.NextKLine.Low.Compare(order.Price) < 0 && order.Side == types.SideTypeSell { order.AveragePrice = order.Price } else {