Files
gocryptotrader/exchanges/kucoin/kucoin_ratelimit.go
Samuael A 6105071114 exchanges: Add Kucoin support (#1102)
* init

* updates config

* wrapper configuration

* updates exchange readme

* adds SendAuthHTTPRequest and SendHTTPRequest

* adds ratelimit file

* adds test case and minor fixes

* improve error handling

* update testcases and improve GetSymbols API

* adds SPOT API's

* minor fix

* WIP

* WIP

* adds test case

* adds check in test case

* fixes in Auth. HTTP

* improvements

* adds trade, kline support and testcases

* adds SPOT API and testcases for same

* adds SPOT API and testcases

* adds SPOT API and testcase

* WIP

* adds API's

* adds API's

* adds test cases

* adds comment to exported data types

* adds API and test cases

* adds API

* adds API

* rearrange functions

* WIP: adds API

* adds API for Post Order SPOT

* adds API and few fixes

* fixes

* WIP

* WIP

* add PostBulkOrder API and its test case

* fix issues

* adds cancel order APIs and test cases for same

* add minor test fixes

* add API

* adds API

* fixes

* add API

* adds API and test cases

* fix test

* adds API

* adds test

* fix test

* adds API and test

* adds deposit API and test cases

* WIP

* adds API and test cases

* WIP

* WIP

* add public future API and test cases

* WIP

* remove v2 API and replace them with v1

* update test cases

* adds future order API and test cases

* adds futures order API

* adds API

* add API and test cases

* adds API and test cases

* adds API and test cases

* adds API and test cases

* Adding wrapper functions

* Fix on wrapper function

* Adding websocket support

* Complete addressing WS push datas

* Adding spot push data unit tests

* adding futures websocket push data handlers

* Adding futures websocket push data handlers

* Added unit tests

* Updating unit tests

* Updating wrapper and unit test functions

* Adding missing wrapper functions and code cleaning up

* Resolved linter issues

* Fixing websocket issues

* Fixing websocket issues

* Slight fix on config_example file

* Minor update

* Basic nits updates

* Fix minor linter issues

* Minor update

* Minor unit test update

* Minor unit test update

* Code update and linter issues fix

* Removed unnecessary type conversion codes

* Monor update based on review comment

* Fix based on review comments

* Adding rate-limiter

* Websocket update and overall minor fixes

* Removed IsAssetTypeEnabled method implementation

* Fix connection and formatting issues

* Updating orderbook issues

* Very minor label fix

* Minor error returning fix

* code cleaning up and minor spelling fix

* Updates on unit test

* Update on unit tests and slight code structure

* unit test update

* orderbook update and minor fix

* fix on race

* Mini linter fix

* fix minor parameter and unit test issues

* handler funcs and models update

* Fixing websocket and unit test issues

* order side string for active orders

* Fix on websocket and unit tests

* Minor type changes

* Minor Orderbook fix and unit test update

* Small fix on orderbook

* Updating orderbook functionality

* FIx on websocket orderbook handlers

* Small update on kucoin websocket

* fix missed review comments

* fix based on review comments

* Updating websocket orderbook and fixing unit tests

* Minor fixes

* unit test update

* Updating unit test according to enabled asset type

* toggle canManipulateRealOrders const

* Unit test update

* Fix minor issues

* minor fix

* documentation fix

* wrapper coverage and unused params fix

* testing and minor changes

* documentation, websocket and unit test update

* minor linter fix

* Websocket spot/margin subscription update

* minor ticker update fix

* minor fixes on endpoints

* timestamp and number convert method and unit tests

* timestamp convert minor update

* minor type and conversion fix

* create a common timestamp convert and fix minor issues

* linter and ticker fix

* Updating unit tests and order placing endpoint methods

* Added a pairs check

* Fix config test error

* rm unused error variable

* Fix source of linter issue

* code update: convert, wrapper and websocket fix

* minor code update

* Websocket code and unit tests update

* Websocket ticker ask/bid type change and small error msg fix

* docs update

* fix: websocket orderbook handling

* change orderbook channel to marketOrderbookLevel2Channels and fix websocket orderbook update

* Minor func rename and reciever change

* Minor orderbook unit test issue fix

* comment: about why we used a random delimiter '-' for futures

* update config files and FetchTradablePair func for futures pairs

* futures config pairs update

* remove ConnextionMonitorDelay from websocket setup

* fix on types and futures pair conversion

* updating config pairs

* change NewPairFromString to DeriveFrom

* unit tests update

* unit tests update

* Added TickerBatching

* added GetStandardConfig to GetDefaultConfig

---------

Co-authored-by: Jaydeep Rajpurohit <jaydeeppurohit1996@gmail.com>
2023-09-27 15:09:38 +10:00

245 lines
9.9 KiB
Go

package kucoin
import (
"context"
"errors"
"fmt"
"time"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"golang.org/x/time/rate"
)
const (
threeSecondsInterval = time.Second * 3
oneMinuteInterval = time.Minute
)
// RateLimit implements the request.Limiter interface
type RateLimit struct {
RetrieveAccountLedger *rate.Limiter
MasterSubUserTransfer *rate.Limiter
RetrieveDepositList *rate.Limiter
RetrieveV1HistoricalDepositList *rate.Limiter
RetrieveWithdrawalList *rate.Limiter
RetrieveV1HistoricalWithdrawalList *rate.Limiter
PlaceOrder *rate.Limiter
PlaceMarginOrders *rate.Limiter
PlaceBulkOrders *rate.Limiter
CancelOrder *rate.Limiter
CancelAllOrders *rate.Limiter
ListOrders *rate.Limiter
ListFills *rate.Limiter
RetrieveFullOrderbook *rate.Limiter
RetrieveMarginAccount *rate.Limiter
SpotRate *rate.Limiter
FuturesRate *rate.Limiter
FRetrieveAccountOverviewRate *rate.Limiter
FRetrieveTransactionHistoryRate *rate.Limiter
FPlaceOrderRate *rate.Limiter
FCancelAnOrderRate *rate.Limiter
FLimitOrderMassCancelationRate *rate.Limiter
FRetrieveOrderListRate *rate.Limiter
FRetrieveFillsRate *rate.Limiter
FRecentFillsRate *rate.Limiter
FRetrievePositionListRate *rate.Limiter
FRetrieveFundingHistoryRate *rate.Limiter
FRetrieveFullOrderbookLevel2Rate *rate.Limiter
}
// rate of request per interval
const (
retrieveAccountLedgerRate = 18
masterSubUserTransferRate = 3
retrieveDepositListRate = 6
retrieveV1HistoricalDepositListRate = 6
retrieveWithdrawalListRate = 6
retrieveV1HistoricalWithdrawalListRate = 6
placeOrderRate = 45
placeMarginOrdersRate = 45
placeBulkOrdersRate = 3
cancelOrderRate = 60
cancelAllOrdersRate = 3
listOrdersRate = 30
listFillsRate = 9
retrieveFullOrderbookRate = 30
retrieveMarginAccountRate = 1
futuresRetrieveAccountOverviewRate = 30
futuresRetrieveTransactionHistoryRate = 9
futuresPlaceOrderRate = 30
futuresCancelAnOrderRate = 40
futuresLimitOrderMassCancelationRate = 9
futuresRetrieveOrderListRate = 30
futuresRetrieveFillsRate = 9
futuresRecentFillsRate = 9
futuresRetrievePositionListRate = 9
futuresRetrieveFundingHistoryRate = 9
futuresRetrieveFullOrderbookLevel2Rate = 30
defaultSpotRate = 1200
defaultFuturesRate = 1200
)
const (
// for spot endpoints
retrieveAccountLedgerEPL request.EndpointLimit = iota
masterSubUserTransferEPL
retrieveDepositListEPL
retrieveV1HistoricalDepositListEPL
retrieveWithdrawalListEPL
retrieveV1HistoricalWithdrawalListEPL
placeOrderEPL
placeMarginOrdersEPL
placeBulkOrdersEPL
cancelOrderEPL
cancelAllOrdersEPL
listOrdersEPL
listFillsEPL
retrieveFullOrderbookEPL
retrieveMarginAccountEPL
defaultSpotEPL
// for futures endpoints
futuresRetrieveAccountOverviewEPL
futuresRetrieveTransactionHistoryEPL
futuresPlaceOrderEPL
futuresCancelAnOrderEPL
futuresLimitOrderMassCancelationEPL
futuresRetrieveOrderListEPL
futuresRetrieveFillsEPL
futuresRecentFillsEPL
futuresRetrievePositionListEPL
futuresRetrieveFundingHistoryEPL
futuresRetrieveFullOrderbookLevel2EPL
defaultFuturesEPL
)
// Limit executes rate limiting functionality for Kucoin
func (r *RateLimit) Limit(ctx context.Context, epl request.EndpointLimit) error {
var limiter *rate.Limiter
var tokens int
switch epl {
case retrieveAccountLedgerEPL:
return r.RetrieveAccountLedger.Wait(ctx)
case masterSubUserTransferEPL:
return r.MasterSubUserTransfer.Wait(ctx)
case retrieveDepositListEPL:
return r.RetrieveDepositList.Wait(ctx)
case retrieveV1HistoricalDepositListEPL:
return r.RetrieveV1HistoricalDepositList.Wait(ctx)
case retrieveWithdrawalListEPL:
return r.RetrieveWithdrawalList.Wait(ctx)
case retrieveV1HistoricalWithdrawalListEPL:
return r.RetrieveV1HistoricalWithdrawalList.Wait(ctx)
case placeOrderEPL:
return r.PlaceOrder.Wait(ctx)
case placeMarginOrdersEPL:
return r.PlaceMarginOrders.Wait(ctx)
case placeBulkOrdersEPL:
return r.PlaceBulkOrders.Wait(ctx)
case cancelOrderEPL:
return r.CancelOrder.Wait(ctx)
case cancelAllOrdersEPL:
return r.CancelAllOrders.Wait(ctx)
case listOrdersEPL:
return r.ListOrders.Wait(ctx)
case listFillsEPL:
return r.ListFills.Wait(ctx)
case retrieveFullOrderbookEPL:
return r.RetrieveFullOrderbook.Wait(ctx)
case retrieveMarginAccountEPL:
return r.RetrieveMarginAccount.Wait(ctx)
case futuresRetrieveAccountOverviewEPL:
return r.FRetrieveAccountOverviewRate.Wait(ctx)
case futuresRetrieveTransactionHistoryEPL:
return r.FRetrieveTransactionHistoryRate.Wait(ctx)
case futuresPlaceOrderEPL:
return r.FPlaceOrderRate.Wait(ctx)
case futuresCancelAnOrderEPL:
return r.FCancelAnOrderRate.Wait(ctx)
case futuresLimitOrderMassCancelationEPL:
return r.FLimitOrderMassCancelationRate.Wait(ctx)
case futuresRetrieveOrderListEPL:
return r.FRetrieveOrderListRate.Wait(ctx)
case futuresRetrieveFillsEPL:
return r.FRetrieveFillsRate.Wait(ctx)
case futuresRecentFillsEPL:
return r.FRecentFillsRate.Wait(ctx)
case futuresRetrievePositionListEPL:
return r.FRetrievePositionListRate.Wait(ctx)
case futuresRetrieveFundingHistoryEPL:
return r.FRetrieveFundingHistoryRate.Wait(ctx)
case futuresRetrieveFullOrderbookLevel2EPL:
return r.FRetrieveFullOrderbookLevel2Rate.Wait(ctx)
case defaultSpotEPL:
limiter, tokens = r.SpotRate, 1
case defaultFuturesEPL:
limiter, tokens = r.FuturesRate, 1
default:
return errors.New("endpoint rate limit functionality not found")
}
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 a RateLimit instance, which implements the request.Limiter interface.
func SetRateLimit() *RateLimit {
return &RateLimit{
// spot specific rate limiters
RetrieveAccountLedger: request.NewRateLimit(threeSecondsInterval, retrieveAccountLedgerRate),
MasterSubUserTransfer: request.NewRateLimit(threeSecondsInterval, masterSubUserTransferRate),
RetrieveDepositList: request.NewRateLimit(threeSecondsInterval, retrieveDepositListRate),
RetrieveV1HistoricalDepositList: request.NewRateLimit(threeSecondsInterval, retrieveV1HistoricalDepositListRate),
RetrieveWithdrawalList: request.NewRateLimit(threeSecondsInterval, retrieveWithdrawalListRate),
RetrieveV1HistoricalWithdrawalList: request.NewRateLimit(threeSecondsInterval, retrieveV1HistoricalWithdrawalListRate),
PlaceOrder: request.NewRateLimit(threeSecondsInterval, placeOrderRate),
PlaceMarginOrders: request.NewRateLimit(threeSecondsInterval, placeMarginOrdersRate),
PlaceBulkOrders: request.NewRateLimit(threeSecondsInterval, placeBulkOrdersRate),
CancelOrder: request.NewRateLimit(threeSecondsInterval, cancelOrderRate),
CancelAllOrders: request.NewRateLimit(threeSecondsInterval, cancelAllOrdersRate),
ListOrders: request.NewRateLimit(threeSecondsInterval, listOrdersRate),
ListFills: request.NewRateLimit(threeSecondsInterval, listFillsRate),
RetrieveFullOrderbook: request.NewRateLimit(threeSecondsInterval, retrieveFullOrderbookRate),
RetrieveMarginAccount: request.NewRateLimit(threeSecondsInterval, retrieveMarginAccountRate),
// default spot and futures rates
SpotRate: request.NewRateLimit(oneMinuteInterval, defaultSpotRate),
FuturesRate: request.NewRateLimit(oneMinuteInterval, defaultFuturesRate),
// futures specific rate limiters
FRetrieveAccountOverviewRate: request.NewRateLimit(threeSecondsInterval, futuresRetrieveAccountOverviewRate),
FRetrieveTransactionHistoryRate: request.NewRateLimit(threeSecondsInterval, futuresRetrieveTransactionHistoryRate),
FPlaceOrderRate: request.NewRateLimit(threeSecondsInterval, futuresPlaceOrderRate),
FCancelAnOrderRate: request.NewRateLimit(threeSecondsInterval, futuresCancelAnOrderRate),
FLimitOrderMassCancelationRate: request.NewRateLimit(threeSecondsInterval, futuresLimitOrderMassCancelationRate),
FRetrieveOrderListRate: request.NewRateLimit(threeSecondsInterval, futuresRetrieveOrderListRate),
FRetrieveFillsRate: request.NewRateLimit(threeSecondsInterval, futuresRetrieveFillsRate),
FRecentFillsRate: request.NewRateLimit(threeSecondsInterval, futuresRecentFillsRate),
FRetrievePositionListRate: request.NewRateLimit(threeSecondsInterval, futuresRetrievePositionListRate),
FRetrieveFundingHistoryRate: request.NewRateLimit(threeSecondsInterval, futuresRetrieveFundingHistoryRate),
FRetrieveFullOrderbookLevel2Rate: request.NewRateLimit(threeSecondsInterval, futuresRetrieveFullOrderbookLevel2Rate),
}
}