Files
gocryptotrader/exchanges/binance/ratelimit.go
Scott 5f2f6f884b Binance,Okx: Add Leverage, MarginType, Positions and CollateralMode support (#1220)
* init

* surprise train commit

* basic distinctions

* the terms of binance are confusing

* renames and introduction of allocatedMargin

* add new margin funcs

* pulling out wires

* implement proper getposition stuff

* bad coding day

* investigate order manager next

* a broken mess, but a progressing one

* finally completes some usdtmargined stuff

* coinMfutures eludes me

* expand to okx

* imports fix

* completes okx wrapper implementations

* cleans and polishes before rpc implementations

* rpc setup, order manager features, exch features

* more rpc, collateral and margin things

* mini test

* looking at rpc response, expansion of features

* reorganising before the storm

* changing how futures requests work

* cleanup and tests of cli usage

* remove silly client side logic

* cleanup

* collateral package, typo fix, margin err, rpc derive

* uses convert.StringToFloat ONLY ON STRUCTS FROM THIS PR

* fix binance order history bug

* niteroos

* adds new funcs to exchange standards testing

* more post merge fixes

* fix binance

* replace simepletimeformat

* fix for merge

* merge fixes

* micro fixes

* order side now required for leverage

* fix up the rest

* global -> portfolio collateral

* Update exchanges/collateral/collateral_test.go

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>

* adds fields and todos

* rm field redundancy

* lint fix oopsie daisy

* fixes panic, expands error and cli explanations (sorry shaz)

* ensures casing is appropriate for underlying

* Adds a shiny TODO

---------

Co-authored-by: Adrian Gallagher <adrian.gallagher@thrasher.io>
2023-09-26 16:16:31 +10:00

288 lines
8.5 KiB
Go

package binance
import (
"context"
"fmt"
"time"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"golang.org/x/time/rate"
)
const (
// Binance limit rates
// Global dictates the max rate limit for general request items which is
// 1200 requests per minute
spotInterval = time.Minute
spotRequestRate = 1200
// Order related limits which are segregated from the global rate limits
// 100 requests per 10 seconds and max 100000 requests per day.
spotOrderInterval = 10 * time.Second
spotOrderRequestRate = 100
cFuturesInterval = time.Minute
cFuturesRequestRate = 6000
cFuturesOrderInterval = time.Minute
cFuturesOrderRequestRate = 1200
uFuturesInterval = time.Minute
uFuturesRequestRate = 2400
uFuturesOrderInterval = time.Minute
uFuturesOrderRequestRate = 1200
)
// Binance Spot rate limits
const (
spotDefaultRate request.EndpointLimit = iota
spotExchangeInfo
spotHistoricalTradesRate
spotOrderbookDepth500Rate
spotOrderbookDepth1000Rate
spotOrderbookDepth5000Rate
spotOrderbookTickerAllRate
spotPriceChangeAllRate
spotSymbolPriceAllRate
spotOpenOrdersAllRate
spotOpenOrdersSpecificRate
spotOrderRate
spotOrderQueryRate
spotAllOrdersRate
spotAccountInformationRate
uFuturesDefaultRate
uFuturesHistoricalTradesRate
uFuturesSymbolOrdersRate
uFuturesPairOrdersRate
uFuturesCurrencyForceOrdersRate
uFuturesAllForceOrdersRate
uFuturesIncomeHistoryRate
uFuturesOrderbook50Rate
uFuturesOrderbook100Rate
uFuturesOrderbook500Rate
uFuturesOrderbook1000Rate
uFuturesKline100Rate
uFuturesKline500Rate
uFuturesKline1000Rate
uFuturesKlineMaxRate
uFuturesTickerPriceHistoryRate
uFuturesOrdersDefaultRate
uFuturesGetAllOrdersRate
uFuturesAccountInformationRate
uFuturesOrderbookTickerAllRate
uFuturesCountdownCancelRate
uFuturesBatchOrdersRate
uFuturesGetAllOpenOrdersRate
cFuturesDefaultRate
cFuturesHistoricalTradesRate
cFuturesTickerPriceHistoryRate
cFuturesIncomeHistoryRate
cFuturesOrderbook50Rate
cFuturesOrderbook100Rate
cFuturesOrderbook500Rate
cFuturesOrderbook1000Rate
cFuturesKline100Rate
cFuturesKline500Rate
cFuturesKline1000Rate
cFuturesKlineMaxRate
cFuturesIndexMarkPriceRate
cFuturesBatchOrdersRate
cFuturesCancelAllOrdersRate
cFuturesGetAllOpenOrdersRate
cFuturesAllForceOrdersRate
cFuturesCurrencyForceOrdersRate
cFuturesPairOrdersRate
cFuturesSymbolOrdersRate
cFuturesAccountInformationRate
cFuturesOrderbookTickerAllRate
cFuturesOrdersDefaultRate
uFuturesMultiAssetMarginRate
uFuturesSetMultiAssetMarginRate
)
// RateLimit implements the request.Limiter interface
type RateLimit struct {
SpotRate *rate.Limiter
SpotOrdersRate *rate.Limiter
UFuturesRate *rate.Limiter
UFuturesOrdersRate *rate.Limiter
CFuturesRate *rate.Limiter
CFuturesOrdersRate *rate.Limiter
}
// Limit executes rate limiting functionality for Binance
func (r *RateLimit) Limit(ctx context.Context, f request.EndpointLimit) error {
var limiter *rate.Limiter
var tokens int
switch f {
case spotDefaultRate:
limiter, tokens = r.SpotRate, 1
case spotOrderbookTickerAllRate,
spotSymbolPriceAllRate:
limiter, tokens = r.SpotRate, 2
case spotHistoricalTradesRate,
spotOrderbookDepth500Rate:
limiter, tokens = r.SpotRate, 5
case spotOrderbookDepth1000Rate,
spotAccountInformationRate,
spotExchangeInfo:
limiter, tokens = r.SpotRate, 10
case spotPriceChangeAllRate:
limiter, tokens = r.SpotRate, 40
case spotOrderbookDepth5000Rate:
limiter, tokens = r.SpotRate, 50
case spotOrderRate:
limiter, tokens = r.SpotOrdersRate, 1
case spotOrderQueryRate:
limiter, tokens = r.SpotOrdersRate, 2
case spotOpenOrdersSpecificRate:
limiter, tokens = r.SpotOrdersRate, 3
case spotAllOrdersRate:
limiter, tokens = r.SpotOrdersRate, 10
case spotOpenOrdersAllRate:
limiter, tokens = r.SpotOrdersRate, 40
case uFuturesDefaultRate,
uFuturesKline100Rate:
limiter, tokens = r.UFuturesRate, 1
case uFuturesOrderbook50Rate,
uFuturesKline500Rate,
uFuturesOrderbookTickerAllRate:
limiter, tokens = r.UFuturesRate, 2
case uFuturesOrderbook100Rate,
uFuturesKline1000Rate,
uFuturesAccountInformationRate:
limiter, tokens = r.UFuturesRate, 5
case uFuturesOrderbook500Rate,
uFuturesKlineMaxRate:
limiter, tokens = r.UFuturesRate, 10
case uFuturesOrderbook1000Rate,
uFuturesHistoricalTradesRate:
limiter, tokens = r.UFuturesRate, 20
case uFuturesTickerPriceHistoryRate:
limiter, tokens = r.UFuturesRate, 40
case uFuturesOrdersDefaultRate:
limiter, tokens = r.UFuturesOrdersRate, 1
case uFuturesBatchOrdersRate,
uFuturesGetAllOrdersRate:
limiter, tokens = r.UFuturesOrdersRate, 5
case uFuturesCountdownCancelRate:
limiter, tokens = r.UFuturesOrdersRate, 10
case uFuturesCurrencyForceOrdersRate,
uFuturesSymbolOrdersRate:
limiter, tokens = r.UFuturesOrdersRate, 20
case uFuturesIncomeHistoryRate:
limiter, tokens = r.UFuturesOrdersRate, 30
case uFuturesPairOrdersRate,
uFuturesGetAllOpenOrdersRate:
limiter, tokens = r.UFuturesOrdersRate, 40
case uFuturesAllForceOrdersRate:
limiter, tokens = r.UFuturesOrdersRate, 50
case cFuturesKline100Rate:
limiter, tokens = r.CFuturesRate, 1
case cFuturesKline500Rate,
cFuturesOrderbookTickerAllRate:
limiter, tokens = r.CFuturesRate, 2
case cFuturesKline1000Rate,
cFuturesAccountInformationRate:
limiter, tokens = r.CFuturesRate, 5
case cFuturesKlineMaxRate,
cFuturesIndexMarkPriceRate:
limiter, tokens = r.CFuturesRate, 10
case cFuturesHistoricalTradesRate,
cFuturesCurrencyForceOrdersRate:
limiter, tokens = r.CFuturesRate, 20
case cFuturesTickerPriceHistoryRate:
limiter, tokens = r.CFuturesRate, 40
case cFuturesAllForceOrdersRate:
limiter, tokens = r.CFuturesRate, 50
case cFuturesOrdersDefaultRate:
limiter, tokens = r.CFuturesOrdersRate, 1
case cFuturesBatchOrdersRate,
cFuturesGetAllOpenOrdersRate:
limiter, tokens = r.CFuturesOrdersRate, 5
case cFuturesCancelAllOrdersRate:
limiter, tokens = r.CFuturesOrdersRate, 10
case cFuturesIncomeHistoryRate,
cFuturesSymbolOrdersRate:
limiter, tokens = r.CFuturesOrdersRate, 20
case cFuturesPairOrdersRate:
limiter, tokens = r.CFuturesOrdersRate, 40
case cFuturesOrderbook50Rate:
limiter, tokens = r.CFuturesRate, 2
case cFuturesOrderbook100Rate:
limiter, tokens = r.CFuturesRate, 5
case cFuturesOrderbook500Rate:
limiter, tokens = r.CFuturesRate, 10
case cFuturesOrderbook1000Rate:
limiter, tokens = r.CFuturesRate, 20
case cFuturesDefaultRate:
limiter, tokens = r.CFuturesRate, 1
case uFuturesMultiAssetMarginRate:
limiter, tokens = r.UFuturesRate, 30
case uFuturesSetMultiAssetMarginRate:
limiter, tokens = r.UFuturesRate, 1
default:
limiter, tokens = r.SpotRate, 1
}
var finalDelay time.Duration
var reserves = make([]*rate.Reservation, tokens)
for i := 0; i < tokens; i++ {
// Consume tokens 1 at a time as this avoids needing burst capacity in the limiter,
// which would otherwise allow the rate limit to be exceeded over short periods
reserves[i] = limiter.Reserve()
finalDelay = reserves[i].Delay()
}
if dl, ok := ctx.Deadline(); ok && dl.Before(time.Now().Add(finalDelay)) {
// Cancel all potential reservations to free up rate limiter if deadline
// is exceeded.
for x := range reserves {
reserves[x].Cancel()
}
return fmt.Errorf("rate limit delay of %s will exceed deadline: %w",
finalDelay,
context.DeadlineExceeded)
}
time.Sleep(finalDelay)
return nil
}
// SetRateLimit returns the rate limit for the exchange
func SetRateLimit() *RateLimit {
return &RateLimit{
SpotRate: request.NewRateLimit(spotInterval, spotRequestRate),
SpotOrdersRate: request.NewRateLimit(spotOrderInterval, spotOrderRequestRate),
UFuturesRate: request.NewRateLimit(uFuturesInterval, uFuturesRequestRate),
UFuturesOrdersRate: request.NewRateLimit(uFuturesOrderInterval, uFuturesOrderRequestRate),
CFuturesRate: request.NewRateLimit(cFuturesInterval, cFuturesRequestRate),
CFuturesOrdersRate: request.NewRateLimit(cFuturesOrderInterval, cFuturesOrderRequestRate),
}
}
func bestPriceLimit(symbol string) request.EndpointLimit {
if symbol == "" {
return spotOrderbookTickerAllRate
}
return spotDefaultRate
}
func openOrdersLimit(symbol string) request.EndpointLimit {
if symbol == "" {
return spotOpenOrdersAllRate
}
return spotOpenOrdersSpecificRate
}
func orderbookLimit(depth int) request.EndpointLimit {
switch {
case depth <= 100:
return spotDefaultRate
case depth <= 500:
return spotOrderbookDepth500Rate
case depth <= 1000:
return spotOrderbookDepth1000Rate
}
return spotOrderbookDepth5000Rate
}