mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-16 23:16:48 +00:00
* orderbook: export orderbook nodes for external strategy inspection * orderbook: Add in methods for locking and unlocking multiple books at the same time e.g. book1.LockWith(book2); defer book1.UnlockWith(book2) * include waiting functionality for depth change alert * backtester: add word. * log: include logger changes to impl with downstream integration * engine: reduce params for loading exchange * assort: rm verbose in tests, change wording in ob, expose sync.waitgroup for ext. sync options * ticker: reduce map look ups and contention when using RW mutex when there are over 80% writes adds find last function to get the latest rate * engine/syncmanager: add in waitgroup for step over for external package calls * cleaup * engine: linter fix * currency/fx: include all references to fiat currencies to default * orderbook: Add in fields to Unsafe type for strategies to detect potential out of sync book operations * syncmanager: changed config variable to display correct time * ordermanager: Add time when none provided * currency/manager: update getasset param to get enabled assets for minor optimizations * ftx: use get all wallet balances for a better accounts breakdown * orderbook: unlock in reverse order * bithumb: fixes bug on market buy and sell orders * bithumb: fix bug for nonce is also time window sensitive * bithumb: get orders add required parameter * bithumb: Add asset type to account struct * currency: improve log output when checking currency and it fails * bithumb: Add error return on incomplete pair * ticker:unexport all service related methods * ticker/currency: fixes * orderbook: fix comment * engine: revert variable name in LoadExchange method * sync_manager: fix panic when enabling disabling manager * engine: fix naming convention of exported function and comments * engine: update comment * orderbook: fix comment for unsafe type
158 lines
3.9 KiB
Go
158 lines
3.9 KiB
Go
package base
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/thrasher-corp/gocryptotrader/common"
|
|
"github.com/thrasher-corp/gocryptotrader/log"
|
|
)
|
|
|
|
// IFXProvider enforces standard functions for all foreign exchange providers
|
|
// supported in GoCryptoTrader
|
|
type IFXProvider interface {
|
|
Setup(config Settings) error
|
|
GetRates(baseCurrency, symbols string) (map[string]float64, error)
|
|
GetName() string
|
|
IsEnabled() bool
|
|
IsPrimaryProvider() bool
|
|
GetSupportedCurrencies() ([]string, error)
|
|
}
|
|
|
|
// FXHandler defines a full suite of FX data providers with failure backup with
|
|
// unsupported currency shunt procedure
|
|
type FXHandler struct {
|
|
Primary Provider
|
|
Support []Provider
|
|
mtx sync.Mutex
|
|
}
|
|
|
|
// Provider defines a singular foreign exchange provider with its supported
|
|
// currencies to cross reference request currencies and if not supported shunt
|
|
// request traffic to and from other providers so that we can maintain full
|
|
// currency list integration
|
|
type Provider struct {
|
|
Provider IFXProvider
|
|
SupportedCurrencies []string
|
|
}
|
|
|
|
// GetNewRate access rates by predetermined logic based on how a provider
|
|
// handles requests
|
|
func (p *Provider) GetNewRate(base string, currencies []string) (map[string]float64, error) {
|
|
if !p.Provider.IsEnabled() {
|
|
return nil, fmt.Errorf("provider %s is not enabled",
|
|
p.Provider.GetName())
|
|
}
|
|
|
|
switch p.Provider.GetName() {
|
|
case "ExchangeRates":
|
|
return p.Provider.GetRates(base, "") // Zero value to get all rates
|
|
|
|
default:
|
|
return p.Provider.GetRates(base, strings.Join(currencies, ","))
|
|
}
|
|
}
|
|
|
|
// CheckCurrencies cross references supplied currencies with exchange supported
|
|
// currencies, if there are any currencies not supported it returns a list
|
|
// to pass on to the next provider
|
|
func (p Provider) CheckCurrencies(currencies []string) []string {
|
|
var spillOver []string
|
|
for _, c := range currencies {
|
|
if !common.StringDataCompareInsensitive(p.SupportedCurrencies, c) {
|
|
spillOver = append(spillOver, c)
|
|
}
|
|
}
|
|
return spillOver
|
|
}
|
|
|
|
// GetCurrencyData returns currency data from enabled FX providers
|
|
func (f *FXHandler) GetCurrencyData(baseCurrency string, currencies []string) (map[string]float64, error) {
|
|
var fullRange = currencies
|
|
|
|
if !common.StringDataCompareInsensitive(currencies, baseCurrency) {
|
|
fullRange = append(fullRange, baseCurrency)
|
|
}
|
|
|
|
f.mtx.Lock()
|
|
defer f.mtx.Unlock()
|
|
|
|
if f.Primary.Provider == nil {
|
|
return nil, errors.New("primary foreign exchange provider details not set")
|
|
}
|
|
|
|
shunt := f.Primary.CheckCurrencies(fullRange)
|
|
rates, err := f.Primary.GetNewRate(baseCurrency, currencies)
|
|
if err != nil {
|
|
return f.backupGetRate(baseCurrency, currencies)
|
|
}
|
|
|
|
if len(shunt) != 0 {
|
|
return rates, nil
|
|
}
|
|
|
|
rateNew, err := f.backupGetRate(baseCurrency, shunt)
|
|
if err != nil {
|
|
log.Warnf(log.Global, "%s and subsequent providers, failed to update rate map for currencies %v %v",
|
|
f.Primary.Provider.GetName(),
|
|
shunt,
|
|
err)
|
|
}
|
|
|
|
for key, val := range rateNew {
|
|
rates[key] = val
|
|
}
|
|
return rates, nil
|
|
}
|
|
|
|
// backupGetRate uses the currencies that are supported and falls through, and
|
|
// errors when unsupported currency found
|
|
func (f *FXHandler) backupGetRate(base string, currencies []string) (map[string]float64, error) {
|
|
if f.Support == nil {
|
|
return nil, errors.New("no supporting foreign exchange providers set")
|
|
}
|
|
|
|
var shunt []string
|
|
rate := make(map[string]float64)
|
|
|
|
for i := range f.Support {
|
|
if len(shunt) != 0 {
|
|
shunt = f.Support[i].CheckCurrencies(shunt)
|
|
newRate, err := f.Support[i].GetNewRate(base, shunt)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for k, v := range newRate {
|
|
rate[k] = v
|
|
}
|
|
|
|
if len(shunt) != 0 {
|
|
continue
|
|
}
|
|
|
|
return rate, nil
|
|
}
|
|
|
|
shunt = f.Support[i].CheckCurrencies(currencies)
|
|
newRate, err := f.Support[i].GetNewRate(base, currencies)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
|
|
for k, v := range newRate {
|
|
rate[k] = v
|
|
}
|
|
|
|
if len(shunt) != 0 {
|
|
continue
|
|
}
|
|
|
|
return rate, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("currencies %s not supported", shunt)
|
|
}
|