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

FIX: [exchange] [coinbase] fill in dummy values for min/max quantity #1918

Merged
merged 2 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from all 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
9 changes: 5 additions & 4 deletions pkg/exchange/coinbase/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,14 @@ func toGlobalTrade(cbTrade *api.Trade) types.Trade {
//
// According to the markets list, the PPP is the max slippage percentage:
// - https://exchange.coinbase.com/markets
func toGlobalMarket(cbMarket *api.MarketInfo, cbTicker *api.Ticker) types.Market {
func toGlobalMarket(cbMarket *api.MarketInfo) types.Market {
pricePrecision := int(math.Log10(fixedpoint.One.Div(cbMarket.QuoteIncrement).Float64()))
volumnPrecision := int(math.Log10(fixedpoint.One.Div(cbMarket.BaseIncrement).Float64()))

// NOTE: Coinbase does not appose a min quantity, but a min notional.
// So we set the min quantity to the base increment. Or it may require more API calls
// to calculate the excact min quantity, which is costy.
minQuantity := cbMarket.BaseIncrement
if cbTicker != nil {
minQuantity = cbMarket.MinMarketFunds.Div(cbTicker.Price)
}
// TODO: estimate max quantity by PPP
// fill a dummy value for now.
maxQuantity := minQuantity.Mul(fixedpoint.NewFromFloat(1.5))
Expand Down
37 changes: 2 additions & 35 deletions pkg/exchange/coinbase/exchage.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,48 +273,15 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {

marketMap := make(types.MarketMap)
for _, m := range markets {
// skip products that are not online
// skip products that is not online
if m.Status != "online" {
continue
}
marketInfo, err := e.queryMarketDetails(ctx, m)
if err != nil {
log.WithError(err).Warnf("failed to query market info for product: %v, skipped", m.ID)
continue
}
marketMap[toGlobalSymbol(m.ID)] = *marketInfo
marketMap[toGlobalSymbol(m.ID)] = toGlobalMarket(&m)
}
return marketMap, nil
}

func (e *Exchange) queryMarketDetails(ctx context.Context, m api.MarketInfo) (*types.Market, error) {
// wait for the rate limit
done := false
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
err := queryMarketDataLimiter.Wait(ctx)
if err == nil {
done = true
break
}
}
if done {
break
}
}
reqTicker := e.client.NewGetTickerRequest()
reqTicker.ProductID(m.ID)
ticker, err := reqTicker.Do(ctx)
if err != nil {
return nil, errors.Wrapf(err, "failed to fetch ticker for %v", m.ID)
}
market := toGlobalMarket(&m, ticker)
return &market, nil
}

func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticker, error) {
req := e.client.NewGetTickerRequest().ProductID(toLocalSymbol(symbol))
cbTicker, err := req.Do(ctx)
Expand Down
33 changes: 24 additions & 9 deletions pkg/exchange/coinbase/exchange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ func Test_Symbols(t *testing.T) {

func Test_OrdersAPI(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

// should fail on unsupported symbol
order, err := ex.SubmitOrder(
Expand Down Expand Up @@ -103,21 +104,26 @@ func Test_OrdersAPI(t *testing.T) {

func Test_QueryAccount(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

_, err := ex.QueryAccount(ctx)
assert.NoError(t, err)
}

func Test_QueryAccountBalances(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

_, err := ex.QueryAccountBalances(ctx)
assert.NoError(t, err)
}

func Test_QueryOpenOrders(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

symbols := []string{"BTCUSD", "ETHUSD", "ETHBTC"}
for _, k := range symbols {
Expand All @@ -128,22 +134,28 @@ func Test_QueryOpenOrders(t *testing.T) {

func Test_QueryMarkets(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

_, err := ex.QueryMarkets(ctx)
assert.NoError(t, err)
}

func Test_QueryTicker(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

ticker, err := ex.QueryTicker(ctx, "BTCUSD")
assert.NoError(t, err)
assert.NotNil(t, ticker)
}

func Test_QueryTickers(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

symbols := []string{"BTCUSD", "ETHUSD", "ETHBTC"}
tickers, err := ex.QueryTickers(ctx, symbols...)
assert.NoError(t, err)
Expand All @@ -152,7 +164,9 @@ func Test_QueryTickers(t *testing.T) {

func Test_QueryKLines(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

// should fail on unsupported interval
_, err := ex.QueryKLines(ctx, "BTCUSD", types.Interval12h, types.KLineQueryOptions{})
assert.Error(t, err)
Expand All @@ -178,7 +192,8 @@ func Test_QueryKLines(t *testing.T) {

func Test_QueryOrderTrades(t *testing.T) {
ex := getExchangeOrSkip(t)
ctx := context.Background()
ctx, cancel := context.WithTimeout(context.Background(), time.Second*10)
defer cancel()

trades, err := ex.QueryOrderTrades(ctx, types.OrderQuery{Symbol: "ETHUSD"})
assert.NoError(t, err)
Expand Down
Loading