engine/exchanges: Add exchange currency state subsystem (#774)

* state: Add management system (init)

* linter: fix

* engine: gofmt

* gct: after merge fixup

* documentation: add

* rpc: implement services for testing

* gctcli: gofmt state_management.go

* documentation: reinstate lost information

* state: Add pair check to determine trading operation

* exchanges: add interface for specific state scoped subsystem functionality

* engine/order_man: reduce code footprint using new method

* RPC: implement pair trading request and change exported name to something specific to state

* engine: add tests

* engine: Add to withdraw manager

* documentation: reinstate soxipy in contrib. list

* engine: const fake name

* Glorious: NITERINOS

* merge: fix issues

* engine: csm incorporate service name into log output

* engine: fix linter issues

* gct: fix tests

* currencystate: remove management type

* rpc: fix tests

* backtester: fix tests

* Update engine/currency_state_manager.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update engine/currency_state_manager.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/currencystate/currency_state.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/alert/alert.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/alert/alert.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* config: integrate with config and remove flag delay adjustment

* gctcli: fix issues after name changes

* engine: gofmt manager file

* Update engine/rpcserver.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* engine: Add enable/disable manager functions, add default popoulation for potential assets

* linter: fix

* engine/test: bump subsystem count

* Update engine/currency_state_manager.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* Update exchanges/bithumb/bithumb.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits addressed

* alert: fix commenting for its generalized purpose

* glorious: nits

* engine: use standard string in log output

* bitfinex: apply patch, thanks @thrasher-

* bitfinex: fix spelling

* engine/currencystate: Add logs/fix logs

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
This commit is contained in:
Ryan O'Hara-Reid
2021-09-27 13:33:49 +10:00
committed by GitHub
parent 1d7c656665
commit 5dfbbf84de
48 changed files with 4685 additions and 1110 deletions

View File

@@ -28,6 +28,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/account"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/binance"
"github.com/thrasher-corp/gocryptotrader/exchanges/currencystate"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
@@ -43,6 +44,7 @@ const (
unexpectedLackOfError = "unexpected lack of error"
migrationsFolder = "migrations"
databaseFolder = "database"
fakeExchangeName = "fake"
)
// fExchange is a fake exchange with function overrides
@@ -53,7 +55,7 @@ type fExchange struct {
func (f fExchange) GetHistoricCandles(ctx context.Context, p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{
Exchange: "fake",
Exchange: fakeExchangeName,
Pair: p,
Asset: a,
Interval: interval,
@@ -72,7 +74,7 @@ func (f fExchange) GetHistoricCandles(ctx context.Context, p currency.Pair, a as
func (f fExchange) GetHistoricCandlesExtended(ctx context.Context, p currency.Pair, a asset.Item, timeStart, _ time.Time, interval kline.Interval) (kline.Item, error) {
return kline.Item{
Exchange: "fake",
Exchange: fakeExchangeName,
Pair: p,
Asset: a,
Interval: interval,
@@ -122,6 +124,36 @@ func (f fExchange) UpdateAccountInfo(ctx context.Context, a asset.Item) (account
}, nil
}
// GetCurrencyStateSnapshot overrides interface function
func (f fExchange) GetCurrencyStateSnapshot() ([]currencystate.Snapshot, error) {
return []currencystate.Snapshot{
{
Code: currency.BTC,
Asset: asset.Spot,
},
}, nil
}
// CanTradePair overrides interface function
func (f fExchange) CanTradePair(p currency.Pair, a asset.Item) error {
return nil
}
// CanTrade overrides interface function
func (f fExchange) CanTrade(c currency.Code, a asset.Item) error {
return nil
}
// CanWithdraw overrides interface function
func (f fExchange) CanWithdraw(c currency.Code, a asset.Item) error {
return nil
}
// CanDeposit overrides interface function
func (f fExchange) CanDeposit(c currency.Code, a asset.Item) error {
return nil
}
// Sets up everything required to run any function inside rpcserver
// Only use if you require a database, this makes tests slow
func RPCTestSetup(t *testing.T) *Engine {
@@ -238,7 +270,7 @@ func TestGetSavedTrades(t *testing.T) {
t.Error(err)
}
_, err = s.GetSavedTrades(context.Background(), &gctrpc.GetSavedTradesRequest{
Exchange: "fake",
Exchange: fakeExchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: currency.DashDelimiter,
Base: currency.BTC.String(),
@@ -849,7 +881,7 @@ func TestGetRecentTrades(t *testing.T) {
t.Error(err)
}
_, err = s.GetRecentTrades(context.Background(), &gctrpc.GetSavedTradesRequest{
Exchange: "fake",
Exchange: fakeExchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: currency.DashDelimiter,
Base: currency.BTC.String(),
@@ -897,7 +929,7 @@ func TestGetHistoricTrades(t *testing.T) {
t.Error(err)
}
err = s.GetHistoricTrades(&gctrpc.GetSavedTradesRequest{
Exchange: "fake",
Exchange: fakeExchangeName,
Pair: &gctrpc.CurrencyPair{
Delimiter: currency.DashDelimiter,
Base: currency.BTC.String(),
@@ -934,7 +966,7 @@ func TestGetAccountInfo(t *testing.T) {
t.Fatal(err)
}
b := exch.GetBase()
b.Name = "fake"
b.Name = fakeExchangeName
b.Enabled = true
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.Spot] = &currency.PairStore{
@@ -945,7 +977,7 @@ func TestGetAccountInfo(t *testing.T) {
}
em.Add(fakeExchange)
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()})
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Spot.String()})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
@@ -959,7 +991,7 @@ func TestUpdateAccountInfo(t *testing.T) {
t.Fatal(err)
}
b := exch.GetBase()
b.Name = "fake"
b.Name = fakeExchangeName
b.Enabled = true
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.Spot] = &currency.PairStore{
@@ -971,18 +1003,18 @@ func TestUpdateAccountInfo(t *testing.T) {
em.Add(fakeExchange)
s := RPCServer{Engine: &Engine{ExchangeManager: em}}
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Spot.String()})
_, err = s.GetAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Spot.String()})
if !errors.Is(err, nil) {
t.Errorf("received '%v', expected '%v'", err, nil)
}
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: "fake", AssetType: asset.Futures.String()})
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{Exchange: fakeExchangeName, AssetType: asset.Futures.String()})
if !errors.Is(err, errAssetTypeDisabled) {
t.Errorf("received '%v', expected '%v'", err, errAssetTypeDisabled)
}
_, err = s.UpdateAccountInfo(context.Background(), &gctrpc.GetAccountInfoRequest{
Exchange: "fake",
Exchange: fakeExchangeName,
AssetType: asset.Spot.String(),
})
if !errors.Is(err, nil) {
@@ -1862,3 +1894,87 @@ func TestUpdateDataHistoryJobPrerequisite(t *testing.T) {
t.Errorf("received %v, expected %v", err, nil)
}
}
func TestCurrencyStateGetAll(t *testing.T) {
t.Parallel()
_, err := (&RPCServer{Engine: &Engine{}}).CurrencyStateGetAll(context.Background(),
&gctrpc.CurrencyStateGetAllRequest{Exchange: fakeExchangeName})
if !errors.Is(err, ErrSubSystemNotStarted) {
t.Errorf("received %v, expected %v", err, ErrSubSystemNotStarted)
}
}
func TestCurrencyStateWithdraw(t *testing.T) {
t.Parallel()
_, err := (&RPCServer{
Engine: &Engine{},
}).CurrencyStateWithdraw(context.Background(),
&gctrpc.CurrencyStateWithdrawRequest{
Exchange: "wow"})
if !errors.Is(err, ErrSubSystemNotStarted) {
t.Fatalf("received: %v, but expected: %v", err, ErrSubSystemNotStarted)
}
}
func TestCurrencyStateDeposit(t *testing.T) {
t.Parallel()
_, err := (&RPCServer{
Engine: &Engine{},
}).CurrencyStateDeposit(context.Background(),
&gctrpc.CurrencyStateDepositRequest{Exchange: "wow"})
if !errors.Is(err, ErrSubSystemNotStarted) {
t.Fatalf("received: %v, but expected: %v", err, ErrSubSystemNotStarted)
}
}
func TestCurrencyStateTrading(t *testing.T) {
t.Parallel()
_, err := (&RPCServer{
Engine: &Engine{},
}).CurrencyStateTrading(context.Background(),
&gctrpc.CurrencyStateTradingRequest{Exchange: "wow"})
if !errors.Is(err, ErrSubSystemNotStarted) {
t.Fatalf("received: %v, but expected: %v", err, ErrSubSystemNotStarted)
}
}
func TestCurrencyStateTradingPair(t *testing.T) {
t.Parallel()
em := SetupExchangeManager()
exch, err := em.NewExchangeByName(testExchange)
if err != nil {
t.Fatal(err)
}
b := exch.GetBase()
b.Name = fakeExchangeName
b.Enabled = true
cp, err := currency.NewPairFromString("btc-usd")
if err != nil {
t.Fatal(err)
}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.Spot] = &currency.PairStore{
AssetEnabled: convert.BoolPtr(true),
ConfigFormat: &currency.PairFormat{},
Available: currency.Pairs{cp},
Enabled: currency.Pairs{cp},
}
fakeExchange := fExchange{
IBotExchange: exch,
}
em.Add(fakeExchange)
s := RPCServer{Engine: &Engine{ExchangeManager: em,
currencyStateManager: &CurrencyStateManager{started: 1, iExchangeManager: em}}}
_, err = s.CurrencyStateTradingPair(context.Background(),
&gctrpc.CurrencyStateTradingPairRequest{
Exchange: fakeExchangeName,
Pair: "btc-usd",
Asset: "spot",
})
if !errors.Is(err, nil) {
t.Fatalf("received: %v, but expected: %v", err, nil)
}
}