Skip to content

Commit

Permalink
Currency package update (thrasher-corp#247)
Browse files Browse the repository at this point in the history
* Initial currency overhaul before service system implementation

* Remove redundant currency string in orderbook.Base
Unexport lastupdated field in orderbook.Base as it was being instantiated multiple times
Add error handling for process orderbook

*  Remove redundant currency string in ticker.Price
 Unexport lastupdated field in ticker.Price
 Add error handling for process ticker function and fix tests

* Phase Two Update

* Update translations to use map type - thankyou to kempeng for spotting this

* Change pair method name from Display -> Format for better readability

* Fixes misspelling and tests

* Implement requested changes from GloriousCode

* Remove reduntant function and streamlined return in currency_translation.go

* Revert pair method naming conventions

* Change currency naming conventions

* Changed code type to exported Item type with underlying string to reduce complexity

* Added interim orderbook process method to orderbook.Base type

* Changed feebuilder struct field to currency.Pair

* Adds fall over system for backup fx providers

* deprecate function and children and fix linter issue with btcmarkets

* Fixed requested changes

* Fix bug and move mtx for rates

* Fixed after rebase oopsies

* Fix linter issues

* Fixes race conditions in testing functions

* Final phase coinmarketcap update

* fix linter issues

* Implement requested changes

* Adds configuration variables to increase/decrease time durations between updating currency file and fetching new currency rates

* Add a collection of tests to improve codecov

* After rebase oopsy fixes for btse

* Fix requested changes

* fix after rebase oopsies and add more efficient comparison checks within currency pair

* Fix linter issues
  • Loading branch information
shazbert authored and thrasher- committed Mar 19, 2019
1 parent ed760e1 commit 0990f9d
Show file tree
Hide file tree
Showing 189 changed files with 11,975 additions and 8,048 deletions.
2 changes: 1 addition & 1 deletion communications/base/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func (b *Base) GetTicker(exchangeName string) string {
for i := range tickerPrices {
packagedTickers = append(packagedTickers, fmt.Sprintf(
"Currency Pair: %s Ask: %f, Bid: %f High: %f Last: %f Low: %f ATH: %f Volume: %f",
tickerPrices[i].CurrencyPair,
tickerPrices[i].Pair,
tickerPrices[i].Ask,
tickerPrices[i].Bid,
tickerPrices[i].High,
Expand Down
13 changes: 6 additions & 7 deletions communications/base/base_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (c IComm) StageTickerData(exchangeName, assetType string, tickerPrice *tick
TickerStaged[exchangeName][assetType] = make(map[string]ticker.Price)
}

TickerStaged[exchangeName][assetType][tickerPrice.CurrencyPair] = *tickerPrice
TickerStaged[exchangeName][assetType][tickerPrice.Pair.String()] = *tickerPrice
}

// StageOrderbookData stages updated orderbook data for the communications
Expand All @@ -97,12 +97,11 @@ func (c IComm) StageOrderbookData(exchangeName, assetType string, ob *orderbook.
OrderbookStaged[exchangeName][assetType] = make(map[string]Orderbook)
}

_, totalAsks := ob.CalculateTotalAsks()
_, totalBids := ob.CalculateTotalBids()
_, totalAsks := ob.TotalAsksAmount()
_, totalBids := ob.TotalBidsAmount()

OrderbookStaged[exchangeName][assetType][ob.CurrencyPair] = Orderbook{
CurrencyPair: ob.CurrencyPair,
OrderbookStaged[exchangeName][assetType][ob.Pair.String()] = Orderbook{
CurrencyPair: ob.Pair.String(),
TotalAsks: totalAsks,
TotalBids: totalBids,
LastUpdated: ob.LastUpdated.String()}
TotalBids: totalBids}
}
112 changes: 58 additions & 54 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/thrasher-/gocryptotrader/currency"
"github.com/thrasher-/gocryptotrader/currency/forexprovider"
"github.com/thrasher-/gocryptotrader/currency/forexprovider/base"
"github.com/thrasher-/gocryptotrader/currency/pair"
log "github.com/thrasher-/gocryptotrader/logger"
"github.com/thrasher-/gocryptotrader/portfolio"
)
Expand Down Expand Up @@ -114,8 +113,8 @@ type Config struct {

// Deprecated config settings, will be removed at a future date
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat,omitempty"`
FiatDisplayCurrency string `json:"fiatDispayCurrency,omitempty"`
Cryptocurrencies string `json:"cryptocurrencies,omitempty"`
FiatDisplayCurrency currency.Code `json:"fiatDispayCurrency,omitempty"`
Cryptocurrencies currency.Currencies `json:"cryptocurrencies,omitempty"`
SMS *SMSGlobalConfig `json:"smsGlobal,omitempty"`
}

Expand Down Expand Up @@ -143,9 +142,9 @@ type ExchangeConfig struct {
ProxyAddress string `json:"proxyAddress"`
WebsocketURL string `json:"websocketUrl"`
ClientID string `json:"clientId,omitempty"`
AvailablePairs string `json:"availablePairs"`
EnabledPairs string `json:"enabledPairs"`
BaseCurrencies string `json:"baseCurrencies"`
AvailablePairs currency.Pairs `json:"availablePairs"`
EnabledPairs currency.Pairs `json:"enabledPairs"`
BaseCurrencies currency.Currencies `json:"baseCurrencies"`
AssetTypes string `json:"assetTypes"`
SupportsAutoPairUpdates bool `json:"supportsAutoPairUpdates"`
PairsLastUpdated int64 `json:"pairsLastUpdated,omitempty"`
Expand Down Expand Up @@ -178,11 +177,13 @@ type BankTransaction struct {

// CurrencyConfig holds all the information needed for currency related manipulation
type CurrencyConfig struct {
ForexProviders []base.Settings `json:"forexProviders"`
CryptocurrencyProvider CryptocurrencyProvider `json:"cryptocurrencyProvider"`
Cryptocurrencies string `json:"cryptocurrencies"`
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat"`
FiatDisplayCurrency string `json:"fiatDisplayCurrency"`
ForexProviders []base.Settings `json:"forexProviders"`
CryptocurrencyProvider CryptocurrencyProvider `json:"cryptocurrencyProvider"`
Cryptocurrencies currency.Currencies `json:"cryptocurrencies"`
CurrencyPairFormat *CurrencyPairFormatConfig `json:"currencyPairFormat"`
FiatDisplayCurrency currency.Code `json:"fiatDisplayCurrency"`
CurrencyFileUpdateDuration time.Duration `json:"currencyFileUpdateDuration"`
ForeignExchangeUpdateDuration time.Duration `json:"foreignExchangeUpdateDuration"`
}

// CryptocurrencyProvider defines coinmarketcap tools
Expand Down Expand Up @@ -539,10 +540,10 @@ func (c *Config) CheckPairConsistency(exchName string) error {
return err
}

var pairs, pairsRemoved []pair.CurrencyPair
var pairs, pairsRemoved currency.Pairs
update := false
for x := range enabledPairs {
if !pair.Contains(availPairs, enabledPairs[x], true) {
if !availPairs.Contains(enabledPairs[x], true) {
update = true
pairsRemoved = append(pairsRemoved, enabledPairs[x])
continue
Expand All @@ -560,55 +561,58 @@ func (c *Config) CheckPairConsistency(exchName string) error {
}

if len(pairs) == 0 {
exchCfg.EnabledPairs = pair.RandomPairFromPairs(availPairs).Pair().String()
log.Debugf("Exchange %s: No enabled pairs found in available pairs, randomly added %v\n", exchName, exchCfg.EnabledPairs)
exchCfg.EnabledPairs = append(exchCfg.EnabledPairs,
availPairs.GetRandomPair())
log.Debugf("Exchange %s: No enabled pairs found in available pairs, randomly added %v\n",
exchName,
exchCfg.EnabledPairs)
} else {
exchCfg.EnabledPairs = common.JoinStrings(pair.PairsToStringArray(pairs), ",")
exchCfg.EnabledPairs = pairs
}

err = c.UpdateExchangeConfig(&exchCfg)
if err != nil {
return err
}

log.Debugf("Exchange %s: Removing enabled pair(s) %v from enabled pairs as it isn't an available pair", exchName, pair.PairsToStringArray(pairsRemoved))
log.Debugf("Exchange %s: Removing enabled pair(s) %v from enabled pairs as it isn't an available pair",
exchName,
pairsRemoved.Strings())
return nil
}

// SupportsPair returns true or not whether the exchange supports the supplied
// pair
func (c *Config) SupportsPair(exchName string, p pair.CurrencyPair) (bool, error) {
func (c *Config) SupportsPair(exchName string, p currency.Pair) (bool, error) {
pairs, err := c.GetAvailablePairs(exchName)
if err != nil {
return false, err
}
return pair.Contains(pairs, p, false), nil
return pairs.Contains(p, false), nil
}

// GetAvailablePairs returns a list of currency pairs for a specifc exchange
func (c *Config) GetAvailablePairs(exchName string) ([]pair.CurrencyPair, error) {
func (c *Config) GetAvailablePairs(exchName string) (currency.Pairs, error) {
exchCfg, err := c.GetExchangeConfig(exchName)
if err != nil {
return nil, err
}

pairs := pair.FormatPairs(common.SplitStrings(exchCfg.AvailablePairs, ","),
exchCfg.ConfigCurrencyPairFormat.Delimiter,
exchCfg.ConfigCurrencyPairFormat.Index)
return pairs, nil
return exchCfg.AvailablePairs.Format(exchCfg.ConfigCurrencyPairFormat.Delimiter,
exchCfg.ConfigCurrencyPairFormat.Index,
exchCfg.ConfigCurrencyPairFormat.Uppercase), nil
}

// GetEnabledPairs returns a list of currency pairs for a specifc exchange
func (c *Config) GetEnabledPairs(exchName string) ([]pair.CurrencyPair, error) {
func (c *Config) GetEnabledPairs(exchName string) (currency.Pairs, error) {
exchCfg, err := c.GetExchangeConfig(exchName)
if err != nil {
return nil, err
}

pairs := pair.FormatPairs(common.SplitStrings(exchCfg.EnabledPairs, ","),
exchCfg.ConfigCurrencyPairFormat.Delimiter,
exchCfg.ConfigCurrencyPairFormat.Index)
return pairs, nil
return exchCfg.AvailablePairs.Format(exchCfg.ConfigCurrencyPairFormat.Delimiter,
exchCfg.ConfigCurrencyPairFormat.Index,
exchCfg.ConfigCurrencyPairFormat.Uppercase), nil
}

// GetEnabledExchanges returns a list of enabled exchanges
Expand Down Expand Up @@ -758,13 +762,13 @@ func (c *Config) CheckExchangeConfigValues() error {
if exch.Name == "" {
return fmt.Errorf(ErrExchangeNameEmpty, i)
}
if exch.AvailablePairs == "" {
if len(exch.AvailablePairs) == 0 {
return fmt.Errorf(ErrExchangeAvailablePairsEmpty, exch.Name)
}
if exch.EnabledPairs == "" {
if len(exch.EnabledPairs) == 0 {
return fmt.Errorf(ErrExchangeEnabledPairsEmpty, exch.Name)
}
if exch.BaseCurrencies == "" {
if len(exch.BaseCurrencies) == 0 {
return fmt.Errorf(ErrExchangeBaseCurrenciesEmpty, exch.Name)
}
if exch.AuthenticatedAPISupport { // non-fatal error
Expand Down Expand Up @@ -962,12 +966,12 @@ func (c *Config) CheckCurrencyConfigValues() error {
}
}

if c.Currency.Cryptocurrencies == "" {
if c.Cryptocurrencies != "" {
if c.Currency.Cryptocurrencies.Join() == "" {
if c.Cryptocurrencies.Join() != "" {
c.Currency.Cryptocurrencies = c.Cryptocurrencies
c.Cryptocurrencies = ""
c.Cryptocurrencies = nil
} else {
c.Currency.Cryptocurrencies = currency.DefaultCryptoCurrencies
c.Currency.Cryptocurrencies = currency.GetDefaultCryptocurrencies()
}
}

Expand All @@ -983,12 +987,12 @@ func (c *Config) CheckCurrencyConfigValues() error {
}
}

if c.Currency.FiatDisplayCurrency == "" {
if c.FiatDisplayCurrency != "" {
if c.Currency.FiatDisplayCurrency.IsEmpty() {
if c.FiatDisplayCurrency.IsEmpty() {
c.Currency.FiatDisplayCurrency = c.FiatDisplayCurrency
c.FiatDisplayCurrency = ""
c.FiatDisplayCurrency = currency.NewCode("")
} else {
c.Currency.FiatDisplayCurrency = "USD"
c.Currency.FiatDisplayCurrency = currency.USD
}
}
return nil
Expand All @@ -997,24 +1001,24 @@ func (c *Config) CheckCurrencyConfigValues() error {
// RetrieveConfigCurrencyPairs splits, assigns and verifies enabled currency
// pairs either cryptoCurrencies or fiatCurrencies
func (c *Config) RetrieveConfigCurrencyPairs(enabledOnly bool) error {
cryptoCurrencies := common.SplitStrings(c.Cryptocurrencies, ",")
fiatCurrencies := common.SplitStrings(currency.DefaultCurrencies, ",")
cryptoCurrencies := c.Currency.Cryptocurrencies
fiatCurrencies := currency.GetFiatCurrencies()

for x := range c.Exchanges {
if !c.Exchanges[x].Enabled && enabledOnly {
continue
}

baseCurrencies := common.SplitStrings(c.Exchanges[x].BaseCurrencies, ",")
baseCurrencies := c.Exchanges[x].BaseCurrencies
for y := range baseCurrencies {
if !common.StringDataCompare(fiatCurrencies, common.StringToUpper(baseCurrencies[y])) {
fiatCurrencies = append(fiatCurrencies, common.StringToUpper(baseCurrencies[y]))
if !fiatCurrencies.Contains(baseCurrencies[y]) {
fiatCurrencies = append(fiatCurrencies, baseCurrencies[y])
}
}
}

for x := range c.Exchanges {
var pairs []pair.CurrencyPair
var pairs []currency.Pair
var err error
if !c.Exchanges[x].Enabled && enabledOnly {
pairs, err = c.GetEnabledPairs(c.Exchanges[x].Name)
Expand All @@ -1027,20 +1031,20 @@ func (c *Config) RetrieveConfigCurrencyPairs(enabledOnly bool) error {
}

for y := range pairs {
if !common.StringDataCompare(fiatCurrencies, pairs[y].FirstCurrency.Upper().String()) &&
!common.StringDataCompare(cryptoCurrencies, pairs[y].FirstCurrency.Upper().String()) {
cryptoCurrencies = append(cryptoCurrencies, pairs[y].FirstCurrency.Upper().String())
if !fiatCurrencies.Contains(pairs[y].Base) &&
!cryptoCurrencies.Contains(pairs[y].Base) {
cryptoCurrencies = append(cryptoCurrencies, pairs[y].Base)
}

if !common.StringDataCompare(fiatCurrencies, pairs[y].SecondCurrency.Upper().String()) &&
!common.StringDataCompare(cryptoCurrencies, pairs[y].SecondCurrency.Upper().String()) {
cryptoCurrencies = append(cryptoCurrencies, pairs[y].SecondCurrency.Upper().String())
if !fiatCurrencies.Contains(pairs[y].Quote) &&
!cryptoCurrencies.Contains(pairs[y].Quote) {
cryptoCurrencies = append(cryptoCurrencies, pairs[y].Quote)
}
}
}

currency.Update(fiatCurrencies, false)
currency.Update(cryptoCurrencies, true)
currency.UpdateCurrencies(fiatCurrencies, false)
currency.UpdateCurrencies(cryptoCurrencies, true)
return nil
}

Expand Down
28 changes: 15 additions & 13 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"testing"

"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/currency"
log "github.com/thrasher-/gocryptotrader/logger"
)

Expand Down Expand Up @@ -304,8 +304,8 @@ func TestCheckPairConsistency(t *testing.T) {
cfg.Exchanges = append(cfg.Exchanges, ExchangeConfig{
Name: "TestExchange",
Enabled: true,
AvailablePairs: "DOGE_USD,DOGE_AUD",
EnabledPairs: "DOGE_USD,DOGE_AUD,DOGE_BTC",
AvailablePairs: currency.NewPairsFromStrings([]string{"DOGE_USD,DOGE_AUD"}),
EnabledPairs: currency.NewPairsFromStrings([]string{"DOGE_USD,DOGE_AUD,DOGE_BTC"}),
ConfigCurrencyPairFormat: &CurrencyPairFormatConfig{
Uppercase: true,
Delimiter: "_",
Expand All @@ -326,7 +326,7 @@ func TestCheckPairConsistency(t *testing.T) {
t.Error("Test failed. CheckPairConsistency error:", err)
}

tec.EnabledPairs = "DOGE_LTC,BTC_LTC"
tec.EnabledPairs = currency.NewPairsFromStrings([]string{"DOGE_LTC,BTC_LTC"})
err = cfg.UpdateExchangeConfig(&tec)
if err != nil {
t.Error("Test failed. CheckPairConsistency Update config failed, error:", err)
Expand All @@ -347,14 +347,16 @@ func TestSupportsPair(t *testing.T) {
)
}

_, err = cfg.SupportsPair("asdf", pair.NewCurrencyPair("BTC", "USD"))
_, err = cfg.SupportsPair("asdf",
currency.NewPair(currency.BTC, currency.USD))
if err == nil {
t.Error(
"Test failed. TestSupportsPair. Non-existent exchange returned nil error",
)
}

_, err = cfg.SupportsPair("Bitfinex", pair.NewCurrencyPair("BTC", "USD"))
_, err = cfg.SupportsPair("Bitfinex",
currency.NewPair(currency.BTC, currency.USD))
if err != nil {
t.Errorf(
"Test failed. TestSupportsPair. Incorrect values. Err: %s", err,
Expand Down Expand Up @@ -687,23 +689,23 @@ func TestCheckExchangeConfigValues(t *testing.T) {
)
}

checkExchangeConfigValues.Exchanges[0].BaseCurrencies = ""
checkExchangeConfigValues.Exchanges[0].BaseCurrencies = currency.NewCurrenciesFromStringArray([]string{""})
err = checkExchangeConfigValues.CheckExchangeConfigValues()
if err == nil {
t.Errorf(
"Test failed. checkExchangeConfigValues.CheckExchangeConfigValues Error",
)
}

checkExchangeConfigValues.Exchanges[0].EnabledPairs = ""
checkExchangeConfigValues.Exchanges[0].EnabledPairs = currency.NewPairsFromStrings([]string{""})
err = checkExchangeConfigValues.CheckExchangeConfigValues()
if err == nil {
t.Errorf(
"Test failed. checkExchangeConfigValues.CheckExchangeConfigValues Error",
)
}

checkExchangeConfigValues.Exchanges[0].AvailablePairs = ""
checkExchangeConfigValues.Exchanges[0].AvailablePairs = currency.NewPairsFromStrings([]string{""})
err = checkExchangeConfigValues.CheckExchangeConfigValues()
if err == nil {
t.Errorf(
Expand All @@ -719,7 +721,7 @@ func TestCheckExchangeConfigValues(t *testing.T) {
)
}

checkExchangeConfigValues.Cryptocurrencies = ""
checkExchangeConfigValues.Cryptocurrencies = currency.NewCurrenciesFromStringArray([]string{""})
err = checkExchangeConfigValues.CheckExchangeConfigValues()
if err == nil {
t.Errorf(
Expand All @@ -728,7 +730,7 @@ func TestCheckExchangeConfigValues(t *testing.T) {
}

checkExchangeConfigValues.Exchanges = checkExchangeConfigValues.Exchanges[:0]
checkExchangeConfigValues.Cryptocurrencies = "TESTYTEST"
checkExchangeConfigValues.Cryptocurrencies = currency.NewCurrenciesFromStringArray([]string{"TESTYTEST"})
err = checkExchangeConfigValues.CheckExchangeConfigValues()
if err == nil {
t.Errorf(
Expand Down Expand Up @@ -924,12 +926,12 @@ func TestUpdateConfig(t *testing.T) {
t.Fatalf("Test failed. Error should of been thrown for invalid path")
}

newCfg.Currency.Cryptocurrencies = ""
newCfg.Currency.Cryptocurrencies = currency.NewCurrenciesFromStringArray([]string{""})
err = c.UpdateConfig(ConfigTestFile, newCfg)
if err != nil {
t.Errorf("Test failed. %s", err)
}
if c.Currency.Cryptocurrencies == "" {
if c.Currency.Cryptocurrencies.Join() == "" {
t.Fatalf("Test failed. Cryptocurrencies should have been repopulated")
}
}
Expand Down
Loading

0 comments on commit 0990f9d

Please sign in to comment.