improve autoborrow checks

This commit is contained in:
c9s 2022-06-02 01:27:04 +08:00
parent 4e666dee98
commit 78f9c7d569
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
4 changed files with 72 additions and 44 deletions

View File

@ -295,15 +295,16 @@ func (session *ExchangeSession) GetAccount() (a *types.Account) {
}
// UpdateAccount locks the account mutex and update the account object
func (session *ExchangeSession) UpdateAccount(ctx context.Context) error {
func (session *ExchangeSession) UpdateAccount(ctx context.Context) (*types.Account, error) {
account, err := session.Exchange.QueryAccount(ctx)
if err != nil {
return err
return nil, err
}
session.accountMutex.Lock()
session.Account = account
session.accountMutex.Unlock()
return nil
return account, nil
}
// Init initializes the basic data structure and market information by its exchange.

View File

@ -38,7 +38,6 @@ type Exchange struct {
v3margin *v3.MarginService
}
func New(key, secret string) *Exchange {
baseURL := maxapi.ProductionAPIURL
if override := os.Getenv("MAX_API_BASE_URL"); len(override) > 0 {
@ -583,6 +582,38 @@ func (e *Exchange) QueryAccount(ctx context.Context) (*types.Account, error) {
return a, nil
}
func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap, error) {
if err := accountQueryLimiter.Wait(ctx); err != nil {
return nil, err
}
walletType := maxapi.WalletTypeSpot
if e.MarginSettings.IsMargin {
walletType = maxapi.WalletTypeMargin
}
req := e.v3order.NewGetWalletAccountsRequest(walletType)
accounts, err := req.Do(ctx)
if err != nil {
return nil, err
}
var balances = make(types.BalanceMap)
for _, b := range accounts {
cur := toGlobalCurrency(b.Currency)
balances[cur] = types.Balance{
Currency: cur,
Available: b.Balance,
Locked: b.Locked,
NetAsset: b.Balance.Add(b.Locked),
Borrowed: b.Debt,
Interest: b.Interest,
}
}
return balances, nil
}
func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []types.Withdraw, err error) {
startTime := since
limit := 1000
@ -744,37 +775,6 @@ func (e *Exchange) QueryDepositHistory(ctx context.Context, asset string, since,
return allDeposits, err
}
func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap, error) {
if err := accountQueryLimiter.Wait(ctx); err != nil {
return nil, err
}
walletType := maxapi.WalletTypeSpot
if e.MarginSettings.IsMargin {
walletType = maxapi.WalletTypeMargin
}
req := e.v3order.NewGetWalletAccountsRequest(walletType)
accounts, err := req.Do(ctx)
if err != nil {
return nil, err
}
var balances = make(types.BalanceMap)
for _, b := range accounts {
cur := toGlobalCurrency(b.Currency)
balances[cur] = types.Balance{
Currency: cur,
Available: b.Balance,
Locked: b.Locked,
NetAsset: b.Balance.Add(b.Locked),
// Borrowed: b.Debt
}
}
return balances, nil
}
func (e *Exchange) QueryTrades(ctx context.Context, symbol string, options *types.TradeQueryOptions) (trades []types.Trade, err error) {
if err := tradeQueryLimiter.Wait(ctx); err != nil {
return nil, err
@ -927,7 +927,6 @@ func (e *Exchange) QueryAveragePrice(ctx context.Context, symbol string) (fixedp
Add(fixedpoint.MustNewFromString(ticker.Buy)).Div(Two), nil
}
func (e *Exchange) RepayMarginAsset(ctx context.Context, asset string, amount fixedpoint.Value) error {
req := e.v3margin.NewMarginRepayRequest()
req.Currency(toLocalCurrency(asset))

View File

@ -75,12 +75,12 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
func (s *Strategy) tryToRepayAnyDebt(ctx context.Context) {
log.Infof("trying to repay any debt...")
if err := s.ExchangeSession.UpdateAccount(ctx); err != nil {
account, err := s.ExchangeSession.UpdateAccount(ctx)
if err != nil {
log.WithError(err).Errorf("can not update account")
return
}
account := s.ExchangeSession.GetAccount()
minMarginLevel := s.MinMarginLevel
curMarginLevel := account.MarginLevel
@ -115,13 +115,13 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
return
}
if err := s.ExchangeSession.UpdateAccount(ctx); err != nil {
account, err := s.ExchangeSession.UpdateAccount(ctx)
if err != nil {
log.WithError(err).Errorf("can not update account")
return
}
minMarginLevel := s.MinMarginLevel
account := s.ExchangeSession.GetAccount()
curMarginLevel := account.MarginLevel
log.Infof("current account margin level: %s margin ratio: %s, margin tolerance: %s",
@ -137,13 +137,15 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
return
}
balances := s.ExchangeSession.GetAccount().Balances()
balances := account.Balances()
if len(balances) == 0 {
log.Warn("balance is empty, skip autoborrow")
return
}
for _, marginAsset := range s.Assets {
changed := false
if marginAsset.Low.IsZero() {
log.Warnf("margin asset low balance is not set: %+v", marginAsset)
continue
@ -176,6 +178,10 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
}
}
if toBorrow.IsZero() {
continue
}
s.Notifiability.Notify(&MarginAction{
Action: "Borrow",
Asset: marginAsset.Asset,
@ -184,7 +190,11 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
MinMarginLevel: minMarginLevel,
})
log.Infof("sending borrow request %f %s", toBorrow.Float64(), marginAsset.Asset)
s.marginBorrowRepay.BorrowMarginAsset(ctx, marginAsset.Asset, toBorrow)
if err := s.marginBorrowRepay.BorrowMarginAsset(ctx, marginAsset.Asset, toBorrow); err != nil {
log.WithError(err).Errorf("repay error")
continue
}
changed = true
} else {
// available balance is less than marginAsset.Low, we should trigger borrow
toBorrow := marginAsset.Low
@ -193,6 +203,10 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
toBorrow = fixedpoint.Min(toBorrow, marginAsset.MaxQuantityPerBorrow)
}
if toBorrow.IsZero() {
continue
}
s.Notifiability.Notify(&MarginAction{
Action: "Borrow",
Asset: marginAsset.Asset,
@ -202,7 +216,21 @@ func (s *Strategy) checkAndBorrow(ctx context.Context) {
})
log.Infof("sending borrow request %f %s", toBorrow.Float64(), marginAsset.Asset)
s.marginBorrowRepay.BorrowMarginAsset(ctx, marginAsset.Asset, toBorrow)
if err := s.marginBorrowRepay.BorrowMarginAsset(ctx, marginAsset.Asset, toBorrow); err != nil {
log.WithError(err).Errorf("borrow error")
continue
}
changed = true
}
// if debt is changed, we need to update account
if changed {
account, err = s.ExchangeSession.UpdateAccount(ctx)
if err != nil {
log.WithError(err).Errorf("can not update account")
return
}
}
}
}

View File

@ -86,7 +86,7 @@ func (s *Strategy) recordNetAssetValue(ctx context.Context, sessions map[string]
// iterate the sessions and record them
for sessionName, session := range sessions {
// update the account balances and the margin information
if err := session.UpdateAccount(ctx); err != nil {
if _, err := session.UpdateAccount(ctx); err != nil {
log.WithError(err).Errorf("can not update account")
return
}