finalize swing strategy and fix trade reporter issue

This commit is contained in:
c9s 2020-10-28 17:44:37 +08:00
parent c96845ff6a
commit 67446670ac
11 changed files with 40 additions and 41 deletions

View File

@ -5,25 +5,25 @@ imports:
notifications: notifications:
slack: slack:
defaultChannel: "#dev-bbgo" defaultChannel: "dev-bbgo"
errorChannel: "#bbgo-error" errorChannel: "bbgo-error"
# if you want to route channel by symbol # if you want to route channel by symbol
symbolChannels: symbolChannels:
"^BTC": "#btc" "^BTC": "btc"
"^ETH": "#eth" "^ETH": "eth"
# if you want to route channel by exchange session # if you want to route channel by exchange session
sessionChannels: sessionChannels:
max: "#bbgo-max" max: "bbgo-max"
binance: "#bbgo-binance" binance: "bbgo-binance"
# routing rules # routing rules
routing: routing:
trade: "$symbol" trade: "$symbol"
order: "$symbol" order: "$symbol"
submitOrder: "$session" submitOrder: "$session"
pnL: "#bbgo-pnl" pnL: "bbgo-pnl"
reportPnL: reportPnL:
- averageCostBySymbols: - averageCostBySymbols:

View File

@ -1,20 +1,20 @@
--- ---
notifications: notifications:
slack: slack:
defaultChannel: "#dev-bbgo" defaultChannel: "dev-bbgo"
errorChannel: "#bbgo-error" errorChannel: "bbgo-error"
# if you want to route channel by symbol # if you want to route channel by symbol
symbolChannels: symbolChannels:
"^BTC": "#btc" "^BTC": "btc"
"^ETH": "#eth" "^ETH": "eth"
# object routing rules # object routing rules
routing: routing:
trade: "$symbol" trade: "$symbol"
order: "$symbol" order: "$symbol"
submitOrder: "$session" # not supported yet submitOrder: "$session" # not supported yet
pnL: "#bbgo-pnl" pnL: "bbgo-pnl"
sessions: sessions:
binance: binance:

View File

@ -1,21 +1,21 @@
--- ---
notifications: notifications:
slack: slack:
defaultChannel: "#dev-bbgo" defaultChannel: "dev-bbgo"
errorChannel: "#bbgo-error" errorChannel: "bbgo-error"
# if you want to route channel by symbol # if you want to route channel by symbol
symbolChannels: symbolChannels:
"^BTC": "#btc" "^BTC": "btc"
"^ETH": "#eth" "^ETH": "eth"
"^BNB": "#bnb" "^BNB": "bnb"
# object routing rules # object routing rules
routing: routing:
trade: "$symbol" trade: "$symbol"
order: "$symbol" order: "$symbol"
submitOrder: "$session" # not supported yet submitOrder: "$session" # not supported yet
pnL: "#bbgo-pnl" pnL: "bbgo-pnl"
sessions: sessions:
binance: binance:

View File

@ -31,10 +31,10 @@ func injectField(rs reflect.Value, fieldName string, obj interface{}) error {
return nil 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() { 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) rv := reflect.ValueOf(obj)

View File

@ -79,8 +79,12 @@ func (store *MarketDataStore) handleKLineClosed(kline types.KLine) {
} }
func (store *MarketDataStore) AddKLine(kline types.KLine) { func (store *MarketDataStore) AddKLine(kline types.KLine) {
window := store.KLineWindows[kline.Interval] window, ok := store.KLineWindows[kline.Interval]
window.Add(kline) if !ok {
window = types.KLineWindow{kline}
} else {
window.Add(kline)
}
store.KLineWindows[kline.Interval] = window store.KLineWindows[kline.Interval] = window
store.LastKLine = kline store.LastKLine = kline

View File

@ -142,15 +142,15 @@ func (router *ObjectChannelRouter) Route(obj interface{}) (channel string, ok bo
} }
type TradeReporter struct { type TradeReporter struct {
notifier Notifier *Notifiability
channel string channel string
channelRoutes map[*regexp.Regexp]string channelRoutes map[*regexp.Regexp]string
} }
func NewTradeReporter(notifier Notifier) *TradeReporter { func NewTradeReporter(notifiability *Notifiability) *TradeReporter {
return &TradeReporter{ return &TradeReporter{
notifier: notifier, Notifiability: notifiability,
channelRoutes: make(map[*regexp.Regexp]string), channelRoutes: make(map[*regexp.Regexp]string),
} }
} }
@ -182,5 +182,5 @@ func (reporter *TradeReporter) Report(trade types.Trade) {
var channel = reporter.getChannel(trade.Symbol) var channel = reporter.getChannel(trade.Symbol)
var text = util.Render(`:handshake: {{ .Symbol }} {{ .Side }} Trade Execution @ {{ .Price }}`, trade) var text = util.Render(`:handshake: {{ .Symbol }} {{ .Side }} Trade Execution @ {{ .Price }}`, trade)
reporter.notifier.NotifyTo(channel, text, trade) reporter.NotifyTo(channel, text, trade)
} }

View File

@ -86,8 +86,6 @@ type ExchangeSession struct {
// standard indicators of each market // standard indicators of each market
standardIndicatorSets map[string]*StandardIndicatorSet standardIndicatorSets map[string]*StandardIndicatorSet
tradeReporter *TradeReporter
loadedSymbols map[string]struct{} loadedSymbols map[string]struct{}
} }
@ -130,11 +128,6 @@ func (session *ExchangeSession) Market(symbol string) (market types.Market, ok b
return market, ok 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 // 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 { func (session *ExchangeSession) Subscribe(channel types.Channel, symbol string, options types.SubscribeOptions) *ExchangeSession {
sub := types.Subscription{ sub := types.Subscription{

View File

@ -107,11 +107,7 @@ func (trader *Trader) Run(ctx context.Context) error {
// session based trade reporter // session based trade reporter
for sessionName := range trader.environment.sessions { for sessionName := range trader.environment.sessions {
var session = trader.environment.sessions[sessionName] var session = trader.environment.sessions[sessionName]
if session.tradeReporter != nil { if trader.tradeReporter != nil {
session.Stream.OnTrade(func(trade types.Trade) {
session.tradeReporter.Report(trade)
})
} else if trader.tradeReporter != nil {
session.Stream.OnTrade(func(trade types.Trade) { session.Stream.OnTrade(func(trade types.Trade) {
trader.tradeReporter.Report(trade) trader.tradeReporter.Report(trade)
}) })

View File

@ -2,6 +2,7 @@ package max
import ( import (
"context" "context"
"math"
"time" "time"
"github.com/google/uuid" "github.com/google/uuid"
@ -54,7 +55,7 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
BaseCurrency: toGlobalCurrency(m.BaseUnit), BaseCurrency: toGlobalCurrency(m.BaseUnit),
MinNotional: m.MinQuoteAmount, MinNotional: m.MinQuoteAmount,
MinAmount: m.MinQuoteAmount, MinAmount: m.MinQuoteAmount,
MinLot: m.MinBaseAmount, MinLot: 1.0 / math.Pow10(m.BaseUnitPrecision), // make it like 0.0001
MinQuantity: m.MinBaseAmount, MinQuantity: m.MinBaseAmount,
MaxQuantity: 10000.0, MaxQuantity: 10000.0,
MinPrice: 0.1, MinPrice: 0.1,

View File

@ -40,6 +40,10 @@ func (n *Notifier) Notify(format string, args ...interface{}) {
} }
func (n *Notifier) NotifyTo(channel, 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 slackAttachments []slack.Attachment
var slackArgsOffset = -1 var slackArgsOffset = -1

View File

@ -22,6 +22,7 @@ type Strategy struct {
*bbgo.MarketDataStore *bbgo.MarketDataStore
*types.Market *types.Market
// OrderExecutor is an interface for submitting order
bbgo.OrderExecutor bbgo.OrderExecutor
// These fields will be filled from the config file (it translates YAML to JSON) // 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: case 1:
// if it goes up and it's above the moving average price, then we sell // if it goes up and it's above the moving average price, then we sell
if closePrice > movingAveragePrice { 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{ _, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
@ -132,7 +133,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
case -1: case -1:
// if it goes down and it's below the moving average price, then we buy // if it goes down and it's below the moving average price, then we buy
if closePrice < movingAveragePrice { 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{ _, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,