forked from thrasher-corp/gocryptotrader
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add dynamic loading/unloading and reloading of exchanges
- Loading branch information
Showing
10 changed files
with
467 additions
and
183 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,224 @@ | ||
package main | ||
|
||
import ( | ||
"errors" | ||
"log" | ||
|
||
"github.com/thrasher-/gocryptotrader/common" | ||
exchange "github.com/thrasher-/gocryptotrader/exchanges" | ||
"github.com/thrasher-/gocryptotrader/exchanges/anx" | ||
"github.com/thrasher-/gocryptotrader/exchanges/bitfinex" | ||
"github.com/thrasher-/gocryptotrader/exchanges/bitstamp" | ||
"github.com/thrasher-/gocryptotrader/exchanges/bittrex" | ||
"github.com/thrasher-/gocryptotrader/exchanges/btcc" | ||
"github.com/thrasher-/gocryptotrader/exchanges/btcmarkets" | ||
"github.com/thrasher-/gocryptotrader/exchanges/coinut" | ||
"github.com/thrasher-/gocryptotrader/exchanges/gdax" | ||
"github.com/thrasher-/gocryptotrader/exchanges/huobi" | ||
"github.com/thrasher-/gocryptotrader/exchanges/itbit" | ||
"github.com/thrasher-/gocryptotrader/exchanges/kraken" | ||
"github.com/thrasher-/gocryptotrader/exchanges/lakebtc" | ||
"github.com/thrasher-/gocryptotrader/exchanges/liqui" | ||
"github.com/thrasher-/gocryptotrader/exchanges/localbitcoins" | ||
"github.com/thrasher-/gocryptotrader/exchanges/okcoin" | ||
"github.com/thrasher-/gocryptotrader/exchanges/poloniex" | ||
"github.com/thrasher-/gocryptotrader/exchanges/wex" | ||
) | ||
|
||
// vars related to exchange functions | ||
var ( | ||
ErrNoExchangesLoaded = errors.New("no exchanges have been loaded") | ||
ErrExchangeNotFound = errors.New("exchange not found") | ||
ErrExchangeAlreadyLoaded = errors.New("exchange already loaded") | ||
ErrExchangeFailedToLoad = errors.New("exchange failed to load") | ||
) | ||
|
||
// CheckExchangeExists returns true whether or not an exchange has already | ||
// been loaded | ||
func CheckExchangeExists(exchName string) bool { | ||
for x := range bot.exchanges { | ||
if common.StringToLower(bot.exchanges[x].GetName()) == common.StringToLower(exchName) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
|
||
// GetExchangeByName returns an exchange given an exchange name | ||
func GetExchangeByName(exchName string) exchange.IBotExchange { | ||
for x := range bot.exchanges { | ||
if common.StringToLower(bot.exchanges[x].GetName()) == common.StringToLower(exchName) { | ||
return bot.exchanges[x] | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// ReloadExchange loads an exchange config by name | ||
func ReloadExchange(name string) error { | ||
nameLower := common.StringToLower(name) | ||
|
||
if len(bot.exchanges) == 0 { | ||
return ErrNoExchangesLoaded | ||
} | ||
|
||
if !CheckExchangeExists(nameLower) { | ||
return ErrExchangeNotFound | ||
} | ||
|
||
exchCfg, err := bot.config.GetExchangeConfig(name) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
e := GetExchangeByName(nameLower) | ||
e.Setup(exchCfg) | ||
log.Printf("%s exchange reloaded successfully.\n", name) | ||
return nil | ||
} | ||
|
||
// UnloadExchange unloads an exchange by | ||
func UnloadExchange(name string) error { | ||
nameLower := common.StringToLower(name) | ||
|
||
if len(bot.exchanges) == 0 { | ||
return ErrNoExchangesLoaded | ||
} | ||
|
||
if !CheckExchangeExists(nameLower) { | ||
return ErrExchangeNotFound | ||
} | ||
|
||
exchCfg, err := bot.config.GetExchangeConfig(name) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
exchCfg.Enabled = false | ||
err = bot.config.UpdateExchangeConfig(exchCfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for x := range bot.exchanges { | ||
if bot.exchanges[x].GetName() == name { | ||
bot.exchanges[x].SetEnabled(false) | ||
bot.exchanges = append(bot.exchanges[:x], bot.exchanges[x+1:]...) | ||
return nil | ||
} | ||
} | ||
|
||
return ErrExchangeNotFound | ||
} | ||
|
||
// LoadExchange loads an exchange by name | ||
func LoadExchange(name string) error { | ||
nameLower := common.StringToLower(name) | ||
var exch exchange.IBotExchange | ||
|
||
if len(bot.exchanges) > 0 { | ||
if CheckExchangeExists(nameLower) { | ||
return ErrExchangeAlreadyLoaded | ||
} | ||
} | ||
|
||
switch nameLower { | ||
case "anx": | ||
exch = new(anx.ANX) | ||
case "bitfinex": | ||
exch = new(bitfinex.Bitfinex) | ||
case "bitstamp": | ||
exch = new(bitstamp.Bitstamp) | ||
case "bittrex": | ||
exch = new(bittrex.Bittrex) | ||
case "btcc": | ||
exch = new(btcc.BTCC) | ||
case "btc markets": | ||
exch = new(btcmarkets.BTCMarkets) | ||
case "coinut": | ||
exch = new(coinut.COINUT) | ||
case "gdax": | ||
exch = new(gdax.GDAX) | ||
case "gemini": | ||
exch = new(gdax.GDAX) | ||
case "huobi": | ||
exch = new(huobi.HUOBI) | ||
case "itbit": | ||
exch = new(itbit.ItBit) | ||
case "kraken": | ||
exch = new(kraken.Kraken) | ||
case "lakebtc": | ||
exch = new(lakebtc.LakeBTC) | ||
case "liqui": | ||
exch = new(liqui.Liqui) | ||
case "localbitcoins": | ||
exch = new(localbitcoins.LocalBitcoins) | ||
case "okcoin china": | ||
exch = new(okcoin.OKCoin) | ||
case "okcoin international": | ||
exch = new(okcoin.OKCoin) | ||
case "poloniex": | ||
exch = new(poloniex.Poloniex) | ||
case "wex": | ||
exch = new(wex.WEX) | ||
default: | ||
return ErrExchangeNotFound | ||
} | ||
|
||
if exch == nil { | ||
return ErrExchangeFailedToLoad | ||
} | ||
|
||
exch.SetDefaults() | ||
bot.exchanges = append(bot.exchanges, exch) | ||
exchCfg, err := bot.config.GetExchangeConfig(name) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
exchCfg.Enabled = true | ||
exch.Setup(exchCfg) | ||
return nil | ||
} | ||
|
||
// SetupExchanges sets up the exchanges used by the bot | ||
func SetupExchanges() { | ||
for _, exch := range bot.config.Exchanges { | ||
if CheckExchangeExists(exch.Name) { | ||
e := GetExchangeByName(exch.Name) | ||
if e == nil { | ||
log.Println(ErrExchangeNotFound) | ||
continue | ||
} | ||
|
||
err := ReloadExchange(exch.Name) | ||
if err != nil { | ||
log.Printf("ReloadExchange %s failed: %s", exch.Name, err) | ||
continue | ||
} | ||
|
||
if !e.IsEnabled() { | ||
UnloadExchange(exch.Name) | ||
continue | ||
} | ||
return | ||
|
||
} | ||
if !exch.Enabled { | ||
log.Printf("%s: Exchange support: Disabled", exch.Name) | ||
continue | ||
} else { | ||
err := LoadExchange(exch.Name) | ||
if err != nil { | ||
log.Printf("LoadExchange %s failed: %s", exch.Name, err) | ||
continue | ||
} | ||
} | ||
log.Printf( | ||
"%s: Exchange support: Enabled (Authenticated API support: %s - Verbose mode: %s).\n", | ||
exch.Name, | ||
common.IsEnabled(exch.AuthenticatedAPISupport), | ||
common.IsEnabled(exch.Verbose), | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
package main | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/thrasher-/gocryptotrader/config" | ||
) | ||
|
||
var testSetup = false | ||
|
||
func SetupTest(t *testing.T) { | ||
if !testSetup { | ||
bot.config = &config.Cfg | ||
err := bot.config.LoadConfig("./testdata/configtest.json") | ||
if err != nil { | ||
t.Fatalf("Test failed. SetupTest: Failed to load config: %s", err) | ||
} | ||
testSetup = true | ||
} | ||
|
||
if CheckExchangeExists("Bitfinex") { | ||
return | ||
} | ||
err := LoadExchange("Bitfinex") | ||
if err != nil { | ||
t.Errorf("Test failed. SetupTest: Failed to load exchange: %s", err) | ||
} | ||
} | ||
|
||
func CleanupTest(t *testing.T) { | ||
if !CheckExchangeExists("Bitfinex") { | ||
return | ||
} | ||
|
||
err := UnloadExchange("Bitfinex") | ||
if err != nil { | ||
t.Fatalf("Test failed. CleanupTest: Failed to unload exchange: %s", | ||
err) | ||
} | ||
} | ||
|
||
func TestCheckExchangeExists(t *testing.T) { | ||
SetupTest(t) | ||
|
||
if !CheckExchangeExists("Bitfinex") { | ||
t.Errorf("Test failed. TestGetExchangeExists: Unable to find exchange") | ||
} | ||
|
||
if CheckExchangeExists("Asdsad") { | ||
t.Errorf("Test failed. TestGetExchangeExists: Non-existant exchange found") | ||
} | ||
|
||
CleanupTest(t) | ||
} | ||
|
||
func TestGetExchangeByName(t *testing.T) { | ||
SetupTest(t) | ||
|
||
exch := GetExchangeByName("Bitfinex") | ||
if exch == nil { | ||
t.Errorf("Test failed. TestGetExchangeByName: Failed to get exchange") | ||
} | ||
|
||
if !exch.IsEnabled() { | ||
t.Errorf("Test failed. TestGetExchangeByName: Unexpected result") | ||
} | ||
|
||
exch.SetEnabled(false) | ||
bfx := GetExchangeByName("Bitfinex") | ||
if bfx.IsEnabled() { | ||
t.Errorf("Test failed. TestGetExchangeByName: Unexpected result") | ||
} | ||
|
||
if exch.GetName() != "Bitfinex" { | ||
t.Errorf("Test failed. TestGetExchangeByName: Unexpected result") | ||
} | ||
|
||
exch = GetExchangeByName("Asdasd") | ||
if exch != nil { | ||
t.Errorf("Test failed. TestGetExchangeByName: Non-existant exchange found") | ||
} | ||
|
||
CleanupTest(t) | ||
} | ||
|
||
func TestReloadExchange(t *testing.T) { | ||
SetupTest(t) | ||
|
||
err := ReloadExchange("asdf") | ||
if err != ErrExchangeNotFound { | ||
t.Errorf("Test failed. TestReloadExchange: Incorrect result: %s", | ||
err) | ||
} | ||
|
||
err = ReloadExchange("Bitfinex") | ||
if err != nil { | ||
t.Errorf("Test failed. TestReloadExchange: Incorrect result: %s", | ||
err) | ||
} | ||
|
||
CleanupTest(t) | ||
|
||
err = ReloadExchange("asdf") | ||
if err != ErrNoExchangesLoaded { | ||
t.Errorf("Test failed. TestReloadExchange: Incorrect result: %s", | ||
err) | ||
} | ||
} | ||
|
||
func TestUnloadExchange(t *testing.T) { | ||
SetupTest(t) | ||
|
||
err := UnloadExchange("asdf") | ||
if err != ErrExchangeNotFound { | ||
t.Errorf("Test failed. TestUnloadExchange: Incorrect result: %s", | ||
err) | ||
} | ||
|
||
err = UnloadExchange("Bitfinex") | ||
if err != nil { | ||
t.Errorf("Test failed. TestUnloadExchange: Failed to get exchange. %s", | ||
err) | ||
} | ||
|
||
err = UnloadExchange("asdf") | ||
if err != ErrNoExchangesLoaded { | ||
t.Errorf("Test failed. TestUnloadExchange: Incorrect result: %s", | ||
err) | ||
} | ||
|
||
CleanupTest(t) | ||
} | ||
|
||
func TestSetupExchanges(t *testing.T) { | ||
SetupTest(t) | ||
SetupExchanges() | ||
CleanupTest(t) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.