mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 08:15:15 +00:00
grid2: add order executor mock for testing reverse order
This commit is contained in:
parent
9215e401d0
commit
9d24540826
95
pkg/strategy/grid2/mocks/order_executor.go
Normal file
95
pkg/strategy/grid2/mocks/order_executor.go
Normal file
|
@ -0,0 +1,95 @@
|
|||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/c9s/bbgo/pkg/strategy/grid2 (interfaces: OrderExecutor)
|
||||
|
||||
// Package mocks is a generated GoMock package.
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
fixedpoint "github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
types "github.com/c9s/bbgo/pkg/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// MockOrderExecutor is a mock of OrderExecutor interface.
|
||||
type MockOrderExecutor struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockOrderExecutorMockRecorder
|
||||
}
|
||||
|
||||
// MockOrderExecutorMockRecorder is the mock recorder for MockOrderExecutor.
|
||||
type MockOrderExecutorMockRecorder struct {
|
||||
mock *MockOrderExecutor
|
||||
}
|
||||
|
||||
// NewMockOrderExecutor creates a new mock instance.
|
||||
func NewMockOrderExecutor(ctrl *gomock.Controller) *MockOrderExecutor {
|
||||
mock := &MockOrderExecutor{ctrl: ctrl}
|
||||
mock.recorder = &MockOrderExecutorMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockOrderExecutor) EXPECT() *MockOrderExecutorMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// ClosePosition mocks base method.
|
||||
func (m *MockOrderExecutor) ClosePosition(arg0 context.Context, arg1 fixedpoint.Value, arg2 ...string) error {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0, arg1}
|
||||
for _, a := range arg2 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "ClosePosition", varargs...)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// ClosePosition indicates an expected call of ClosePosition.
|
||||
func (mr *MockOrderExecutorMockRecorder) ClosePosition(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0, arg1}, arg2...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ClosePosition", reflect.TypeOf((*MockOrderExecutor)(nil).ClosePosition), varargs...)
|
||||
}
|
||||
|
||||
// GracefulCancel mocks base method.
|
||||
func (m *MockOrderExecutor) GracefulCancel(arg0 context.Context, arg1 ...types.Order) error {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0}
|
||||
for _, a := range arg1 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "GracefulCancel", varargs...)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GracefulCancel indicates an expected call of GracefulCancel.
|
||||
func (mr *MockOrderExecutorMockRecorder) GracefulCancel(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0}, arg1...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GracefulCancel", reflect.TypeOf((*MockOrderExecutor)(nil).GracefulCancel), varargs...)
|
||||
}
|
||||
|
||||
// SubmitOrders mocks base method.
|
||||
func (m *MockOrderExecutor) SubmitOrders(arg0 context.Context, arg1 ...types.SubmitOrder) (types.OrderSlice, error) {
|
||||
m.ctrl.T.Helper()
|
||||
varargs := []interface{}{arg0}
|
||||
for _, a := range arg1 {
|
||||
varargs = append(varargs, a)
|
||||
}
|
||||
ret := m.ctrl.Call(m, "SubmitOrders", varargs...)
|
||||
ret0, _ := ret[0].(types.OrderSlice)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// SubmitOrders indicates an expected call of SubmitOrders.
|
||||
func (mr *MockOrderExecutorMockRecorder) SubmitOrders(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
varargs := append([]interface{}{arg0}, arg1...)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitOrders", reflect.TypeOf((*MockOrderExecutor)(nil).SubmitOrders), varargs...)
|
||||
}
|
|
@ -28,6 +28,13 @@ func init() {
|
|||
bbgo.RegisterStrategy(ID, &Strategy{})
|
||||
}
|
||||
|
||||
//go:generate mockgen -destination=mocks/order_executor.go -package=mocks . OrderExecutor
|
||||
type OrderExecutor interface {
|
||||
SubmitOrders(ctx context.Context, submitOrders ...types.SubmitOrder) (types.OrderSlice, error)
|
||||
ClosePosition(ctx context.Context, percentage fixedpoint.Value, tags ...string) error
|
||||
GracefulCancel(ctx context.Context, orders ...types.Order) error
|
||||
}
|
||||
|
||||
type Strategy struct {
|
||||
Environment *bbgo.Environment
|
||||
|
||||
|
@ -102,7 +109,7 @@ type Strategy struct {
|
|||
session *bbgo.ExchangeSession
|
||||
orderQueryService types.ExchangeOrderQueryService
|
||||
|
||||
orderExecutor *bbgo.GeneralOrderExecutor
|
||||
orderExecutor OrderExecutor
|
||||
historicalTrades *bbgo.TradeStore
|
||||
|
||||
// groupID is the group ID used for the strategy instance for canceling orders
|
||||
|
@ -705,6 +712,12 @@ func (s *Strategy) closeGrid(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Strategy) newGrid() *Grid {
|
||||
grid := NewGrid(s.LowerPrice, s.UpperPrice, fixedpoint.NewFromInt(s.GridNum), s.Market.TickSize)
|
||||
grid.CalculateArithmeticPins()
|
||||
return grid
|
||||
}
|
||||
|
||||
// openGrid
|
||||
// 1) if quantity or amount is set, we should use quantity/amount directly instead of using investment amount to calculate.
|
||||
// 2) if baseInvestment, quoteInvestment is set, then we should calculate the quantity from the given base investment and quote investment.
|
||||
|
@ -715,9 +728,7 @@ func (s *Strategy) openGrid(ctx context.Context, session *bbgo.ExchangeSession)
|
|||
return nil
|
||||
}
|
||||
|
||||
s.grid = NewGrid(s.LowerPrice, s.UpperPrice, fixedpoint.NewFromInt(s.GridNum), s.Market.TickSize)
|
||||
s.grid.CalculateArithmeticPins()
|
||||
|
||||
s.grid = s.newGrid()
|
||||
s.logger.Info("OPENING GRID: ", s.grid.String())
|
||||
|
||||
lastPrice, err := s.getLastTradePrice(ctx, session)
|
||||
|
@ -957,7 +968,7 @@ func (s *Strategy) checkMinimalQuoteInvestment() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
|
||||
instanceID := s.InstanceID()
|
||||
|
||||
s.session = session
|
||||
|
@ -1004,19 +1015,18 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
s.historicalTrades.EnablePrune = true
|
||||
s.historicalTrades.BindStream(session.UserDataStream)
|
||||
|
||||
s.orderExecutor = bbgo.NewGeneralOrderExecutor(session, s.Symbol, ID, instanceID, s.Position)
|
||||
s.orderExecutor.BindEnvironment(s.Environment)
|
||||
s.orderExecutor.BindProfitStats(s.ProfitStats)
|
||||
s.orderExecutor.Bind()
|
||||
|
||||
s.orderExecutor.TradeCollector().OnTrade(func(trade types.Trade, _, _ fixedpoint.Value) {
|
||||
orderExecutor := bbgo.NewGeneralOrderExecutor(session, s.Symbol, ID, instanceID, s.Position)
|
||||
orderExecutor.BindEnvironment(s.Environment)
|
||||
orderExecutor.BindProfitStats(s.ProfitStats)
|
||||
orderExecutor.Bind()
|
||||
orderExecutor.TradeCollector().OnTrade(func(trade types.Trade, _, _ fixedpoint.Value) {
|
||||
s.GridProfitStats.AddTrade(trade)
|
||||
})
|
||||
s.orderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) {
|
||||
orderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) {
|
||||
bbgo.Sync(ctx, s)
|
||||
})
|
||||
|
||||
s.orderExecutor.ActiveMakerOrders().OnFilled(s.handleOrderFilled)
|
||||
orderExecutor.ActiveMakerOrders().OnFilled(s.handleOrderFilled)
|
||||
s.orderExecutor = orderExecutor
|
||||
|
||||
// TODO: detect if there are previous grid orders on the order book
|
||||
if s.ClearOpenOrdersWhenStart {
|
||||
|
|
|
@ -15,6 +15,8 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/c9s/bbgo/pkg/types/mocks"
|
||||
|
||||
gridmocks "github.com/c9s/bbgo/pkg/strategy/grid2/mocks"
|
||||
)
|
||||
|
||||
func TestStrategy_checkRequiredInvestmentByQuantity(t *testing.T) {
|
||||
|
@ -269,6 +271,7 @@ func newTestStrategy() *Strategy {
|
|||
|
||||
s := &Strategy{
|
||||
logger: logrus.NewEntry(logrus.New()),
|
||||
Symbol: "BTCUSDT",
|
||||
Market: market,
|
||||
GridProfitStats: newGridProfitStats(market),
|
||||
UpperPrice: number(20_000),
|
||||
|
@ -397,6 +400,75 @@ func TestStrategy_aggregateOrderBaseFee(t *testing.T) {
|
|||
assert.Equal(t, "0.01", baseFee.String())
|
||||
}
|
||||
|
||||
func TestStrategy_handleOrderFilled(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("no fee token", func(t *testing.T) {
|
||||
gridQuantity := number(0.1)
|
||||
orderID := uint64(1)
|
||||
|
||||
s := newTestStrategy()
|
||||
s.Quantity = gridQuantity
|
||||
s.grid = s.newGrid()
|
||||
|
||||
mockCtrl := gomock.NewController(t)
|
||||
defer mockCtrl.Finish()
|
||||
|
||||
mockService := mocks.NewMockExchangeOrderQueryService(mockCtrl)
|
||||
mockService.EXPECT().QueryOrderTrades(ctx, types.OrderQuery{
|
||||
Symbol: "BTCUSDT",
|
||||
OrderID: "1",
|
||||
}).Return([]types.Trade{
|
||||
{
|
||||
ID: 1,
|
||||
OrderID: orderID,
|
||||
Exchange: "binance",
|
||||
Price: number(11000.0),
|
||||
Quantity: gridQuantity,
|
||||
Symbol: "BTCUSDT",
|
||||
Side: types.SideTypeBuy,
|
||||
IsBuyer: true,
|
||||
FeeCurrency: "BTC",
|
||||
Fee: number(gridQuantity.Float64() * 0.1 * 0.01),
|
||||
},
|
||||
}, nil)
|
||||
|
||||
s.orderQueryService = mockService
|
||||
|
||||
expectedSubmitOrder := types.SubmitOrder{
|
||||
Symbol: "BTCUSDT",
|
||||
Type: types.OrderTypeLimit,
|
||||
Price: number(12_000.0),
|
||||
Quantity: number(0.0999),
|
||||
Side: types.SideTypeSell,
|
||||
TimeInForce: types.TimeInForceGTC,
|
||||
Market: s.Market,
|
||||
Tag: "grid",
|
||||
}
|
||||
|
||||
orderExecutor := gridmocks.NewMockOrderExecutor(mockCtrl)
|
||||
orderExecutor.EXPECT().SubmitOrders(ctx, expectedSubmitOrder).Return([]types.Order{
|
||||
{SubmitOrder: expectedSubmitOrder},
|
||||
}, nil)
|
||||
s.orderExecutor = orderExecutor
|
||||
|
||||
s.handleOrderFilled(types.Order{
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Symbol: "BTCUSDT",
|
||||
Side: types.SideTypeBuy,
|
||||
Type: types.OrderTypeLimit,
|
||||
Quantity: gridQuantity,
|
||||
Price: number(11000.0),
|
||||
TimeInForce: types.TimeInForceGTC,
|
||||
},
|
||||
Exchange: "binance",
|
||||
OrderID: orderID,
|
||||
Status: types.OrderStatusFilled,
|
||||
ExecutedQuantity: gridQuantity,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestStrategy_aggregateOrderBaseFeeRetry(t *testing.T) {
|
||||
s := newTestStrategy()
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user