mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 07:26:47 +00:00
bugfixes: Backtester credentials, Binance ExecutionLimits, Mock recording (#1539)
* fix mock recording, binance, backtester * minor credential streamlining
This commit is contained in:
@@ -843,7 +843,7 @@ func (bt *BackTest) loadData(cfg *config.Config, exch gctexchange.IBotExchange,
|
||||
cfg.DataSettings.Interval)
|
||||
}
|
||||
err = bt.exchangeManager.Add(exch)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, engine.ErrExchangeAlreadyLoaded) {
|
||||
return nil, err
|
||||
}
|
||||
err = bt.LiveDataHandler.AppendDataSource(&liveDataSourceSetup{
|
||||
@@ -955,7 +955,8 @@ func setExchangeCredentials(cfg *config.Config, base *gctexchange.Base) error {
|
||||
cfg.DataSettings.LiveData.ExchangeCredentials[i].Keys.IsEmpty() {
|
||||
return fmt.Errorf("%v %w, please review your live, real order config", base.GetName(), gctexchange.ErrCredentialsAreEmpty)
|
||||
}
|
||||
|
||||
base.API.AuthenticatedSupport = true
|
||||
base.API.AuthenticatedWebsocketSupport = true
|
||||
base.SetCredentials(
|
||||
cfg.DataSettings.LiveData.ExchangeCredentials[i].Keys.Key,
|
||||
cfg.DataSettings.LiveData.ExchangeCredentials[i].Keys.Secret,
|
||||
@@ -964,10 +965,9 @@ func setExchangeCredentials(cfg *config.Config, base *gctexchange.Base) error {
|
||||
cfg.DataSettings.LiveData.ExchangeCredentials[i].Keys.PEMKey,
|
||||
cfg.DataSettings.LiveData.ExchangeCredentials[i].Keys.OneTimePassword,
|
||||
)
|
||||
validated := base.AreCredentialsValid(context.TODO())
|
||||
base.API.AuthenticatedSupport = validated
|
||||
if !validated {
|
||||
return fmt.Errorf("%v %w", base.GetName(), errInvalidCredentials)
|
||||
_, err := base.GetCredentials(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@ var (
|
||||
ErrExchangeFailedToLoad = errors.New("exchange failed to load")
|
||||
ErrExchangeNameIsEmpty = errors.New("exchange name is empty")
|
||||
|
||||
errExchangeIsNil = errors.New("exchange is nil")
|
||||
errExchangeAlreadyLoaded = errors.New("exchange already loaded")
|
||||
errExchangeIsNil = errors.New("exchange is nil")
|
||||
)
|
||||
|
||||
// CustomExchangeBuilder interface allows external applications to create
|
||||
@@ -55,7 +54,7 @@ func (m *ExchangeManager) Add(exch exchange.IBotExchange) error {
|
||||
defer m.mtx.Unlock()
|
||||
_, ok := m.exchanges[strings.ToLower(exch.GetName())]
|
||||
if ok {
|
||||
return fmt.Errorf("exchange manager: %s %w", exch.GetName(), errExchangeAlreadyLoaded)
|
||||
return fmt.Errorf("exchange manager: %s %w", exch.GetName(), ErrExchangeAlreadyLoaded)
|
||||
}
|
||||
m.exchanges[strings.ToLower(exch.GetName())] = exch
|
||||
return nil
|
||||
|
||||
@@ -48,8 +48,8 @@ func TestExchangeManagerAdd(t *testing.T) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, nil)
|
||||
}
|
||||
err = m.Add(b)
|
||||
if !errors.Is(err, errExchangeAlreadyLoaded) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, errExchangeAlreadyLoaded)
|
||||
if !errors.Is(err, ErrExchangeAlreadyLoaded) {
|
||||
t.Fatalf("received: '%v' but expected: '%v'", err, ErrExchangeAlreadyLoaded)
|
||||
}
|
||||
exchanges, err := m.GetExchanges()
|
||||
if err != nil {
|
||||
|
||||
@@ -1233,46 +1233,46 @@ func (b *Binance) FetchExchangeLimits(ctx context.Context, a asset.Item) ([]orde
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !slices.Contains(s.Permissions, aUpper) {
|
||||
continue
|
||||
}
|
||||
|
||||
l := order.MinMaxLevel{
|
||||
Pair: cp,
|
||||
Asset: a,
|
||||
}
|
||||
|
||||
for _, f := range s.Filters {
|
||||
// TODO: Unhandled filters:
|
||||
// maxPosition, trailingDelta, percentPriceBySide, maxNumAlgoOrders
|
||||
switch f.FilterType {
|
||||
case priceFilter:
|
||||
l.MinPrice = f.MinPrice
|
||||
l.MaxPrice = f.MaxPrice
|
||||
l.PriceStepIncrementSize = f.TickSize
|
||||
case percentPriceFilter:
|
||||
l.MultiplierUp = f.MultiplierUp
|
||||
l.MultiplierDown = f.MultiplierDown
|
||||
l.AveragePriceMinutes = f.AvgPriceMinutes
|
||||
case lotSizeFilter:
|
||||
l.MaximumBaseAmount = f.MaxQty
|
||||
l.MinimumBaseAmount = f.MinQty
|
||||
l.AmountStepIncrementSize = f.StepSize
|
||||
case notionalFilter:
|
||||
l.MinNotional = f.MinNotional
|
||||
case icebergPartsFilter:
|
||||
l.MaxIcebergParts = f.Limit
|
||||
case marketLotSizeFilter:
|
||||
l.MarketMinQty = f.MinQty
|
||||
l.MarketMaxQty = f.MaxQty
|
||||
l.MarketStepIncrementSize = f.StepSize
|
||||
case maxNumOrdersFilter:
|
||||
l.MaxTotalOrders = f.MaxNumOrders
|
||||
l.MaxAlgoOrders = f.MaxNumAlgoOrders
|
||||
for i := range s.PermissionSets {
|
||||
if !slices.Contains(s.PermissionSets[i], aUpper) {
|
||||
continue
|
||||
}
|
||||
l := order.MinMaxLevel{
|
||||
Pair: cp,
|
||||
Asset: a,
|
||||
}
|
||||
for _, f := range s.Filters {
|
||||
// TODO: Unhandled filters:
|
||||
// maxPosition, trailingDelta, percentPriceBySide, maxNumAlgoOrders
|
||||
switch f.FilterType {
|
||||
case priceFilter:
|
||||
l.MinPrice = f.MinPrice
|
||||
l.MaxPrice = f.MaxPrice
|
||||
l.PriceStepIncrementSize = f.TickSize
|
||||
case percentPriceFilter:
|
||||
l.MultiplierUp = f.MultiplierUp
|
||||
l.MultiplierDown = f.MultiplierDown
|
||||
l.AveragePriceMinutes = f.AvgPriceMinutes
|
||||
case lotSizeFilter:
|
||||
l.MaximumBaseAmount = f.MaxQty
|
||||
l.MinimumBaseAmount = f.MinQty
|
||||
l.AmountStepIncrementSize = f.StepSize
|
||||
case notionalFilter:
|
||||
l.MinNotional = f.MinNotional
|
||||
case icebergPartsFilter:
|
||||
l.MaxIcebergParts = f.Limit
|
||||
case marketLotSizeFilter:
|
||||
l.MarketMinQty = f.MinQty
|
||||
l.MarketMaxQty = f.MaxQty
|
||||
l.MarketStepIncrementSize = f.StepSize
|
||||
case maxNumOrdersFilter:
|
||||
l.MaxTotalOrders = f.MaxNumOrders
|
||||
l.MaxAlgoOrders = f.MaxNumAlgoOrders
|
||||
}
|
||||
}
|
||||
limits = append(limits, l)
|
||||
break
|
||||
}
|
||||
|
||||
limits = append(limits, l)
|
||||
}
|
||||
return limits, nil
|
||||
}
|
||||
|
||||
@@ -1085,8 +1085,8 @@ func TestGetExchangeInfo(t *testing.T) {
|
||||
info, err := b.GetExchangeInfo(context.Background())
|
||||
require.NoError(t, err, "GetExchangeInfo must not error")
|
||||
if mockTests {
|
||||
exp := time.Date(2022, 2, 25, 3, 50, 40, int(601*time.Millisecond), time.UTC)
|
||||
assert.True(t, info.ServerTime.Equal(exp), "ServerTime should be correct")
|
||||
exp := time.Date(2024, 5, 10, 6, 8, 1, int(707*time.Millisecond), time.UTC)
|
||||
assert.True(t, info.ServerTime.Equal(exp), "expected %v received %v", exp.UTC(), info.ServerTime.UTC())
|
||||
} else {
|
||||
assert.WithinRange(t, info.ServerTime, time.Now().Add(-24*time.Hour), time.Now().Add(24*time.Hour), "ServerTime should be within a day of now")
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ type ExchangeInfo struct {
|
||||
IsMarginTradingAllowed bool `json:"isMarginTradingAllowed"`
|
||||
Filters []*filterData `json:"filters"`
|
||||
Permissions []string `json:"permissions"`
|
||||
PermissionSets [][]string `json:"permissionSets"`
|
||||
} `json:"symbols"`
|
||||
}
|
||||
|
||||
|
||||
230277
exchanges/binance/testdata/http.json
vendored
230277
exchanges/binance/testdata/http.json
vendored
File diff suppressed because it is too large
Load Diff
@@ -47,9 +47,21 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
|
||||
}
|
||||
service = strings.ToLower(service)
|
||||
|
||||
fileout := filepath.Join(DefaultDirectory, service, service+".json")
|
||||
outputFilePath := filepath.Join(DefaultDirectory, service, service+".json")
|
||||
_, err := os.Stat(outputFilePath)
|
||||
if err != nil {
|
||||
if os.IsExist(err) {
|
||||
return err
|
||||
}
|
||||
// check alternative path to add compatibility with /internal/testing/exchange/exchange.go MockHTTPInstance
|
||||
outputFilePath = filepath.Join("..", service, "testdata", "http.json")
|
||||
_, err = os.Stat(outputFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
contents, err := os.ReadFile(fileout)
|
||||
contents, err := os.ReadFile(outputFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -227,7 +239,7 @@ func HTTPRecord(res *http.Response, service string, respContents []byte) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return file.Write(fileout, payload)
|
||||
return file.Write(outputFilePath, payload)
|
||||
}
|
||||
|
||||
// GetFilteredHeader filters excluded http headers for insertion into a mock
|
||||
|
||||
@@ -25,10 +25,10 @@ import (
|
||||
const (
|
||||
// WebsocketResponseDefaultTimeout used in websocket testing
|
||||
// Defines wait time for receiving websocket response before cancelling
|
||||
WebsocketResponseDefaultTimeout = (3 * time.Second)
|
||||
WebsocketResponseDefaultTimeout = 3 * time.Second
|
||||
// WebsocketResponseExtendedTimeout used in websocket testing
|
||||
// Defines wait time for receiving websocket response before cancelling
|
||||
WebsocketResponseExtendedTimeout = (15 * time.Second)
|
||||
WebsocketResponseExtendedTimeout = 15 * time.Second
|
||||
// WebsocketChannelOverrideCapacity used in websocket testing
|
||||
// Defines channel capacity as defaults size can block tests
|
||||
WebsocketChannelOverrideCapacity = 500
|
||||
|
||||
Reference in New Issue
Block a user