mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-25 07:26:48 +00:00
exchanges/kraken,bittrex,gemini: Resolve Kraken panic, lint corrections, Bittrex batch tickers, set Gemini order limits and update tradable pairs (#1372)
* fix kraken, batch bittrex, fix lint * surprise gemini! * thought this happened automatically * fix before shazbert sees * fixes annoying atoi bug * rm futures from gemini * lint * bittrex UpdatedAt, gemini Limits, stats relook * STATS used HARDEN!(improve stats package) * Whoopsies in your Daisies * rm RWMutex, json stringeroo * fixes additional index issues 😆 😭
This commit is contained in:
@@ -24,7 +24,7 @@ const (
|
||||
geminiAPIVersion = "1"
|
||||
|
||||
geminiSymbols = "symbols"
|
||||
geminiTicker = "pubticker"
|
||||
geminiSymbolDetails = "symbols/details"
|
||||
geminiAuction = "auction"
|
||||
geminiAuctionHistory = "history"
|
||||
geminiOrderbook = "book"
|
||||
@@ -62,6 +62,21 @@ func (g *Gemini) GetSymbols(ctx context.Context) ([]string, error) {
|
||||
return symbols, g.SendHTTPRequest(ctx, exchange.RestSpot, path, &symbols)
|
||||
}
|
||||
|
||||
// GetSymbolDetails returns extra symbol details
|
||||
// use symbol "all" to get everything
|
||||
func (g *Gemini) GetSymbolDetails(ctx context.Context, symbol string) ([]SymbolDetails, error) {
|
||||
if symbol == "all" {
|
||||
var details []SymbolDetails
|
||||
return details, g.SendHTTPRequest(ctx, exchange.RestSpot, "/v"+geminiAPIVersion+"/"+geminiSymbolDetails+"/"+symbol, &details)
|
||||
}
|
||||
var details SymbolDetails
|
||||
err := g.SendHTTPRequest(ctx, exchange.RestSpot, "/v"+geminiAPIVersion+"/"+geminiSymbolDetails+"/"+symbol, &details)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []SymbolDetails{details}, nil
|
||||
}
|
||||
|
||||
// GetTicker returns information about recent trading activity for the symbol
|
||||
func (g *Gemini) GetTicker(ctx context.Context, currencyPair string) (TickerV2, error) {
|
||||
ticker := TickerV2{}
|
||||
|
||||
@@ -1259,3 +1259,42 @@ func TestGetOrderInfo(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSymbolDetails(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := g.GetSymbolDetails(context.Background(), "all")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
_, err = g.GetSymbolDetails(context.Background(), "btcusd")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetExchangeOrderExecutionLimits(t *testing.T) {
|
||||
t.Parallel()
|
||||
err := g.UpdateOrderExecutionLimits(context.Background(), asset.Spot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = g.UpdateOrderExecutionLimits(context.Background(), asset.Futures)
|
||||
if !errors.Is(err, asset.ErrNotSupported) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
availPairs, err := g.GetAvailablePairs(asset.Spot)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for x := range availPairs {
|
||||
var limit order.MinMaxLevel
|
||||
limit, err = g.GetOrderExecutionLimits(asset.Spot, availPairs[x])
|
||||
if err != nil {
|
||||
t.Fatal(err, availPairs[x])
|
||||
}
|
||||
if limit == (order.MinMaxLevel{}) {
|
||||
t.Fatal("exchange limit should be loaded")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package gemini
|
||||
|
||||
import (
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
)
|
||||
|
||||
@@ -29,6 +30,21 @@ type Ticker struct {
|
||||
}
|
||||
}
|
||||
|
||||
// SymbolDetails contains additional symbol details
|
||||
type SymbolDetails struct {
|
||||
Symbol string `json:"symbol"`
|
||||
BaseCurrency string `json:"base_currency"`
|
||||
QuoteCurrency string `json:"quote_currency"`
|
||||
TickSize float64 `json:"tick_size"`
|
||||
QuoteIncrement float64 `json:"quote_increment"`
|
||||
MinOrderSize convert.StringToFloat64 `json:"min_order_size"`
|
||||
Status string `json:"status"`
|
||||
WrapEnabled bool `json:"wrap_enabled"`
|
||||
ProductType string `json:"product_type"`
|
||||
ContractType string `json:"contract_type"`
|
||||
ContractPriceCurrency string `json:"contract_price_currency"`
|
||||
}
|
||||
|
||||
// TickerV2 holds returned ticker data from the exchange
|
||||
type TickerV2 struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"net/url"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -259,7 +260,12 @@ func (g *Gemini) Run(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := g.UpdateOrderExecutionLimits(ctx, asset.Spot); err != nil {
|
||||
log.Errorf(log.ExchangeSys,
|
||||
"%s failed to set exchange order execution limits. Err: %v",
|
||||
g.Name,
|
||||
err)
|
||||
}
|
||||
if !g.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
|
||||
return
|
||||
}
|
||||
@@ -278,26 +284,26 @@ func (g *Gemini) FetchTradablePairs(ctx context.Context, a asset.Item) (currency
|
||||
return nil, asset.ErrNotSupported
|
||||
}
|
||||
|
||||
symbols, err := g.GetSymbols(ctx)
|
||||
details, err := g.GetSymbolDetails(ctx, "all")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pairs := make([]currency.Pair, len(symbols))
|
||||
for x := range symbols {
|
||||
var pair currency.Pair
|
||||
switch len(symbols[x]) {
|
||||
case 8:
|
||||
pair, err = currency.NewPairFromStrings(symbols[x][0:5], symbols[x][5:])
|
||||
case 7:
|
||||
pair, err = currency.NewPairFromStrings(symbols[x][0:4], symbols[x][4:])
|
||||
default:
|
||||
pair, err = currency.NewPairFromStrings(symbols[x][0:3], symbols[x][3:])
|
||||
pairs := make([]currency.Pair, 0, len(details))
|
||||
for i := range details {
|
||||
status := strings.ToLower(details[i].Status)
|
||||
if status != "open" && status != "limit_only" {
|
||||
continue
|
||||
}
|
||||
if !strings.EqualFold(details[i].ContractType, "vanilla") {
|
||||
// TODO: add support for futures
|
||||
continue
|
||||
}
|
||||
|
||||
cp, err := currency.NewPairFromStrings(details[i].BaseCurrency, details[i].Symbol[len(details[i].BaseCurrency):])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pairs[x] = pair
|
||||
pairs = append(pairs, cp)
|
||||
}
|
||||
return pairs, nil
|
||||
}
|
||||
@@ -918,3 +924,33 @@ func (g *Gemini) GetHistoricCandlesExtended(_ context.Context, _ currency.Pair,
|
||||
func (g *Gemini) GetFuturesContractDetails(context.Context, asset.Item) ([]futures.Contract, error) {
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// UpdateOrderExecutionLimits sets exchange executions for a required asset type
|
||||
func (g *Gemini) UpdateOrderExecutionLimits(ctx context.Context, a asset.Item) error {
|
||||
if a != asset.Spot {
|
||||
return fmt.Errorf("%w %v", asset.ErrNotSupported, a)
|
||||
}
|
||||
details, err := g.GetSymbolDetails(ctx, "all")
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update exchange execution limits: %w", err)
|
||||
}
|
||||
resp := make([]order.MinMaxLevel, 0, len(details))
|
||||
for i := range details {
|
||||
status := strings.ToLower(details[i].Status)
|
||||
if status != "open" && status != "limit_only" {
|
||||
continue
|
||||
}
|
||||
cp, err := currency.NewPairFromStrings(details[i].BaseCurrency, details[i].QuoteCurrency)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resp = append(resp, order.MinMaxLevel{
|
||||
Pair: cp,
|
||||
Asset: a,
|
||||
AmountStepIncrementSize: details[i].TickSize,
|
||||
MinimumBaseAmount: details[i].MinOrderSize.Float64(),
|
||||
QuoteStepIncrementSize: details[i].QuoteIncrement,
|
||||
})
|
||||
}
|
||||
return g.LoadLimits(resp)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user