Skip to content

Commit

Permalink
FEATURE: [xalign] add notification when order quote is over alert amount
Browse files Browse the repository at this point in the history
  • Loading branch information
kbearXD committed Nov 5, 2024
1 parent 822c2bd commit caf5d69
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 12 deletions.
6 changes: 6 additions & 0 deletions config/xalign.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,9 @@ crossExchangeStrategies:
USDT: 100
USDC: 100
TWD: 3000
maxAmountAlert:
quote: USDT
amount: 200
slackMentions:
- '<@USER_ID>'
- '<!subteam^TEAM_ID>'
108 changes: 96 additions & 12 deletions pkg/strategy/xalign/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/sirupsen/logrus"
"github.com/slack-go/slack"
"golang.org/x/time/rate"

"github.com/c9s/bbgo/pkg/bbgo"
Expand Down Expand Up @@ -39,6 +40,55 @@ type QuoteCurrencyPreference struct {
Sell []string `json:"sell"`
}

type MaxAmountAlertConfig struct {
QuoteCurrency string `json:"quoteCurrency"`
Amount fixedpoint.Value `json:"amount"`
SlackMentions []string `json:"slackMentions"`
}

type MaxAmountAlert struct {
QuoteCurrency string
AlertAmount fixedpoint.Value
SlackMentions []string

BaseCurrency string
Side types.SideType
Price fixedpoint.Value
Quantity fixedpoint.Value
Amount fixedpoint.Value
}

func (m *MaxAmountAlert) SlackAttachment() slack.Attachment {
return slack.Attachment{
Color: "red",
Title: fmt.Sprintf("xalign amount alert - try to align %s with quote %s amount %f > %f",
m.BaseCurrency, m.QuoteCurrency, m.Amount.Float64(), m.AlertAmount.Float64()),
Text: strings.Join(m.SlackMentions, " "),
Fields: []slack.AttachmentField{
{
Title: "Base Currency",
Value: m.BaseCurrency,
Short: true,
},
{
Title: "Side",
Value: m.Side.String(),
Short: true,
},
{
Title: "Price",
Value: m.Price.String(),
Short: true,
},
{
Title: "Quantity",
Value: m.Quantity.String(),
Short: true,
},
},
}
}

type Strategy struct {
*bbgo.Environment
Interval types.Interval `json:"interval"`
Expand All @@ -50,6 +100,7 @@ type Strategy struct {
BalanceToleranceRange fixedpoint.Value `json:"balanceToleranceRange"`
Duration types.Duration `json:"for"`
MaxAmounts map[string]fixedpoint.Value `json:"maxAmounts"`
MaxAmountAlert *MaxAmountAlertConfig `json:"maxAmountAlert"`

SlackNotify bool `json:"slackNotify"`
SlackNotifyMentions []string `json:"slackNotifyMentions"`
Expand Down Expand Up @@ -84,7 +135,6 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
}

func (s *Strategy) CrossSubscribe(sessions map[string]*bbgo.ExchangeSession) {

}

func (s *Strategy) Defaults() error {
Expand Down Expand Up @@ -191,20 +241,20 @@ func (s *Strategy) detectActiveDeposit(
func (s *Strategy) selectSessionForCurrency(
ctx context.Context, sessions map[string]*bbgo.ExchangeSession, currency string, changeQuantity fixedpoint.Value,
) (*bbgo.ExchangeSession, *types.SubmitOrder) {
var taker = s.UseTakerOrder
var side types.SideType
var quoteCurrencies []string
if changeQuantity.Sign() > 0 {
quoteCurrencies = s.PreferredQuoteCurrencies.Buy
side = types.SideTypeBuy
} else {
quoteCurrencies = s.PreferredQuoteCurrencies.Sell
side = types.SideTypeSell
}

for _, sessionName := range s.PreferredSessions {
session := sessions[sessionName]

var taker = s.UseTakerOrder
var side types.SideType
var quoteCurrencies []string
if changeQuantity.Sign() > 0 {
quoteCurrencies = s.PreferredQuoteCurrencies.Buy
side = types.SideTypeBuy
} else {
quoteCurrencies = s.PreferredQuoteCurrencies.Sell
side = types.SideTypeSell
}

for _, fromQuoteCurrency := range quoteCurrencies {
// skip the same currency, because there is no such USDT/USDT market
if currency == fromQuoteCurrency {
Expand Down Expand Up @@ -405,6 +455,16 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
}

s.priceResolver = pricesolver.NewSimplePriceResolver(markets)
for _, session := range s.sessions {
// init the price
marketPrices := session.LastPrices()
for market, price := range marketPrices {
s.priceResolver.Update(market, price)
}

// bind on trade to update price
session.UserDataStream.OnTradeUpdate(s.priceResolver.UpdateFromTrade)
}

bbgo.OnShutdown(ctx, func(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done()
Expand Down Expand Up @@ -528,6 +588,30 @@ func (s *Strategy) align(ctx context.Context, sessions map[string]*bbgo.Exchange
}
}

if price, ok := s.priceResolver.ResolvePrice(currency, s.MaxAmountAlert.QuoteCurrency); ok {
quantity := q.Abs()
amount := price.Mul(quantity)
if amount.Compare(s.MaxAmountAlert.Amount) > 0 {
alert := &MaxAmountAlert{
QuoteCurrency: s.MaxAmountAlert.QuoteCurrency,
AlertAmount: s.MaxAmountAlert.Amount,
SlackMentions: s.MaxAmountAlert.SlackMentions,
BaseCurrency: currency,
Price: price,
Quantity: quantity,
Amount: amount,
}

if q.Sign() > 0 {
alert.Side = types.SideTypeBuy
} else {
alert.Side = types.SideTypeSell
}

bbgo.Notify(alert)
}
}

selectedSession, submitOrder := s.selectSessionForCurrency(ctx, sessions, currency, q)
if selectedSession != nil && submitOrder != nil {
log.Infof("placing %s order on %s: %+v", submitOrder.Symbol, selectedSession.Name, submitOrder)
Expand Down

0 comments on commit caf5d69

Please sign in to comment.