mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
engine: Add overridable exchanges command line flag (#1630)
* engine: Add overridable exchanges command line flag * Improve tests * engine: Add additional SetupExchanges edge case test and prevent suppressed dry run warnings
This commit is contained in:
@@ -854,11 +854,12 @@ func (bot *Engine) dryRunParamInteraction(param string) {
|
||||
return
|
||||
}
|
||||
|
||||
gctlog.Warnf(gctlog.Global,
|
||||
"Command line argument '-%s' induces dry run mode."+
|
||||
" Set -dryrun=false if you wish to override this.",
|
||||
param)
|
||||
|
||||
if !bot.Settings.EnableDryRun {
|
||||
gctlog.Warnf(gctlog.Global,
|
||||
"Command line argument '-%s' induces dry run mode."+
|
||||
" Set -dryrun=false if you wish to override this.",
|
||||
param)
|
||||
bot.Settings.EnableDryRun = true
|
||||
}
|
||||
}
|
||||
@@ -897,12 +898,40 @@ func (bot *Engine) SetupExchanges() error {
|
||||
bot.dryRunParamInteraction("exchangehttpdebugging")
|
||||
}
|
||||
|
||||
var exchangesOverride []string
|
||||
if bot.Settings.Exchanges != "" {
|
||||
bot.dryRunParamInteraction("exchanges")
|
||||
exchangesOverride = strings.Split(bot.Settings.Exchanges, ",")
|
||||
for x := range exchangesOverride {
|
||||
if !common.StringDataCompareInsensitive(exchange.Exchanges, exchangesOverride[x]) {
|
||||
return fmt.Errorf("exchange %s not found", exchangesOverride[x])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if bot.Settings.EnableAllExchanges && len(exchangesOverride) > 0 {
|
||||
return errors.New("cannot enable all exchanges and specific exchanges concurrently")
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for x := range configs {
|
||||
if !configs[x].Enabled && !bot.Settings.EnableAllExchanges {
|
||||
shouldLoad := false
|
||||
if len(exchangesOverride) > 0 {
|
||||
for y := range exchangesOverride {
|
||||
if strings.EqualFold(configs[x].Name, exchangesOverride[y]) {
|
||||
shouldLoad = true
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
shouldLoad = configs[x].Enabled || bot.Settings.EnableAllExchanges
|
||||
}
|
||||
|
||||
if !shouldLoad {
|
||||
gctlog.Debugf(gctlog.ExchangeSys, "%s: Exchange support: Disabled\n", configs[x].Name)
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(c config.Exchange) {
|
||||
defer wg.Done()
|
||||
|
||||
@@ -9,9 +9,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/bitfinex"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp"
|
||||
)
|
||||
|
||||
// blockedCIExchanges are exchanges that are not able to be tested on CI
|
||||
@@ -415,3 +418,117 @@ func TestGetDefaultConfigurations(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetupExchanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("No enabled exchanges", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := &Engine{
|
||||
Config: &config.Config{Exchanges: []config.Exchange{{Name: testExchange}}},
|
||||
}
|
||||
assert.ErrorIs(t, e.SetupExchanges(), ErrNoExchangesLoaded)
|
||||
})
|
||||
|
||||
t.Run("EnableAllExchanges with specific exchanges set", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := &Engine{
|
||||
Config: &config.Config{},
|
||||
Settings: Settings{
|
||||
CoreSettings: CoreSettings{
|
||||
EnableAllExchanges: true,
|
||||
Exchanges: "Bitstamp,Bitfinex",
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.EqualError(t, e.SetupExchanges(), "cannot enable all exchanges and specific exchanges concurrently")
|
||||
})
|
||||
|
||||
t.Run("Settings dry run toggling", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := &Engine{
|
||||
Config: &config.Config{},
|
||||
Settings: Settings{
|
||||
CoreSettings: CoreSettings{
|
||||
EnableAllPairs: true,
|
||||
EnableAllExchanges: true,
|
||||
},
|
||||
ExchangeTuningSettings: ExchangeTuningSettings{
|
||||
EnableExchangeVerbose: true,
|
||||
EnableExchangeWebsocketSupport: true,
|
||||
EnableExchangeAutoPairUpdates: true,
|
||||
DisableExchangeAutoPairUpdates: true,
|
||||
HTTPUserAgent: "test",
|
||||
HTTPProxy: "test",
|
||||
HTTPTimeout: 1,
|
||||
EnableExchangeHTTPDebugging: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
assert.ErrorIs(t, e.SetupExchanges(), ErrNoExchangesLoaded)
|
||||
assert.False(t, e.Settings.EnableDryRun)
|
||||
e.Settings.CheckParamInteraction = true
|
||||
assert.ErrorIs(t, e.SetupExchanges(), ErrNoExchangesLoaded)
|
||||
assert.True(t, e.Settings.EnableDryRun)
|
||||
})
|
||||
|
||||
// Test that overridden exchange inputs are handled correctly
|
||||
testCases := []struct {
|
||||
name string
|
||||
exchangeString string
|
||||
expectedError string
|
||||
}{
|
||||
{"Invalid exchange pair", "bob|jill", "exchange bob|jill not found"},
|
||||
{"Single invalid exchange", "bob", "exchange bob not found"},
|
||||
{"Mixed valid and invalid exchanges", "bob,bitstamp", "exchange bob not found"},
|
||||
{"Valid exchange", "BiTSTaMp", "no exchanges have been loaded"}, // Proper exchange name, but not loaded
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := &Engine{
|
||||
Config: &config.Config{},
|
||||
Settings: Settings{CoreSettings: CoreSettings{Exchanges: tc.exchangeString}},
|
||||
}
|
||||
assert.ErrorContains(t, e.SetupExchanges(), tc.expectedError)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("Two valid exchanges with exchanges flag toggled", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := &Engine{Config: &config.Config{}}
|
||||
|
||||
exchLoader := func(exch exchange.IBotExchange) {
|
||||
exch.SetDefaults()
|
||||
exch.GetBase().Features.Supports.RESTCapabilities.AutoPairUpdates = false
|
||||
cfg, err := exchange.GetDefaultConfig(context.Background(), exch)
|
||||
require.NoError(t, err)
|
||||
e.Config.Exchanges = append(e.Config.Exchanges, *cfg)
|
||||
}
|
||||
|
||||
e.ExchangeManager = NewExchangeManager()
|
||||
exchLoader(new(bitstamp.Bitstamp))
|
||||
exchLoader(new(bitfinex.Bitfinex))
|
||||
assert.ElementsMatch(t, []string{"Bitstamp", "Bitfinex"}, e.Config.GetEnabledExchanges())
|
||||
|
||||
t.Run("Load specific exchange", func(t *testing.T) {
|
||||
e.Settings.Exchanges = "BiTfInEx"
|
||||
assert.NoError(t, e.SetupExchanges(), "SetupExchanges with a valid exchange should not error")
|
||||
exchanges, err := e.ExchangeManager.GetExchanges()
|
||||
require.NoError(t, err)
|
||||
require.Len(t, exchanges, 1)
|
||||
assert.Equal(t, "Bitfinex", exchanges[0].GetName())
|
||||
})
|
||||
|
||||
t.Run("Load all enabled exchanges", func(t *testing.T) {
|
||||
e.Settings.Exchanges = ""
|
||||
assert.NoError(t, e.SetupExchanges(), "SetupExchanges with all enabled exchanges should not error")
|
||||
exchanges, err := e.ExchangeManager.GetExchanges()
|
||||
require.NoError(t, err)
|
||||
require.Len(t, exchanges, 2)
|
||||
exchangeNames := []string{exchanges[0].GetName(), exchanges[1].GetName()}
|
||||
assert.ElementsMatch(t, []string{"Bitstamp", "Bitfinex"}, exchangeNames)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ type CoreSettings struct {
|
||||
EnableDispatcher bool
|
||||
DispatchMaxWorkerAmount int
|
||||
DispatchJobsLimit int
|
||||
Exchanges string
|
||||
}
|
||||
|
||||
// ExchangeSyncerSettings defines settings for the exchange pair synchronisation
|
||||
|
||||
1
main.go
1
main.go
@@ -96,6 +96,7 @@ func main() {
|
||||
flag.DurationVar(&settings.TradeBufferProcessingInterval, "tradeprocessinginterval", trade.DefaultProcessorIntervalTime, "sets the interval to save trade buffer data to the database")
|
||||
flag.IntVar(&settings.AlertSystemPreAllocationCommsBuffer, "alertbuffer", alert.PreAllocCommsDefaultBuffer, "sets the size of the pre-allocation communications buffer")
|
||||
flag.DurationVar(&settings.ExchangeShutdownTimeout, "exchangeshutdowntimeout", time.Second*10, "sets the maximum amount of time the program will wait for an exchange to shut down gracefully")
|
||||
flag.StringVar(&settings.Exchanges, "exchanges", "", "sets a comma-separated list of exchanges to load. If left empty, all enabled exchanges will be loaded from the config file")
|
||||
|
||||
// Common tuning settings
|
||||
flag.DurationVar(&settings.GlobalHTTPTimeout, "globalhttptimeout", 0, "sets common HTTP timeout value for HTTP requests")
|
||||
|
||||
Reference in New Issue
Block a user