diff --git a/pkg/bbgo/environment.go b/pkg/bbgo/environment.go index cc85b13e4..76426b756 100644 --- a/pkg/bbgo/environment.go +++ b/pkg/bbgo/environment.go @@ -21,7 +21,7 @@ import ( "github.com/spf13/viper" "gopkg.in/tucnak/telebot.v2" - exchange2 "github.com/c9s/bbgo/pkg/exchange" + "github.com/c9s/bbgo/pkg/exchange" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/interact" "github.com/c9s/bbgo/pkg/notifier/slacknotifier" @@ -223,12 +223,12 @@ func (environ *Environment) ConfigureExchangeSessions(userConfig *Config) error func (environ *Environment) AddExchangesByViperKeys() error { for _, n := range types.SupportedExchanges { if viper.IsSet(string(n) + "-api-key") { - exchange, err := exchange2.NewWithEnvVarPrefix(n, "") + ex, err := exchange.NewWithEnvVarPrefix(n, "") if err != nil { return err } - environ.AddExchange(n.String(), exchange) + environ.AddExchange(n.String(), ex) } } diff --git a/pkg/bbgo/log.go b/pkg/bbgo/log.go new file mode 100644 index 000000000..f30d11b65 --- /dev/null +++ b/pkg/bbgo/log.go @@ -0,0 +1 @@ +package bbgo diff --git a/pkg/bbgo/order_executor_general.go b/pkg/bbgo/order_executor_general.go index da679e8b4..64c07d7db 100644 --- a/pkg/bbgo/order_executor_general.go +++ b/pkg/bbgo/order_executor_general.go @@ -9,7 +9,6 @@ import ( log "github.com/sirupsen/logrus" "github.com/c9s/bbgo/pkg/fixedpoint" - "github.com/c9s/bbgo/pkg/risk" "github.com/c9s/bbgo/pkg/types" ) @@ -180,7 +179,7 @@ func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPos if options.Long { if quantity.IsZero() { - quoteQuantity, err := risk.CalculateQuoteQuantity(ctx, e.session, e.position.QuoteCurrency, options.Leverage) + quoteQuantity, err := CalculateQuoteQuantity(ctx, e.session, e.position.QuoteCurrency, options.Leverage) if err != nil { return err } @@ -200,7 +199,7 @@ func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPos } else if options.Short { if quantity.IsZero() { var err error - quantity, err = risk.CalculateBaseQuantity(e.session, e.position.Market, price, quantity, options.Leverage) + quantity, err = CalculateBaseQuantity(e.session, e.position.Market, price, quantity, options.Leverage) if err != nil { return err } diff --git a/pkg/risk/account_value.go b/pkg/bbgo/risk.go similarity index 81% rename from pkg/risk/account_value.go rename to pkg/bbgo/risk.go index d8c4f718a..a28617f53 100644 --- a/pkg/risk/account_value.go +++ b/pkg/bbgo/risk.go @@ -1,34 +1,30 @@ -package risk +package bbgo import ( "context" "fmt" "time" - "github.com/sirupsen/logrus" + log "github.com/sirupsen/logrus" - "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/fixedpoint" + "github.com/c9s/bbgo/pkg/risk" "github.com/c9s/bbgo/pkg/types" ) -var log = logrus.WithField("risk", "AccountValueCalculator") - -var one = fixedpoint.One - var defaultLeverage = fixedpoint.NewFromInt(3) var maxLeverage = fixedpoint.NewFromInt(10) type AccountValueCalculator struct { - session *bbgo.ExchangeSession + session *ExchangeSession quoteCurrency string prices map[string]fixedpoint.Value tickers map[string]types.Ticker updateTime time.Time } -func NewAccountValueCalculator(session *bbgo.ExchangeSession, quoteCurrency string) *AccountValueCalculator { +func NewAccountValueCalculator(session *ExchangeSession, quoteCurrency string) *AccountValueCalculator { return &AccountValueCalculator{ session: session, quoteCurrency: quoteCurrency, @@ -190,7 +186,7 @@ func (c *AccountValueCalculator) MarginLevel(ctx context.Context) (fixedpoint.Va return marginLevel, nil } -func CalculateBaseQuantity(session *bbgo.ExchangeSession, market types.Market, price, quantity, leverage fixedpoint.Value) (fixedpoint.Value, error) { +func CalculateBaseQuantity(session *ExchangeSession, market types.Market, price, quantity, leverage fixedpoint.Value) (fixedpoint.Value, error) { // default leverage guard if leverage.IsZero() { leverage = defaultLeverage @@ -205,7 +201,7 @@ func CalculateBaseQuantity(session *bbgo.ExchangeSession, market types.Market, p balance, hasBalance := session.Account.Balance(market.BaseCurrency) if hasBalance { if quantity.IsZero() { - logrus.Warnf("sell quantity is not set, using all available base balance: %v", balance) + log.Warnf("sell quantity is not set, using all available base balance: %v", balance) if !balance.Available.IsZero() { return balance.Available, nil } @@ -222,7 +218,7 @@ func CalculateBaseQuantity(session *bbgo.ExchangeSession, market types.Market, p } // using leverage -- starts from here - logrus.Infof("calculating available leveraged base quantity: base balance = %+v, quote balance = %+v", baseBalance, quoteBalance) + log.Infof("calculating available leveraged base quantity: base balance = %+v, quote balance = %+v", baseBalance, quoteBalance) // calculate the quantity automatically if session.Margin || session.IsolatedMargin { @@ -232,22 +228,22 @@ func CalculateBaseQuantity(session *bbgo.ExchangeSession, market types.Market, p // avoid using all account value since there will be some trade loss for interests and the fee accountValue = accountValue.Mul(one.Sub(fixedpoint.NewFromFloat(0.01))) - logrus.Infof("calculated account value %f %s", accountValue.Float64(), market.QuoteCurrency) + log.Infof("calculated account value %f %s", accountValue.Float64(), market.QuoteCurrency) if session.IsolatedMargin { originLeverage := leverage leverage = fixedpoint.Min(leverage, maxLeverage) - logrus.Infof("using isolated margin, maxLeverage=10 originalLeverage=%f currentLeverage=%f", + log.Infof("using isolated margin, maxLeverage=10 originalLeverage=%f currentLeverage=%f", originLeverage.Float64(), leverage.Float64()) } // spot margin use the equity value, so we use the total quote balance here - maxPosition := CalculateMaxPosition(price, accountValue, leverage) + maxPosition := risk.CalculateMaxPosition(price, accountValue, leverage) debt := baseBalance.Debt() maxQuantity := maxPosition.Sub(debt) - logrus.Infof("margin leverage: calculated maxQuantity=%f maxPosition=%f debt=%f price=%f accountValue=%f %s leverage=%f", + log.Infof("margin leverage: calculated maxQuantity=%f maxPosition=%f debt=%f price=%f accountValue=%f %s leverage=%f", maxQuantity.Float64(), maxPosition.Float64(), debt.Float64(), @@ -261,8 +257,8 @@ func CalculateBaseQuantity(session *bbgo.ExchangeSession, market types.Market, p if session.Futures || session.IsolatedFutures { // TODO: get mark price here - maxPositionQuantity := CalculateMaxPosition(price, quoteBalance.Available, leverage) - requiredPositionCost := CalculatePositionCost(price, price, maxPositionQuantity, leverage, types.SideTypeSell) + maxPositionQuantity := risk.CalculateMaxPosition(price, quoteBalance.Available, leverage) + requiredPositionCost := risk.CalculatePositionCost(price, price, maxPositionQuantity, leverage, types.SideTypeSell) if quoteBalance.Available.Compare(requiredPositionCost) < 0 { return maxPositionQuantity, fmt.Errorf("available margin %f %s is not enough, can not submit order", quoteBalance.Available.Float64(), market.QuoteCurrency) } @@ -273,7 +269,7 @@ func CalculateBaseQuantity(session *bbgo.ExchangeSession, market types.Market, p return quantity, fmt.Errorf("quantity is zero, can not submit sell order, please check your settings") } -func CalculateQuoteQuantity(ctx context.Context, session *bbgo.ExchangeSession, quoteCurrency string, leverage fixedpoint.Value) (fixedpoint.Value, error) { +func CalculateQuoteQuantity(ctx context.Context, session *ExchangeSession, quoteCurrency string, leverage fixedpoint.Value) (fixedpoint.Value, error) { // default leverage guard if leverage.IsZero() { leverage = defaultLeverage @@ -294,7 +290,8 @@ func CalculateQuoteQuantity(ctx context.Context, session *bbgo.ExchangeSession, log.WithError(err).Errorf("can not update available quote") return fixedpoint.Zero, err } - logrus.Infof("calculating available leveraged quote quantity: account available quote = %+v", availableQuote) + + log.Infof("calculating available leveraged quote quantity: account available quote = %+v", availableQuote) return availableQuote.Mul(leverage), nil } diff --git a/pkg/risk/account_value_test.go b/pkg/bbgo/risk_test.go similarity index 95% rename from pkg/risk/account_value_test.go rename to pkg/bbgo/risk_test.go index 940ae0b45..fcd9f532b 100644 --- a/pkg/risk/account_value_test.go +++ b/pkg/bbgo/risk_test.go @@ -1,4 +1,4 @@ -package risk +package bbgo import ( "context" @@ -8,7 +8,6 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types/mocks" @@ -40,7 +39,7 @@ func TestAccountValueCalculator_NetValue(t *testing.T) { "BTCUSDT": newTestTicker(), }, nil) - session := bbgo.NewExchangeSession("test", mockEx) + session := NewExchangeSession("test", mockEx) session.Account.UpdateBalances(types.BalanceMap{ "BTC": { Currency: "BTC", @@ -81,7 +80,7 @@ func TestAccountValueCalculator_NetValue(t *testing.T) { "BTCUSDT": newTestTicker(), }, nil) - session := bbgo.NewExchangeSession("test", mockEx) + session := NewExchangeSession("test", mockEx) session.Account.UpdateBalances(types.BalanceMap{ "BTC": { Currency: "BTC", @@ -123,7 +122,7 @@ func TestNewAccountValueCalculator_MarginLevel(t *testing.T) { "BTCUSDT": newTestTicker(), }, nil) - session := bbgo.NewExchangeSession("test", mockEx) + session := NewExchangeSession("test", mockEx) session.Account.UpdateBalances(types.BalanceMap{ "BTC": { Currency: "BTC", diff --git a/pkg/strategy/pivotshort/breaklow.go b/pkg/strategy/pivotshort/breaklow.go index cecc56c86..3f52deead 100644 --- a/pkg/strategy/pivotshort/breaklow.go +++ b/pkg/strategy/pivotshort/breaklow.go @@ -6,7 +6,6 @@ import ( "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/indicator" - "github.com/c9s/bbgo/pkg/risk" "github.com/c9s/bbgo/pkg/types" ) @@ -197,7 +196,7 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener // graceful cancel all active orders _ = orderExecutor.GracefulCancel(ctx) - quantity, err := risk.CalculateBaseQuantity(s.session, s.Market, closePrice, s.Quantity, s.Leverage) + quantity, err := bbgo.CalculateBaseQuantity(s.session, s.Market, closePrice, s.Quantity, s.Leverage) if err != nil { log.WithError(err).Errorf("quantity calculation error") } @@ -241,7 +240,7 @@ func (s *BreakLow) pilotQuantityCalculation() { s.Quantity.Float64(), s.Leverage.Float64()) - quantity, err := risk.CalculateBaseQuantity(s.session, s.Market, s.lastLow, s.Quantity, s.Leverage) + quantity, err := bbgo.CalculateBaseQuantity(s.session, s.Market, s.lastLow, s.Quantity, s.Leverage) if err != nil { log.WithError(err).Errorf("quantity calculation error") } diff --git a/pkg/strategy/pivotshort/failedbreakhigh.go b/pkg/strategy/pivotshort/failedbreakhigh.go index 21574679d..58562976e 100644 --- a/pkg/strategy/pivotshort/failedbreakhigh.go +++ b/pkg/strategy/pivotshort/failedbreakhigh.go @@ -6,7 +6,6 @@ import ( "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/indicator" - "github.com/c9s/bbgo/pkg/risk" "github.com/c9s/bbgo/pkg/types" ) @@ -209,7 +208,7 @@ func (s *FailedBreakHigh) Bind(session *bbgo.ExchangeSession, orderExecutor *bbg // graceful cancel all active orders _ = orderExecutor.GracefulCancel(ctx) - quantity, err := risk.CalculateBaseQuantity(s.session, s.Market, closePrice, s.Quantity, s.Leverage) + quantity, err := bbgo.CalculateBaseQuantity(s.session, s.Market, closePrice, s.Quantity, s.Leverage) if err != nil { log.WithError(err).Errorf("quantity calculation error") } @@ -260,7 +259,7 @@ func (s *FailedBreakHigh) pilotQuantityCalculation() { s.Quantity.Float64(), s.Leverage.Float64()) - quantity, err := risk.CalculateBaseQuantity(s.session, s.Market, s.lastHigh, s.Quantity, s.Leverage) + quantity, err := bbgo.CalculateBaseQuantity(s.session, s.Market, s.lastHigh, s.Quantity, s.Leverage) if err != nil { log.WithError(err).Errorf("quantity calculation error") } diff --git a/pkg/strategy/pivotshort/resistance.go b/pkg/strategy/pivotshort/resistance.go index 8ee4c2c5d..1a7c04ae0 100644 --- a/pkg/strategy/pivotshort/resistance.go +++ b/pkg/strategy/pivotshort/resistance.go @@ -7,7 +7,6 @@ import ( "github.com/c9s/bbgo/pkg/datatype/floats" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/indicator" - "github.com/c9s/bbgo/pkg/risk" "github.com/c9s/bbgo/pkg/types" ) @@ -128,7 +127,7 @@ func (s *ResistanceShort) updateResistanceOrders(closePrice fixedpoint.Value) { } func (s *ResistanceShort) placeResistanceOrders(ctx context.Context, resistancePrice fixedpoint.Value) { - totalQuantity, err := risk.CalculateBaseQuantity(s.session, s.Market, resistancePrice, s.Quantity, s.Leverage) + totalQuantity, err := bbgo.CalculateBaseQuantity(s.session, s.Market, resistancePrice, s.Quantity, s.Leverage) if err != nil { log.WithError(err).Errorf("quantity calculation error") } diff --git a/pkg/strategy/supertrend/strategy.go b/pkg/strategy/supertrend/strategy.go index 1c70be8fb..ae99aadfe 100644 --- a/pkg/strategy/supertrend/strategy.go +++ b/pkg/strategy/supertrend/strategy.go @@ -6,13 +6,12 @@ import ( "os" "sync" - "github.com/c9s/bbgo/pkg/data/tsv" - "github.com/c9s/bbgo/pkg/datatype/floats" - "github.com/c9s/bbgo/pkg/risk" - "github.com/pkg/errors" "github.com/sirupsen/logrus" + "github.com/c9s/bbgo/pkg/data/tsv" + "github.com/c9s/bbgo/pkg/datatype/floats" + "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/indicator" @@ -173,7 +172,7 @@ type Strategy struct { Leverage fixedpoint.Value `json:"leverage"` // Quantity sets the fixed order qty, takes precedence over Leverage Quantity fixedpoint.Value `json:"quantity"` - AccountValueCalculator *risk.AccountValueCalculator + AccountValueCalculator *bbgo.AccountValueCalculator // TakeProfitAtrMultiplier TP according to ATR multiple, 0 to disable this TakeProfitAtrMultiplier float64 `json:"takeProfitAtrMultiplier"` @@ -389,7 +388,7 @@ func (s *Strategy) calculateQuantity(ctx context.Context, currentPrice fixedpoin return balance.Available.Mul(fixedpoint.Min(s.Leverage, fixedpoint.One)) } else { // Using leverage or spot buy - quoteQty, err := risk.CalculateQuoteQuantity(ctx, s.session, s.Market.QuoteCurrency, s.Leverage) + quoteQty, err := bbgo.CalculateQuoteQuantity(ctx, s.session, s.Market.QuoteCurrency, s.Leverage) if err != nil { log.WithError(err).Errorf("can not update %s quote balance from exchange", s.Symbol) return fixedpoint.Zero @@ -449,7 +448,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se s.orderExecutor.Bind() // AccountValueCalculator - s.AccountValueCalculator = risk.NewAccountValueCalculator(s.session, s.Market.QuoteCurrency) + s.AccountValueCalculator = bbgo.NewAccountValueCalculator(s.session, s.Market.QuoteCurrency) // Accumulated profit report if bbgo.IsBackTesting {