From 3ea333fd527070de11171d7a1dcc25b42607d093 Mon Sep 17 00:00:00 2001 From: c9s Date: Mon, 20 Nov 2023 16:14:09 +0800 Subject: [PATCH 1/3] bbgo: add DisableStartupBalanceQuery option --- pkg/bbgo/config.go | 9 +++++++-- pkg/bbgo/session.go | 23 +++++++++++++++-------- pkg/types/account.go | 20 +++++++++++++++++++- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/pkg/bbgo/config.go b/pkg/bbgo/config.go index 1fac9e314..f892f2138 100644 --- a/pkg/bbgo/config.go +++ b/pkg/bbgo/config.go @@ -329,8 +329,13 @@ type ServiceConfig struct { type EnvironmentConfig struct { DisableDefaultKLineSubscription bool `json:"disableDefaultKLineSubscription"` DisableHistoryKLinePreload bool `json:"disableHistoryKLinePreload"` - DisableSessionTradeBuffer bool `json:"disableSessionTradeBuffer"` - MaxSessionTradeBufferSize int `json:"maxSessionTradeBufferSize"` + + // DisableStartUpBalanceQuery disables the balance query in the startup process + // which initializes the session.Account with the QueryAccount method. + DisableStartupBalanceQuery bool `json:"disableStartupBalanceQuery"` + + DisableSessionTradeBuffer bool `json:"disableSessionTradeBuffer"` + MaxSessionTradeBufferSize int `json:"maxSessionTradeBufferSize"` } type Config struct { diff --git a/pkg/bbgo/session.go b/pkg/bbgo/session.go index 75012fb03..ba10b1e1e 100644 --- a/pkg/bbgo/session.go +++ b/pkg/bbgo/session.go @@ -256,15 +256,22 @@ func (session *ExchangeSession) Init(ctx context.Context, environ *Environment) } } - logger.Infof("querying account balances...") - account, err := session.Exchange.QueryAccount(ctx) - if err != nil { - return err - } + disableStartupBalanceQuery := environ.environmentConfig != nil && environ.environmentConfig.DisableStartupBalanceQuery + if disableStartupBalanceQuery { + session.accountMutex.Lock() + session.Account = types.NewAccount() + session.accountMutex.Unlock() + } else { + logger.Infof("querying account balances...") + account, err := session.Exchange.QueryAccount(ctx) + if err != nil { + return err + } - session.accountMutex.Lock() - session.Account = account - session.accountMutex.Unlock() + session.accountMutex.Lock() + session.Account = account + session.accountMutex.Unlock() + } logger.Infof("account %s balances:\n%s", session.Name, account.Balances().String()) diff --git a/pkg/types/account.go b/pkg/types/account.go index cd590f530..5cb4ca92d 100644 --- a/pkg/types/account.go +++ b/pkg/types/account.go @@ -103,8 +103,26 @@ type IsolatedMarginAccountInfo struct { func NewAccount() *Account { return &Account{ - balances: make(BalanceMap), + AccountType: "spot", + FuturesInfo: nil, + MarginInfo: nil, + IsolatedMarginInfo: nil, + MarginLevel: fixedpoint.Zero, + MarginTolerance: fixedpoint.Zero, + BorrowEnabled: false, + TransferEnabled: false, + MarginRatio: fixedpoint.Zero, + LiquidationPrice: fixedpoint.Zero, + LiquidationRate: fixedpoint.Zero, + MakerFeeRate: fixedpoint.Zero, + TakerFeeRate: fixedpoint.Zero, + TotalAccountValue: fixedpoint.Zero, + CanDeposit: false, + CanTrade: false, + CanWithdraw: false, + balances: make(BalanceMap), } + } // Balances lock the balances and returned the copied balances From 7c59e3ddc4633b55afa78f40c997ebe9c8721a19 Mon Sep 17 00:00:00 2001 From: c9s Date: Mon, 20 Nov 2023 16:15:33 +0800 Subject: [PATCH 2/3] bbgo: add setAccount for account mutex protection --- pkg/bbgo/session.go | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/pkg/bbgo/session.go b/pkg/bbgo/session.go index ba10b1e1e..bac3e0cf1 100644 --- a/pkg/bbgo/session.go +++ b/pkg/bbgo/session.go @@ -177,12 +177,16 @@ func (session *ExchangeSession) UpdateAccount(ctx context.Context) (*types.Accou return nil, err } - session.accountMutex.Lock() - session.Account = account - session.accountMutex.Unlock() + session.setAccount(account) return account, nil } +func (session *ExchangeSession) setAccount(a *types.Account) { + session.accountMutex.Lock() + session.Account = a + session.accountMutex.Unlock() +} + // Init initializes the basic data structure and market information by its exchange. // Note that the subscribed symbols are not loaded in this stage. func (session *ExchangeSession) Init(ctx context.Context, environ *Environment) error { @@ -268,13 +272,10 @@ func (session *ExchangeSession) Init(ctx context.Context, environ *Environment) return err } - session.accountMutex.Lock() - session.Account = account - session.accountMutex.Unlock() + session.setAccount(account) + logger.Infof("account %s balances:\n%s", session.Name, account.Balances().String()) } - logger.Infof("account %s balances:\n%s", session.Name, account.Balances().String()) - // forward trade updates and order updates to the order executor session.UserDataStream.OnTradeUpdate(session.OrderExecutor.EmitTradeUpdate) session.UserDataStream.OnOrderUpdate(session.OrderExecutor.EmitOrderUpdate) From c360c6045cd69a3484f3b6b17da7f06a72014f8a Mon Sep 17 00:00:00 2001 From: c9s Date: Mon, 20 Nov 2023 16:20:39 +0800 Subject: [PATCH 3/3] bbgo: call retry.QueryAccountUntilSuccessful in the startup time --- pkg/bbgo/session.go | 5 +++-- pkg/exchange/retry/order.go | 28 ++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/pkg/bbgo/session.go b/pkg/bbgo/session.go index bac3e0cf1..6778ce35b 100644 --- a/pkg/bbgo/session.go +++ b/pkg/bbgo/session.go @@ -15,6 +15,7 @@ import ( "github.com/c9s/bbgo/pkg/cache" "github.com/c9s/bbgo/pkg/core" + "github.com/c9s/bbgo/pkg/exchange/retry" "github.com/c9s/bbgo/pkg/util/templateutil" exchange2 "github.com/c9s/bbgo/pkg/exchange" @@ -267,12 +268,13 @@ func (session *ExchangeSession) Init(ctx context.Context, environ *Environment) session.accountMutex.Unlock() } else { logger.Infof("querying account balances...") - account, err := session.Exchange.QueryAccount(ctx) + account, err := retry.QueryAccountUntilSuccessful(ctx, session.Exchange) if err != nil { return err } session.setAccount(account) + session.metricsBalancesUpdater(account.Balances()) logger.Infof("account %s balances:\n%s", session.Name, account.Balances().String()) } @@ -296,7 +298,6 @@ func (session *ExchangeSession) Init(ctx context.Context, environ *Environment) // if metrics mode is enabled, we bind the callbacks to update metrics if viper.GetBool("metrics") { - session.metricsBalancesUpdater(account.Balances()) session.bindUserDataStreamMetrics(session.UserDataStream) } } diff --git a/pkg/exchange/retry/order.go b/pkg/exchange/retry/order.go index df6ef6b59..66a690a54 100644 --- a/pkg/exchange/retry/order.go +++ b/pkg/exchange/retry/order.go @@ -16,7 +16,9 @@ type advancedOrderCancelService interface { CancelOrdersByGroupID(ctx context.Context, groupID uint32) ([]types.Order, error) } -func QueryOrderUntilFilled(ctx context.Context, queryOrderService types.ExchangeOrderQueryService, symbol string, orderId uint64) (o *types.Order, err error) { +func QueryOrderUntilFilled( + ctx context.Context, queryOrderService types.ExchangeOrderQueryService, symbol string, orderId uint64, +) (o *types.Order, err error) { var op = func() (err2 error) { o, err2 = queryOrderService.QueryOrder(ctx, types.OrderQuery{ Symbol: symbol, @@ -56,7 +58,9 @@ func GeneralLiteBackoff(ctx context.Context, op backoff.Operation) (err error) { return err } -func QueryOpenOrdersUntilSuccessful(ctx context.Context, ex types.Exchange, symbol string) (openOrders []types.Order, err error) { +func QueryOpenOrdersUntilSuccessful( + ctx context.Context, ex types.Exchange, symbol string, +) (openOrders []types.Order, err error) { var op = func() (err2 error) { openOrders, err2 = ex.QueryOpenOrders(ctx, symbol) return err2 @@ -66,7 +70,9 @@ func QueryOpenOrdersUntilSuccessful(ctx context.Context, ex types.Exchange, symb return openOrders, err } -func QueryOpenOrdersUntilSuccessfulLite(ctx context.Context, ex types.Exchange, symbol string) (openOrders []types.Order, err error) { +func QueryOpenOrdersUntilSuccessfulLite( + ctx context.Context, ex types.Exchange, symbol string, +) (openOrders []types.Order, err error) { var op = func() (err2 error) { openOrders, err2 = ex.QueryOpenOrders(ctx, symbol) return err2 @@ -76,7 +82,21 @@ func QueryOpenOrdersUntilSuccessfulLite(ctx context.Context, ex types.Exchange, return openOrders, err } -func QueryOrderUntilSuccessful(ctx context.Context, query types.ExchangeOrderQueryService, opts types.OrderQuery) (order *types.Order, err error) { +func QueryAccountUntilSuccessful( + ctx context.Context, ex types.ExchangeAccountService, +) (account *types.Account, err error) { + var op = func() (err2 error) { + account, err2 = ex.QueryAccount(ctx) + return err2 + } + + err = GeneralBackoff(ctx, op) + return account, err +} + +func QueryOrderUntilSuccessful( + ctx context.Context, query types.ExchangeOrderQueryService, opts types.OrderQuery, +) (order *types.Order, err error) { var op = func() (err2 error) { order, err2 = query.QueryOrder(ctx, opts) return err2