def setUpClass(cls) -> None: super().setUpClass() cls.ev_loop: asyncio.AbstractEventLoop = asyncio.get_event_loop() cls.rate_limits: List[RateLimit] = [ RateLimit(limit_id=TEST_POOL_ID, limit=1, time_interval=5.0), RateLimit(limit_id=TEST_PATH_URL, limit=1, time_interval=5.0, linked_limits=[LinkedLimitWeightPair(TEST_POOL_ID)]), RateLimit(limit_id=TEST_WEIGHTED_POOL_ID, limit=10, time_interval=5.0), RateLimit(limit_id=TEST_WEIGHTED_TASK_1_ID, limit=1000, time_interval=5.0, linked_limits=[ LinkedLimitWeightPair(TEST_WEIGHTED_POOL_ID, 5) ]), RateLimit(limit_id=TEST_WEIGHTED_TASK_2_ID, limit=1000, time_interval=5.0, linked_limits=[ LinkedLimitWeightPair(TEST_WEIGHTED_POOL_ID, 1) ]), ]
def _build_public_rate_limits(): public_rate_limits = [ RateLimit( # same for linear and non-linear limit_id=CONSTANTS.LATEST_SYMBOL_INFORMATION_ENDPOINT[ CONSTANTS.NON_LINEAR_MARKET], limit=CONSTANTS.GET_RATE, time_interval=1, linked_limits=[LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID)], ), RateLimit( # same for linear and non-linear limit_id=CONSTANTS.QUERY_SYMBOL_ENDPOINT[ CONSTANTS.NON_LINEAR_MARKET], limit=CONSTANTS.GET_RATE, time_interval=1, linked_limits=[LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID)], ), RateLimit( # same for linear and non-linear limit_id=CONSTANTS.ORDER_BOOK_ENDPOINT[ CONSTANTS.NON_LINEAR_MARKET], limit=CONSTANTS.GET_RATE, time_interval=1, linked_limits=[LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID)], ), RateLimit( # same for linear and non-linear limit_id=CONSTANTS.SERVER_TIME_PATH_URL[ CONSTANTS.NON_LINEAR_MARKET], limit=CONSTANTS.GET_RATE, time_interval=1, linked_limits=[LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID)], ) ] return public_rate_limits
def _build_private_general_rate_limits() -> List[RateLimit]: rate_limits = [ RateLimit( # same for linear and non-linear limit_id=CONSTANTS.GET_WALLET_BALANCE_PATH_URL[ CONSTANTS.NON_LINEAR_MARKET], limit=120, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID), LinkedLimitWeightPair( CONSTANTS.NON_LINEAR_PRIVATE_BUCKET_120_B_LIMIT_ID) ], ), RateLimit( # same for linear and non-linear limit_id=CONSTANTS.SET_POSITION_MODE_URL[CONSTANTS.LINEAR_MARKET], limit=120, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID), LinkedLimitWeightPair( CONSTANTS.NON_LINEAR_PRIVATE_BUCKET_120_B_LIMIT_ID) ], ), ] return rate_limits
def _build_private_pair_specific_linear_rate_limits( trading_pair: str) -> List[RateLimit]: pair_specific_linear_private_bucket_100_limit_id = get_pair_specific_limit_id( base_limit_id=CONSTANTS.LINEAR_PRIVATE_BUCKET_100_LIMIT_ID, trading_pair=trading_pair) pair_specific_linear_private_bucket_600_limit_id = get_pair_specific_limit_id( base_limit_id=CONSTANTS.LINEAR_PRIVATE_BUCKET_600_LIMIT_ID, trading_pair=trading_pair) pair_specific_linear_private_bucket_75_limit_id = get_pair_specific_limit_id( base_limit_id=CONSTANTS.LINEAR_PRIVATE_BUCKET_75_LIMIT_ID, trading_pair=trading_pair) pair_specific_linear_private_bucket_120_a_limit_id = get_pair_specific_limit_id( base_limit_id=CONSTANTS.LINEAR_PRIVATE_BUCKET_120_A_LIMIT_ID, trading_pair=trading_pair) rate_limits = [ RateLimit(limit_id=pair_specific_linear_private_bucket_100_limit_id, limit=100, time_interval=60), RateLimit(limit_id=pair_specific_linear_private_bucket_600_limit_id, limit=600, time_interval=60), RateLimit(limit_id=pair_specific_linear_private_bucket_75_limit_id, limit=75, time_interval=60), RateLimit(limit_id=pair_specific_linear_private_bucket_120_a_limit_id, limit=120, time_interval=60), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.SET_LEVERAGE_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair), limit=75, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.POST_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_75_limit_id) ], ), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.GET_LAST_FUNDING_RATE_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair, ), limit=120, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_120_a_limit_id) ], ), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.GET_POSITIONS_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair), limit=120, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_120_a_limit_id) ], ), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.PLACE_ACTIVE_ORDER_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair), limit=100, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.POST_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_100_limit_id) ], ), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.CANCEL_ACTIVE_ORDER_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair), limit=100, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.POST_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_100_limit_id) ], ), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.QUERY_ACTIVE_ORDER_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair), limit=600, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_600_limit_id) ], ), RateLimit( limit_id=get_pair_specific_limit_id( base_limit_id=CONSTANTS.USER_TRADE_RECORDS_PATH_URL[ CONSTANTS.LINEAR_MARKET], trading_pair=trading_pair), limit=120, time_interval=60, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.GET_LIMIT_ID), LinkedLimitWeightPair( pair_specific_linear_private_bucket_120_a_limit_id) ], ), ] return rate_limits
class Constants: """ API Documentation Links: https://api-docs.coinzoom.com/ https://api-markets.coinzoom.com/ """ EXCHANGE_NAME = "coinzoom" REST_URL = "https://api.coinzoom.com/api/v1/public" # REST_URL = "https://api.stage.coinzoom.com/api/v1/public" WS_PRIVATE_URL = "wss://api.coinzoom.com/api/v1/public/market/data/stream" # WS_PRIVATE_URL = "wss://api.stage.coinzoom.com/api/v1/public/market/data/stream" WS_PUBLIC_URL = "wss://api.coinzoom.com/api/v1/public/market/data/stream" # WS_PUBLIC_URL = "wss://api.stage.coinzoom.com/api/v1/public/market/data/stream" HBOT_BROKER_ID = "CZ_API_HBOT" ENDPOINT = { # Public Endpoints "NETWORK_CHECK": "currencies", "TICKER": "marketwatch/ticker", "SYMBOL": "instruments", "ORDER_BOOK": "marketwatch/orderbook/{trading_pair}/150/2", "ORDER_CREATE": "orders/new", "ORDER_DELETE": "orders/cancel", "ORDER_STATUS": "orders/list", "USER_ORDERS": "orders/list", "USER_BALANCES": "ledger/list", } WS_SUB = { "TRADES": "TradeSummaryRequest", "ORDERS": "OrderBookRequest", "USER_ORDERS_TRADES": "OrderUpdateRequest", } WS_METHODS = { "ORDERS_SNAPSHOT": "ob", "ORDERS_UPDATE": "oi", "TRADES_UPDATE": "ts", "USER_BALANCE": "getTradingBalance", "USER_ORDERS": "OrderResponse", "USER_ORDERS_CANCEL": "OrderCancelResponse", } # Timeouts MESSAGE_TIMEOUT = 30.0 PING_TIMEOUT = 10.0 API_CALL_TIMEOUT = 10.0 API_MAX_RETRIES = 4 # Intervals # Only used when nothing is received from WS SHORT_POLL_INTERVAL = 5.0 # One minute should be fine since we request balance updates on order updates LONG_POLL_INTERVAL = 60.0 # One minute should be fine for order status since we get these via WS UPDATE_ORDER_STATUS_INTERVAL = 60.0 # 10 minute interval to update trading rules, these would likely never change whilst running. INTERVAL_TRADING_RULES = 600 REST_TOTAL_LIMIT_ID = "RestAPITotal" WS_REQUEST_LIMIT_ID = "WSRequest" REST_ORDERBOOK_LIMIT_ID = "OrderBook" RATE_LIMITS = [ RateLimit(limit_id=REST_TOTAL_LIMIT_ID, limit=120, time_interval=60), RateLimit(limit_id=WS_REQUEST_LIMIT_ID, limit=30, time_interval=60), RateLimit(limit_id=ENDPOINT["NETWORK_CHECK"], limit=12, time_interval=1, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=ENDPOINT["TICKER"], limit=12, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=ENDPOINT["SYMBOL"], limit=12, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=REST_ORDERBOOK_LIMIT_ID, limit=12, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=ENDPOINT["ORDER_CREATE"], limit=60, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=ENDPOINT["ORDER_DELETE"], limit=60, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=ENDPOINT["ORDER_STATUS"], limit=30, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), RateLimit(limit_id=ENDPOINT["USER_BALANCES"], limit=60, time_interval=60, linked_limits=[LinkedLimitWeightPair(REST_TOTAL_LIMIT_ID)]), ]
} # Websocket event types DIFF_EVENT_TYPE = "depthUpdate" TRADE_EVENT_TYPE = "trade" RATE_LIMITS = [ # Pools RateLimit(limit_id=REQUEST_WEIGHT, limit=1200, time_interval=ONE_MINUTE), RateLimit(limit_id=ORDERS, limit=10, time_interval=ONE_SECOND), RateLimit(limit_id=ORDERS_24HR, limit=100000, time_interval=ONE_DAY), # Weighted Limits RateLimit(limit_id=TICKER_PRICE_CHANGE_PATH_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, 40)]), RateLimit(limit_id=EXCHANGE_INFO_PATH_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[(LinkedLimitWeightPair(REQUEST_WEIGHT, 10))]), RateLimit(limit_id=SNAPSHOT_PATH_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, 50)]), RateLimit(limit_id=BINANCE_USER_STREAM_PATH_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, 1)]), RateLimit(limit_id=SERVER_TIME_PATH_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE,
# Intervals # Only used when nothing is received from WS SHORT_POLL_INTERVAL = 5.0 # 45 seconds should be fine since we get trades, orders and balances via WS LONG_POLL_INTERVAL = 45.0 # One minute should be fine since we get trades, orders and balances via WS UPDATE_ORDER_STATUS_INTERVAL = 60.0 # 10 minute interval to update trading rules, these would likely never change whilst running. INTERVAL_TRADING_RULES = 600 PUBLIC_URL_POINTS_LIMIT_ID = "PublicPoints" PRIVATE_URL_POINTS_LIMIT_ID = "PrivatePoints" # includes place-orders CANCEL_ORDERS_LIMITS_ID = "CancelOrders" ORDER_DELETE_LIMIT_ID = "OrderDelete" ORDER_STATUS_LIMIT_ID = "OrderStatus" RATE_LIMITS = [ RateLimit(limit_id=PUBLIC_URL_POINTS_LIMIT_ID, limit=900, time_interval=1), RateLimit(limit_id=PRIVATE_URL_POINTS_LIMIT_ID, limit=900, time_interval=1), RateLimit(limit_id=CANCEL_ORDERS_LIMITS_ID, limit=5_000, time_interval=1), RateLimit(limit_id=NETWORK_CHECK_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PUBLIC_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=SYMBOL_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PUBLIC_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=ORDER_CREATE_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PRIVATE_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=ORDER_DELETE_LIMIT_ID, limit=5_000, time_interval=1, linked_limits=[LinkedLimitWeightPair(CANCEL_ORDERS_LIMITS_ID)]), RateLimit(limit_id=USER_BALANCES_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PRIVATE_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=ORDER_STATUS_LIMIT_ID, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PRIVATE_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=USER_ORDERS_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PRIVATE_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=TICKER_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PUBLIC_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=ORDER_BOOK_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PUBLIC_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=MY_TRADES_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PRIVATE_URL_POINTS_LIMIT_ID)]), ]
RateLimit( limit_id=PRIVATE_ENDPOINT_LIMIT_ID, limit=PRIVATE_ENDPOINT_LIMIT, time_interval=PRIVATE_ENDPOINT_LIMIT_INTERVAL, ), RateLimit( limit_id=MATCHING_ENGINE_LIMIT_ID, limit=MATCHING_ENGINE_LIMIT, time_interval=MATCHING_ENGINE_LIMIT_INTERVAL, ), # public endpoints RateLimit( limit_id=SNAPSHOT_PATH_URL, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, linked_limits=[LinkedLimitWeightPair(PUBLIC_ENDPOINT_LIMIT_ID)], ), RateLimit( limit_id=ASSET_PAIRS_PATH_URL, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, linked_limits=[LinkedLimitWeightPair(PUBLIC_ENDPOINT_LIMIT_ID)], ), RateLimit( limit_id=TICKER_PATH_URL, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, linked_limits=[LinkedLimitWeightPair(PUBLIC_ENDPOINT_LIMIT_ID)], ), RateLimit( limit_id=TIME_PATH_URL,
ONE_MINUTE = 60 ONE_SECOND = 1 ONE_DAY = 86400 MAX_REQUEST = 2400 RATE_LIMITS = [ # Pool Limits RateLimit(limit_id=REQUEST_WEIGHT, limit=2400, time_interval=ONE_MINUTE), RateLimit(limit_id=ORDERS_1MIN, limit=1200, time_interval=ONE_MINUTE), RateLimit(limit_id=ORDERS_1SEC, limit=300, time_interval=10), # Weight Limits for individual endpoints RateLimit(limit_id=SNAPSHOT_REST_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, weight=20)]), RateLimit(limit_id=TICKER_PRICE_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, weight=2)]), RateLimit(limit_id=TICKER_PRICE_CHANGE_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, weight=1)]), RateLimit(limit_id=EXCHANGE_INFO_URL, limit=MAX_REQUEST, time_interval=ONE_MINUTE, linked_limits=[LinkedLimitWeightPair(REQUEST_WEIGHT, weight=40)]), RateLimit(limit_id=RECENT_TRADES_URL, limit=MAX_REQUEST,
MINUTE = 60 HTTP_ENDPOINTS_LIMIT_ID = "AllHTTP" HTTP_LIMIT = 600 WS_AUTH_LIMIT_ID = "AllWsAuth" WS_ENDPOINTS_LIMIT_ID = "AllWs" WS_LIMIT = 500 RATE_LIMITS = [ RateLimit(limit_id=HTTP_ENDPOINTS_LIMIT_ID, limit=HTTP_LIMIT, time_interval=MINUTE), # public http RateLimit( limit_id=MARKETS_URL, limit=HTTP_LIMIT, time_interval=MINUTE, linked_limits=[LinkedLimitWeightPair(HTTP_ENDPOINTS_LIMIT_ID)], ), RateLimit( limit_id=ORDER_BOOK_URL, limit=HTTP_LIMIT, time_interval=MINUTE, linked_limits=[LinkedLimitWeightPair(HTTP_ENDPOINTS_LIMIT_ID)], ), RateLimit( limit_id=LAST_TRADE_PRICE_URL, limit=HTTP_LIMIT, time_interval=MINUTE, linked_limits=[LinkedLimitWeightPair(HTTP_ENDPOINTS_LIMIT_ID)], ), # private http RateLimit(
# OrderStates ORDER_STATE = { "PendingNew": OrderState.PENDING_CREATE, "New": OrderState.OPEN, "Filled": OrderState.FILLED, "PartiallyFilled": OrderState.PARTIALLY_FILLED, "Canceled": OrderState.CANCELLED, "Rejected": OrderState.FAILED, } # AscendEx has multiple pools for API request limits # Any call increases call rate in ALL pool, so e.g. a cash/order call will contribute to both ALL and cash/order pools. ALL_ENDPOINTS_LIMIT = "All" RATE_LIMITS = [ RateLimit(limit_id=ALL_ENDPOINTS_LIMIT, limit=100, time_interval=1), RateLimit(limit_id=ORDER_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=ORDER_BATCH_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=ORDER_OPEN_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=ORDER_STATUS_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=BALANCE_PATH_URL, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=HIST_PATH_URL, limit=60, time_interval=60, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=TICKER_PATH_URL, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=PRODUCTS_PATH_URL, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=TRADES_PATH_URL, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=DEPTH_PATH_URL, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=INFO_PATH_URL, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=SUB_ENDPOINT_NAME, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=PONG_ENDPOINT_NAME, limit=100, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), ]
LISTEN_KEY_KEEP_ALIVE_INTERVAL = float(TWELVE_HOURS) UPDATE_ORDER_STATUS_MIN_INTERVAL = 10.0 * SECOND WS_HEARTBEAT_TIME_INTERVAL = 30 * SECOND GENERAL_TPS = 700 MAX_ALLOWED_TPS = 3500 SUBSCRIPTION_ID_BOOKS = 0 SUBSCRIPTION_ID_TRADES = 1 SUBSCRIPTION_ID_ACCOUNT = 2 SUBSCRIPTION_ID_ORDERS = 3 SUBSCRIPTION_ID_TRADE_UPDATE = 4 PUBLIC_LIMIT_ID = "PublicPoints" PRIVATE_LIMIT_ID = "PrivatePoints" # includes place-orders PUBLIC_LINKED_LIMITS = [LinkedLimitWeightPair(PUBLIC_LIMIT_ID)] PRIVATE_LINKED_LIMITS = [LinkedLimitWeightPair(PRIVATE_LIMIT_ID)] RATE_LIMITS = [ RateLimit(limit_id=PUBLIC_LIMIT_ID, limit=GENERAL_TPS, time_interval=SECOND), RateLimit(limit_id=PRIVATE_LIMIT_ID, limit=GENERAL_TPS, time_interval=SECOND), # Public API RateLimit(limit_id=TICKER_PATH_URL, limit=GENERAL_TPS, time_interval=SECOND, linked_limits=PUBLIC_LINKED_LIMITS), RateLimit(limit_id=CURRENCY_PATH_URL,
class Constants: EXCHANGE_NAME = "altmarkets" REST_URL = "https://v2.altmarkets.io/api/v2/peatio" WS_PRIVATE_URL = "wss://v2.altmarkets.io/api/v2/ranger/private" WS_PUBLIC_URL = "wss://v2.altmarkets.io/api/v2/ranger/public" HBOT_BROKER_ID = "HBOT" USER_AGENT = "HBOT_AMv2" ENDPOINT = { # Public Endpoints "NETWORK_CHECK": "public/timestamp", "TICKER": "public/markets/tickers", "TICKER_SINGLE": "public/markets/{trading_pair}/tickers", "SYMBOL": "public/markets", "ORDER_BOOK": "public/markets/{trading_pair}/depth", "ORDER_CREATE": "market/orders", "ORDER_DELETE": "market/orders/{id}/cancel", "ORDER_STATUS": "market/orders/{id}", "USER_ORDERS": "market/orders", "USER_BALANCES": "account/balances", } WS_SUB = { "TRADES": "{trading_pair}.trades", "ORDERS": "{trading_pair}.ob-inc", "USER_ORDERS_TRADES": ['balance', 'order', 'trade'], } WS_EVENT_SUBSCRIBE = "subscribe" WS_EVENT_UNSUBSCRIBE = "unsubscribe" WS_METHODS = { "ORDERS_SNAPSHOT": ".ob-snap", "ORDERS_UPDATE": ".ob-inc", "TRADES_UPDATE": ".trades", "USER_BALANCES": "balance", "USER_ORDERS": "order", "USER_TRADES": "trade", } ORDER_STATES = { "DONE": {"done", "cancel", "partial-canceled", "reject", "fail"}, "FAIL": {"reject", "fail"}, "OPEN": {"submitted", "wait", "pending"}, "CANCEL": {"partial-canceled", "cancel"}, "CANCEL_WAIT": {'wait', 'cancel', 'done', 'reject'}, } # Timeouts MESSAGE_TIMEOUT = 30.0 PING_TIMEOUT = 10.0 API_CALL_TIMEOUT = 10.0 API_MAX_RETRIES = 4 # Intervals # Only used when nothing is received from WS SHORT_POLL_INTERVAL = 10.0 # Two minutes should be fine since we get balances via WS LONG_POLL_INTERVAL = 120.0 # Two minutes should be fine for order status since we get these via WS UPDATE_ORDER_STATUS_INTERVAL = 120.0 # We don't get many messages here if we're not updating orders so set this pretty high USER_TRACKER_MAX_AGE = 300.0 # 10 minute interval to update trading rules, these would likely never change whilst running. INTERVAL_TRADING_RULES = 600 # Trading pair splitter regex TRADING_PAIR_SPLITTER = r"^(\w+)(btc|ltc|altm|doge|eth|bnb|usdt|usdc|usds|tusd|cro|roger)$" RL_TIME_INTERVAL = 12 RL_ID_HTTP_ENDPOINTS = "AllHTTP" RL_ID_WS_ENDPOINTS = "AllWs" RL_ID_WS_AUTH = "AllWsAuth" RL_ID_TICKER = "Ticker" RL_ID_ORDER_BOOK = "OrderBook" RL_ID_ORDER_CREATE = "OrderCreate" RL_ID_ORDER_DELETE = "OrderDelete" RL_ID_ORDER_STATUS = "OrderStatus" RL_ID_USER_ORDERS = "OrdersUser" RL_HTTP_LIMIT = 30 RL_WS_LIMIT = 50 RATE_LIMITS = [ RateLimit(limit_id=RL_ID_HTTP_ENDPOINTS, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL), # http RateLimit( limit_id=ENDPOINT["NETWORK_CHECK"], limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=RL_ID_TICKER, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=ENDPOINT["SYMBOL"], limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=RL_ID_ORDER_BOOK, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=RL_ID_ORDER_CREATE, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=RL_ID_ORDER_DELETE, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=RL_ID_ORDER_STATUS, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=RL_ID_USER_ORDERS, limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), RateLimit( limit_id=ENDPOINT["USER_BALANCES"], limit=RL_HTTP_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_HTTP_ENDPOINTS)], ), # ws RateLimit(limit_id=RL_ID_WS_ENDPOINTS, limit=RL_WS_LIMIT, time_interval=RL_TIME_INTERVAL), RateLimit( limit_id=WS_EVENT_SUBSCRIBE, limit=RL_WS_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_WS_ENDPOINTS)], ), RateLimit( limit_id=WS_EVENT_UNSUBSCRIBE, limit=RL_WS_LIMIT, time_interval=RL_TIME_INTERVAL, linked_limits=[LinkedLimitWeightPair(RL_ID_WS_ENDPOINTS)], ), ]
MATCHING_ENGINE_LIMIT_INTERVAL = 60 WS_CONNECTION_LIMIT_ID = "WSConnectionLimitID" PUBLIC_API_LIMITS = [ # Public API Pool RateLimit( limit_id=PUBLIC_ENDPOINT_LIMIT_ID, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, ), # Public Endpoints RateLimit( limit_id=SNAPSHOT_PATH_URL, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, linked_limits=[LinkedLimitWeightPair(PUBLIC_ENDPOINT_LIMIT_ID)], ), RateLimit( limit_id=ASSET_PAIRS_PATH_URL, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, linked_limits=[LinkedLimitWeightPair(PUBLIC_ENDPOINT_LIMIT_ID)], ), RateLimit( limit_id=TICKER_PATH_URL, limit=PUBLIC_ENDPOINT_LIMIT, time_interval=PUBLIC_ENDPOINT_LIMIT_INTERVAL, linked_limits=[LinkedLimitWeightPair(PUBLIC_ENDPOINT_LIMIT_ID)], ), RateLimit( limit_id=TIME_PATH_URL,
PUBLIC_URL_POINTS_LIMIT_ID = "PublicPoints" PRIVATE_URL_POINTS_LIMIT_ID = "PrivatePoints" # includes place-orders CANCEL_ORDERS_LIMITS_ID = "CancelOrders" ORDER_DELETE_LIMIT_ID = "OrderDelete" ORDER_STATUS_LIMIT_ID = "OrderStatus" RATE_LIMITS = [ RateLimit(limit_id=PUBLIC_URL_POINTS_LIMIT_ID, limit=900, time_interval=1), RateLimit(limit_id=PRIVATE_URL_POINTS_LIMIT_ID, limit=900, time_interval=1), RateLimit(limit_id=CANCEL_ORDERS_LIMITS_ID, limit=5_000, time_interval=1), RateLimit( limit_id=NETWORK_CHECK_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PUBLIC_URL_POINTS_LIMIT_ID)]), RateLimit( limit_id=SYMBOL_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PUBLIC_URL_POINTS_LIMIT_ID)]), RateLimit( limit_id=ORDER_CREATE_PATH_URL, limit=900, time_interval=1, linked_limits=[LinkedLimitWeightPair(PRIVATE_URL_POINTS_LIMIT_ID)]), RateLimit(limit_id=ORDER_DELETE_LIMIT_ID, limit=5_000, time_interval=1, linked_limits=[LinkedLimitWeightPair(CANCEL_ORDERS_LIMITS_ID)]), RateLimit(
def _build_private_rate_limits( tier: KrakenAPITier = KrakenAPITier.STARTER) -> List[RateLimit]: private_rate_limits = [] PRIVATE_ENDPOINT_LIMIT, MATCHING_ENGINE_LIMIT = CONSTANTS.KRAKEN_TIER_LIMITS[ tier] # Private REST endpoints private_rate_limits.extend([ # Private API Pool RateLimit( limit_id=CONSTANTS.PRIVATE_ENDPOINT_LIMIT_ID, limit=PRIVATE_ENDPOINT_LIMIT, time_interval=CONSTANTS.PRIVATE_ENDPOINT_LIMIT_INTERVAL, ), # Private endpoints RateLimit( limit_id=CONSTANTS.GET_TOKEN_PATH_URL, limit=PRIVATE_ENDPOINT_LIMIT, time_interval=CONSTANTS.PRIVATE_ENDPOINT_LIMIT_INTERVAL, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.PRIVATE_ENDPOINT_LIMIT_ID) ], ), RateLimit( limit_id=CONSTANTS.BALANCE_PATH_URL, limit=PRIVATE_ENDPOINT_LIMIT, time_interval=CONSTANTS.PRIVATE_ENDPOINT_LIMIT_INTERVAL, weight=2, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.PRIVATE_ENDPOINT_LIMIT_ID) ], ), RateLimit( limit_id=CONSTANTS.OPEN_ORDERS_PATH_URL, limit=PRIVATE_ENDPOINT_LIMIT, time_interval=CONSTANTS.PRIVATE_ENDPOINT_LIMIT_INTERVAL, weight=2, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.PRIVATE_ENDPOINT_LIMIT_ID) ], ), RateLimit( limit_id=CONSTANTS.QUERY_ORDERS_PATH_URL, limit=PRIVATE_ENDPOINT_LIMIT, time_interval=CONSTANTS.PRIVATE_ENDPOINT_LIMIT_INTERVAL, weight=2, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.PRIVATE_ENDPOINT_LIMIT_ID) ], ), ]) # Matching Engine Limits private_rate_limits.extend([ RateLimit( limit_id=CONSTANTS.ADD_ORDER_PATH_URL, limit=MATCHING_ENGINE_LIMIT, time_interval=CONSTANTS.MATCHING_ENGINE_LIMIT_INTERVAL, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.MATCHING_ENGINE_LIMIT_ID) ], ), RateLimit( limit_id=CONSTANTS.CANCEL_ORDER_PATH_URL, limit=MATCHING_ENGINE_LIMIT, time_interval=CONSTANTS.MATCHING_ENGINE_LIMIT_INTERVAL, linked_limits=[ LinkedLimitWeightPair(CONSTANTS.MATCHING_ENGINE_LIMIT_ID) ], ), ]) return private_rate_limits
"New": OrderState.OPEN, "Filled": OrderState.FILLED, "PartiallyFilled": OrderState.PARTIALLY_FILLED, "Canceled": OrderState.CANCELLED, "Rejected": OrderState.FAILED, } # AscendEx has multiple pools for API request limits # Any call increases call rate in ALL pool, so e.g. a cash/order call will contribute to both ALL and cash/order pools. ALL_ENDPOINTS_LIMIT = "All" RATE_LIMITS = [ RateLimit(limit_id=ALL_ENDPOINTS_LIMIT, limit=100, time_interval=1), RateLimit(limit_id=ORDER_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=ORDER_BATCH_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=ORDER_OPEN_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=ORDER_STATUS_PATH_URL, limit=50, time_interval=1, linked_limits=[LinkedLimitWeightPair(ALL_ENDPOINTS_LIMIT)]), RateLimit(limit_id=BALANCE_PATH_URL, limit=100, time_interval=1,
time_interval=SIX_SECONDS), RateLimit(limit_id=REQUEST_POST, limit=MAX_REQUEST_POST, time_interval=TWO_MINUTES), RateLimit(limit_id=REQUEST_POST_BURST, limit=MAX_REQUEST_POST_BURST, time_interval=ONE_SECOND), RateLimit(limit_id=REQUEST_POST_MIXED, limit=MAX_REQUEST_POST_MIXED, time_interval=SIX_SECONDS), # Linked limits RateLimit(limit_id=LAST_TRADED_PRICE_PATH, limit=MAX_REQUEST_GET, time_interval=TWO_MINUTES, linked_limits=[ LinkedLimitWeightPair(REQUEST_GET, 1), LinkedLimitWeightPair(REQUEST_GET_BURST, 1), LinkedLimitWeightPair(REQUEST_GET_MIXED, 1) ]), RateLimit(limit_id=EXCHANGE_INFO_PATH_URL, limit=MAX_REQUEST_GET, time_interval=TWO_MINUTES, linked_limits=[ LinkedLimitWeightPair(REQUEST_GET, 1), LinkedLimitWeightPair(REQUEST_GET_BURST, 1), LinkedLimitWeightPair(REQUEST_GET_MIXED, 1) ]), RateLimit(limit_id=SNAPSHOT_PATH_URL, limit=MAX_REQUEST_GET, time_interval=TWO_MINUTES, linked_limits=[