xalign: add withdraw detection notification

This commit is contained in:
c9s 2024-08-01 16:58:07 +08:00
parent 600d81049e
commit 089e69a221
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54

View File

@ -9,6 +9,7 @@ import (
"time" "time"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/time/rate"
"github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/bbgo"
"github.com/c9s/bbgo/pkg/core" "github.com/c9s/bbgo/pkg/core"
@ -20,6 +21,8 @@ const ID = "xalign"
var log = logrus.WithField("strategy", ID) var log = logrus.WithField("strategy", ID)
var activeTransferNotificationLimiter = rate.NewLimiter(rate.Every(5*time.Minute), 1)
func init() { func init() {
bbgo.RegisterStrategy(ID, &Strategy{}) bbgo.RegisterStrategy(ID, &Strategy{})
} }
@ -47,6 +50,10 @@ type Strategy struct {
Duration types.Duration `json:"for"` Duration types.Duration `json:"for"`
MaxAmounts map[string]fixedpoint.Value `json:"maxAmounts"` MaxAmounts map[string]fixedpoint.Value `json:"maxAmounts"`
SlackNotify bool `json:"slackNotify"`
SlackNotifyMentions []string `json:"slackNotifyMentions"`
SlackNotifyThresholdAmount fixedpoint.Value `json:"slackNotifyThresholdAmount,omitempty"`
faultBalanceRecords map[string][]TimeBalance faultBalanceRecords map[string][]TimeBalance
sessions map[string]*bbgo.ExchangeSession sessions map[string]*bbgo.ExchangeSession
@ -114,7 +121,10 @@ func (s *Strategy) aggregateBalances(
return totalBalances, sessionBalances return totalBalances, sessionBalances
} }
func (s *Strategy) detectActiveTransfers(ctx context.Context, sessions map[string]*bbgo.ExchangeSession) (bool, error) { func (s *Strategy) detectActiveWithdraw(
ctx context.Context,
sessions map[string]*bbgo.ExchangeSession,
) (*types.Withdraw, error) {
var err2 error var err2 error
until := time.Now() until := time.Now()
since := until.Add(-time.Hour * 24) since := until.Add(-time.Hour * 24)
@ -134,12 +144,12 @@ func (s *Strategy) detectActiveTransfers(ctx context.Context, sessions map[strin
for _, withdraw := range withdraws { for _, withdraw := range withdraws {
switch withdraw.Status { switch withdraw.Status {
case types.WithdrawStatusProcessing, types.WithdrawStatusSent, types.WithdrawStatusAwaitingApproval: case types.WithdrawStatusProcessing, types.WithdrawStatusSent, types.WithdrawStatusAwaitingApproval:
return true, nil return &withdraw, nil
} }
} }
} }
return false, err2 return nil, err2
} }
func (s *Strategy) selectSessionForCurrency( func (s *Strategy) selectSessionForCurrency(
@ -405,7 +415,6 @@ func (s *Strategy) recordBalance(totalBalances types.BalanceMap) {
} }
func (s *Strategy) align(ctx context.Context, sessions map[string]*bbgo.ExchangeSession) { func (s *Strategy) align(ctx context.Context, sessions map[string]*bbgo.ExchangeSession) {
for sessionName, session := range sessions { for sessionName, session := range sessions {
ob, ok := s.orderBooks[sessionName] ob, ok := s.orderBooks[sessionName]
if !ok { if !ok {
@ -414,16 +423,20 @@ func (s *Strategy) align(ctx context.Context, sessions map[string]*bbgo.Exchange
} }
if ok { if ok {
if err := ob.GracefulCancel(ctx, session.Exchange); err != nil { if err := ob.GracefulCancel(ctx, session.Exchange); err != nil {
log.WithError(err).Errorf("can not cancel order") log.WithError(err).Errorf("unable to cancel order")
} }
} }
} }
foundActiveTransfer, err := s.detectActiveTransfers(ctx, sessions) pendingWithdraw, err := s.detectActiveWithdraw(ctx, sessions)
if err != nil { if err != nil {
log.WithError(err).Errorf("unable to check active transfers") log.WithError(err).Errorf("unable to check active transfers")
} else if foundActiveTransfer { } else if pendingWithdraw != nil {
log.Warnf("found active transfer, skip balance align check") log.Warnf("found active transfer, skip balance align check")
if activeTransferNotificationLimiter.Allow() {
bbgo.Notify("Found active withdraw, skip balance align", pendingWithdraw)
}
return return
} }