autoborrow: add repaid alert

This commit is contained in:
c9s 2024-01-09 09:58:20 +08:00
parent f33ed6a527
commit 2ff74a5f86
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 79 additions and 14 deletions

View File

@ -13,11 +13,17 @@ exchangeStrategies:
# if the margin ratio is high enough, we don't have the urge to repay # if the margin ratio is high enough, we don't have the urge to repay
maxMarginLevel: 20.0 maxMarginLevel: 20.0
marginLevelAlertInterval: 5m marginRepayAlert:
marginLevelAlertMinMargin: 2.0 slackMentions:
marginLevelAlertSlackMentions: - '<@USER_ID>'
- '<@USER_ID>' - '<!subteam^TEAM_ID>'
- '<!subteam^TEAM_ID>'
marginLevelAlert:
interval: 5m
minMargin: 2.0
slackMentions:
- '<@USER_ID>'
- '<!subteam^TEAM_ID>'
assets: assets:
- asset: ETH - asset: ETH

View File

@ -43,6 +43,8 @@ func init() {
maxQuantityPerBorrow: 100.0 maxQuantityPerBorrow: 100.0
maxTotalBorrow: 10.0 maxTotalBorrow: 10.0
*/ */
// MarginAlert is used to send the slack mention alerts when the current margin is less than the required margin level
type MarginAlert struct { type MarginAlert struct {
CurrentMarginLevel fixedpoint.Value CurrentMarginLevel fixedpoint.Value
MinimalMarginLevel fixedpoint.Value MinimalMarginLevel fixedpoint.Value
@ -78,6 +80,36 @@ func (m *MarginAlert) SlackAttachment() slack.Attachment {
} }
} }
// RepaidAlert
type RepaidAlert struct {
SessionName string
Asset string
Amount fixedpoint.Value
SlackMentions []string
}
func (m *RepaidAlert) SlackAttachment() slack.Attachment {
return slack.Attachment{
Color: "red",
Title: fmt.Sprintf("Margin Repaid on %s session", m.SessionName),
Text: strings.Join(m.SlackMentions, " "),
Fields: []slack.AttachmentField{
{
Title: "Session",
Value: m.SessionName,
Short: true,
},
{
Title: "Asset",
Value: m.Amount.String() + " " + m.Asset,
Short: true,
},
},
// Footer: "",
// FooterIcon: "",
}
}
type MarginAsset struct { type MarginAsset struct {
Asset string `json:"asset"` Asset string `json:"asset"`
Low fixedpoint.Value `json:"low"` Low fixedpoint.Value `json:"low"`
@ -87,15 +119,24 @@ type MarginAsset struct {
DebtRatio fixedpoint.Value `json:"debtRatio"` DebtRatio fixedpoint.Value `json:"debtRatio"`
} }
type MarginLevelAlert struct {
Interval types.Duration `json:"interval"`
MinMargin fixedpoint.Value `json:"minMargin"`
SlackMentions []string `json:"slackMentions"`
}
type MarginRepayAlert struct {
SlackMentions []string `json:"slackMentions"`
}
type Strategy struct { type Strategy struct {
Interval types.Interval `json:"interval"` Interval types.Interval `json:"interval"`
MinMarginLevel fixedpoint.Value `json:"minMarginLevel"` MinMarginLevel fixedpoint.Value `json:"minMarginLevel"`
MaxMarginLevel fixedpoint.Value `json:"maxMarginLevel"` MaxMarginLevel fixedpoint.Value `json:"maxMarginLevel"`
AutoRepayWhenDeposit bool `json:"autoRepayWhenDeposit"` AutoRepayWhenDeposit bool `json:"autoRepayWhenDeposit"`
MarginLevelAlertInterval types.Duration `json:"marginLevelAlertInterval"` MarginLevelAlert *MarginLevelAlert `json:"marginLevelAlert"`
MarginLevelAlertMinMargin fixedpoint.Value `json:"marginLevelAlertMinMargin"` MarginRepayAlert *MarginRepayAlert `json:"marginRepayAlert"`
MarginLevelAlertSlackMentions []string `json:"marginLevelAlertSlackMentions"`
Assets []MarginAsset `json:"assets"` Assets []MarginAsset `json:"assets"`
@ -155,6 +196,15 @@ func (s *Strategy) tryToRepayAnyDebt(ctx context.Context) {
log.WithError(err).Errorf("margin repay error") log.WithError(err).Errorf("margin repay error")
} }
if s.MarginRepayAlert != nil {
bbgo.Notify(&RepaidAlert{
SessionName: s.ExchangeSession.Name,
Asset: b.Currency,
Amount: toRepay,
SlackMentions: s.MarginRepayAlert.SlackMentions,
})
}
return return
} }
} }
@ -255,6 +305,15 @@ func (s *Strategy) reBalanceDebt(ctx context.Context) {
log.WithError(err).Errorf("margin repay error") log.WithError(err).Errorf("margin repay error")
} }
if s.MarginRepayAlert != nil {
bbgo.Notify(&RepaidAlert{
SessionName: s.ExchangeSession.Name,
Asset: b.Currency,
Amount: toRepay,
SlackMentions: s.MarginRepayAlert.SlackMentions,
})
}
if accountUpdate, err2 := s.ExchangeSession.UpdateAccount(ctx); err2 != nil { if accountUpdate, err2 := s.ExchangeSession.UpdateAccount(ctx); err2 != nil {
log.WithError(err).Errorf("unable to update account") log.WithError(err).Errorf("unable to update account")
} else { } else {
@ -584,10 +643,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} }
} }
if !s.MarginLevelAlertMinMargin.IsZero() { if s.MarginLevelAlert != nil && !s.MarginLevelAlert.MinMargin.IsZero() {
alertInterval := time.Minute * 5 alertInterval := time.Minute * 5
if s.MarginLevelAlertInterval > 0 { if s.MarginLevelAlert.Interval > 0 {
alertInterval = s.MarginLevelAlertInterval.Duration() alertInterval = s.MarginLevelAlert.Interval.Duration()
} }
go s.marginAlertWorker(ctx, alertInterval) go s.marginAlertWorker(ctx, alertInterval)
@ -607,11 +666,11 @@ func (s *Strategy) marginAlertWorker(ctx context.Context, alertInterval time.Dur
return return
case <-ticker.C: case <-ticker.C:
account := s.ExchangeSession.GetAccount() account := s.ExchangeSession.GetAccount()
if account.MarginLevel.Compare(s.MarginLevelAlertMinMargin) <= 0 { if s.MarginLevelAlert != nil && account.MarginLevel.Compare(s.MarginLevelAlert.MinMargin) <= 0 {
bbgo.Notify(&MarginAlert{ bbgo.Notify(&MarginAlert{
CurrentMarginLevel: account.MarginLevel, CurrentMarginLevel: account.MarginLevel,
MinimalMarginLevel: s.MarginLevelAlertMinMargin, MinimalMarginLevel: s.MarginLevelAlert.MinMargin,
SlackMentions: s.MarginLevelAlertSlackMentions, SlackMentions: s.MarginLevelAlert.SlackMentions,
SessionName: s.ExchangeSession.Name, SessionName: s.ExchangeSession.Name,
}) })
bbgo.Notify(account.Balances().Debts()) bbgo.Notify(account.Balances().Debts())