Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exchanges/wrappers: shift bespoke fetch ticker, orderbook and accountinfo #1440

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backtester/eventhandlers/exchange/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ func TestExecuteOrder(t *testing.T) {

p := currency.NewPair(currency.BTC, currency.USDT)
a := asset.Spot
_, err = exch.FetchOrderbook(context.Background(), p, a)
_, err = exch.UpdateOrderbook(context.Background(), p, a)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -403,7 +403,7 @@ func TestExecuteOrderBuySellSizeLimit(t *testing.T) {
}
p := currency.NewPair(currency.BTC, currency.AUD)
a := asset.Spot
_, err = exch.FetchOrderbook(context.Background(), p, a)
_, err = exch.UpdateOrderbook(context.Background(), p, a)
if err != nil {
t.Fatal(err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestCalculateSlippageByOrderbook(t *testing.T) {
t.Fatal(err)
}
cp := currency.NewPair(currency.BTC, currency.USD)
ob, err := b.FetchOrderbook(context.Background(), cp, asset.Spot)
ob, err := b.UpdateOrderbook(context.Background(), cp, asset.Spot)
if err != nil {
t.Error(err)
}
Expand Down
33 changes: 0 additions & 33 deletions cmd/exchange_template/wrapper_file.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -266,24 +266,6 @@ func ({{.Variable}} *{{.CapitalName}}) UpdateTickers(ctx context.Context, assetT
return nil
}

// FetchTicker returns the ticker for a currency pair
func ({{.Variable}} *{{.CapitalName}}) FetchTicker(ctx context.Context, p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
tickerNew, err := ticker.GetTicker({{.Variable}}.Name, p, assetType)
if err != nil {
return {{.Variable}}.UpdateTicker(ctx, p, assetType)
}
return tickerNew, nil
}

// FetchOrderbook returns orderbook base on the currency pair
func ({{.Variable}} *{{.CapitalName}}) FetchOrderbook(ctx context.Context, pair currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
ob, err := orderbook.Get({{.Variable}}.Name, pair, assetType)
if err != nil {
return {{.Variable}}.UpdateOrderbook(ctx, pair, assetType)
}
return ob, nil
}

// UpdateOrderbook updates and returns the orderbook for a currency pair
func ({{.Variable}} *{{.CapitalName}}) UpdateOrderbook(ctx context.Context, pair currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
book := &orderbook.Base{
Expand Down Expand Up @@ -332,21 +314,6 @@ func ({{.Variable}} *{{.CapitalName}}) UpdateAccountInfo(ctx context.Context, as
return account.Holdings{}, common.ErrNotYetImplemented
}

// FetchAccountInfo retrieves balances for all enabled currencies
func ({{.Variable}} *{{.CapitalName}}) FetchAccountInfo(ctx context.Context, assetType asset.Item) (account.Holdings, error) {
// Example implementation below:
// creds, err := {{.Variable}}.GetCredentials(ctx)
// if err != nil {
// return account.Holdings{}, err
// }
// acc, err := account.GetHoldings({{.Variable}}.Name, creds, assetType)
// if err != nil {
// return {{.Variable}}.UpdateAccountInfo(ctx, assetType)
// }
// return acc, nil
return account.Holdings{}, common.ErrNotYetImplemented
}

// GetFundingHistory returns funding history, deposits and
// withdrawals
func ({{.Variable}} *{{.CapitalName}}) GetAccountFundingHistory(ctx context.Context) ([]exchange.FundingHistory, error) {
Expand Down
32 changes: 16 additions & 16 deletions cmd/exchange_wrapper_issues/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -349,60 +349,60 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
log.Printf("Executing wrappers for %v %v %v", base.GetName(), assetTypes[i], p)

if !authenticatedOnly {
var fetchTickerResponse *ticker.Price
fetchTickerResponse, err = e.FetchTicker(context.TODO(), p, assetTypes[i])
var updateTickerResponse *ticker.Price
updateTickerResponse, err = e.UpdateTicker(context.TODO(), p, assetTypes[i])
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}),
Function: "FetchTicker",
Function: "UpdateTicker",
Error: msg,
Response: jsonifyInterface([]interface{}{fetchTickerResponse}),
Response: jsonifyInterface([]interface{}{updateTickerResponse}),
})

var updateTickerResponse *ticker.Price
updateTickerResponse, err = e.UpdateTicker(context.TODO(), p, assetTypes[i])
var fetchTickerResponse *ticker.Price
fetchTickerResponse, err = e.FetchTicker(context.TODO(), p, assetTypes[i])
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}),
Function: "UpdateTicker",
Function: "FetchTicker",
Error: msg,
Response: jsonifyInterface([]interface{}{updateTickerResponse}),
Response: jsonifyInterface([]interface{}{fetchTickerResponse}),
})

var fetchOrderbookResponse *orderbook.Base
fetchOrderbookResponse, err = e.FetchOrderbook(context.TODO(), p, assetTypes[i])
var updateOrderbookResponse *orderbook.Base
updateOrderbookResponse, err = e.UpdateOrderbook(context.TODO(), p, assetTypes[i])
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}),
Function: "FetchOrderbook",
Function: "UpdateOrderbook",
Error: msg,
Response: jsonifyInterface([]interface{}{fetchOrderbookResponse}),
Response: jsonifyInterface([]interface{}{updateOrderbookResponse}),
})

var updateOrderbookResponse *orderbook.Base
updateOrderbookResponse, err = e.UpdateOrderbook(context.TODO(), p, assetTypes[i])
var fetchOrderbookResponse *orderbook.Base
fetchOrderbookResponse, err = e.FetchOrderbook(context.TODO(), p, assetTypes[i])
msg = ""
if err != nil {
msg = err.Error()
responseContainer.ErrorCount++
}
responseContainer.EndpointResponses = append(responseContainer.EndpointResponses, EndpointResponse{
SentParams: jsonifyInterface([]interface{}{p, assetTypes[i]}),
Function: "UpdateOrderbook",
Function: "FetchOrderbook",
Error: msg,
Response: jsonifyInterface([]interface{}{updateOrderbookResponse}),
Response: jsonifyInterface([]interface{}{fetchOrderbookResponse}),
})

var fetchTradablePairsResponse []currency.Pair
Expand Down
127 changes: 83 additions & 44 deletions cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,59 +175,90 @@ func executeExchangeWrapperTests(ctx context.Context, t *testing.T, exch exchang
t.Helper()
iExchange := reflect.TypeOf(&exch).Elem()
actualExchange := reflect.ValueOf(exch)

var firstPriority []string
var secondPriority []string

for x := 0; x < iExchange.NumMethod(); x++ {
methodName := iExchange.Method(x).Name
if _, ok := excludedMethodNames[methodName]; ok {
continue
}
method := actualExchange.MethodByName(methodName)

var assetLen int
for y := 0; y < method.Type().NumIn(); y++ {
input := method.Type().In(y)
if input.AssignableTo(assetParam) ||
input.AssignableTo(orderSubmitParam) ||
input.AssignableTo(orderModifyParam) ||
input.AssignableTo(orderCancelParam) ||
input.AssignableTo(orderCancelsParam) ||
input.AssignableTo(pairKeySliceParam) ||
input.AssignableTo(getOrdersRequestParam) ||
input.AssignableTo(pairKeySliceParam) {
// this allows wrapper functions that support assets types
// to be tested with all supported assets
assetLen = len(assetParams) - 1
}
}
tt := time.Now()
e := time.Date(tt.Year(), tt.Month(), tt.Day()-1, 0, 0, 0, 0, time.UTC)
s := e.Add(-time.Hour * 24 * 2)
if methodName == "GetHistoricTrades" {
// limit trade history
e = time.Now()
s = e.Add(-time.Minute * 3)

if _, ok := priorityMethodNames[methodName]; ok {
firstPriority = append(firstPriority, methodName)
} else {
secondPriority = append(secondPriority, methodName)
}
for y := 0; y <= assetLen; y++ {
inputs := make([]reflect.Value, method.Type().NumIn())
argGenerator := &MethodArgumentGenerator{
Exchange: exch,
AssetParams: assetParams[y],
MethodName: methodName,
Start: s,
End: e,
}
handleExchangeWrapperTests(ctx, t, actualExchange, firstPriority, exch, assetParams, "PRIORITY GROUP")
handleExchangeWrapperTests(ctx, t, actualExchange, secondPriority, exch, assetParams, "SECONDARY GROUP")
}

func handleExchangeWrapperTests(ctx context.Context, t *testing.T, actualExchange reflect.Value, methodNames []string, exch exchange.IBotExchange, assetParams []assetPair, groupTestID string) {
t.Helper()
if groupTestID == "PRIORITY GROUP" {
// Some update requests check for authenticated support, but we don't
// want to test them. This will fail fetcher functions in secondary
// group.
exch.GetBase().API.AuthenticatedSupport = false
} else {
exch.GetBase().API.AuthenticatedSupport = true
}
gloriousCode marked this conversation as resolved.
Show resolved Hide resolved

t.Run(groupTestID, func(t *testing.T) {
for x := range methodNames {
method := actualExchange.MethodByName(methodNames[x])

var assetLen int
for y := 0; y < method.Type().NumIn(); y++ {
input := method.Type().In(y)
if input.AssignableTo(assetParam) ||
input.AssignableTo(orderSubmitParam) ||
input.AssignableTo(orderModifyParam) ||
input.AssignableTo(orderCancelParam) ||
input.AssignableTo(orderCancelsParam) ||
input.AssignableTo(pairKeySliceParam) ||
input.AssignableTo(getOrdersRequestParam) ||
input.AssignableTo(pairKeySliceParam) {
// this allows wrapper functions that support assets types
// to be tested with all supported assets
assetLen = len(assetParams) - 1
}
}
for z := 0; z < method.Type().NumIn(); z++ {
argGenerator.MethodInputType = method.Type().In(z)
generatedArg := generateMethodArg(ctx, t, argGenerator)
inputs[z] = *generatedArg
tt := time.Now()
e := time.Date(tt.Year(), tt.Month(), tt.Day()-1, 0, 0, 0, 0, time.UTC)
s := e.Add(-time.Hour * 24 * 2)
if methodNames[x] == "GetHistoricTrades" {
// limit trade history
e = time.Now()
s = e.Add(-time.Minute * 3)
}
for y := 0; y <= assetLen; y++ {
inputs := make([]reflect.Value, method.Type().NumIn())
methodName := methodNames[x]
argGenerator := &MethodArgumentGenerator{
Exchange: exch,
AssetParams: assetParams[y],
MethodName: methodName,
Start: s,
End: e,
}
for z := 0; z < method.Type().NumIn(); z++ {
argGenerator.MethodInputType = method.Type().In(z)
generatedArg := generateMethodArg(ctx, t, argGenerator)
inputs[z] = *generatedArg
}
assetY := assetParams[y].Asset.String()
pairY := assetParams[y].Pair.String()

t.Run(methodName+"-"+assetY+"-"+pairY, func(t *testing.T) {
t.Parallel()
CallExchangeMethod(t, method, inputs, methodName, exch)
})
}
assetY := assetParams[y].Asset.String()
pairY := assetParams[y].Pair.String()
t.Run(methodName+"-"+assetY+"-"+pairY, func(t *testing.T) {
t.Parallel()
CallExchangeMethod(t, method, inputs, methodName, exch)
})
}
}
})
}

// CallExchangeMethod will call an exchange's method using generated arguments
Expand Down Expand Up @@ -549,6 +580,13 @@ type assetPair struct {
Asset asset.Item
}

// priorityMethodNames are called before other exchange functions
var priorityMethodNames = map[string]struct{}{
"UpdateTickers": {}, // Is required before FetchTickers is called
"UpdateTicker": {}, // Is required before FetchTicker is called
"UpdateOrderbook": {}, // Is required before FetchOrderbook is called
}

// excludedMethodNames represent the functions that are not
// currently tested under this suite due to irrelevance
// or not worth checking yet
Expand Down Expand Up @@ -590,6 +628,7 @@ var excludedMethodNames = map[string]struct{}{
"GetLeverage": {},
"SetMarginType": {},
"ChangePositionMargin": {},
"FetchAccountInfo": {}, // Account info is not retrieved in these tests
}

// blockedCIExchanges are exchanges that are not able to be tested on CI
Expand Down
6 changes: 2 additions & 4 deletions engine/event_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,8 +306,7 @@ func TestCheckEventCondition(t *testing.T) {
t.Error("expected error")
}
m.m.Unlock()
_, err = exch.FetchTicker(context.Background(),
currency.NewPair(currency.BTC, currency.USD), asset.Spot)
_, err = exch.UpdateTicker(context.Background(), currency.NewPair(currency.BTC, currency.USD), asset.Spot)
if !errors.Is(err, nil) {
t.Errorf("error '%v', expected '%v'", err, nil)
}
Expand All @@ -331,8 +330,7 @@ func TestCheckEventCondition(t *testing.T) {
}
m.m.Unlock()

_, err = exch.FetchOrderbook(context.Background(),
currency.NewPair(currency.BTC, currency.USD), asset.Spot)
_, err = exch.UpdateOrderbook(context.Background(), currency.NewPair(currency.BTC, currency.USD), asset.Spot)
if !errors.Is(err, nil) {
t.Errorf("error '%v', expected '%v'", err, nil)
}
Expand Down
22 changes: 0 additions & 22 deletions engine/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/lbank"
"github.com/thrasher-corp/gocryptotrader/exchanges/okcoin"
"github.com/thrasher-corp/gocryptotrader/exchanges/okx"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/poloniex"
"github.com/thrasher-corp/gocryptotrader/exchanges/stats"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
"github.com/thrasher-corp/gocryptotrader/exchanges/yobit"
"github.com/thrasher-corp/gocryptotrader/gctscript/vm"
"github.com/thrasher-corp/gocryptotrader/log"
Expand Down Expand Up @@ -574,26 +572,6 @@ func GetRelatableCurrencies(p currency.Pair, incOrig, incUSDT bool) currency.Pai
return pairs
}

// GetSpecificOrderbook returns a specific orderbook given the currency,
// exchangeName and assetType
func (bot *Engine) GetSpecificOrderbook(ctx context.Context, p currency.Pair, exchangeName string, assetType asset.Item) (*orderbook.Base, error) {
exch, err := bot.GetExchangeByName(exchangeName)
if err != nil {
return nil, err
}
return exch.FetchOrderbook(ctx, p, assetType)
}

// GetSpecificTicker returns a specific ticker given the currency,
// exchangeName and assetType
func (bot *Engine) GetSpecificTicker(ctx context.Context, p currency.Pair, exchangeName string, assetType asset.Item) (*ticker.Price, error) {
exch, err := bot.GetExchangeByName(exchangeName)
if err != nil {
return nil, err
}
return exch.FetchTicker(ctx, p, assetType)
}

// GetCollatedExchangeAccountInfoByCoin collates individual exchange account
// information and turns it into a map string of exchange.AccountCurrencyInfo
func GetCollatedExchangeAccountInfoByCoin(accounts []account.Holdings) map[currency.Code]account.Balance {
Expand Down
Loading
Loading