diff --git a/pkg/cmd/account.go b/pkg/cmd/account.go index fca38e0aa..ef2a9fad0 100644 --- a/pkg/cmd/account.go +++ b/pkg/cmd/account.go @@ -3,7 +3,6 @@ package cmd import ( "context" "fmt" - "os" "github.com/pkg/errors" log "github.com/sirupsen/logrus" @@ -25,18 +24,12 @@ var accountCmd = &cobra.Command{ Use: "account [--session=[exchange_name]]", Short: "show user account details (ex: balance)", SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - configFile, err := cmd.Flags().GetString("config") - if err != nil { - return err - } - - if len(configFile) == 0 { - return errors.New("--config option is required") - } - showTotal, err := cmd.Flags().GetBool("total") if err != nil { return err @@ -47,21 +40,6 @@ var accountCmd = &cobra.Command{ return err } - var userConfig *bbgo.Config - if _, err := os.Stat(configFile); err == nil { - // load successfully - userConfig, err = bbgo.Load(configFile, false) - if err != nil { - return err - } - } else if os.IsNotExist(err) { - // config file doesn't exist - userConfig = &bbgo.Config{} - } else { - // other error - return err - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureDatabase(ctx); err != nil { return err diff --git a/pkg/cmd/balances.go b/pkg/cmd/balances.go index cb810f8ff..58019f186 100644 --- a/pkg/cmd/balances.go +++ b/pkg/cmd/balances.go @@ -20,6 +20,10 @@ var balancesCmd = &cobra.Command{ Use: "balances [--session SESSION]", Short: "Show user account balances", SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + "session", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -28,10 +32,6 @@ var balancesCmd = &cobra.Command{ return err } - if userConfig == nil { - return fmt.Errorf("user config is not loaded") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { diff --git a/pkg/cmd/cancel.go b/pkg/cmd/cancel.go index 3e401b6e8..3daa9ac79 100644 --- a/pkg/cmd/cancel.go +++ b/pkg/cmd/cancel.go @@ -4,7 +4,6 @@ import ( "context" "fmt" - "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -35,7 +34,7 @@ var cancelOrderCmd = &cobra.Command{ // SilenceUsage is an option to silence usage when an error occurs. SilenceUsage: true, - + PreRunE: cobraInitRequired([]string{"config"}), RunE: func(cmd *cobra.Command, args []string) error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -70,10 +69,6 @@ var cancelOrderCmd = &cobra.Command{ return err } - if userConfig == nil { - return errors.New("config file is required") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { return err diff --git a/pkg/cmd/kline.go b/pkg/cmd/kline.go index a55852cdc..bf1ae5cc6 100644 --- a/pkg/cmd/kline.go +++ b/pkg/cmd/kline.go @@ -8,7 +8,6 @@ import ( "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/cmd/cmdutil" "github.com/c9s/bbgo/pkg/types" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -17,13 +16,15 @@ import ( var klineCmd = &cobra.Command{ Use: "kline", Short: "connect to the kline market data streaming service of an exchange", + PreRunE: cobraInitRequired([]string{ + "config", + "session", + "symbol", + "interval", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("--config option or config file is missing") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { return err diff --git a/pkg/cmd/orderbook.go b/pkg/cmd/orderbook.go index e4d810643..bd1ca36ba 100644 --- a/pkg/cmd/orderbook.go +++ b/pkg/cmd/orderbook.go @@ -6,7 +6,6 @@ import ( "syscall" "time" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -19,6 +18,11 @@ import ( var orderbookCmd = &cobra.Command{ Use: "orderbook --session=[exchange_name] --symbol=[pair_name]", Short: "connect to the order book market data streaming service of an exchange", + PreRunE: cobraInitRequired([]string{ + "config", + "session", + "symbol", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() @@ -41,10 +45,6 @@ var orderbookCmd = &cobra.Command{ return err } - if userConfig == nil { - return errors.New("--config option or config file is missing") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { return err @@ -112,15 +112,15 @@ var orderbookCmd = &cobra.Command{ // go run ./cmd/bbgo orderupdate --session=ftx var orderUpdateCmd = &cobra.Command{ - Use: "orderupdate", + Use: "orderupdate", Short: "Listen to order update events", + PreRunE: cobraInitRequired([]string{ + "config", + "session", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("--config option or config file is missing") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { return err diff --git a/pkg/cmd/orders.go b/pkg/cmd/orders.go index 4ac36fffd..2f6dcc493 100644 --- a/pkg/cmd/orders.go +++ b/pkg/cmd/orders.go @@ -23,13 +23,14 @@ var getOrderCmd = &cobra.Command{ Use: "get-order --session SESSION --order-id ORDER_ID", Short: "Get order status", SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + "order-id", + "symbol", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("config file is required") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { return err @@ -76,13 +77,14 @@ var listOrdersCmd = &cobra.Command{ // default is open which means we query open orders if you haven't provided args. ValidArgs: []string{"", "open", "closed"}, SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + "session", + "symbol", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("config file is required") - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { return err @@ -146,13 +148,16 @@ var executeOrderCmd = &cobra.Command{ Use: "execute-order --session SESSION --symbol SYMBOL --side SIDE --target-quantity TOTAL_QUANTITY --slice-quantity SLICE_QUANTITY", Short: "execute buy/sell on the balance/position you have on specific symbol", SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + "symbol", + "side", + "target-quantity", + "slice-quantity", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("config file is required") - } - sessionName, err := cmd.Flags().GetString("session") if err != nil { return err @@ -294,13 +299,17 @@ var submitOrderCmd = &cobra.Command{ Use: "submit-order --session SESSION --symbol SYMBOL --side SIDE --quantity QUANTITY [--price PRICE]", Short: "place order to the exchange", SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + "session", + "symbol", + "side", + "price", + "quantity", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("config file is required") - } - sessionName, err := cmd.Flags().GetString("session") if err != nil { return err diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index fa845ba1a..d69f062d4 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -40,7 +40,10 @@ var RunCmd = &cobra.Command{ // SilenceUsage is an option to silence usage when an error occurs. SilenceUsage: true, - RunE: run, + PreRunE: cobraInitRequired([]string{ + "config", + }), + RunE: run, } func runSetup(baseCtx context.Context, userConfig *bbgo.Config, enableApiServer bool) error { @@ -228,8 +231,6 @@ func run(cmd *cobra.Command, args []string) error { return err } - var userConfig = &bbgo.Config{} - if !setup { // if it's not setup, then the config file option is required. if len(configFile) == 0 { @@ -240,10 +241,6 @@ func run(cmd *cobra.Command, args []string) error { return err } - userConfig, err = bbgo.Load(configFile, false) - if err != nil { - return err - } } ctx, cancel := context.WithCancel(context.Background()) @@ -259,6 +256,7 @@ func run(cmd *cobra.Command, args []string) error { return runSetup(ctx, userConfig, true) } + // default setting is false, here load as true userConfig, err = bbgo.Load(configFile, true) if err != nil { return err diff --git a/pkg/cmd/trades.go b/pkg/cmd/trades.go index fed3490d8..f230599e7 100644 --- a/pkg/cmd/trades.go +++ b/pkg/cmd/trades.go @@ -3,11 +3,9 @@ package cmd import ( "context" "fmt" - "os" "syscall" "time" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -21,35 +19,14 @@ var tradesCmd = &cobra.Command{ Use: "trades --session=[exchange_name] --symbol=[pair_name]", Short: "Query trading history", SilenceUsage: true, + PreRunE: cobraInitRequired([]string{ + "config", + "session", + "symbol", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - configFile, err := cmd.Flags().GetString("config") - if err != nil { - return err - } - - if len(configFile) == 0 { - return errors.New("--config option is required") - } - - // if config file exists, use the config loaded from the config file. - // otherwise, use a empty config object - var userConfig *bbgo.Config - if _, err := os.Stat(configFile); err == nil { - // load successfully - userConfig, err = bbgo.Load(configFile, false) - if err != nil { - return err - } - } else if os.IsNotExist(err) { - // config file doesn't exist - userConfig = &bbgo.Config{} - } else { - // other error - return err - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { @@ -118,37 +95,15 @@ var tradesCmd = &cobra.Command{ // go run ./cmd/bbgo tradeupdate --session=ftx var tradeUpdateCmd = &cobra.Command{ - Use: "tradeupdate --session=[exchange_name]", + Use: "tradeupdate --session=[exchange_name]", Short: "Listen to trade update events", + PreRunE: cobraInitRequired([]string{ + "config", + "session", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - configFile, err := cmd.Flags().GetString("config") - if err != nil { - return err - } - - if len(configFile) == 0 { - return errors.New("--config option is required") - } - - // if config file exists, use the config loaded from the config file. - // otherwise, use a empty config object - var userConfig *bbgo.Config - if _, err := os.Stat(configFile); err == nil { - // load successfully - userConfig, err = bbgo.Load(configFile, false) - if err != nil { - return err - } - } else if os.IsNotExist(err) { - // config file doesn't exist - userConfig = &bbgo.Config{} - } else { - // other error - return err - } - environ := bbgo.NewEnvironment() if err := environ.ConfigureExchangeSessions(userConfig); err != nil { diff --git a/pkg/cmd/userdatastream.go b/pkg/cmd/userdatastream.go index 2b93e1612..9426e5a2c 100644 --- a/pkg/cmd/userdatastream.go +++ b/pkg/cmd/userdatastream.go @@ -6,7 +6,6 @@ import ( "syscall" "time" - "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -17,15 +16,15 @@ import ( // go run ./cmd/bbgo userdatastream --session=ftx var userDataStreamCmd = &cobra.Command{ - Use: "userdatastream", + Use: "userdatastream", Short: "Listen to session events (orderUpdate, tradeUpdate, balanceUpdate, balanceSnapshot)", + PreRunE: cobraInitRequired([]string{ + "config", + "session", + }), RunE: func(cmd *cobra.Command, args []string) error { ctx := context.Background() - if userConfig == nil { - return errors.New("--config option or config file is missing") - } - sessionName, err := cmd.Flags().GetString("session") if err != nil { return err diff --git a/pkg/cmd/utils.go b/pkg/cmd/utils.go index 97d022a77..efff19eb3 100644 --- a/pkg/cmd/utils.go +++ b/pkg/cmd/utils.go @@ -8,8 +8,21 @@ import ( "github.com/c9s/bbgo/pkg/exchange/ftx" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/types" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" ) +func cobraInitRequired(required []string) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + for _, key := range required { + if err := cmd.MarkFlagRequired(key); err != nil { + log.WithError(err).Errorf("cannot mark --%s option required", key) + } + } + return nil + } +} + func inQuoteAsset(balances types.BalanceMap, market types.Market, price fixedpoint.Value) fixedpoint.Value { quote := balances[market.QuoteCurrency] base := balances[market.BaseCurrency]