Kraken: Load order execution limits for tradable pairs (#1255)

* Kraken: Load asset limits for pairs

* Kraken: Add test for spot order limit loading

* Kraken: move Limits to UpdateExecutionLimits

* Kraken: Whitespace fixed

* Kraken: added ErrNotYetImplemented for the futures

* Kraken: Fix FetchTradablePairs Loading Limits

* Kraken: changed the error to match the Go 1.13 error package

---------

Co-authored-by: Gareth Kirwan <gbjkirwan@gmail.com>
This commit is contained in:
Bea
2023-07-24 10:42:49 +07:00
committed by GitHub
parent b797934854
commit 0522a54681
3 changed files with 124 additions and 41 deletions

View File

@@ -99,6 +99,44 @@ func TestWrapperGetServerTime(t *testing.T) {
}
}
func TestUpdateOrderExecutionLimits(t *testing.T) {
t.Parallel()
type limitTest struct {
pair currency.Pair
step float64
min float64
}
tests := map[asset.Item][]limitTest{
asset.Spot: {
{currency.NewPair(currency.ETH, currency.USDT), 0.01, 0.01},
{currency.NewPair(currency.XBT, currency.USDT), 0.1, 0.0001},
},
}
for assetItem, limitTests := range tests {
if err := k.UpdateOrderExecutionLimits(context.Background(), assetItem); err != nil {
t.Errorf("Error fetching %s pairs for test: %v", assetItem, err)
}
for _, limitTest := range limitTests {
limits, err := k.GetOrderExecutionLimits(assetItem, limitTest.pair)
if err != nil {
t.Errorf("Kraken GetOrderExecutionLimits() error during TestExecutionLimits; Asset: %s Pair: %s Err: %v", assetItem, limitTest.pair, err)
continue
}
if got := limits.PriceStepIncrementSize; got != limitTest.step {
t.Errorf("Kraken UpdateOrderExecutionLimits wrong PriceStepIncrementSize; Asset: %s Pair: %s Expected: %v Got: %v", assetItem, limitTest.pair, limitTest.step, got)
}
if got := limits.MinimumBaseAmount; got != limitTest.min {
t.Errorf("Kraken UpdateOrderExecutionLimits wrong MinAmount; Pair: %s Expected: %v Got: %v", limitTest.pair, limitTest.min, got)
}
}
}
}
func TestFetchTradablePairs(t *testing.T) {
t.Parallel()
_, err := k.FetchTradablePairs(context.Background(), asset.Futures)

View File

@@ -122,7 +122,8 @@ type AssetPairs struct {
FeeVolumeCurrency string `json:"fee_volume_currency"`
MarginCall int `json:"margin_call"`
MarginStop int `json:"margin_stop"`
Ordermin string `json:"ordermin"`
OrderMinimum float64 `json:"ordermin,string"`
TickSize float64 `json:"tick_size,string"`
Status string `json:"status"`
}

View File

@@ -328,23 +328,92 @@ func (k *Kraken) Run(ctx context.Context) {
}
}
if !k.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
return
if k.GetEnabledFeatures().AutoPairUpdates || forceUpdate {
if err := k.UpdateTradablePairs(ctx, forceUpdate); err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
k.Name,
err)
}
}
err := k.UpdateTradablePairs(ctx, forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
k.Name,
err)
for _, a := range k.GetAssetTypes(true) {
if err := k.UpdateOrderExecutionLimits(ctx, a); err != nil && err != common.ErrNotYetImplemented {
log.Errorln(log.ExchangeSys, err.Error())
}
}
}
// UpdateOrderExecutionLimits sets exchange execution order limits for an asset type
func (k *Kraken) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error {
if a != asset.Spot {
return common.ErrNotYetImplemented
}
pairInfo, err := k.fetchSpotPairInfo(ctx)
if err != nil {
return fmt.Errorf("%s failed to load %s pair execution limits. Err: %s", k.Name, a, err)
}
limits := make([]order.MinMaxLevel, 0, len(pairInfo))
for pair, info := range pairInfo {
limits = append(limits, order.MinMaxLevel{
Asset: a,
Pair: pair,
PriceStepIncrementSize: info.TickSize,
MinimumBaseAmount: info.OrderMinimum,
})
}
if err := k.LoadLimits(limits); err != nil {
return fmt.Errorf("%s Error loading %s exchange limits: %w", k.Name, a, err)
}
return nil
}
func (k *Kraken) fetchSpotPairInfo(ctx context.Context) (map[currency.Pair]*AssetPairs, error) {
pairs := make(map[currency.Pair]*AssetPairs)
pairInfo, err := k.GetAssetPairs(ctx, nil, "")
if err != nil {
return pairs, err
}
for _, info := range pairInfo {
if info.Status != "online" {
continue
}
base := assetTranslator.LookupAltname(info.Base)
if base == "" {
log.Warnf(log.ExchangeSys,
"%s unable to lookup altname for base currency %s",
k.Name,
info.Base)
continue
}
quote := assetTranslator.LookupAltname(info.Quote)
if quote == "" {
log.Warnf(log.ExchangeSys,
"%s unable to lookup altname for quote currency %s",
k.Name,
info.Quote)
continue
}
pair, err := currency.NewPairFromStrings(base, quote)
if err != nil {
return pairs, err
}
pairs[pair] = info
}
return pairs, nil
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
func (k *Kraken) FetchTradablePairs(ctx context.Context, a asset.Item) (currency.Pairs, error) {
var pairs []currency.Pair
var pair currency.Pair
pairs := currency.Pairs{}
switch a {
case asset.Spot:
if !assetTranslator.Seeded() {
@@ -352,36 +421,12 @@ func (k *Kraken) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
return nil, err
}
}
symbols, err := k.GetAssetPairs(ctx, nil, "")
pairInfo, err := k.fetchSpotPairInfo(ctx)
if err != nil {
return nil, err
return pairs, err
}
pairs = make([]currency.Pair, 0, len(symbols))
for _, info := range symbols {
if info.Status != "online" {
continue
}
base := assetTranslator.LookupAltname(info.Base)
if base == "" {
log.Warnf(log.ExchangeSys,
"%s unable to lookup altname for base currency %s",
k.Name,
info.Base)
continue
}
quote := assetTranslator.LookupAltname(info.Quote)
if quote == "" {
log.Warnf(log.ExchangeSys,
"%s unable to lookup altname for quote currency %s",
k.Name,
info.Quote)
continue
}
pair, err = currency.NewPairFromStrings(base, quote)
if err != nil {
return nil, err
}
pairs = make(currency.Pairs, 0, len(pairInfo))
for pair := range pairInfo {
pairs = append(pairs, pair)
}
case asset.Futures:
@@ -404,8 +449,7 @@ func (k *Kraken) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
return pairs, nil
}
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
// UpdateTradablePairs updates the exchanges available pairs and stores them in the exchanges config
func (k *Kraken) UpdateTradablePairs(ctx context.Context, forceUpdate bool) error {
assets := k.GetAssetTypes(false)
for x := range assets {