diff --git a/config/bbgo.yaml b/config/bbgo.yaml index 6d326eff6..b54f47bef 100644 --- a/config/bbgo.yaml +++ b/config/bbgo.yaml @@ -5,25 +5,25 @@ imports: notifications: slack: - defaultChannel: "#dev-bbgo" - errorChannel: "#bbgo-error" + defaultChannel: "dev-bbgo" + errorChannel: "bbgo-error" # if you want to route channel by symbol symbolChannels: - "^BTC": "#btc" - "^ETH": "#eth" + "^BTC": "btc" + "^ETH": "eth" # if you want to route channel by exchange session sessionChannels: - max: "#bbgo-max" - binance: "#bbgo-binance" + max: "bbgo-max" + binance: "bbgo-binance" # routing rules routing: trade: "$symbol" order: "$symbol" submitOrder: "$session" - pnL: "#bbgo-pnl" + pnL: "bbgo-pnl" reportPnL: - averageCostBySymbols: diff --git a/config/pricealert.yaml b/config/pricealert.yaml index ee0976b1e..2b7180285 100644 --- a/config/pricealert.yaml +++ b/config/pricealert.yaml @@ -1,20 +1,20 @@ --- notifications: slack: - defaultChannel: "#dev-bbgo" - errorChannel: "#bbgo-error" + defaultChannel: "dev-bbgo" + errorChannel: "bbgo-error" # if you want to route channel by symbol symbolChannels: - "^BTC": "#btc" - "^ETH": "#eth" + "^BTC": "btc" + "^ETH": "eth" # object routing rules routing: trade: "$symbol" order: "$symbol" submitOrder: "$session" # not supported yet - pnL: "#bbgo-pnl" + pnL: "bbgo-pnl" sessions: binance: diff --git a/config/swing.yaml b/config/swing.yaml index 0ffb2eedd..92b0eb0cd 100644 --- a/config/swing.yaml +++ b/config/swing.yaml @@ -1,21 +1,21 @@ --- notifications: slack: - defaultChannel: "#dev-bbgo" - errorChannel: "#bbgo-error" + defaultChannel: "dev-bbgo" + errorChannel: "bbgo-error" # if you want to route channel by symbol symbolChannels: - "^BTC": "#btc" - "^ETH": "#eth" - "^BNB": "#bnb" + "^BTC": "btc" + "^ETH": "eth" + "^BNB": "bnb" # object routing rules routing: trade: "$symbol" order: "$symbol" submitOrder: "$session" # not supported yet - pnL: "#bbgo-pnl" + pnL: "bbgo-pnl" sessions: binance: diff --git a/pkg/bbgo/injection.go b/pkg/bbgo/injection.go index e8dd8b362..644455b33 100644 --- a/pkg/bbgo/injection.go +++ b/pkg/bbgo/injection.go @@ -31,10 +31,10 @@ func injectField(rs reflect.Value, fieldName string, obj interface{}) error { return nil } - logrus.Infof("found %s in %T, injecting %T...", fieldName, rs.Type(), obj) + logrus.Infof("found %s in %s, injecting %T...", fieldName, rs.Type(), obj) if !field.CanSet() { - return errors.Errorf("field %s of %T can not be set", fieldName, rs.Type()) + return errors.Errorf("field %s of %s can not be set", fieldName, rs.Type()) } rv := reflect.ValueOf(obj) diff --git a/pkg/bbgo/marketdatastore.go b/pkg/bbgo/marketdatastore.go index 0cb2a498a..7f05e7b5e 100644 --- a/pkg/bbgo/marketdatastore.go +++ b/pkg/bbgo/marketdatastore.go @@ -79,8 +79,12 @@ func (store *MarketDataStore) handleKLineClosed(kline types.KLine) { } func (store *MarketDataStore) AddKLine(kline types.KLine) { - window := store.KLineWindows[kline.Interval] - window.Add(kline) + window, ok := store.KLineWindows[kline.Interval] + if !ok { + window = types.KLineWindow{kline} + } else { + window.Add(kline) + } store.KLineWindows[kline.Interval] = window store.LastKLine = kline diff --git a/pkg/bbgo/reporter.go b/pkg/bbgo/reporter.go index 5a61a2bb3..7415e4e9e 100644 --- a/pkg/bbgo/reporter.go +++ b/pkg/bbgo/reporter.go @@ -142,15 +142,15 @@ func (router *ObjectChannelRouter) Route(obj interface{}) (channel string, ok bo } type TradeReporter struct { - notifier Notifier + *Notifiability channel string channelRoutes map[*regexp.Regexp]string } -func NewTradeReporter(notifier Notifier) *TradeReporter { +func NewTradeReporter(notifiability *Notifiability) *TradeReporter { return &TradeReporter{ - notifier: notifier, + Notifiability: notifiability, channelRoutes: make(map[*regexp.Regexp]string), } } @@ -182,5 +182,5 @@ func (reporter *TradeReporter) Report(trade types.Trade) { var channel = reporter.getChannel(trade.Symbol) var text = util.Render(`:handshake: {{ .Symbol }} {{ .Side }} Trade Execution @ {{ .Price }}`, trade) - reporter.notifier.NotifyTo(channel, text, trade) + reporter.NotifyTo(channel, text, trade) } diff --git a/pkg/bbgo/session.go b/pkg/bbgo/session.go index 670b6ad91..e5571dbde 100644 --- a/pkg/bbgo/session.go +++ b/pkg/bbgo/session.go @@ -86,8 +86,6 @@ type ExchangeSession struct { // standard indicators of each market standardIndicatorSets map[string]*StandardIndicatorSet - tradeReporter *TradeReporter - loadedSymbols map[string]struct{} } @@ -130,11 +128,6 @@ func (session *ExchangeSession) Market(symbol string) (market types.Market, ok b return market, ok } -func (session *ExchangeSession) ReportTrade(notifier Notifier) *TradeReporter { - session.tradeReporter = NewTradeReporter(notifier) - return session.tradeReporter -} - // Subscribe save the subscription info, later it will be assigned to the stream func (session *ExchangeSession) Subscribe(channel types.Channel, symbol string, options types.SubscribeOptions) *ExchangeSession { sub := types.Subscription{ diff --git a/pkg/bbgo/trader.go b/pkg/bbgo/trader.go index 18bb2958c..79eabb42f 100644 --- a/pkg/bbgo/trader.go +++ b/pkg/bbgo/trader.go @@ -107,11 +107,7 @@ func (trader *Trader) Run(ctx context.Context) error { // session based trade reporter for sessionName := range trader.environment.sessions { var session = trader.environment.sessions[sessionName] - if session.tradeReporter != nil { - session.Stream.OnTrade(func(trade types.Trade) { - session.tradeReporter.Report(trade) - }) - } else if trader.tradeReporter != nil { + if trader.tradeReporter != nil { session.Stream.OnTrade(func(trade types.Trade) { trader.tradeReporter.Report(trade) }) diff --git a/pkg/exchange/max/exchange.go b/pkg/exchange/max/exchange.go index 747bcc874..6ff53abbc 100644 --- a/pkg/exchange/max/exchange.go +++ b/pkg/exchange/max/exchange.go @@ -2,6 +2,7 @@ package max import ( "context" + "math" "time" "github.com/google/uuid" @@ -54,7 +55,7 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) { BaseCurrency: toGlobalCurrency(m.BaseUnit), MinNotional: m.MinQuoteAmount, MinAmount: m.MinQuoteAmount, - MinLot: m.MinBaseAmount, + MinLot: 1.0 / math.Pow10(m.BaseUnitPrecision), // make it like 0.0001 MinQuantity: m.MinBaseAmount, MaxQuantity: 10000.0, MinPrice: 0.1, diff --git a/pkg/notifier/slacknotifier/slack.go b/pkg/notifier/slacknotifier/slack.go index 1148e0690..4ec0e4c7a 100644 --- a/pkg/notifier/slacknotifier/slack.go +++ b/pkg/notifier/slacknotifier/slack.go @@ -40,6 +40,10 @@ func (n *Notifier) Notify(format string, args ...interface{}) { } func (n *Notifier) NotifyTo(channel, format string, args ...interface{}) { + if len(channel) == 0 { + channel = n.channel + } + var slackAttachments []slack.Attachment var slackArgsOffset = -1 diff --git a/pkg/strategy/swing/strategy.go b/pkg/strategy/swing/strategy.go index 90e580592..fb48e22d6 100644 --- a/pkg/strategy/swing/strategy.go +++ b/pkg/strategy/swing/strategy.go @@ -22,6 +22,7 @@ type Strategy struct { *bbgo.MarketDataStore *types.Market + // OrderExecutor is an interface for submitting order bbgo.OrderExecutor // These fields will be filled from the config file (it translates YAML to JSON) @@ -116,7 +117,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se case 1: // if it goes up and it's above the moving average price, then we sell if closePrice > movingAveragePrice { - s.notify(":chart_with_upwards_trend: closePrice %f is above movingAveragePrice %f, submitting sell order", closePrice, movingAveragePrice) + s.notify(":chart_with_upwards_trend: closePrice %f is above movingAveragePrice %f, submitting SELL order", closePrice, movingAveragePrice) _, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ Symbol: s.Symbol, @@ -132,7 +133,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se case -1: // if it goes down and it's below the moving average price, then we buy if closePrice < movingAveragePrice { - s.notify(":chart_with_downwards_trend: closePrice %f is below movingAveragePrice %f, submitting buy order", closePrice, movingAveragePrice) + s.notify(":chart_with_downwards_trend: closePrice %f is below movingAveragePrice %f, submitting BUY order", closePrice, movingAveragePrice) _, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ Symbol: s.Symbol,