Skip to content

Commit f6b178e

Browse files
author
River.Shi
committed
Update rate limiting configurations across multiple exchanges and bump package versions
- Increased timeout values for Bitget, Bybit, HyperLiquid, and OKX rate limiters to improve request handling. - Refactored Bybit rate limiter to use sliding window strategy and adjusted rate limits for various endpoints. - Updated version in pyproject.toml and uv.lock to 0.2.22 and throttled-py to 2.2.3 for enhanced performance and stability.
1 parent 1f22a68 commit f6b178e

File tree

9 files changed

+412
-357
lines changed

9 files changed

+412
-357
lines changed

nexustrader/exchange/binance/constants.py

Lines changed: 217 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -587,110 +587,225 @@ class BinanceRateLimitType(Enum):
587587

588588

589589
class BinanceRateLimiter(RateLimiter):
590+
# /api/v3 rate limits
591+
# [
592+
# {
593+
# "rateLimitType": "REQUEST_WEIGHT",
594+
# "interval": "MINUTE",
595+
# "intervalNum": 1,
596+
# "limit": 6000,
597+
# },
598+
# {
599+
# "rateLimitType": "ORDERS",
600+
# "interval": "SECOND",
601+
# "intervalNum": 10,
602+
# "limit": 100,
603+
# },
604+
# {
605+
# "rateLimitType": "ORDERS",
606+
# "interval": "DAY",
607+
# "intervalNum": 1,
608+
# "limit": 200000,
609+
# },
610+
# {
611+
# "rateLimitType": "RAW_REQUESTS",
612+
# "interval": "MINUTE",
613+
# "intervalNum": 5,
614+
# "limit": 61000,
615+
# },
616+
# ]
617+
618+
# /fapi/v1 rate limits
619+
# [
620+
# {
621+
# "rateLimitType": "REQUEST_WEIGHT",
622+
# "interval": "MINUTE",
623+
# "intervalNum": 1,
624+
# "limit": 2400,
625+
# },
626+
# {
627+
# "rateLimitType": "ORDERS",
628+
# "interval": "MINUTE",
629+
# "intervalNum": 1,
630+
# "limit": 1200,
631+
# },
632+
# {
633+
# "rateLimitType": "ORDERS",
634+
# "interval": "SECOND",
635+
# "intervalNum": 10,
636+
# "limit": 300,
637+
# },
638+
# ]
639+
640+
# [
641+
# {
642+
# "rateLimitType": "REQUEST_WEIGHT",
643+
# "interval": "MINUTE",
644+
# "intervalNum": 1,
645+
# "limit": 2400,
646+
# },
647+
# {
648+
# "rateLimitType": "ORDERS",
649+
# "interval": "MINUTE",
650+
# "intervalNum": 1,
651+
# "limit": 1200,
652+
# },
653+
# ]
654+
590655
def __init__(self, enable_rate_limit: bool = True):
591-
self._throttled: dict[
592-
BinanceAccountType, dict[BinanceRateLimitType, Throttled]
593-
] = {
594-
BinanceAccountType.SPOT: {
595-
BinanceRateLimitType.ORDERS: Throttled(
596-
quota=rate_limiter.per_duration(timedelta(seconds=10), limit=50),
597-
timeout=10 if enable_rate_limit else -1,
598-
),
599-
BinanceRateLimitType.REQUEST_WEIGHT: Throttled(
600-
quota=rate_limiter.per_min(6000),
601-
timeout=60 if enable_rate_limit else -1,
602-
),
603-
},
604-
BinanceAccountType.USD_M_FUTURE: {
605-
BinanceRateLimitType.ORDERS: Throttled(
606-
quota=rate_limiter.per_duration(timedelta(seconds=10), limit=300),
607-
timeout=10 if enable_rate_limit else -1,
608-
),
609-
BinanceRateLimitType.REQUEST_WEIGHT: Throttled(
610-
quota=rate_limiter.per_min(6000),
611-
timeout=60 if enable_rate_limit else -1,
612-
),
613-
},
614-
BinanceAccountType.COIN_M_FUTURE: {
615-
BinanceRateLimitType.ORDERS: Throttled(
616-
quota=rate_limiter.per_min(6000),
617-
timeout=60 if enable_rate_limit else -1,
618-
),
619-
BinanceRateLimitType.REQUEST_WEIGHT: Throttled(
620-
quota=rate_limiter.per_min(6000),
621-
timeout=60 if enable_rate_limit else -1,
622-
),
623-
},
624-
BinanceAccountType.PORTFOLIO_MARGIN: {
625-
BinanceRateLimitType.ORDERS: Throttled(
626-
quota=rate_limiter.per_min(1200),
627-
timeout=60 if enable_rate_limit else -1,
628-
),
629-
BinanceRateLimitType.REQUEST_WEIGHT: Throttled(
630-
quota=rate_limiter.per_min(6000),
631-
timeout=60 if enable_rate_limit else -1,
632-
),
633-
},
634-
}
635-
636-
def __call__(
637-
self, account_type: BinanceAccountType, rate_limit_type: BinanceRateLimitType
638-
) -> Throttled:
639-
return self._throttled[account_type][rate_limit_type]
656+
self._api_weight_limit = Throttled(
657+
quota=rate_limiter.per_min(6000),
658+
timeout=120 if enable_rate_limit else -1,
659+
)
660+
self._api_order_sec_limit = Throttled(
661+
quota=rate_limiter.per_duration(timedelta(seconds=10), limit=100),
662+
timeout=60 if enable_rate_limit else -1,
663+
)
664+
self._api_order_day_limit = Throttled(
665+
quota=rate_limiter.per_day(200000),
666+
timeout=24 * 60 * 60 * 2 if enable_rate_limit else -1,
667+
)
668+
669+
self._fapi_weight_limit = Throttled(
670+
quota=rate_limiter.per_min(2400),
671+
timeout=120 if enable_rate_limit else -1,
672+
)
673+
self._fapi_order_sec_limit = Throttled(
674+
quota=rate_limiter.per_duration(timedelta(seconds=10), limit=300),
675+
timeout=60 if enable_rate_limit else -1,
676+
)
677+
self._fapi_order_min_limit = Throttled(
678+
quota=rate_limiter.per_min(1200),
679+
timeout=120 if enable_rate_limit else -1,
680+
)
681+
self._dapi_weight_limit = Throttled(
682+
quota=rate_limiter.per_min(2400),
683+
timeout=120 if enable_rate_limit else -1,
684+
)
685+
self._dapi_order_min_limit = Throttled(
686+
quota=rate_limiter.per_min(1200),
687+
timeout=120 if enable_rate_limit else -1,
688+
)
689+
690+
self._papi_weight_limit = Throttled(
691+
quota=rate_limiter.per_min(6000),
692+
timeout=120 if enable_rate_limit else -1,
693+
)
694+
self._papi_order_min_limit = Throttled(
695+
quota=rate_limiter.per_min(1200),
696+
timeout=120 if enable_rate_limit else -1,
697+
)
698+
699+
async def api_weight_limit(self, cost: int):
700+
await self._api_weight_limit.limit(key="/api", cost=cost)
701+
702+
async def api_order_limit(
703+
self, cost: int, order_sec_cost: int = 1, order_day_cost: int = 1
704+
):
705+
await self._api_weight_limit.limit(key="/api", cost=cost)
706+
await self._api_order_sec_limit.limit(key="/api", cost=order_sec_cost)
707+
await self._api_order_day_limit.limit(key="/api", cost=order_day_cost)
708+
709+
async def fapi_weight_limit(self, cost: int):
710+
await self._fapi_weight_limit.limit(key="/fapi", cost=cost)
711+
712+
async def fapi_order_limit(
713+
self, cost: int = 1, order_sec_cost: int = 1, order_min_cost: int = 1
714+
):
715+
await self._fapi_weight_limit.limit(key="/fapi", cost=cost)
716+
await self._fapi_order_sec_limit.limit(key="/fapi", cost=order_sec_cost)
717+
await self._fapi_order_min_limit.limit(key="/fapi", cost=order_min_cost)
718+
719+
async def dapi_weight_limit(self, cost: int):
720+
await self._dapi_weight_limit.limit(key="/dapi", cost=cost)
721+
722+
async def dapi_order_limit(self, cost: int = 1, order_min_cost: int = 1):
723+
await self._dapi_weight_limit.limit(key="/dapi", cost=cost)
724+
await self._dapi_order_min_limit.limit(key="/dapi", cost=order_min_cost)
725+
726+
async def papi_weight_limit(self, cost: int):
727+
await self._papi_weight_limit.limit(key="/papi", cost=cost)
728+
729+
async def papi_order_limit(self, cost: int = 1, order_min_cost: int = 1):
730+
await self._papi_weight_limit.limit(key="/papi", cost=cost)
731+
await self._papi_order_min_limit.limit(key="/papi", cost=order_min_cost)
640732

641733

642734
class BinanceRateLimiterSync(RateLimiterSync):
643735
def __init__(self, enable_rate_limit: bool = True):
644-
self._throttled: dict[
645-
BinanceAccountType, dict[BinanceRateLimitType, ThrottledSync]
646-
] = {
647-
BinanceAccountType.SPOT: {
648-
BinanceRateLimitType.ORDERS: ThrottledSync(
649-
quota=rate_limiter_sync.per_duration(
650-
timedelta(seconds=10), limit=50
651-
),
652-
timeout=10 if enable_rate_limit else -1,
653-
),
654-
BinanceRateLimitType.REQUEST_WEIGHT: ThrottledSync(
655-
quota=rate_limiter_sync.per_min(6000),
656-
timeout=60 if enable_rate_limit else -1,
657-
),
658-
},
659-
BinanceAccountType.USD_M_FUTURE: {
660-
BinanceRateLimitType.ORDERS: ThrottledSync(
661-
quota=rate_limiter_sync.per_duration(
662-
timedelta(seconds=10), limit=300
663-
),
664-
timeout=10 if enable_rate_limit else -1,
665-
),
666-
BinanceRateLimitType.REQUEST_WEIGHT: ThrottledSync(
667-
quota=rate_limiter_sync.per_min(6000),
668-
timeout=60 if enable_rate_limit else -1,
669-
),
670-
},
671-
BinanceAccountType.COIN_M_FUTURE: {
672-
BinanceRateLimitType.ORDERS: ThrottledSync(
673-
quota=rate_limiter_sync.per_min(6000),
674-
timeout=60 if enable_rate_limit else -1,
675-
),
676-
BinanceRateLimitType.REQUEST_WEIGHT: ThrottledSync(
677-
quota=rate_limiter_sync.per_min(6000),
678-
timeout=60 if enable_rate_limit else -1,
679-
),
680-
},
681-
BinanceAccountType.PORTFOLIO_MARGIN: {
682-
BinanceRateLimitType.ORDERS: ThrottledSync(
683-
quota=rate_limiter_sync.per_min(1200),
684-
timeout=60 if enable_rate_limit else -1,
685-
),
686-
BinanceRateLimitType.REQUEST_WEIGHT: ThrottledSync(
687-
quota=rate_limiter_sync.per_min(6000),
688-
timeout=60 if enable_rate_limit else -1,
689-
),
690-
},
691-
}
692-
693-
def __call__(
694-
self, account_type: BinanceAccountType, rate_limit_type: BinanceRateLimitType
695-
) -> ThrottledSync:
696-
return self._throttled[account_type][rate_limit_type]
736+
self._api_weight_limit = ThrottledSync(
737+
quota=rate_limiter_sync.per_min(6000),
738+
timeout=60 if enable_rate_limit else -1,
739+
)
740+
self._api_order_sec_limit = ThrottledSync(
741+
quota=rate_limiter_sync.per_duration(timedelta(seconds=10), limit=100),
742+
timeout=60 if enable_rate_limit else -1,
743+
)
744+
self._api_order_day_limit = ThrottledSync(
745+
quota=rate_limiter_sync.per_day(200000),
746+
timeout=24 * 60 * 60 * 2 if enable_rate_limit else -1,
747+
)
748+
749+
self._fapi_weight_limit = ThrottledSync(
750+
quota=rate_limiter_sync.per_min(2400),
751+
timeout=60 if enable_rate_limit else -1,
752+
)
753+
self._fapi_order_sec_limit = ThrottledSync(
754+
quota=rate_limiter_sync.per_duration(timedelta(seconds=10), limit=300),
755+
timeout=60 if enable_rate_limit else -1,
756+
)
757+
self._fapi_order_min_limit = ThrottledSync(
758+
quota=rate_limiter_sync.per_min(1200),
759+
timeout=60 if enable_rate_limit else -1,
760+
)
761+
self._dapi_weight_limit = ThrottledSync(
762+
quota=rate_limiter_sync.per_min(2400),
763+
timeout=60 if enable_rate_limit else -1,
764+
)
765+
self._dapi_order_min_limit = ThrottledSync(
766+
quota=rate_limiter_sync.per_min(1200),
767+
timeout=60 if enable_rate_limit else -1,
768+
)
769+
770+
self._papi_weight_limit = ThrottledSync(
771+
quota=rate_limiter_sync.per_min(6000),
772+
timeout=60 if enable_rate_limit else -1,
773+
)
774+
self._papi_order_min_limit = ThrottledSync(
775+
quota=rate_limiter_sync.per_min(1200),
776+
timeout=60 if enable_rate_limit else -1,
777+
)
778+
779+
def api_weight_limit(self, cost: int):
780+
self._api_weight_limit.limit(key="/api", cost=cost)
781+
782+
def api_order_limit(
783+
self, cost: int, order_sec_cost: int = 1, order_day_cost: int = 1
784+
):
785+
self._api_weight_limit.limit(key="/api", cost=cost)
786+
self._api_order_sec_limit.limit(key="/api", cost=order_sec_cost)
787+
self._api_order_day_limit.limit(key="/api", cost=order_day_cost)
788+
789+
def fapi_weight_limit(self, cost: int):
790+
self._fapi_weight_limit.limit(key="/fapi", cost=cost)
791+
792+
def fapi_order_limit(
793+
self, cost: int = 1, order_sec_cost: int = 1, order_min_cost: int = 1
794+
):
795+
self._fapi_weight_limit.limit(key="/fapi", cost=cost)
796+
self._fapi_order_sec_limit.limit(key="/fapi", cost=order_sec_cost)
797+
self._fapi_order_min_limit.limit(key="/fapi", cost=order_min_cost)
798+
799+
def dapi_weight_limit(self, cost: int):
800+
self._dapi_weight_limit.limit(key="/dapi", cost=cost)
801+
802+
def dapi_order_limit(self, cost: int = 1, order_min_cost: int = 1):
803+
self._dapi_weight_limit.limit(key="/dapi", cost=cost)
804+
self._dapi_order_min_limit.limit(key="/dapi", cost=order_min_cost)
805+
806+
def papi_weight_limit(self, cost: int):
807+
self._papi_weight_limit.limit(key="/papi", cost=cost)
808+
809+
def papi_order_limit(self, cost: int = 1, order_min_cost: int = 1):
810+
self._papi_weight_limit.limit(key="/papi", cost=cost)
811+
self._papi_order_min_limit.limit(key="/papi", cost=order_min_cost)

0 commit comments

Comments
 (0)