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 31 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0af3a8d
acrost: Pull thread, examine
Jan 4, 2024
7391cf1
fix tests
Jan 4, 2024
1fcc8e1
linter
Jan 4, 2024
ab41331
Merge branch 'master' into fetch_sillyness
Jan 17, 2024
9f795a5
fix_linter
Jan 17, 2024
33061cb
Merge branch 'master' into fetch_sillyness
Jan 29, 2024
9cd6001
revert rm ctx param to limit breakages when merging usptream
Jan 29, 2024
6b5bae0
linter fix
Jan 29, 2024
065b3b1
Add in priority update grouping so that tests pass
Jan 29, 2024
d1156cf
Update cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go
shazbert Jan 30, 2024
10c2448
glorious nits
Jan 30, 2024
7eea11e
fixed spelling
Jan 30, 2024
f837ce0
whoopsie
Jan 30, 2024
c999444
aanother whoops
Jan 30, 2024
14fd6c8
Merge branch 'master' into fetch_sillyness
Feb 1, 2024
82f252b
Merge branch 'master' into fetch_sillyness
Feb 15, 2024
294fea1
Merge branch 'master' into fetch_sillyness
Mar 7, 2024
7e8bad8
glorious: NITTERS!
Mar 7, 2024
3984f89
glorious: further nitters
Mar 7, 2024
4ad6acd
srry linter gods
Mar 7, 2024
0798c1a
glorious: nits continued
Mar 8, 2024
b9bffe0
sub test p ara lel
Mar 8, 2024
88d23d0
Merge branch 'master' into fetch_sillyness
Apr 15, 2024
861976e
Merge branch 'master' into fetch_sillyness
May 1, 2024
ce7f1e5
drop main t.Parallel
May 1, 2024
187dfba
fix whoops
May 1, 2024
c3c4a06
wrappertests: use context with cancel (test)
May 1, 2024
33dfb4b
Merge branch 'master' into fetch_sillyness
May 15, 2024
6c74d85
Merge branch 'master' into fetch_sillyness
Oct 12, 2024
2824a2f
Merge branch 'master' into fetch_sillyness
Dec 30, 2024
9e7b0d7
linter: fix
Dec 30, 2024
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 @@ -304,24 +304,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 @@ -370,21 +352,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 @@ -347,60 +347,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
113 changes: 69 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,83 @@ 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 strings.Contains(methodName, "Update") {
gloriousCode marked this conversation as resolved.
Show resolved Hide resolved
// Update functions are tested first as they are required for other
// functions to work.
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()
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())
argGenerator := &MethodArgumentGenerator{
Exchange: exch,
AssetParams: assetParams[y],
MethodName: methodNames[x],
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()

methodNameBro := methodNames[x]
gloriousCode marked this conversation as resolved.
Show resolved Hide resolved
t.Run(methodNames[x]+"-"+assetY+"-"+pairY, func(t *testing.T) {
t.Parallel()
CallExchangeMethod(t, method, inputs, methodNameBro, 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 @@ -584,6 +608,7 @@ var excludedMethodNames = map[string]struct{}{
"GetLeverage": {},
"SetMarginType": {},
"ChangePositionMargin": {},
"FetchAccountInfo": {}, // Cannot be set correctly with UpdateAccountInfo
shazbert marked this conversation as resolved.
Show resolved Hide resolved
}

// 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
12 changes: 6 additions & 6 deletions engine/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,22 +577,22 @@ func GetRelatableCurrencies(p currency.Pair, incOrig, incUSDT bool) currency.Pai

// 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) {
func (bot *Engine) GetSpecificOrderbook(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)
return exch.FetchOrderbook(context.TODO(), p, assetType)
gloriousCode marked this conversation as resolved.
Show resolved Hide resolved
}

// 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) {
func (bot *Engine) GetSpecificTicker(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)
return exch.FetchTicker(context.TODO(), p, assetType)
}

// GetCollatedExchangeAccountInfoByCoin collates individual exchange account
Expand Down Expand Up @@ -831,7 +831,7 @@ func (bot *Engine) GetExchangeNames(enabledOnly bool) []string {
}

// GetAllActiveTickers returns all enabled exchange tickers
func (bot *Engine) GetAllActiveTickers(ctx context.Context) []EnabledExchangeCurrencies {
func (bot *Engine) GetAllActiveTickers() []EnabledExchangeCurrencies {
var tickerData []EnabledExchangeCurrencies
exchanges := bot.GetExchanges()
for x := range exchanges {
Expand All @@ -850,7 +850,7 @@ func (bot *Engine) GetAllActiveTickers(ctx context.Context) []EnabledExchangeCur
continue
}
for z := range currencies {
tp, err := exchanges[x].FetchTicker(ctx, currencies[z], assets[y])
tp, err := exchanges[x].FetchTicker(context.TODO(), currencies[z], assets[y])
if err != nil {
log.Errorf(log.ExchangeSys, "Exchange %s failed to retrieve %s ticker. Err: %s\n", exchName,
currencies[z].String(),
Expand Down
12 changes: 4 additions & 8 deletions engine/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,8 +774,7 @@ func TestGetSpecificOrderbook(t *testing.T) {
t.Fatal(err)
}

ob, err := e.GetSpecificOrderbook(context.Background(),
btsusd, testExchange, asset.Spot)
ob, err := e.GetSpecificOrderbook(btsusd, testExchange, asset.Spot)
if err != nil {
t.Fatal(err)
}
Expand All @@ -789,8 +788,7 @@ func TestGetSpecificOrderbook(t *testing.T) {
t.Fatal(err)
}

_, err = e.GetSpecificOrderbook(context.Background(),
ethltc, testExchange, asset.Spot)
_, err = e.GetSpecificOrderbook(ethltc, testExchange, asset.Spot)
if err == nil {
t.Fatal("Unexpected result")
}
Expand Down Expand Up @@ -818,8 +816,7 @@ func TestGetSpecificTicker(t *testing.T) {
t.Fatal("ProcessTicker error", err)
}

tick, err := e.GetSpecificTicker(context.Background(),
p, testExchange, asset.Spot)
tick, err := e.GetSpecificTicker(p, testExchange, asset.Spot)
if err != nil {
t.Fatal(err)
}
Expand All @@ -833,8 +830,7 @@ func TestGetSpecificTicker(t *testing.T) {
t.Fatal(err)
}

_, err = e.GetSpecificTicker(context.Background(),
ethltc, testExchange, asset.Spot)
_, err = e.GetSpecificTicker(ethltc, testExchange, asset.Spot)
if err == nil {
t.Fatal("Unexpected result")
}
Expand Down
Loading
Loading