From a714af739ad064cb58e7b3800f8538012fae341b Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 21 Oct 2020 19:52:55 +0800 Subject: [PATCH] implement TradeReporter --- pkg/bbgo/environment.go | 48 +++++++++++++++++++++++++++++ pkg/bbgo/notifier.go | 12 ++------ pkg/bbgo/trader.go | 2 ++ pkg/notifier/slacknotifier/slack.go | 4 ++- 4 files changed, 56 insertions(+), 10 deletions(-) diff --git a/pkg/bbgo/environment.go b/pkg/bbgo/environment.go index fc4af3173..5037e54a2 100644 --- a/pkg/bbgo/environment.go +++ b/pkg/bbgo/environment.go @@ -3,6 +3,7 @@ package bbgo import ( "context" "fmt" + "regexp" "strings" "time" @@ -15,6 +16,7 @@ import ( "github.com/c9s/bbgo/pkg/service" "github.com/c9s/bbgo/pkg/store" "github.com/c9s/bbgo/pkg/types" + "github.com/c9s/bbgo/pkg/util" ) var LoadedExchangeStrategies = make(map[string]SingleExchangeStrategy) @@ -29,6 +31,52 @@ func RegisterCrossExchangeStrategy(key string, configmap CrossExchangeStrategy) LoadedCrossExchangeStrategies[key] = configmap } +type TradeReporter struct { + notifier Notifier + + channel string + channelRoutes map[*regexp.Regexp]string +} + +func NewTradeReporter(notifier Notifier) *TradeReporter { + return &TradeReporter{ + notifier: notifier, + channelRoutes: make(map[*regexp.Regexp]string), + } +} + +func (reporter *TradeReporter) Channel(channel string) *TradeReporter { + reporter.channel = channel + return reporter +} + +func (reporter *TradeReporter) ChannelBySymbol(routes map[string]string) *TradeReporter { + for pattern, channel := range routes { + reporter.channelRoutes[regexp.MustCompile(pattern)] = channel + } + + return reporter +} + +func (reporter *TradeReporter) getChannel(symbol string) string { + for pattern, channel := range reporter.channelRoutes { + if pattern.MatchString(symbol) { + return channel + } + } + + return reporter.channel +} + +func (reporter *TradeReporter) Report(trade types.Trade) { + var channel = reporter.getChannel(trade.Symbol) + + var text = util.Render(`:handshake: {{ .Symbol }} {{ .Side }} Trade Execution @ {{ .Price }}`, trade) + if err := reporter.notifier.Notify(channel, text, trade); err != nil { + log.WithError(err).Error("notifier error") + } +} + // Environment presents the real exchange data layer type Environment struct { TradeService *service.TradeService diff --git a/pkg/bbgo/notifier.go b/pkg/bbgo/notifier.go index 1a4a81d2c..e6285bd80 100644 --- a/pkg/bbgo/notifier.go +++ b/pkg/bbgo/notifier.go @@ -1,17 +1,11 @@ package bbgo -import ( - "github.com/c9s/bbgo/pkg/accounting/pnl" - "github.com/c9s/bbgo/pkg/types" -) - type Notifier interface { - Notify(channel, format string, args ...interface{}) - NotifyTrade(trade *types.Trade) - NotifyPnL(report *pnl.AverageCostPnlReport) + Notify(channel, format string, args ...interface{}) error } type NullNotifier struct{} -func (n *NullNotifier) Notify(format string, args ...interface{}) { +func (n *NullNotifier) Notify(format string, args ...interface{}) error { + return nil } diff --git a/pkg/bbgo/trader.go b/pkg/bbgo/trader.go index 9747bc2d0..a2ea87055 100644 --- a/pkg/bbgo/trader.go +++ b/pkg/bbgo/trader.go @@ -240,11 +240,13 @@ func (trader *Trader) NotifyPnL(report *accounting.ProfitAndLossReport) { } */ +/* func (trader *Trader) NotifyTrade(trade *types.Trade) { for _, n := range trader.notifiers { n.NotifyTrade(trade) } } +*/ func (trader *Trader) SubmitOrder(ctx context.Context, order types.SubmitOrder) { trader.Notify(":memo: Submitting %s %s %s order with quantity: %s", order.Symbol, order.Type, order.Side, order.QuantityString, order) diff --git a/pkg/notifier/slacknotifier/slack.go b/pkg/notifier/slacknotifier/slack.go index 5691a9e80..81cd7068b 100644 --- a/pkg/notifier/slacknotifier/slack.go +++ b/pkg/notifier/slacknotifier/slack.go @@ -32,7 +32,7 @@ func New(token string, options ...NotifyOption) *Notifier { return notifier } -func (n *Notifier) Notify(channel, format string, args ...interface{}) { +func (n *Notifier) Notify(channel, format string, args ...interface{}) error { var slackAttachments []slack.Attachment var slackArgsOffset = -1 @@ -70,6 +70,8 @@ func (n *Notifier) Notify(channel, format string, args ...interface{}) { if err != nil { logrus.WithError(err).Errorf("slack error: %s", err.Error()) } + + return err } /*