UNPKG

ccxt-xigua

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges

5,156 lines 237 kB
'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { TICK_SIZE } = require ('./base/functions/number');
const { AuthenticationError, ExchangeError, ArgumentsRequired, PermissionDenied, InvalidOrder, OrderNotFound, InsufficientFunds, BadRequest, RateLimitExceeded, InvalidNonce, NotSupported, InvalidAddress } = require ('./base/errors');
const Precise = require ('./base/Precise');

//  ---------------------------------------------------------------------------

module.exports = class bybit extends Exchange {
    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'bybit',
            'name': 'Bybit',
            'countries': [ 'VG' ], // British Virgin Islands
            'version': 'v2',
            'userAgent': undefined,
            // 50 requests per second for GET requests, 1000ms / 50 = 20ms between requests
            // 20 requests per second for POST requests, cost = 50 / 20 = 2.5
            'rateLimit': 20,
            'hostname': 'bybit.com', // bybit.com, bytick.com
            'pro': true,
            'has': {
                'CORS': true,
                'spot': true,
                'margin': false,
                'swap': true,
                'future': true,
                'option': undefined,
                'cancelAllOrders': true,
                'cancelOrder': true,
                'createOrder': true,
                'createStopLimitOrder': true,
                'createStopMarketOrder': true,
                'createStopOrder': true,
                'editOrder': true,
                'fetchBalance': true,
                'fetchBorrowRate': false,
                'fetchBorrowRates': false,
                'fetchClosedOrders': true,
                'fetchCurrencies': true,
                'fetchDepositAddress': true,
                'fetchDepositAddresses': false,
                'fetchDepositAddressesByNetwork': true,
                'fetchDeposits': true,
                'fetchFundingRate': true,
                'fetchFundingRateHistory': false,
                'fetchIndexOHLCV': true,
                'fetchLedger': true,
                'fetchMarketLeverageTiers': true,
                'fetchMarkets': true,
                'fetchMarkOHLCV': true,
                'fetchMyTrades': true,
                'fetchOHLCV': true,
                'fetchOpenInterestHistory': true,
                'fetchOpenOrders': true,
                'fetchOrder': true,
                'fetchOrderBook': true,
                'fetchOrders': true,
                'fetchOrderTrades': true,
                'fetchPositions': true,
                'fetchPremiumIndexOHLCV': true,
                'fetchTicker': true,
                'fetchTickers': true,
                'fetchTime': true,
                'fetchTrades': true,
                'fetchTradingFee': false,
                'fetchTradingFees': false,
                'fetchTransactions': undefined,
                'fetchWithdrawals': true,
                'setLeverage': true,
                'setMarginMode': true,
                'setPositionMode': true,
                'withdraw': true,
            },
            'timeframes': {
                '1m': '1',
                '3m': '3',
                '5m': '5',
                '15m': '15',
                '30m': '30',
                '1h': '60',
                '2h': '120',
                '4h': '240',
                '6h': '360',
                '12h': '720',
                '1d': 'D',
                '1w': 'W',
                '1M': 'M',
                '1y': 'Y',
            },
            'urls': {
                'test': {
                    'spot': 'https://api-testnet.{hostname}',
                    'futures': 'https://api-testnet.{hostname}',
                    'v2': 'https://api-testnet.{hostname}',
                    'public': 'https://api-testnet.{hostname}',
                    'private': 'https://api-testnet.{hostname}',
                },
                'logo': 'https://user-images.githubusercontent.com/51840849/76547799-daff5b80-649e-11ea-87fb-3be9bac08954.jpg',
                'api': {
                    'spot': 'https://api.{hostname}',
                    'futures': 'https://api.{hostname}',
                    'v2': 'https://api.{hostname}',
                    'public': 'https://api.{hostname}',
                    'private': 'https://api.{hostname}',
                },
                'www': 'https://www.bybit.com',
                'doc': [
                    'https://bybit-exchange.github.io/docs/inverse/',
                    'https://bybit-exchange.github.io/docs/linear/',
                    'https://github.com/bybit-exchange',
                ],
                'fees': 'https://help.bybit.com/hc/en-us/articles/360039261154',
                'referral': 'https://partner.bybit.com/b/ccxt',
            },
            'api': {
                'public': {
                    'get': {
                        // inverse swap
                        'v2/public/orderBook/L2': 1,
                        'v2/public/kline/list': 3,
                        'v2/public/tickers': 1,
                        'v2/public/trading-records': 1,
                        'v2/public/symbols': 1,
                        'v2/public/mark-price-kline': 3,
                        'v2/public/index-price-kline': 3,
                        'v2/public/premium-index-kline': 2,
                        'v2/public/open-interest': 1,
                        'v2/public/big-deal': 1,
                        'v2/public/account-ratio': 1,
                        'v2/public/funding-rate': 1,
                        'v2/public/elite-ratio': 1,
                        'v2/public/funding/prev-funding-rate': 1,
                        'v2/public/risk-limit/list': 1,
                        // linear swap USDT
                        'public/linear/kline': 3,
                        'public/linear/recent-trading-records': 1,
                        'public/linear/risk-limit': 1,
                        'public/linear/funding/prev-funding-rate': 1,
                        'public/linear/mark-price-kline': 1,
                        'public/linear/index-price-kline': 1,
                        'public/linear/premium-index-kline': 1,
                        // spot
                        'spot/v1/time': 1,
                        'spot/v1/symbols': 1,
                        'spot/quote/v1/depth': 1,
                        'spot/quote/v1/depth/merged': 1,
                        'spot/quote/v1/trades': 1,
                        'spot/quote/v1/kline': 1,
                        'spot/quote/v1/ticker/24hr': 1,
                        'spot/quote/v1/ticker/price': 1,
                        'spot/quote/v1/ticker/book_ticker': 1,
                        // data
                        'v2/public/time': 1,
                        'v2/public/announcement': 1,
                        // USDC endpoints
                        // option USDC
                        'option/usdc/openapi/public/v1/order-book': 1,
                        'option/usdc/openapi/public/v1/symbols': 1,
                        'option/usdc/openapi/public/v1/tick': 1,
                        'option/usdc/openapi/public/v1/delivery-price': 1,
                        'option/usdc/openapi/public/v1/query-trade-latest': 1,
                        // perpetual swap USDC
                        'perpetual/usdc/openapi/public/v1/order-book': 1,
                        'perpetual/usdc/openapi/public/v1/symbols': 1,
                        'perpetual/usdc/openapi/public/v1/tick': 1,
                        'perpetual/usdc/openapi/public/v1/kline/list': 1,
                        'perpetual/usdc/openapi/public/v1/mark-price-kline': 1,
                        'perpetual/usdc/openapi/public/v1/index-price-kline': 1,
                        'perpetual/usdc/openapi/public/v1/premium-index-kline': 1,
                        'perpetual/usdc/openapi/public/v1/open-interest': 1,
                        'perpetual/usdc/openapi/public/v1/big-deal': 1,
                        'perpetual/usdc/openapi/public/v1/account-ratio': 1,
                        'perpetual/usdc/openapi/public/v1/prev-funding-rate': 1,
                        'perpetual/usdc/openapi/public/v1/risk-limit/list': 1,
                        // account
                        'asset/v1/public/deposit/allowed-deposit-list': 1,
                        'contract/v3/public/copytrading/symbol/list': 1,
                    },
                },
                'private': {
                    'get': {
                        // inverse swap
                        'v2/private/order/list': 5,
                        'v2/private/order': 5,
                        'v2/private/stop-order/list': 5,
                        'v2/private/stop-order': 1,
                        'v2/private/position/list': 25,
                        'v2/private/position/fee-rate': 40,
                        'v2/private/execution/list': 25,
                        'v2/private/trade/closed-pnl/list': 1,
                        'v2/public/risk-limit/list': 1, // TODO check
                        'v2/public/funding/prev-funding-rate': 25, // TODO check
                        'v2/private/funding/prev-funding': 25,
                        'v2/private/funding/predicted-funding': 25,
                        'v2/private/account/api-key': 5,
                        'v2/private/account/lcp': 1,
                        'v2/private/wallet/balance': 25, // 120 per minute = 2 per second => cost = 50 / 2 = 25
                        'v2/private/wallet/fund/records': 25,
                        'v2/private/wallet/withdraw/list': 25,
                        'v2/private/exchange-order/list': 1,
                        // linear swap USDT
                        'private/linear/order/list': 5, // 600 per minute = 10 per second => cost = 50 / 10 =  5
                        'private/linear/order/search': 5,
                        'private/linear/stop-order/list': 5,
                        'private/linear/stop-order/search': 5,
                        'private/linear/position/list': 25,
                        'private/linear/trade/execution/list': 25,
                        'private/linear/trade/closed-pnl/list': 25,
                        'public/linear/risk-limit': 1,
                        'private/linear/funding/predicted-funding': 25,
                        'private/linear/funding/prev-funding': 25,
                        // inverse futures
                        'futures/private/order/list': 5,
                        'futures/private/order': 5,
                        'futures/private/stop-order/list': 5,
                        'futures/private/stop-order': 5,
                        'futures/private/position/list': 25,
                        'futures/private/execution/list': 25,
                        'futures/private/trade/closed-pnl/list': 1,
                        // spot
                        'spot/v1/account': 2.5,
                        'spot/v1/order': 2.5,
                        'spot/v1/open-orders': 2.5,
                        'spot/v1/history-orders': 2.5,
                        'spot/v1/myTrades': 2.5,
                        'spot/v1/cross-margin/order': 10,
                        'spot/v1/cross-margin/accounts/balance': 10,
                        'spot/v1/cross-margin/loan-info': 10,
                        'spot/v1/cross-margin/repay/history': 10,
                        // account
                        'asset/v1/private/transfer/list': 50, // 60 per minute = 1 per second => cost = 50 / 1 = 50
                        'asset/v1/private/sub-member/transfer/list': 50,
                        'asset/v1/private/sub-member/member-ids': 50,
                        'asset/v1/private/deposit/record/query': 50,
                        'asset/v1/private/withdraw/record/query': 25,
                        'asset/v1/private/coin-info/query': 25,
                        'asset/v1/private/asset-info/query': 50,
                        'asset/v1/private/deposit/address': 100,
                        'contract/v3/private/copytrading/order/list': 1,
                        'contract/v3/private/copytrading/position/list': 1,
                        'contract/v3/private/copytrading/wallet/balance': 1,
                    },
                    'post': {
                        // inverse swap
                        'v2/private/order/create': 30,
                        'v2/private/order/cancel': 30,
                        'v2/private/order/cancelAll': 300, // 100 per minute + 'consumes 10 requests'
                        'v2/private/order/replace': 30,
                        'v2/private/stop-order/create': 30,
                        'v2/private/stop-order/cancel': 30,
                        'v2/private/stop-order/cancelAll': 300,
                        'v2/private/stop-order/replace': 30,
                        'v2/private/position/change-position-margin': 40,
                        'v2/private/position/trading-stop': 40,
                        'v2/private/position/leverage/save': 40,
                        'v2/private/tpsl/switch-mode': 40,
                        'v2/private/position/switch-isolated': 2.5,
                        'v2/private/position/risk-limit': 2.5,
                        'v2/private/position/switch-mode': 2.5,
                        // linear swap USDT
                        'private/linear/order/create': 30, // 100 per minute = 1.666 per second => cost = 50 / 1.6666 = 30
                        'private/linear/order/cancel': 30,
                        'private/linear/order/cancel-all': 300, // 100 per minute + 'consumes 10 requests'
                        'private/linear/order/replace': 30,
                        'private/linear/stop-order/create': 30,
                        'private/linear/stop-order/cancel': 30,
                        'private/linear/stop-order/cancel-all': 300,
                        'private/linear/stop-order/replace': 30,
                        'private/linear/position/set-auto-add-margin': 40,
                        'private/linear/position/switch-isolated': 40,
                        'private/linear/position/switch-mode': 40,
                        'private/linear/tpsl/switch-mode': 2.5,
                        'private/linear/position/add-margin': 40,
                        'private/linear/position/set-leverage': 40, // 75 per minute = 1.25 per second => cost = 50 / 1.25 = 40
                        'private/linear/position/trading-stop': 40,
                        'private/linear/position/set-risk': 2.5,
                        // inverse futures
                        'futures/private/order/create': 30,
                        'futures/private/order/cancel': 30,
                        'futures/private/order/cancelAll': 30,
                        'futures/private/order/replace': 30,
                        'futures/private/stop-order/create': 30,
                        'futures/private/stop-order/cancel': 30,
                        'futures/private/stop-order/cancelAll': 30,
                        'futures/private/stop-order/replace': 30,
                        'futures/private/position/change-position-margin': 40,
                        'futures/private/position/trading-stop': 40,
                        'futures/private/position/leverage/save': 40,
                        'futures/private/position/switch-mode': 40,
                        'futures/private/tpsl/switch-mode': 40,
                        'futures/private/position/switch-isolated': 40,
                        'futures/private/position/risk-limit': 2.5,
                        // spot
                        'spot/v1/order': 2.5,
                        'spot/v1/cross-margin/loan': 10,
                        'spot/v1/cross-margin/repay': 10,
                        // account
                        'asset/v1/private/transfer': 150, // 20 per minute = 0.333 per second => cost = 50 / 0.3333 = 150
                        'asset/v1/private/sub-member/transfer': 150,
                        'asset/v1/private/withdraw': 50,
                        'asset/v1/private/withdraw/cancel': 50,
                        // USDC endpoints
                        // option USDC
                        'option/usdc/openapi/private/v1/place-order': 2.5,
                        'option/usdc/openapi/private/v1/batch-place-order': 2.5,
                        'option/usdc/openapi/private/v1/replace-order': 2.5,
                        'option/usdc/openapi/private/v1/batch-replace-orders': 2.5,
                        'option/usdc/openapi/private/v1/cancel-order': 2.5,
                        'option/usdc/openapi/private/v1/batch-cancel-orders': 2.5,
                        'option/usdc/openapi/private/v1/cancel-all': 2.5,
                        'option/usdc/openapi/private/v1/query-active-orders': 2.5,
                        'option/usdc/openapi/private/v1/query-order-history': 2.5,
                        'option/usdc/openapi/private/v1/execution-list': 2.5,
                        'option/usdc/openapi/private/v1/query-transaction-log': 2.5,
                        'option/usdc/openapi/private/v1/query-wallet-balance': 2.5,
                        'option/usdc/openapi/private/v1/query-asset-info': 2.5,
                        'option/usdc/openapi/private/v1/query-margin-info': 2.5,
                        'option/usdc/openapi/private/v1/query-position': 2.5,
                        'option/usdc/openapi/private/v1/query-delivery-list': 2.5,
                        'option/usdc/openapi/private/v1/query-position-exp-date': 2.5,
                        'option/usdc/openapi/private/v1/mmp-modify': 2.5,
                        'option/usdc/openapi/private/v1/mmp-reset': 2.5,
                        // perpetual swap USDC
                        'perpetual/usdc/openapi/private/v1/place-order': 2.5,
                        'perpetual/usdc/openapi/private/v1/replace-order': 2.5,
                        'perpetual/usdc/openapi/private/v1/cancel-order': 2.5,
                        'perpetual/usdc/openapi/private/v1/cancel-all': 2.5,
                        'perpetual/usdc/openapi/private/v1/position/leverage/save': 2.5,
                        'option/usdc/openapi/private/v1/session-settlement': 2.5,
                        'perpetual/usdc/openapi/public/v1/risk-limit/list': 2.5,
                        'perpetual/usdc/openapi/private/v1/position/set-risk-limit': 2.5,
                        // 'perpetual/usdc/openapi/private/v1/predicted-funding': 2.5,
                        'contract/v3/private/copytrading/order/create': 2.5,
                        'contract/v3/private/copytrading/order/cancel': 2.5,
                        'contract/v3/private/copytrading/order/close': 2.5,
                        'contract/v3/private/copytrading/position/close': 2.5,
                        'contract/v3/private/copytrading/position/set-leverage': 2.5,
                        'contract/v3/private/copytrading/wallet/transfer': 2.5,
                    },
                    'delete': {
                        // spot
                        'spot/v1/order': 2.5,
                        'spot/v1/order/fast': 2.5,
                        'spot/order/batch-cancel': 2.5,
                        'spot/order/batch-fast-cancel': 2.5,
                        'spot/order/batch-cancel-by-ids': 2.5,
                    },
                },
            },
            'httpExceptions': {
                '403': RateLimitExceeded, // Forbidden -- You request too many times
            },
            'exceptions': {
                'exact': {
                    '-10009': BadRequest, // {"ret_code":-10009,"ret_msg":"Invalid period!","result":null,"token":null}
                    '-2013': InvalidOrder, // {"ret_code":-2013,"ret_msg":"Order does not exist.","ext_code":null,"ext_info":null,"result":null}
                    '-2015': AuthenticationError, // Invalid API-key, IP, or permissions for action.
                    '-1021': BadRequest, // {"ret_code":-1021,"ret_msg":"Timestamp for this request is outside of the recvWindow.","ext_code":null,"ext_info":null,"result":null}
                    '-1004': BadRequest, // {"ret_code":-1004,"ret_msg":"Missing required parameter \u0027symbol\u0027","ext_code":null,"ext_info":null,"result":null}
                    '7001': BadRequest, // {"retCode":7001,"retMsg":"request params type error"}
                    '10001': BadRequest, // parameter error
                    '10002': InvalidNonce, // request expired, check your timestamp and recv_window
                    '10003': AuthenticationError, // Invalid apikey
                    '10004': AuthenticationError, // invalid sign
                    '10005': PermissionDenied, // permission denied for current apikey
                    '10006': RateLimitExceeded, // too many requests
                    '10007': AuthenticationError, // api_key not found in your request parameters
                    '10010': PermissionDenied, // request ip mismatch
                    '10016': ExchangeError, // {"retCode":10016,"retMsg":"System error. Please try again later."}
                    '10017': BadRequest, // request path not found or request method is invalid
                    '10018': RateLimitExceeded, // exceed ip rate limit
                    '20001': OrderNotFound, // Order not exists
                    '20003': InvalidOrder, // missing parameter side
                    '20004': InvalidOrder, // invalid parameter side
                    '20005': InvalidOrder, // missing parameter symbol
                    '20006': InvalidOrder, // invalid parameter symbol
                    '20007': InvalidOrder, // missing parameter order_type
                    '20008': InvalidOrder, // invalid parameter order_type
                    '20009': InvalidOrder, // missing parameter qty
                    '20010': InvalidOrder, // qty must be greater than 0
                    '20011': InvalidOrder, // qty must be an integer
                    '20012': InvalidOrder, // qty must be greater than zero and less than 1 million
                    '20013': InvalidOrder, // missing parameter price
                    '20014': InvalidOrder, // price must be greater than 0
                    '20015': InvalidOrder, // missing parameter time_in_force
                    '20016': InvalidOrder, // invalid value for parameter time_in_force
                    '20017': InvalidOrder, // missing parameter order_id
                    '20018': InvalidOrder, // invalid date format
                    '20019': InvalidOrder, // missing parameter stop_px
                    '20020': InvalidOrder, // missing parameter base_price
                    '20021': InvalidOrder, // missing parameter stop_order_id
                    '20022': BadRequest, // missing parameter leverage
                    '20023': BadRequest, // leverage must be a number
                    '20031': BadRequest, // leverage must be greater than zero
                    '20070': BadRequest, // missing parameter margin
                    '20071': BadRequest, // margin must be greater than zero
                    '20084': BadRequest, // order_id or order_link_id is required
                    '30001': BadRequest, // order_link_id is repeated
                    '30003': InvalidOrder, // qty must be more than the minimum allowed
                    '30004': InvalidOrder, // qty must be less than the maximum allowed
                    '30005': InvalidOrder, // price exceeds maximum allowed
                    '30007': InvalidOrder, // price exceeds minimum allowed
                    '30008': InvalidOrder, // invalid order_type
                    '30009': ExchangeError, // no position found
                    '30010': InsufficientFunds, // insufficient wallet balance
                    '30011': PermissionDenied, // operation not allowed as position is undergoing liquidation
                    '30012': PermissionDenied, // operation not allowed as position is undergoing ADL
                    '30013': PermissionDenied, // position is in liq or adl status
                    '30014': InvalidOrder, // invalid closing order, qty should not greater than size
                    '30015': InvalidOrder, // invalid closing order, side should be opposite
                    '30016': ExchangeError, // TS and SL must be cancelled first while closing position
                    '30017': InvalidOrder, // estimated fill price cannot be lower than current Buy liq_price
                    '30018': InvalidOrder, // estimated fill price cannot be higher than current Sell liq_price
                    '30019': InvalidOrder, // cannot attach TP/SL params for non-zero position when placing non-opening position order
                    '30020': InvalidOrder, // position already has TP/SL params
                    '30021': InvalidOrder, // cannot afford estimated position_margin
                    '30022': InvalidOrder, // estimated buy liq_price cannot be higher than current mark_price
                    '30023': InvalidOrder, // estimated sell liq_price cannot be lower than current mark_price
                    '30024': InvalidOrder, // cannot set TP/SL/TS for zero-position
                    '30025': InvalidOrder, // trigger price should bigger than 10% of last price
                    '30026': InvalidOrder, // price too high
                    '30027': InvalidOrder, // price set for Take profit should be higher than Last Traded Price
                    '30028': InvalidOrder, // price set for Stop loss should be between Liquidation price and Last Traded Price
                    '30029': InvalidOrder, // price set for Stop loss should be between Last Traded Price and Liquidation price
                    '30030': InvalidOrder, // price set for Take profit should be lower than Last Traded Price
                    '30031': InsufficientFunds, // insufficient available balance for order cost
                    '30032': InvalidOrder, // order has been filled or cancelled
                    '30033': RateLimitExceeded, // The number of stop orders exceeds maximum limit allowed
                    '30034': OrderNotFound, // no order found
                    '30035': RateLimitExceeded, // too fast to cancel
                    '30036': ExchangeError, // the expected position value after order execution exceeds the current risk limit
                    '30037': InvalidOrder, // order already cancelled
                    '30041': ExchangeError, // no position found
                    '30042': InsufficientFunds, // insufficient wallet balance
                    '30043': InvalidOrder, // operation not allowed as position is undergoing liquidation
                    '30044': InvalidOrder, // operation not allowed as position is undergoing AD
                    '30045': InvalidOrder, // operation not allowed as position is not normal status
                    '30049': InsufficientFunds, // insufficient available balance
                    '30050': ExchangeError, // any adjustments made will trigger immediate liquidation
                    '30051': ExchangeError, // due to risk limit, cannot adjust leverage
                    '30052': ExchangeError, // leverage can not less than 1
                    '30054': ExchangeError, // position margin is invalid
                    '30057': ExchangeError, // requested quantity of contracts exceeds risk limit
                    '30063': ExchangeError, // reduce-only rule not satisfied
                    '30067': InsufficientFunds, // insufficient available balance
                    '30068': ExchangeError, // exit value must be positive
                    '30074': InvalidOrder, // can't create the stop order, because you expect the order will be triggered when the LastPrice(or IndexPrice、 MarkPrice, determined by trigger_by) is raising to stop_px, but the LastPrice(or IndexPrice、 MarkPrice) is already equal to or greater than stop_px, please adjust base_price or stop_px
                    '30075': InvalidOrder, // can't create the stop order, because you expect the order will be triggered when the LastPrice(or IndexPrice、 MarkPrice, determined by trigger_by) is falling to stop_px, but the LastPrice(or IndexPrice、 MarkPrice) is already equal to or less than stop_px, please adjust base_price or stop_px
                    '30078': ExchangeError, // {"ret_code":30078,"ret_msg":"","ext_code":"","ext_info":"","result":null,"time_now":"1644853040.916000","rate_limit_status":73,"rate_limit_reset_ms":1644853040912,"rate_limit":75}
                    // '30084': BadRequest, // Isolated not modified, see handleErrors below
                    '33004': AuthenticationError, // apikey already expired
                    '34026': ExchangeError, // the limit is no change
                    '34036': BadRequest, // {"ret_code":34036,"ret_msg":"leverage not modified","ext_code":"","ext_info":"","result":null,"time_now":"1652376449.258918","rate_limit_status":74,"rate_limit_reset_ms":1652376449255,"rate_limit":75}
                    '35015': BadRequest, // {"ret_code":35015,"ret_msg":"Qty not in range","ext_code":"","ext_info":"","result":null,"time_now":"1652277215.821362","rate_limit_status":99,"rate_limit_reset_ms":1652277215819,"rate_limit":100}
                    '130021': InsufficientFunds, // {"ret_code":130021,"ret_msg":"orderfix price failed for CannotAffordOrderCost.","ext_code":"","ext_info":"","result":null,"time_now":"1644588250.204878","rate_limit_status":98,"rate_limit_reset_ms":1644588250200,"rate_limit":100}
                    '130074': InvalidOrder, // {"ret_code":130074,"ret_msg":"expect Rising, but trigger_price[190000000] \u003c= current[211280000]??LastPrice","ext_code":"","ext_info":"","result":null,"time_now":"1655386638.067076","rate_limit_status":97,"rate_limit_reset_ms":1655386638065,"rate_limit":100}
                    '3100116': BadRequest, // {"retCode":3100116,"retMsg":"Order quantity below the lower limit 0.01.","result":null,"retExtMap":{"key0":"0.01"}}
                    '3100198': BadRequest, // {"retCode":3100198,"retMsg":"orderLinkId can not be empty.","result":null,"retExtMap":{}}
                    '3200300': InsufficientFunds, // {"retCode":3200300,"retMsg":"Insufficient margin balance.","result":null,"retExtMap":{}}
                },
                'broad': {
                    'unknown orderInfo': OrderNotFound, // {"ret_code":-1,"ret_msg":"unknown orderInfo","ext_code":"","ext_info":"","result":null,"time_now":"1584030414.005545","rate_limit_status":99,"rate_limit_reset_ms":1584030414003,"rate_limit":100}
                    'invalid api_key': AuthenticationError, // {"ret_code":10003,"ret_msg":"invalid api_key","ext_code":"","ext_info":"","result":null,"time_now":"1599547085.415797"}
                },
            },
            'precisionMode': TICK_SIZE,
            'options': {
                'createMarketBuyOrderRequiresPrice': true,
                'defaultType': 'swap',  // 'swap', 'future', 'option', 'spot'
                'defaultSubType': 'linear',  // 'linear', 'inverse'
                'defaultSettle': 'USDT', // USDC for USDC settled markets
                'code': 'BTC',
                'recvWindow': 5 * 1000, // 5 sec default
                'timeDifference': 0, // the difference between system clock and exchange server clock
                'adjustForTimeDifference': false, // controls the adjustment logic upon instantiation
                'brokerId': 'CCXT',
            },
            'fees': {
                'trading': {
                    'tierBased': false,
                    'percentage': true,
                    'taker': 0.00075,
                    'maker': -0.00025,
                },
                'funding': {
                    'tierBased': false,
                    'percentage': false,
                    'withdraw': {},
                    'deposit': {},
                },
            },
        });
    }

    nonce () {
        return this.milliseconds () - this.options['timeDifference'];
    }

    async fetchTime (params = {}) {
        /**
         * @method
         * @name bybit#fetchTime
         * @description fetches the current integer timestamp in milliseconds from the exchange server
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {int} the current integer timestamp in milliseconds from the exchange server
         */
        const response = await this.publicGetV2PublicTime (params);
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: {},
        //         time_now: '1583933682.448826'
        //     }
        //
        return this.safeTimestamp (response, 'time_now');
    }

    safeNetwork (networkId) {
        const networksById = {
            'ETH': 'ERC20',
            'TRX': 'TRC20',
        };
        return this.safeString (networksById, networkId, networkId);
    }

    async fetchCurrencies (params = {}) {
        /**
         * @method
         * @name bybit#fetchCurrencies
         * @description fetches all available currencies on an exchange
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} an associative dictionary of currencies
         */
        if (!this.checkRequiredCredentials (false)) {
            return undefined;
        }
        const response = await this.privateGetAssetV1PrivateCoinInfoQuery (params);
        //
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "result":{
        //             "rows":[
        //                 {
        //                     "name":"BUSD",
        //                     "coin":"BUSD",
        //                     "remain_amount":"7500000",
        //                     "chains":[
        //                         {"chain_type":"BSC (BEP20)","confirmation":"20","withdraw_fee":"0.8","deposit_min":"0","withdraw_min":"1.6","chain":"BSC"},
        //                         {"chain_type":"ERC20","confirmation":"12","withdraw_fee":"30","deposit_min":"0","withdraw_min":"30","chain":"ETH"},
        //                     ],
        //                 },
        //                 {
        //                     "name":"USDT",
        //                     "coin":"USDT",
        //                     "remain_amount":"15000000",
        //                     "chains":[
        //                         {"chain_type":"ERC20","confirmation":"12","withdraw_fee":"10","deposit_min":"0","withdraw_min":"20","chain":"ETH"},
        //                         {"chain_type":"TRC20","confirmation":"100","withdraw_fee":"1","deposit_min":"0","withdraw_min":"10","chain":"TRX"},
        //                         {"chain_type":"Arbitrum One","confirmation":"12","withdraw_fee":"10","deposit_min":"0","withdraw_min":"20","chain":"ARBI"},
        //                         {"chain_type":"SOL","confirmation":"300","withdraw_fee":"1","deposit_min":"0","withdraw_min":"10","chain":"SOL"},
        //                         {"chain_type":"BSC (BEP20)","confirmation":"20","withdraw_fee":"2","deposit_min":"0","withdraw_min":"10","chain":"BSC"},
        //                         {"chain_type":"Zksync","confirmation":"1","withdraw_fee":"3","deposit_min":"0","withdraw_min":"3","chain":"ZKSYNC"},
        //                         {"chain_type":"MATIC","confirmation":"128","withdraw_fee":"0.3","deposit_min":"0","withdraw_min":"0.3","chain":"MATIC"},
        //                         {"chain_type":"OMNI","confirmation":"1","withdraw_fee":"","deposit_min":"0","withdraw_min":"","chain":"OMNI"},
        //                     ],
        //                 },
        //             ],
        //         },
        //         "ext_info":null,
        //         "time_now":1653312027278,
        //         "rate_limit_status":119,
        //         "rate_limit_reset_ms":1653312027278,
        //         "rate_limit":1,
        //     }
        //
        const data = this.safeValue (response, 'result', []);
        const rows = this.safeValue (data, 'rows', []);
        const result = {};
        for (let i = 0; i < rows.length; i++) {
            const currency = rows[i];
            const currencyId = this.safeString (currency, 'coin');
            const code = this.safeCurrencyCode (currencyId);
            const name = this.safeString (currency, 'name');
            const chains = this.safeValue (currency, 'chains', []);
            const networks = {};
            for (let j = 0; j < chains.length; j++) {
                const chain = chains[j];
                const networkId = this.safeString (chain, 'chain');
                const network = this.safeNetwork (networkId);
                networks[network] = {
                    'info': chain,
                    'id': networkId,
                    'network': network,
                    'active': undefined,
                    'deposit': undefined,
                    'withdraw': undefined,
                    'fee': this.safeNumber (chain, 'withdraw_fee'),
                    'precision': undefined,
                    'limits': {
                        'withdraw': {
                            'min': this.safeNumber (chain, 'withdraw_min'),
                            'max': undefined,
                        },
                        'deposit': {
                            'min': this.safeNumber (chain, 'deposit_min'),
                            'max': undefined,
                        },
                    },
                };
            }
            result[code] = {
                'info': currency,
                'code': code,
                'id': currencyId,
                'name': name,
                'active': undefined,
                'deposit': undefined,
                'withdraw': undefined,
                'fee': undefined,
                'precision': this.parseNumber ('0.00000001'),
                'limits': {
                    'amount': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'networks': networks,
            };
        }
        return result;
    }

    async fetchMarkets (params = {}) {
        /**
         * @method
         * @name bybit#fetchMarkets
         * @description retrieves data on all markets for bybit
         * @param {dict} params extra parameters specific to the exchange api endpoint
         * @returns {[dict]} an array of objects representing market data
         */
        if (this.options['adjustForTimeDifference']) {
            await this.loadTimeDifference ();
        }
        let type = undefined;
        [ type, params ] = this.handleMarketTypeAndParams ('fetchMarkets', undefined, params);
        if (type === 'spot') {
            // spot and swap ids are equal
            // so they can't be loaded together
            const spotMarkets = await this.fetchSpotMarkets (params);
            return spotMarkets;
        }
        let promises = [ this.fetchSwapAndFutureMarkets (params), this.fetchUSDCMarkets (params) ];
        promises = await Promise.all (promises);
        const contractMarkets = promises[0];
        const usdcMarkets = promises[1];
        let markets = contractMarkets;
        markets = this.arrayConcat (markets, usdcMarkets);
        return markets;
    }

    async fetchSpotMarkets (params) {
        const response = await this.publicGetSpotV1Symbols (params);
        //
        //     {
        //         "ret_code":0,
        //         "ret_msg":"",
        //         "ext_code":null,
        //         "ext_info":null,
        //         "result":[
        //             {
        //                 "name":"BTCUSDT",
        //                 "alias":"BTCUSDT",
        //                 "baseCurrency":"BTC",
        //                 "quoteCurrency":"USDT",
        //                 "basePrecision":"0.000001",
        //                 "quotePrecision":"0.00000001",
        //                 "minTradeQuantity":"0.000158",
        //                 "minTradeAmount":"10",
        //                 "maxTradeQuantity":"4",
        //                 "maxTradeAmount":"100000",
        //                 "minPricePrecision":"0.01",
        //                 "category":1,
        //                 "showStatus":true
        //             },
        //         ]
        //     }
        const markets = this.safeValue (response, 'result', []);
        const result = [];
        for (let i = 0; i < markets.length; i++) {
            const market = markets[i];
            const id = this.safeString (market, 'name');
            const baseId = this.safeString (market, 'baseCurrency');
            const quoteId = this.safeString (market, 'quoteCurrency');
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            const symbol = base + '/' + quote;
            const active = this.safeValue (market, 'showStatus');
            const quotePrecision = this.safeNumber (market, 'quotePrecision');
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'settle': undefined,
                'baseId': baseId,
                'quoteId': quoteId,
                'settleId': undefined,
                'type': 'spot',
                'spot': true,
                'margin': undefined,
                'swap': false,
                'future': false,
                'option': false,
                'active': active,
                'contract': false,
                'linear': undefined,
                'inverse': undefined,
                'taker': undefined,
                'maker': undefined,
                'contractSize': undefined,
                'expiry': undefined,
                'expiryDatetime': undefined,
                'strike': undefined,
                'optionType': undefined,
                'precision': {
                    'amount': this.safeNumber (market, 'basePrecision'),
                    'price': this.safeNumber (market, 'minPricePrecision', quotePrecision),
                },
                'limits': {
                    'leverage': {
                        'min': this.parseNumber ('1'),
                        'max': undefined,
                    },
                    'amount': {
                        'min': this.safeNumber (market, 'minTradeQuantity'),
                        'max': this.safeNumber (market, 'maxTradeQuantity'),
                    },
                    'price': {
                        'min': undefined,
                        'max': undefined,
                    },
                    'cost': {
                        'min': this.safeNumber (market, 'minTradeAmount'),
                        'max': this.safeNumber (market, 'maxTradeAmount'),
                    },
                },
                'info': market,
            });
        }
        return result;
    }

    async fetchSwapAndFutureMarkets (params) {
        const response = await this.publicGetV2PublicSymbols (params);
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":[
        //             // inverse swap
        //             {
        //                 "name":"BTCUSD",
        //                 "alias":"BTCUSD",
        //                 "status":"Trading",
        //                 "base_currency":"BTC",
        //                 "quote_currency":"USD",
        //                 "price_scale":2,
        //                 "taker_fee":"0.00075",
        //                 "maker_fee":"-0.00025",
        //                 "leverage_filter":{"min_leverage":1,"max_leverage":100,"leverage_step":"0.01"},
        //                 "price_filter":{"min_price":"0.5","max_price":"999999","tick_size":"0.5"},
        //                 "lot_size_filter":{"max_trading_qty":1000000,"min_trading_qty":1,"qty_step":1}
        //             },
        //             // linear swap
        //             {
        //                 "name":"BTCUSDT",
        //                 "alias":"BTCUSDT",
        //                 "status":"Trading",
        //                 "base_currency":"BTC",
        //                 "quote_currency":"USDT",
        //                 "price_scale":2,
        //                 "taker_fee":"0.00075",
        //                 "maker_fee":"-0.00025",
        //                 "leverage_filter":{"min_leverage":1,"max_leverage":100,"leverage_step":"0.01"},
        //                 "price_filter":{"min_price":"0.5","max_price":"999999","tick_size":"0.5"},
        //                 "lot_size_filter":{"max_trading_qty":100,"min_trading_qty":0.001, "qty_step":0.001}
        //             },
        //  inverse futures
        //            {
        //                "name": "BTCUSDU22",
        //                "alias": "BTCUSD0930",
        //                "status": "Trading",
        //                "base_currency": "BTC",
        //                "quote_currency": "USD",
        //                "price_scale": "2",
        //                "taker_fee": "0.0006",
        //                "maker_fee": "0.0001",
        //                "funding_interval": "480",
        //                "leverage_filter": {
        //                    "min_leverage": "1",
        //                    "max_leverage": "100",
        //                    "leverage_step": "0.01"
        //                },
        //                "price_filter": {
        //                    "min_price": "0.5",
        //                    "max_price": "999999",
        //                    "tick_size": "0.5"
        //                },
        //                "lot_size_filter": {
        //                    "max_trading_qty": "1000000",
        //                    "min_trading_qty": "1",
        //                    "qty_step": "1",
        //                    "post_only_max_trading_qty": "5000000"
        //                }
        //            }
        //         ],
        //         "time_now":"1642369942.072113"
        //     }
        //
        const markets = this.safeValue (response, 'result', []);
        const result = [];
        const options = this.safeValue (this.options, 'fetchMarkets', {});
        const linearQuoteCurrencies = this.safeValue (options, 'linear', { 'USDT': true });
        for (let i = 0; i < markets.length; i++) {
            const market = markets[i];
            const id = this.safeString (market, 'name');
            const baseId = this.safeString (market, 'base_currency');
            const quoteId = this.safeString (market, 'quote_currency');
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            const linear = (quote in linearQuoteCurrencies);
            let symbol = base + '/' + quote;
            const baseQuote = base + quote;
            let type = 'swap';
            if (baseQuote !== id) {
                type = 'future';
            }
            const lotSizeFilter = this.safeValue (market, 'lot_size_filter', {});
            const priceFilter = this.safeValue (market, 'price_filter', {});
            const leverage = this.safeValue (market, 'leverage_filter', {});
            const status = this.safeString (market, 'status');
            let active = undefined;
            if (status !== undefined) {
                active = (status === 'Trading');
            }
            const swap = (type === 'swap');
            const future = (type === 'future');
            let expiry = undefined;
            let expiryDatetime = undefined;
            const settleId = linear ? quoteId : baseId;
            const settle = this.safeCurrencyCode (settleId);
            symbol = symbol + ':' + settle;
            if (future) {
                // we have to do some gymnastics here because bybit
                // only provides the day and month regarding the contract expiration
                const alias = this.safeString (market, 'alias'); // BTCUSD0930
                const aliasDate = alias.slice (-4); // 0930
                const aliasMonth = aliasDate.slice (0, 2); // 09
                const aliasDay = aliasDate.slice (2, 4); // 30
                const dateNow = this.yyyymmdd (this.milliseconds ());
                const dateParts = dateNow.split ('-');
                const year = this.safeValue (dateParts, 0);
                const artificial8601Date = year + '-' + aliasMonth + '-' + aliasDay + 'T00:00:00.000Z';
                expiryDatetime = artificial8601Date;
                expiry = this.parse8601 (expiryDatetime);
                symbol = symbol + '-' + this.yymmdd (expiry);
            }
            const inverse = !linear;
            const contractSize = inverse ? this.safeNumber (lotSizeFilter, 'min_trading_qty') : this.parseNumber ('1');
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'settle': settle,
                'baseId': baseId,
                'quoteId': quoteId,
                'settleId': settleId,
                'type': type,
                'spot': false,
                'margin': undefined,
                'swap': swap,
                'future': future,
                'option': false,
                'active': active,
                'contract': true,
                'linear': linear,
                'inverse': inverse,
                'taker': this.safeNumber (market, 'taker_fee'),
                'maker': this.safeNumber (market, 'maker_fee'),
                'contractSize': contractSize,
                'expiry': expiry,
                'expiryDatetime': expiryDatetime,
                'strike': undefined,
                'optionType': undefined,
                'precision': {
                    'amount': this.safeNumber (lotSizeFilter, 'qty_step'),
                    'price': this.safeNumber (priceFilter, 'tick_size'),
                },
                'limits': {
                    'leverage': {
                        'min': this.parseNumber ('1'),
                        'max': this.safeNumber (leverage, 'max_leverage', 1),
                    },
                    'amount': {
                        'min': this.safeNumber (lotSizeFilter, 'min_trading_qty'),
                        'max': this.safeNumber (lotSizeFilter, 'max_trading_qty'),
                    },
                    'price': {
                        'min': this.safeNumber (priceFilter, 'min_price'),
                        'max': this.safeNumber (priceFilter, 'max_price'),
                    },
                    'cost': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'info': market,
            });
        }
        return result;
    }

    async fetchUSDCMarkets (params) {
        const linearOptionsResponse = await this.publicGetOptionUsdcOpenapiPublicV1Symbols (params);
        const usdcLinearPerpetualSwaps = await this.publicGetPerpetualUsdcOpenapiPublicV1Symbols (params);
        //
        // USDC linear options
        //     {
        //         "retCode":0,
        //         "retMsg":"success",
        //         "result":{
        //             "resultTotalSize":424,
        //             "cursor":"0%2C500",
        //             "dataList":[
        //                 {
        //                     "symbol":"BTC-24JUN22-300000-C",
        //                     "status":"ONLINE",
        //                     "baseCoin":"BTC",
        //                     "quoteCoin":"USD",
        //                     "settleCoin":"USDC",
        //                     "takerFee":"0.0003",
        //                     "makerFee":"0.0003",
        //                     "minLeverage":"",
        //                     "maxLeverage":"",
        //                     "leverageStep":"",
        //                     "minOrderPrice":"0.5",
        //                     "maxOrderPrice":"10000000",
        //                     "minOrderSize":"0.01",
        //                     "maxOrderSize":"200",
        //                     "tickSize":"0.5",
        //                     "minOrderSizeIncrement":"0.01",
        //                     "basicDeliveryFeeRate":"0.00015",
        //                     "deliveryTime":"1656057600000"
        //                 },
        //                 {
        //                     "symbol":"BTC-24JUN22-300000-P",
        //                     "status":"ONLINE",
        //                     "baseCoin":"BTC",
        //                     "quoteCoin":"USD",
        //                     "settleCoin":"USDC",
        //                     "takerFee":"0.0003",
        //                     "makerFee":"0.0003",
        //                     "minLeverage":"",
        //                     "maxLeverage":"",
        //                     "leverageStep":"",
        //                     "minOrderPrice":"0.5",
        //                     "maxOrderPrice":"10000000",
        //                     "minOrderSize":"0.01",
        //                     "maxOrderSize":"200",
        //                     "tickSize":"0.5",
        //                     "minOrderSizeIncrement":"0.01",
        //                     "basicDeliveryFeeRate":"0.00015",
        //                     "deliveryTime":"1656057600000"
        //                 },
        //             ]
        //         }
        //     }
        //
        // USDC linear perpetual swaps
        //
        //     {
        //         "retCode":0,
        //         "retMsg":"",
        //         "result":[
        //             {
        //                 "symbol":"BTCPERP",
        //                 "status":"ONLINE",
        //                 "baseCoin":"BTC",
        //                 "quoteCoin":"USD",
        //                 "takerFeeRate":"0.00075",
        //                 "makerFeeRate":"-0.00025",
        //                 "minLeverage":"1",
        //                 "maxLeverage":"100",
        //                 "leverageStep":"0.01",
        //                 "minPrice":"0.50",
        //                 "maxPrice":"999999.00",
        //                 "tickSize":"0.50",
        //                 "maxTradingQty":"5.000",
        //                 "minTradingQty":"0.001",
        //                 "qtyStep":"0.001",
        //                 "deliveryFeeRate":"",
        //                 "deliveryTime":"0"
        //             }
        //         ]
        //     }
        //
        const optionsResponse = this.safeValue (linearOptionsResponse, 'result', []);
        const options = this.safeValue (optionsResponse, 'dataList', []);
        const contractsResponse = this.safeValue (usdcLinearPerpetualSwaps, 'result', []);
        const markets = this.arrayConcat (options, contractsResponse);
        const result = [];
        // all markets fetched here are linear
        const linear = true;
        for (let i = 0; i < markets.length; i++) {
            const market = markets[i];
            const id = this.safeString (market, 'symbol');
            const baseId = this.safeString (market, 'baseCoin');
            const quoteId = this.safeString (market, 'quoteCoin');
            let settleId = this.safeString (market, 'settleCoin');
            const base = this.safeCurrencyCode (baseId);
            const quote = this.safeCurrencyCode (quoteId);
            let settle = this.safeCurrencyCode (settleId);
            let symbol = base + '/' + quote;
            let type = 'swap';
            if (settleId !== undefined) {
                type = 'option';
            }
            const swap = (type === 'swap');
            const option = (type === 'option');
            const leverage = this.safeValue (market, 'leverage_filter', {});
            const status = this.safeString (market, 'status');
            let active = undefined;
            if (status !== undefined) {
                active = (status === 'ONLINE');
            }
            let expiry = undefined;
            let expiryDatetime = undefined;
            let strike = undefined;
            let optionType = undefined;
            if (settle === undefined) {
                settleId = 'USDC';
                settle = 'USDC';
            }
            symbol = symbol + ':' + settle;
            if (option) {
                expiry = this.safeInteger (market, 'deliveryTime');
                expiryDatetime = this.iso8601 (expiry);
                const splitId = id.split ('-');
                strike = this.safeString (splitId, 2);
                const optionLetter = this.safeString (splitId, 3);
                symbol = symbol + '-' + this.yymmdd (expiry) + ':' + strike + ':' + optionLetter;
                if (optionLetter === 'P') {
                    optionType = 'put';
                } else if (optionLetter === 'C') {
                    optionType = 'call';
                }
            }
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'settle': settle,
                'baseId': baseId,
                'quoteId': quoteId,
                'settleId': settleId,
                'type': type,
                'spot': false,
                'margin': undefined,
                'swap': swap,
                'future': false,
                'option': option,
                'active': active,
                'contract': true,
                'linear': linear,
                'inverse': !linear,
                'taker': this.safeNumber2 (market, 'taker_fee', 'takerFeeRate'),
                'maker': this.safeNumber2 (market, 'maker_fee', 'makerFeeRate'),
                'contractSize': this.parseNumber ('1'),
                'expiry': expiry,
                'expiryDatetime': expiryDatetime,
                'strike': strike,
                'optionType': optionType,
                'precision': {
                    'amount': this.safeNumber2 (market, 'minOrderSizeIncrement', 'qtyStep'),
                    'price': this.safeNumber (market, 'tickSize'),
                },
                'limits': {
                    'leverage': {
                        'min': this.safeNumber (leverage, 'minLeverage', 1),
                        'max': this.safeNumber (leverage, 'maxLeverage', 1),
                    },
                    'amount': {
                        'min': this.safeNumber2 (market, 'minOrderSize', 'minTradingQty'),
                        'max': this.safeNumber2 (market, 'maxOrderSize', 'maxTradingQty'),
                    },
                    'price': {
                        'min': this.safeNumber2 (market, 'minOrderPrice', 'minPrice'),
                        'max': this.safeNumber2 (market, 'maxOrderPrice', 'maxPrice'),
                    },
                    'cost': {
                        'min': undefined,
                        'max': undefined,
                    },
                },
                'info': market,
            });
        }
        return result;
    }

    parseTicker (ticker, market = undefined) {
        // spot
        //
        //    {
        //        "time": "1651743420061",
        //        "symbol": "BTCUSDT",
        //        "bestBidPrice": "39466.75",
        //        "bestAskPrice": "39466.83",
        //        "volume": "4396.082921",
        //        "quoteVolume": "172664909.03216557",
        //        "lastPrice": "39466.71",
        //        "highPrice": "40032.79",
        //        "lowPrice": "38602.39",
        //        "openPrice": "39031.53"
        //    }
        //
        // linear usdt/ inverse swap and future
        //     {
        //         "symbol": "BTCUSDT",
        //         "bid_price": "39458",
        //         "ask_price": "39458.5",
        //         "last_price": "39458.00",
        //         "last_tick_direction": "ZeroMinusTick",
        //         "prev_price_24h": "39059.50",
        //         "price_24h_pcnt": "0.010202",
        //         "high_price_24h": "40058.50",
        //         "low_price_24h": "38575.50",
        //         "prev_price_1h": "39534.00",
        //         "price_1h_pcnt": "-0.001922",
        //         "mark_price": "39472.49",
        //         "index_price": "39469.81",
        //         "open_interest": "28343.61",
        //         "open_value": "0.00",
        //         "total_turnover": "85303326477.54",
        //         "turnover_24h": "4221589085.06",
        //         "total_volume": "30628792.45",
        //         "volume_24h": "107569.75",
        //         "funding_rate": "0.0001",
        //         "predicted_funding_rate": "0.0001",
        //         "next_funding_time": "2022-05-05T16:00:00Z",
        //         "countdown_hour": "7",
        //         "delivery_fee_rate": "",
        //         "predicted_delivery_price": "",
        //         "delivery_time": ""
        //     }
        //
        // usdc option/ swap
        //     {
        //          "symbol": "BTC-30SEP22-400000-C",
        //          "bid": "0",
        //          "bidIv": "0",
        //          "bidSize": "0",
        //          "ask": "15",
        //          "askIv": "1.1234",
        //          "askSize": "0.01",
        //          "lastPrice": "5",
        //          "openInterest": "0.03",
        //          "indexPrice": "39458.6",
        //          "markPrice": "0.51901394",
        //          "markPriceIv": "0.9047",
        //          "change24h": "0",
        //          "high24h": "0",
        //          "low24h": "0",
        //          "volume24h": "0",
        //          "turnover24h": "0",
        //          "totalVolume": "1",
        //          "totalTurnover": "4",
        //          "predictedDeliveryPrice": "0",
        //          "underlyingPrice": "40129.73",
        //          "delta": "0.00010589",
        //          "gamma": "0.00000002",
        //          "vega": "0.10670892",
        //          "theta": "-0.03262827"
        //      }
        //
        const timestamp = this.safeInteger (ticker, 'time');
        const marketId = this.safeString (ticker, 'symbol');
        const symbol = this.safeSymbol (marketId, market);
        const last = this.safeString2 (ticker, 'last_price', 'lastPrice');
        const open = this.safeString2 (ticker, 'prev_price_24h', 'openPrice');
        let percentage = this.safeString2 (ticker, 'price_24h_pcnt', 'change24h');
        percentage = Precise.stringMul (percentage, '100');
        let baseVolume = this.safeString2 (ticker, 'turnover_24h', 'turnover24h');
        if (baseVolume === undefined) {
            baseVolume = this.safeString (ticker, 'volume');
        }
        let quoteVolume = this.safeString2 (ticker, 'volume_24h', 'volume24h');
        if (quoteVolume === undefined) {
            quoteVolume = this.safeString (ticker, 'quoteVolume');
        }
        let bid = this.safeString2 (ticker, 'bid_price', 'bid');
        if (bid === undefined) {
            bid = this.safeString (ticker, 'bestBidPrice');
        }
        let ask = this.safeString2 (ticker, 'ask_price', 'ask');
        if (ask === undefined) {
            ask = this.safeString (ticker, 'bestAskPrice');
        }
        let high = this.safeString2 (ticker, 'high_price_24h', 'high24h');
        if (high === undefined) {
            high = this.safeString (ticker, 'highPrice');
        }
        let low = this.safeString2 (ticker, 'low_price_24h', 'low24h');
        if (low === undefined) {
            low = this.safeString (ticker, 'lowPrice');
        }
        return this.safeTicker ({
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': high,
            'low': low,
            'bid': bid,
            'bidVolume': this.safeString (ticker, 'bidSize'),
            'ask': ask,
            'askVolume': this.safeString (ticker, 'askSize'),
            'vwap': undefined,
            'open': open,
            'close': last,
            'last': last,
            'previousClose': undefined,
            'change': undefined,
            'percentage': percentage,
            'average': undefined,
            'baseVolume': baseVolume,
            'quoteVolume': quoteVolume,
            'info': ticker,
        }, market);
    }

    async fetchTicker (symbol, params = {}) {
        /**
         * @method
         * @name bybit#fetchTicker
         * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
         * @param {str} symbol unified symbol of the market to fetch the ticker for
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
         */
        await this.loadMarkets ();
        const market = this.market (symbol);
        let method = undefined;
        const isUsdcSettled = market['settle'] === 'USDC';
        if (market['spot']) {
            method = 'publicGetSpotQuoteV1Ticker24hr';
        } else if (!isUsdcSettled) {
            // inverse perpetual // usdt linear // inverse futures
            method = 'publicGetV2PublicTickers';
        } else if (market['option']) {
            // usdc option
            method = 'publicGetOptionUsdcOpenapiPublicV1Tick';
        } else {
            // usdc swap
            method = 'publicGetPerpetualUsdcOpenapiPublicV1Tick';
        }
        const request = {
            'symbol': market['id'],
        };
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: [
        //             {
        //                 symbol: 'BTCUSD',
        //                 bid_price: '7680',
        //                 ask_price: '7680.5',
        //                 last_price: '7680.00',
        //                 last_tick_direction: 'MinusTick',
        //                 prev_price_24h: '7870.50',
        //                 price_24h_pcnt: '-0.024204',
        //                 high_price_24h: '8035.00',
        //                 low_price_24h: '7671.00',
        //                 prev_price_1h: '7780.00',
        //                 price_1h_pcnt: '-0.012853',
        //                 mark_price: '7683.27',
        //                 index_price: '7682.74',
        //                 open_interest: 188829147,
        //                 open_value: '23670.06',
        //                 total_turnover: '25744224.90',
        //                 turnover_24h: '102997.83',
        //                 total_volume: 225448878806,
        //                 volume_24h: 809919408,
        //                 funding_rate: '0.0001',
        //                 predicted_funding_rate: '0.0001',
        //                 next_funding_time: '2020-03-12T00:00:00Z',
        //                 countdown_hour: 7
        //             }
        //         ],
        //         time_now: '1583948195.818255'
        //     }
        //  usdc ticker
        //     {
        //         "retCode": 0,
        //           "retMsg": "SUCCESS",
        //           "result": {
        //                  "symbol": "BTC-28JAN22-250000-C",
        //                    "bid": "0",
        //                    "bidIv": "0",
        //                    "bidSize": "0",
        //                    "ask": "0",
        //                    "askIv": "0",
        //                    "askSize": "0",
        //                    "lastPrice": "0",
        //                    "openInterest": "0",
        //                    "indexPrice": "56171.79000000",
        //                    "markPrice": "12.72021285",
        //                    "markPriceIv": "1.1701",
        //                    "change24h": "0",
        //                    "high24h": "0",
        //                    "low24h": "0",
        //                    "volume24h": "0",
        //                    "turnover24h": "0",
        //                    "totalVolume": "0",
        //                    "totalTurnover": "0",
        //                    "predictedDeliveryPrice": "0",
        //                    "underlyingPrice": "57039.61000000",
        //                    "delta": "0.00184380",
        //                    "gamma": "0.00000022",
        //                    "vega": "1.35132531",
        //                    "theta": "-1.33819821"
        //          }
        //     }
        //
        const result = this.safeValue (response, 'result', []);
        let rawTicker = undefined;
        if (Array.isArray (result)) {
            rawTicker = this.safeValue (result, 0);
        } else {
            rawTicker = result;
        }
        const ticker = this.parseTicker (rawTicker, market);
        return ticker;
    }

    async fetchTickers (symbols = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchTickers
         * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
         * @param {[str]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure}
         */
        await this.loadMarkets ();
        let type = undefined;
        let market = undefined;
        let isUsdcSettled = undefined;
        if (symbols !== undefined) {
            const symbol = this.safeValue (symbols, 0);
            market = this.market (symbol);
            type = market['type'];
            isUsdcSettled = market['settle'] === 'USDC';
        } else {
            [ type, params ] = this.handleMarketTypeAndParams ('fetchTickers', market, params);
            if (type !== 'spot') {
                let defaultSettle = this.safeString (this.options, 'defaultSettle', 'USDT');
                defaultSettle = this.safeString2 (params, 'settle', 'defaultSettle', isUsdcSettled);
                params = this.omit (params, [ 'settle', 'defaultSettle' ]);
                isUsdcSettled = defaultSettle === 'USDC';
            }
        }
        let method = undefined;
        if (type === 'spot') {
            method = 'publicGetSpotQuoteV1Ticker24hr';
        } else if (!isUsdcSettled) {
            // inverse perpetual // usdt linear // inverse futures
            method = 'publicGetV2PublicTickers';
        } else {
            throw new NotSupported (this.id + ' fetchTickers() is not supported for USDC markets');
        }
        const response = await this[method] (params);
        const result = this.safeValue (response, 'result', []);
        const tickers = {};
        for (let i = 0; i < result.length; i++) {
            const ticker = this.parseTicker (result[i]);
            const symbol = ticker['symbol'];
            tickers[symbol] = ticker;
        }
        return this.filterByArray (tickers, 'symbol', symbols);
    }

    parseOHLCV (ohlcv, market = undefined) {
        //
        // inverse perpetual BTC/USD
        //
        //     {
        //         symbol: 'BTCUSD',
        //         interval: '1',
        //         open_time: 1583952540,
        //         open: '7760.5',
        //         high: '7764',
        //         low: '7757',
        //         close: '7763.5',
        //         volume: '1259766',
        //         turnover: '162.32773718999994'
        //     }
        //
        // linear perpetual BTC/USDT
        //
        //     {
        //         "id":143536,
        //         "symbol":"BTCUSDT",
        //         "period":"15",
        //         "start_at":1587883500,
        //         "volume":1.035,
        //         "open":7540.5,
        //         "high":7541,
        //         "low":7540.5,
        //         "close":7541
        //     }
        //
        // usdc perpetual
        //     {
        //         "symbol":"BTCPERP",
        //         "volume":"0.01",
        //         "period":"1",
        //         "openTime":"1636358160",
        //         "open":"66001.50",
        //         "high":"66001.50",
        //         "low":"66001.50",
        //         "close":"66001.50",
        //         "turnover":"1188.02"
        //     }
        //
        // spot
        //     [
        //         1651837620000, // start tame
        //         "35831.5", // open
        //         "35831.5", // high
        //         "35801.93", // low
        //         "35817.11", // close
        //         "1.23453", // volume
        //         0, // end time
        //         "44213.97591627", // quote asset volume
        //         24, // number of trades
        //         "0", // taker base volume
        //         "0" // taker quote volume
        //     ]
        //
        if (Array.isArray (ohlcv)) {
            return [
                this.safeNumber (ohlcv, 0),
                this.safeNumber (ohlcv, 1),
                this.safeNumber (ohlcv, 2),
                this.safeNumber (ohlcv, 3),
                this.safeNumber (ohlcv, 4),
                this.safeNumber (ohlcv, 5),
            ];
        }
        let timestamp = this.safeTimestamp2 (ohlcv, 'open_time', 'openTime');
        if (timestamp === undefined) {
            timestamp = this.safeTimestamp (ohlcv, 'start_at');
        }
        return [
            timestamp,
            this.safeNumber (ohlcv, 'open'),
            this.safeNumber (ohlcv, 'high'),
            this.safeNumber (ohlcv, 'low'),
            this.safeNumber (ohlcv, 'close'),
            this.safeNumber2 (ohlcv, 'volume', 'turnover'),
        ];
    }

    async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOHLCV
         * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
         * @param {str} symbol unified symbol of the market to fetch OHLCV data for
         * @param {str} timeframe the length of time each candle represents
         * @param {int|undefined} since timestamp in ms of the earliest candle to fetch
         * @param {int|undefined} limit the maximum amount of candles to fetch
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume
         */
        await this.loadMarkets ();
        const market = this.market (symbol);
        const price = this.safeString (params, 'price');
        params = this.omit (params, 'price');
        const request = {
            'symbol': market['id'],
        };
        const duration = this.parseTimeframe (timeframe);
        const now = this.seconds ();
        let sinceTimestamp = undefined;
        if (since === undefined) {
            if (limit === undefined) {
                throw new ArgumentsRequired (this.id + ' fetchOHLCV() requires a since argument or a limit argument');
            } else {
                sinceTimestamp = now - limit * duration;
            }
        } else {
            sinceTimestamp = parseInt (since / 1000);
        }
        if (limit !== undefined) {
            request['limit'] = limit; // max 200, default 200
        }
        let method = undefined;
        let intervalKey = 'interval';
        let sinceKey = 'from';
        const isUsdcSettled = market['settle'] === 'USDC';
        if (market['spot']) {
            method = 'publicGetSpotQuoteV1Kline';
        } else if (market['contract'] && !isUsdcSettled) {
            if (market['linear']) {
                // linear swaps/futures
                const methods = {
                    'mark': 'publicGetPublicLinearMarkPriceKline',
                    'index': 'publicGetPublicLinearIndexPriceKline',
                    'premium': 'publicGetPublicLinearPremiumIndexKline',
                };
                method = this.safeValue (methods, price, 'publicGetPublicLinearKline');
            } else {
                // inverse swaps/ futures
                const methods = {
                    'mark': 'publicGetV2PublicMarkPriceKline',
                    'index': 'publicGetV2PublicIndexPriceKline',
                    'premium': 'publicGetV2PublicPremiumPriceKline',
                };
                method = this.safeValue (methods, price, 'publicGetV2PublicKlineList');
            }
        } else {
            // usdc markets
            if (market['option']) {
                throw new NotSupported (this.id + ' fetchOHLCV() is not supported for USDC options markets');
            }
            intervalKey = 'period';
            sinceKey = 'startTime';
            const methods = {
                'mark': 'publicGetPerpetualUsdcOpenapiPublicV1MarkPriceKline',
                'index': 'publicGetPerpetualUsdcOpenapiPublicV1IndexPriceKline',
                'premium': 'publicGetPerpetualUsdcOpenapiPublicV1PremiumPriceKline',
            };
            method = this.safeValue (methods, price, 'publicGetPerpetualUsdcOpenapiPublicV1KlineList');
        }
        // spot markets use the same interval format as ccxt
        // so we don't need  to convert it
        request[intervalKey] = market['spot'] ? timeframe : this.timeframes[timeframe];
        request[sinceKey] = sinceTimestamp;
        const response = await this[method] (this.extend (request, params));
        //
        // inverse perpetual BTC/USD
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: [
        //             {
        //                 symbol: 'BTCUSD',
        //                 interval: '1',
        //                 open_time: 1583952540,
        //                 open: '7760.5',
        //                 high: '7764',
        //                 low: '7757',
        //                 close: '7763.5',
        //                 volume: '1259766',
        //                 turnover: '162.32773718999994'
        //             },
        //         ],
        //         time_now: '1583953082.397330'
        //     }
        //
        // linear perpetual BTC/USDT
        //
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":[
        //             {
        //                 "id":143536,
        //                 "symbol":"BTCUSDT",
        //                 "period":"15",
        //                 "start_at":1587883500,
        //                 "volume":1.035,
        //                 "open":7540.5,
        //                 "high":7541,
        //                 "low":7540.5,
        //                 "close":7541
        //             }
        //         ],
        //         "time_now":"1587884120.168077"
        //     }
        // spot
        //     {
        //    "ret_code": "0",
        //    "ret_msg": null,
        //     "result": [
        //         [
        //             1651837620000,
        //             "35831.5",
        //             "35831.5",
        //             "35801.93",
        //             "35817.11",
        //             "1.23453",
        //             0,
        //             "44213.97591627",
        //             24,
        //             "0",
        //             "0"
        //         ]
        //     ],
        //     "ext_code": null,
        //     "ext_info": null
        // }
        //
        const result = this.safeValue (response, 'result', {});
        return this.parseOHLCVs (result, market, timeframe, since, limit);
    }

    async fetchFundingRate (symbol, params = {}) {
        /**
         * @method
         * @name bybit#fetchFundingRate
         * @description fetch the current funding rate
         * @param {str} symbol unified market symbol
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a [funding rate structure]{@link https://docs.ccxt.com/en/latest/manual.html#funding-rate-structure}
         */
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'symbol': market['id'],
        };
        const isUsdcSettled = market['settle'] === 'USDC';
        let method = undefined;
        let fundingRateFromTickerMethod = undefined;
        if (isUsdcSettled) {
            method = 'publicGetPerpetualUsdcOpenapiPublicV1PrevFundingRate';
            fundingRateFromTickerMethod = 'publicGetPerpetualUsdcOpenapiPublicV1Tick';
        } else {
            method = market['linear'] ? 'publicGetPublicLinearFundingPrevFundingRate' : 'publicGetV2PublicFundingPrevFundingRate';
            fundingRateFromTickerMethod = 'publicGetV2PublicTickers';
        }
        const fetchFundingRateFromTicker = await this[fundingRateFromTickerMethod] (this.extend (request, params));
        const response = await this[method] (this.extend (request, params));
        //
        // fetchFundingRateFromTicker
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: [
        //             {
        //                 symbol: 'BTCUSD',
        //                 bid_price: '7680',
        //                 ask_price: '7680.5',
        //                 last_price: '7680.00',
        //                 last_tick_direction: 'MinusTick',
        //                 prev_price_24h: '7870.50',
        //                 price_24h_pcnt: '-0.024204',
        //                 high_price_24h: '8035.00',
        //                 low_price_24h: '7671.00',
        //                 prev_price_1h: '7780.00',
        //                 price_1h_pcnt: '-0.012853',
        //                 mark_price: '7683.27',
        //                 index_price: '7682.74',
        //                 open_interest: 188829147,
        //                 open_value: '23670.06',
        //                 total_turnover: '25744224.90',
        //                 turnover_24h: '102997.83',
        //                 total_volume: 225448878806,
        //                 volume_24h: 809919408,
        //                 funding_rate: '0.0001',
        //                 predicted_funding_rate: '0.0001',
        //                 next_funding_time: '2020-03-12T00:00:00Z',
        //                 countdown_hour: 7
        //             }
        //         ],
        //         time_now: '1583948195.818255'
        //     }
        //
        // fetchFundingRateFromTicker USDC settled
        //     {
        //         "retCode": 0,
        //         "retMsg": "",
        //         "result": {
        //             "symbol": "BTCPERP",
        //             "bid": "30085",
        //             "bidIv": "",
        //             "bidSize": "2.3",
        //             "ask": "30245.5",
        //             "askIv": "",
        //             "askSize": "0.882",
        //             "lastPrice": "30245.00",
        //             "openInterest": "1080.03",
        //             "indexPrice": "30246.88",
        //             "markPrice": "30241.83",
        //             "markPriceIv": "",
        //             "change24h": "0.034211",
        //             "high24h": "30416.50",
        //             "low24h": "28400.00",
        //             "volume24h": "158.04",
        //             "turnover24h": "4656073.32",
        //             "totalVolume": "17728.56",
        //             "totalTurnover": "706887856.04",
        //             "fundingRate": "-0.000531",
        //             "predictedFundingRate": "-0.000156",
        //             "nextFundingTime": "2022-05-20T00:00:00Z",
        //             "countdownHour": "3",
        //             "predictedDeliveryPrice": "",
        //             "underlyingPrice": "",
        //             "delta": "",
        //             "gamma": "",
        //             "vega": "",
        //             "theta": ""
        //         }
        //     }
        //
        // linear
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":{
        //             "symbol":"BTCUSDT",
        //             "funding_rate":0.00006418,
        //             "funding_rate_timestamp":"2022-03-11T16:00:00.000Z"
        //         },
        //         "time_now":"1647040818.724895"
        //     }
        //
        // inverse
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":{
        //             "symbol":"BTCUSD",
        //             "funding_rate":"0.00009536",
        //             "funding_rate_timestamp":1647014400
        //         },
        //         "time_now":"1647040852.515724"
        //     }
        //
        // usdc
        //     {
        //         "retCode":0,
        //         "retMsg":"",
        //         "result":{
        //            "symbol":"BTCPERP",
        //            "fundingRate":"0.00010000",
        //            "fundingRateTimestamp":"1652112000000"
        //         }
        //     }
        //
        const result = this.safeValue (response, 'result');
        const fundingRate = this.safeNumber2 (result, 'funding_rate', 'fundingRate');
        let fundingTimestamp = this.parse8601 (this.safeString (result, 'funding_rate_timestamp'));
        if (fundingTimestamp === undefined) {
            fundingTimestamp = this.safeTimestamp2 (result, 'funding_rate_timestamp', fundingTimestamp);
            if (fundingTimestamp === undefined) {
                fundingTimestamp = this.safeInteger (result, 'fundingRateTimestamp');
            }
        }
        const currentTime = this.milliseconds ();
        const fetchTickerResult = isUsdcSettled ? this.safeValue (fetchFundingRateFromTicker, 'result', {}) : this.safeValue (fetchFundingRateFromTicker, 'result', []);
        const markPrice = isUsdcSettled ? this.safeNumber (fetchTickerResult, 'markPrice') : this.safeNumber (fetchTickerResult[0], 'mark_price');
        const indexPrice = isUsdcSettled ? this.safeNumber (fetchTickerResult, 'indexPrice') : this.safeNumber (fetchTickerResult[0], 'index_price');
        const nextFundingRate = isUsdcSettled ? this.safeNumber (fetchTickerResult, 'predictedFundingRate') : this.safeNumber (fetchTickerResult[0], 'predicted_funding_rate');
        const nextFundingDatetime = isUsdcSettled ? this.safeString (fetchTickerResult, 'nextFundingTime') : this.safeString (fetchTickerResult[0], 'next_funding_time');
        return {
            'info': result,
            'symbol': symbol,
            'markPrice': markPrice,
            'indexPrice': indexPrice,
            'interestRate': undefined,
            'estimatedSettlePrice': undefined,
            'timestamp': currentTime,
            'datetime': this.iso8601 (currentTime),
            'fundingRate': fundingRate,
            'fundingTimestamp': fundingTimestamp,
            'fundingDatetime': this.iso8601 (fundingTimestamp),
            'nextFundingRate': nextFundingRate,
            'nextFundingTimestamp': this.parse8601 (nextFundingDatetime),
            'nextFundingDatetime': nextFundingDatetime,
            'previousFundingRate': undefined,
            'previousFundingTimestamp': undefined,
            'previousFundingDatetime': undefined,
        };
    }

    async fetchIndexOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        if (since === undefined && limit === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchIndexOHLCV() requires a since argument or a limit argument');
        }
        const request = {
            'price': 'index',
        };
        return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
    }

    async fetchMarkOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        if (since === undefined && limit === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchMarkOHLCV() requires a since argument or a limit argument');
        }
        const request = {
            'price': 'mark',
        };
        return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
    }

    async fetchPremiumIndexOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
        if (since === undefined && limit === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchPremiumIndexOHLCV() requires a since argument or a limit argument');
        }
        const request = {
            'price': 'premiumIndex',
        };
        return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
    }

    parseTrade (trade, market = undefined) {
        //
        //  public spot
        //
        //    {
        //        "price": "39548.68",
        //        "time": "1651748717850",
        //        "qty": "0.166872",
        //        "isBuyerMaker": true
        //    }
        //
        // public linear/inverse swap/future
        //
        //     {
        //         "id": "112348766532",
        //         "symbol": "BTCUSDT",
        //         "price": "39536",
        //         "qty": "0.011",
        //         "side": "Buy",
        //         "time": "2022-05-05T11:16:02.000Z",
        //         "trade_time_ms": "1651749362196"
        //     }
        //
        // public usdc market
        //
        //     {
        //         "symbol": "BTC-30SEP22-400000-C",
        //         "orderQty": "0.010",
        //         "orderPrice": "5.00",
        //         "time": "1651104300208"
        //     }
        //
        // private futures/swap
        //
        //      {
        //          "order_id": "b020b4bc-6fe2-45b5-adbc-dd07794f9746",
        //          "order_link_id": "",
        //          "side": "Buy",
        //          "symbol": "AAVEUSDT",
        //          "exec_id": "09abe8f0-aea6-514e-942b-7da8cb935120",
        //          "price": "269.3",
        //          "order_price": "269.3",
        //          "order_qty": "0.1",
        //          "order_type": "Market",
        //          "fee_rate": "0.00075",
        //          "exec_price": "256.35",
        //          "exec_type": "Trade",
        //          "exec_qty": "0.1",
        //          "exec_fee": "0.01922625",
        //          "exec_value": "25.635",
        //          "leaves_qty": "0",
        //          "closed_size": "0",
        //          "last_liquidity_ind": "RemovedLiquidity",
        //          "trade_time": "1638276374",
        //          "trade_time_ms": "1638276374312"
        //      }
        //
        // spot
        //    {
        //         "id": "1149467000412631552",
        //         "symbol": "LTCUSDT",
        //         "symbolName": "LTCUSDT",
        //         "orderId": "1149467000244912384",
        //         "ticketId": "2200000000002601358",
        //         "matchOrderId": "1149465793552007078",
        //         "price": "100.19",
        //         "qty": "0.09973",
        //         "commission": "0.0099919487",
        //         "commissionAsset": "USDT",
        //         "time": "1651763144465",
        //         "isBuyer": false,
        //         "isMaker": false,
        //         "fee": {
        //             "feeTokenId": "USDT",
        //             "feeTokenName": "USDT",
        //             "fee": "0.0099919487"
        //         },
        //         "feeTokenId": "USDT",
        //         "feeAmount": "0.0099919487",
        //         "makerRebate": "0"
        //     }
        //
        const id = this.safeString2 (trade, 'id', 'exec_id');
        const marketId = this.safeString (trade, 'symbol');
        market = this.safeMarket (marketId, market);
        const symbol = market['symbol'];
        let amountString = this.safeString2 (trade, 'qty', 'exec_qty');
        if (amountString === undefined) {
            amountString = this.safeString (trade, 'orderQty');
        }
        let priceString = this.safeString2 (trade, 'exec_price', 'price');
        if (priceString === undefined) {
            priceString = this.safeString (trade, 'orderPrice');
        }
        const costString = this.safeString (trade, 'exec_value');
        let timestamp = this.parse8601 (this.safeString (trade, 'time'));
        if (timestamp === undefined) {
            timestamp = this.safeInteger2 (trade, 'trade_time_ms', 'time');
        }
        let side = this.safeStringLower (trade, 'side');
        if (side === undefined) {
            const isBuyer = this.safeValue (trade, 'isBuyer');
            if (isBuyer !== undefined) {
                side = isBuyer ? 'buy' : 'sell';
            }
        }
        const isMaker = this.safeValue (trade, 'isMaker');
        let takerOrMaker = undefined;
        if (isMaker !== undefined) {
            takerOrMaker = isMaker ? 'maker' : 'taker';
        } else {
            const lastLiquidityInd = this.safeString (trade, 'last_liquidity_ind');
            takerOrMaker = (lastLiquidityInd === 'AddedLiquidity') ? 'maker' : 'taker';
        }
        const feeCostString = this.safeString (trade, 'exec_fee');
        let fee = undefined;
        if (feeCostString !== undefined) {
            const feeCurrencyCode = market['inverse'] ? market['base'] : market['quote'];
            fee = {
                'cost': feeCostString,
                'currency': feeCurrencyCode,
                'rate': this.safeString (trade, 'fee_rate'),
            };
        }
        return this.safeTrade ({
            'id': id,
            'info': trade,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': symbol,
            'order': this.safeString2 (trade, 'order_id', 'orderId'),
            'type': this.safeStringLower (trade, 'order_type'),
            'side': side,
            'takerOrMaker': takerOrMaker,
            'price': priceString,
            'amount': amountString,
            'cost': costString,
            'fee': fee,
        }, market);
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchTrades
         * @description get the list of most recent trades for a particular symbol
         * @param {str} symbol unified symbol of the market to fetch trades for
         * @param {int|undefined} since timestamp in ms of the earliest trade to fetch
         * @param {int|undefined} limit the maximum amount of trades to fetch
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
         */
        await this.loadMarkets ();
        const market = this.market (symbol);
        let method = undefined;
        const request = {
            'symbol': market['id'],
        };
        const isUsdcSettled = market['settle'] === 'USDC';
        if (market['type'] === 'spot') {
            method = 'publicGetSpotQuoteV1Trades';
        } else if (!isUsdcSettled) {
            // inverse perpetual // usdt linear // inverse futures
            method = market['linear'] ? 'publicGetPublicLinearRecentTradingRecords' : 'publicGetV2PublicTradingRecords';
        } else {
            // usdc option/ swap
            method = 'publicGetOptionUsdcOpenapiPublicV1QueryTradeLatest';
            request['category'] = market['option'] ? 'OPTION' : 'PERPETUAL';
        }
        if (limit !== undefined) {
            request['limit'] = limit; // default 500, max 1000
        }
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: [
        //             {
        //                 id: 43785688,
        //                 symbol: 'BTCUSD',
        //                 price: 7786,
        //                 qty: 67,
        //                 side: 'Sell',
        //                 time: '2020-03-11T19:18:30.123Z'
        //             },
        //         ],
        //         time_now: '1583954313.393362'
        //     }
        //
        // usdc trades
        //     {
        //         "retCode": 0,
        //           "retMsg": "Success.",
        //           "result": {
        //           "resultTotalSize": 2,
        //             "cursor": "",
        //             "dataList": [
        //                  {
        //                    "id": "3caaa0ca",
        //                    "symbol": "BTCPERP",
        //                    "orderPrice": "58445.00",
        //                    "orderQty": "0.010",
        //                    "side": "Buy",
        //                    "time": "1638275679673"
        //                  }
        //              ]
        //         }
        //     }
        //
        let trades = this.safeValue (response, 'result', {});
        if (!Array.isArray (trades)) {
            trades = this.safeValue (trades, 'dataList', []);
        }
        return this.parseTrades (trades, market, since, limit);
    }

    parseOrderBook (orderbook, symbol, timestamp = undefined, bidsKey = 'bids', asksKey = 'asks', priceKey = 0, amountKey = 1) {
        const market = this.market (symbol);
        if (market['spot']) {
            return super.parseOrderBook (orderbook, symbol, timestamp, bidsKey, asksKey, priceKey, amountKey);
        }
        const bids = [];
        const asks = [];
        for (let i = 0; i < orderbook.length; i++) {
            const bidask = orderbook[i];
            const side = this.safeString (bidask, 'side');
            if (side === 'Buy') {
                bids.push (this.parseBidAsk (bidask, priceKey, amountKey));
            } else if (side === 'Sell') {
                asks.push (this.parseBidAsk (bidask, priceKey, amountKey));
            } else {
                throw new ExchangeError (this.id + ' parseOrderBook() encountered an unrecognized bidask format: ' + this.json (bidask));
            }
        }
        return {
            'symbol': symbol,
            'bids': this.sortBy (bids, 0, true),
            'asks': this.sortBy (asks, 0),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'nonce': undefined,
        };
    }

    async fetchOrderBook (symbol, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOrderBook
         * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
         * @param {str} symbol unified symbol of the market to fetch the order book for
         * @param {int|undefined} limit the maximum amount of order book entries to return
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols
         */
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'symbol': market['id'],
        };
        const isUsdcSettled = market['settle'] === 'USDC';
        let method = undefined;
        if (market['spot']) {
            method = 'publicGetSpotQuoteV1Depth';
        } else if (!isUsdcSettled) {
            // inverse perpetual // usdt linear // inverse futures
            method = 'publicGetV2PublicOrderBookL2';
        } else {
            // usdc option/ swap
            method = market['option'] ? 'publicGetOptionUsdcOpenapiPublicV1OrderBook' : 'publicGetPerpetualUsdcOpenapiPublicV1OrderBook';
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this[method] (this.extend (request, params));
        //
        // spot
        //     {
        //         "ret_code": 0,
        //         "ret_msg": null,
        //         "result": {
        //             "time": 1620886105740,
        //             "bids": [
        //                 ["50005.12","403.0416"]
        //             ],
        //             "asks": [
        //                 ["50006.34", "0.2297" ]
        //             ]
        //         },
        //         "ext_code": null,
        //         "ext_info": null
        //     }
        //
        // linear/inverse swap/futures
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: [
        //             { symbol: 'BTCUSD', price: '7767.5', size: 677956, side: 'Buy' },
        //             { symbol: 'BTCUSD', price: '7767', size: 580690, side: 'Buy' },
        //             { symbol: 'BTCUSD', price: '7766.5', size: 475252, side: 'Buy' },
        //         ],
        //         time_now: '1583954829.874823'
        //     }
        //
        // usdc markets
        //
        //     {
        //         "retCode": 0,
        //           "retMsg": "SUCCESS",
        //           "result": [
        //           {
        //             "price": "5000.00000000",
        //             "size": "2.0000",
        //             "side": "Buy" // bids
        //           },
        //           {
        //             "price": "5900.00000000",
        //             "size": "0.9000",
        //             "side": "Sell" // asks
        //           }
        //         ]
        //    }
        //
        const result = this.safeValue (response, 'result', []);
        let timestamp = this.safeTimestamp (response, 'time_now');
        if (timestamp === undefined) {
            timestamp = this.safeInteger (response, 'time');
        }
        const bidsKey = market['spot'] ? 'bids' : 'Buy';
        const asksKey = market['spot'] ? 'asks' : 'Sell';
        const priceKey = market['spot'] ? 0 : 'price';
        const sizeKey = market['spot'] ? 1 : 'size';
        return this.parseOrderBook (result, symbol, timestamp, bidsKey, asksKey, priceKey, sizeKey);
    }

    parseBalance (response) {
        //
        // spot balance
        //    {
        //        "ret_code": "0",
        //        "ret_msg": "",
        //        "ext_code": null,
        //        "ext_info": null,
        //        "result": {
        //            "balances": [
        //                {
        //                    "coin": "LTC",
        //                    "coinId": "LTC",
        //                    "coinName": "LTC",
        //                    "total": "0.00000783",
        //                    "free": "0.00000783",
        //                    "locked": "0"
        //                }
        //            ]
        //        }
        //    }
        //
        // linear/inverse swap/futures
        //    {
        //        "ret_code": "0",
        //        "ret_msg": "OK",
        //        "ext_code": "",
        //        "ext_info": "",
        //        "result": {
        //            "ADA": {
        //                "equity": "0",
        //                "available_balance": "0",
        //                "used_margin": "0",
        //                "order_margin": "0",
        //                "position_margin": "0",
        //                "occ_closing_fee": "0",
        //                "occ_funding_fee": "0",
        //                "wallet_balance": "0",
        //                "realised_pnl": "0",
        //                "unrealised_pnl": "0",
        //                "cum_realised_pnl": "0",
        //                "given_cash": "0",
        //                "service_cash": "0"
        //            },
        //        },
        //        "time_now": "1651772170.050566",
        //        "rate_limit_status": "119",
        //        "rate_limit_reset_ms": "1651772170042",
        //        "rate_limit": "120"
        //    }
        //
        // usdc wallet
        //    {
        //      "result": {
        //           "walletBalance": "10.0000",
        //           "accountMM": "0.0000",
        //           "bonus": "0.0000",
        //           "accountIM": "0.0000",
        //           "totalSessionRPL": "0.0000",
        //           "equity": "10.0000",
        //           "totalRPL": "0.0000",
        //           "marginBalance": "10.0000",
        //           "availableBalance": "10.0000",
        //           "totalSessionUPL": "0.0000"
        //       },
        //       "retCode": "0",
        //       "retMsg": "Success."
        //    }
        //
        const result = {
            'info': response,
        };
        const data = this.safeValue (response, 'result', {});
        const balances = this.safeValue (data, 'balances');
        if (Array.isArray (balances)) {
            // spot balances
            for (let i = 0; i < balances.length; i++) {
                const balance = balances[i];
                const currencyId = this.safeString (balance, 'coin');
                const code = this.safeCurrencyCode (currencyId);
                const account = this.account ();
                account['free'] = this.safeString (balance, 'availableBalance');
                account['used'] = this.safeString (balance, 'locked');
                account['total'] = this.safeString (balance, 'total');
                result[code] = account;
            }
        } else {
            if ('walletBalance' in data) {
                // usdc wallet
                const code = 'USDC';
                const account = this.account ();
                account['free'] = this.safeString (data, 'availableBalance');
                account['total'] = this.safeString (data, 'walletBalance');
                result[code] = account;
            } else {
                // linear/inverse swap/futures
                const currencyIds = Object.keys (data);
                for (let i = 0; i < currencyIds.length; i++) {
                    const currencyId = currencyIds[i];
                    const balance = data[currencyId];
                    const code = this.safeCurrencyCode (currencyId);
                    const account = this.account ();
                    account['free'] = this.safeString (balance, 'available_balance');
                    account['total'] = this.safeString (balance, 'wallet_balance');
                    result[code] = account;
                }
            }
        }
        return this.safeBalance (result);
    }

    async fetchBalance (params = {}) {
        /**
         * @method
         * @name bybit#fetchBalance
         * @description query for balance and get the amount of funds available for trading or funds locked in orders
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure}
         */
        const request = {};
        let type = undefined;
        [ type, params ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params);
        let method = undefined;
        if (type === 'spot') {
            method = 'privateGetSpotV1Account';
        } else {
            let settle = this.safeString (this.options, 'defaultSettle');
            settle = this.safeString2 (params, 'settle', 'defaultSettle', settle);
            params = this.omit (params, [ 'settle', 'defaultSettle' ]);
            const isUsdcSettled = settle === 'USDC';
            if (!isUsdcSettled) {
                // linear/inverse future/swap
                method = 'privateGetV2PrivateWalletBalance';
                const coin = this.safeString2 (params, 'coin', 'code');
                params = this.omit (params, [ 'coin', 'code' ]);
                if (coin !== undefined) {
                    const currency = this.currency (coin);
                    request['coin'] = currency['id'];
                }
            } else {
                // usdc account
                method = 'privatePostOptionUsdcOpenapiPrivateV1QueryWalletBalance';
            }
        }
        await this.loadMarkets ();
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: {
        //             BTC: {
        //                 equity: 0,
        //                 available_balance: 0,
        //                 used_margin: 0,
        //                 order_margin: 0,
        //                 position_margin: 0,
        //                 occ_closing_fee: 0,
        //                 occ_funding_fee: 0,
        //                 wallet_balance: 0,
        //                 realised_pnl: 0,
        //                 unrealised_pnl: 0,
        //                 cum_realised_pnl: 0,
        //                 given_cash: 0,
        //                 service_cash: 0
        //             }
        //         },
        //         time_now: '1583937810.370020',
        //         rate_limit_status: 119,
        //         rate_limit_reset_ms: 1583937810367,
        //         rate_limit: 120
        //     }
        //
        return this.parseBalance (response);
    }

    parseOrderStatus (status) {
        const statuses = {
            // basic orders
            'Created': 'open',
            'Rejected': 'rejected', // order is triggered but failed upon being placed
            'New': 'open',
            'Partiallyfilled': 'open',
            'Filled': 'closed',
            'Cancelled': 'canceled',
            'Pendingcancel': 'canceling', // the engine has received the cancellation but there is no guarantee that it will be successful
            'CREATED': 'open',
            'REJECTED': 'rejected',
            'NEW': 'open',
            'PENDING_NEW': 'open',
            'PARTIALLYFILLED': 'open',
            'PARTIALLY_FILLED': 'open',
            'FILLED': 'closed',
            'CANCELED': 'canceled',
            'PENDINGCANCEL': 'canceling',
            'PENDING_CANCEL': 'canceling',
            // conditional orders
            'Active': 'open', // order is triggered and placed successfully
            'Untriggered': 'open', // order waits to be triggered
            'Triggered': 'closed', // order is triggered
            // 'Cancelled': 'canceled', // order is cancelled
            // 'Rejected': 'rejected', // order is triggered but fail to be placed
            'Deactivated': 'canceled', // conditional order was cancelled before triggering
        };
        return this.safeString (statuses, status, status);
    }

    parseTimeInForce (timeInForce) {
        const timeInForces = {
            'GoodTillCancel': 'GTC',
            'ImmediateOrCancel': 'IOC',
            'FillOrKill': 'FOK',
            'PostOnly': 'PO',
        };
        return this.safeString (timeInForces, timeInForce, timeInForce);
    }

    parseOrder (order, market = undefined) {
        //
        // createOrder
        //
        //     {
        //         "user_id": 1,
        //         "order_id": "335fd977-e5a5-4781-b6d0-c772d5bfb95b",
        //         "symbol": "BTCUSD",
        //         "side": "Buy",
        //         "order_type": "Limit",
        //         "price": 8800,
        //         "qty": 1,
        //         "time_in_force": "GoodTillCancel",
        //         "order_status": "Created",
        //         "last_exec_time": 0,
        //         "last_exec_price": 0,
        //         "leaves_qty": 1,
        //         "cum_exec_qty": 0, // in contracts, where 1 contract = 1 quote currency unit (USD for inverse contracts)
        //         "cum_exec_value": 0, // in contract's underlying currency (BTC for inverse contracts)
        //         "cum_exec_fee": 0,
        //         "reject_reason": "",
        //         "order_link_id": "",
        //         "created_at": "2019-11-30T11:03:43.452Z",
        //         "updated_at": "2019-11-30T11:03:43.455Z"
        //     }
        //
        // fetchOrder
        //
        //     {
        //         "user_id" : 599946,
        //         "symbol" : "BTCUSD",
        //         "side" : "Buy",
        //         "order_type" : "Limit",
        //         "price" : "7948",
        //         "qty" : 10,
        //         "time_in_force" : "GoodTillCancel",
        //         "order_status" : "Filled",
        //         "ext_fields" : {
        //             "o_req_num" : -1600687220498,
        //             "xreq_type" : "x_create"
        //         },
        //         "last_exec_time" : "1588150113.968422",
        //         "last_exec_price" : "7948",
        //         "leaves_qty" : 0,
        //         "leaves_value" : "0",
        //         "cum_exec_qty" : 10,
        //         "cum_exec_value" : "0.00125817",
        //         "cum_exec_fee" : "-0.00000031",
        //         "reject_reason" : "",
        //         "cancel_type" : "",
        //         "order_link_id" : "",
        //         "created_at" : "2020-04-29T08:45:24.399146Z",
        //         "updated_at" : "2020-04-29T08:48:33.968422Z",
        //         "order_id" : "dd2504b9-0157-406a-99e1-efa522373944"
        //     }
        //
        // fetchOrders linear swaps
        //
        //     {
        //         "order_id":"7917bd70-e7c3-4af5-8147-3285cd99c509",
        //         "user_id":22919890,
        //         "symbol":"GMTUSDT",
        //         "side":"Buy",
        //         "order_type":"Limit",
        //         "price":2.9262,
        //         "qty":50,
        //         "time_in_force":"GoodTillCancel",
        //         "order_status":"Filled",
        //         "last_exec_price":2.9219,
        //         "cum_exec_qty":50,
        //         "cum_exec_value":146.095,
        //         "cum_exec_fee":0.087657,
        //         "reduce_only":false,
        //         "close_on_trigger":false,
        //         "order_link_id":"",
        //         "created_time":"2022-04-18T17:09:54Z",
        //         "updated_time":"2022-04-18T17:09:54Z",
        //         "take_profit":0,
        //         "stop_loss":0,
        //         "tp_trigger_by":"UNKNOWN",
        //         "sl_trigger_by":"UNKNOWN"
        //     }
        //
        // conditional order
        //
        //    {
        //        "user_id":"24478789",
        //        "stop_order_id":"68e996af-fa55-4ca1-830e-4bf68ffbff3e",
        //        "symbol":"LTCUSDT",
        //        "side":"Buy",
        //        "order_type":"Limit",
        //        "price":"86",
        //        "qty":"0.1",
        //        "time_in_force":"GoodTillCancel",
        //        "order_status":"Filled",
        //        "trigger_price":"86",
        //        "order_link_id":"",
        //        "created_time":"2022-05-09T14:36:36Z",
        //        "updated_time":"2022-05-09T14:39:25Z",
        //        "take_profit":"0",
        //        "stop_loss":"0",
        //        "trigger_by":"LastPrice",
        //        "base_price":"86.96",
        //        "tp_trigger_by":"UNKNOWN",
        //        "sl_trigger_by":"UNKNOWN",
        //        "reduce_only":false,
        //        "close_on_trigger":false
        //    }
        // future
        //    {
        //        "user_id":24478789,
        //        "position_idx":0,
        //        "order_status":"Filled",
        //        "symbol":"ETHUSDM22",
        //        "side":"Buy",
        //        "order_type":"Market",
        //        "price":"2523.35",
        //        "qty":"10",
        //        "time_in_force":"ImmediateOrCancel",
        //        "order_link_id":"",
        //        "order_id":"54feb0e2-ece7-484f-b870-47910609b5ac",
        //        "created_at":"2022-05-09T14:46:42.346Z",
        //        "updated_at":"2022-05-09T14:46:42.350Z",
        //        "leaves_qty":"0",
        //        "leaves_value":"0",
        //        "cum_exec_qty":"10",
        //        "cum_exec_value":"0.00416111",
        //        "cum_exec_fee":"0.0000025",
        //        "reject_reason":"EC_NoError",
        //        "take_profit":"0.0000",
        //        "stop_loss":"0.0000",
        //        "tp_trigger_by":"UNKNOWN",
        //        "sl_trigger_by":"UNKNOWN"
        //    }
        //
        // fetchOpenOrder spot
        //     {
        //        "accountId":"24478790",
        //        "exchangeId":"301",
        //        "symbol":"LTCUSDT",
        //        "symbolName":"LTCUSDT",
        //        "orderLinkId":"1652115972506",
        //        "orderId":"1152426740986003968",
        //        "price":"50",
        //        "origQty":"0.2",
        //        "executedQty":"0",
        //        "cummulativeQuoteQty":"0",
        //        "avgPrice":"0",
        //        "status":"NEW",
        //        "timeInForce":"GTC",
        //        "type":"LIMIT",
        //        "side":"BUY",
        //        "stopPrice":"0.0",
        //        "icebergQty":"0.0",
        //        "time":"1652115973053",
        //        "updateTime":"1652115973063",
        //        "isWorking":true
        //     }
        //
        // create order usdc
        //      {
        //            "orderId":"34450a59-325e-4296-8af0-63c7c524ae33",
        //            "orderLinkId":"",
        //            "mmp":false,
        //            "symbol":"BTCPERP",
        //            "orderType":"Limit",
        //            "side":"Buy",
        //            "orderQty":"0.00100000",
        //            "orderPrice":"20000.00",
        //            "iv":"0",
        //            "timeInForce":"GoodTillCancel",
        //            "orderStatus":"Created",
        //            "createdAt":"1652261746007873",
        //            "basePrice":"0.00",
        //            "triggerPrice":"0.00",
        //            "takeProfit":"0.00",
        //            "stopLoss":"0.00",
        //            "slTriggerBy":"UNKNOWN",
        //            "tpTriggerBy":"UNKNOWN"
        //     }
        //
        const marketId = this.safeString (order, 'symbol');
        market = this.safeMarket (marketId, market);
        const symbol = market['symbol'];
        let timestamp = this.parse8601 (this.safeStringN (order, [ 'created_at', 'created_time', 'create_time', 'timestamp' ]));
        if (timestamp === undefined) {
            timestamp = this.safeNumber2 (order, 'time', 'transactTime');
            if (timestamp === undefined) {
                timestamp = this.safeIntegerProduct (order, 'createdAt', 0.001);
            }
        }
        const id = this.safeStringN (order, [ 'order_id', 'stop_order_id', 'orderId' ]);
        const type = this.safeStringLowerN (order, [ 'order_type', 'type', 'orderType' ]);
        const price = this.safeString2 (order, 'price', 'orderPrice');
        const average = this.safeString2 (order, 'average_price', 'avgPrice');
        const amount = this.safeStringN (order, [ 'qty', 'origQty', 'orderQty' ]);
        const cost = this.safeString2 (order, 'cum_exec_value', 'cumExecValue');
        const filled = this.safeStringN (order, [ 'cum_exec_qty', 'executedQty', 'cumExecQty' ]);
        const remaining = this.safeString2 (order, 'leaves_qty', 'leavesQty');
        let lastTradeTimestamp = this.safeTimestamp (order, 'last_exec_time');
        if (lastTradeTimestamp === 0) {
            lastTradeTimestamp = undefined;
        } else if (lastTradeTimestamp === undefined) {
            lastTradeTimestamp = this.parse8601 (this.safeStringN (order, [ 'updated_time', 'updated_at', 'update_time' ]));
            if (lastTradeTimestamp === undefined) {
                lastTradeTimestamp = this.safeNumber (order, 'updateTime');
            }
        }
        const raw_status = this.safeStringN (order, [ 'order_status', 'stop_order_status', 'status', 'orderStatus' ]);
        const status = this.parseOrderStatus (raw_status);
        const side = this.safeStringLower (order, 'side');
        let fee = undefined;
        const isContract = this.safeValue (market, 'contract');
        if (isContract) {
            const feeCostString = this.safeString2 (order, 'cum_exec_fee', 'cumExecFee');
            if (feeCostString !== undefined) {
                const feeCurrency = market['linear'] ? market['quote'] : market['base'];
                fee = {
                    'cost': feeCostString,
                    'currency': feeCurrency,
                };
            }
        }
        let clientOrderId = this.safeString2 (order, 'order_link_id', 'orderLinkId');
        if ((clientOrderId !== undefined) && (clientOrderId.length < 1)) {
            clientOrderId = undefined;
        }
        const timeInForce = this.parseTimeInForce (this.safeString2 (order, 'time_in_force', 'timeInForce'));
        const stopPrice = this.safeStringN (order, [ 'trigger_price', 'stop_px', 'stopPrice', 'triggerPrice' ]);
        const postOnly = (timeInForce === 'PO');
        return this.safeOrder ({
            'info': order,
            'id': id,
            'clientOrderId': clientOrderId,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'lastTradeTimestamp': lastTradeTimestamp,
            'symbol': symbol,
            'type': type,
            'timeInForce': timeInForce,
            'postOnly': postOnly,
            'side': side,
            'price': price,
            'stopPrice': stopPrice,
            'amount': amount,
            'cost': cost,
            'average': average,
            'filled': filled,
            'remaining': remaining,
            'status': status,
            'fee': fee,
            'trades': undefined,
        }, market);
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOrder
         * @description fetches information on an order made by the user
         * @param {str|undefined} symbol unified symbol of the market the order was made in
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
         */
        await this.loadMarkets ();
        let market = undefined;
        if (symbol !== undefined) {
            market = this.market (symbol);
        }
        let type = undefined;
        [ type, params ] = this.handleMarketTypeAndParams ('fetchOrder', market, params);
        if (type !== 'spot' && symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument for ' + type + ' markets');
        }
        if (type === 'spot') {
            // only spot markets have a dedicated endpoint for fetching a order
            const request = {
                'orderId': id,
            };
            const response = await this.privateGetSpotV1Order (this.extend (params, request));
            const result = this.safeValue (response, 'result', {});
            return this.parseOrder (result);
        }
        const isUsdcSettled = (market['settle'] === 'USDC');
        const stopOrderId = this.safeString (params, 'stop_order_id');
        const stop = this.safeValue (params, 'stop', false);
        const orderType = this.safeStringLower (params, 'orderType');
        const isConditional = stop || (stopOrderId !== undefined) || (orderType === 'stop' || orderType === 'conditional');
        if (stopOrderId === undefined) {
            let orderKey = undefined;
            if (isConditional) {
                orderKey = 'stop_order_id';
            } else {
                orderKey = isUsdcSettled ? 'orderId' : 'order_id';
            }
            params[orderKey] = id;
        }
        if (isUsdcSettled || market['future'] || market['inverse']) {
            throw new NotSupported (this.id + ' fetchOrder() supports spot markets and linear non-USDC perpetual swap markets only');
        } else {
            // only linear swap markets allow using all purpose
            // fetchOrders endpoint filtering by id
            const orders = await this.fetchOrders (symbol, undefined, undefined, params);
            const order = this.safeValue (orders, 0);
            if (order === undefined) {
                throw new OrderNotFound (this.id + ' fetchOrder() order ' + id + ' not found');
            }
            return order;
        }
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        /**
         * @method
         * @name bybit#createOrder
         * @description create a trade order
         * @param {str} symbol unified symbol of the market to create an order in
         * @param {str} type 'market' or 'limit'
         * @param {str} side 'buy' or 'sell'
         * @param {float} amount how much of currency you want to trade in units of base currency
         * @param {float|undefined} price the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} an [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
         */
        await this.loadMarkets ();
        const market = this.market (symbol);
        symbol = market['symbol'];
        const isUsdcSettled = (market['settle'] === 'USDC');
        if (market['spot']) {
            return await this.createSpotOrder (symbol, type, side, amount, price, params);
        } else if (isUsdcSettled) {
            return await this.createUsdcOrder (symbol, type, side, amount, price, params);
        } else {
            return await this.createContractOrder (symbol, type, side, amount, price, params);
        }
    }

    async createSpotOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (type === 'market' && side === 'buy') {
            // for market buy it requires the amount of quote currency to spend
            if (this.options['createMarketBuyOrderRequiresPrice']) {
                const cost = this.safeNumber (params, 'cost');
                params = this.omit (params, 'cost');
                if (price === undefined && cost === undefined) {
                    throw new InvalidOrder (this.id + " createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = false to supply the cost in the amount argument (the exchange-specific behaviour)");
                } else {
                    amount = (cost !== undefined) ? cost : amount * price;
                }
            }
        }
        const upperCaseType = type.toUpperCase ();
        const request = {
            'symbol': market['id'],
            'side': this.capitalize (side),
            'type': upperCaseType, // limit, market or limit_maker
            'timeInForce': 'GTC', // FOK, IOC
            'qty': this.amountToPrecision (symbol, amount),
            // 'orderLinkId': 'string', // unique client order id, max 36 characters
        };
        if ((upperCaseType === 'LIMIT') || (upperCaseType === 'LIMIT_MAKER')) {
            if (price === undefined) {
                throw new InvalidOrder (this.id + ' createOrder requires a price argument for a ' + type + ' order');
            }
            request['price'] = parseFloat (this.priceToPrecision (symbol, price));
        }
        const isPostOnly = this.isPostOnly (upperCaseType === 'MARKET', type === 'LIMIT_MAKER', params);
        if (isPostOnly) {
            request['type'] = 'LIMIT_MAKER';
        }
        const clientOrderId = this.safeString2 (params, 'clientOrderId', 'orderLinkId');
        if (clientOrderId !== undefined) {
            request['orderLinkId'] = clientOrderId;
        }
        params = this.omit (params, [ 'clientOrderId', 'orderLinkId', 'postOnly' ]);
        const brokerId = this.safeString (this.options, 'brokerId');
        if (brokerId !== undefined) {
            request['agentSource'] = brokerId;
        }
        const response = await this.privatePostSpotV1Order (this.extend (request, params));
        //    {
        //        "ret_code":0,
        //        "ret_msg":"",
        //        "ext_code":null,
        //        "ext_info":null,
        //        "result":{
        //           "accountId":"24478790",
        //           "symbol":"ETHUSDT",
        //           "symbolName":"ETHUSDT",
        //           "orderLinkId":"1652266305358517",
        //           "orderId":"1153687819821127168",
        //           "transactTime":"1652266305365",
        //           "price":"80",
        //           "origQty":"0.05",
        //           "executedQty":"0",
        //           "status":"NEW",
        //           "timeInForce":"GTC",
        //           "type":"LIMIT",
        //           "side":"BUY"
        //        }
        //    }
        const order = this.safeValue (response, 'result', {});
        return this.parseOrder (order);
    }

    async createUsdcOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (type === 'market') {
            throw new NotSupported (this.id + 'createOrder does not allow market orders for ' + symbol + ' markets');
        }
        if (price === undefined && type === 'limit') {
            throw new ArgumentsRequired (this.id + ' createOrder requires a price argument for limit orders');
        }
        const lowerCaseType = type.toLowerCase ();
        const request = {
            'symbol': market['id'],
            'side': this.capitalize (side),
            'orderType': this.capitalize (lowerCaseType), // limit or market
            'timeInForce': 'GoodTillCancel', // ImmediateOrCancel, FillOrKill, PostOnly
            'orderQty': this.amountToPrecision (symbol, amount),
            // 'takeProfit': 123.45, // take profit price, only take effect upon opening the position
            // 'stopLoss': 123.45, // stop loss price, only take effect upon opening the position
            // 'reduceOnly': false, // reduce only, required for linear orders
            // when creating a closing order, bybit recommends a True value for
            //  closeOnTrigger to avoid failing due to insufficient available margin
            // 'closeOnTrigger': false, required for linear orders
            // 'orderLinkId': 'string', // unique client order id, max 36 characters
            // 'triggerPrice': 123.45, // trigger price, required for conditional orders
            // 'trigger_by': 'MarkPrice', // IndexPrice, MarkPrice
            // 'tptriggerby': 'MarkPrice', // IndexPrice, MarkPrice
            // 'slTriggerBy': 'MarkPrice', // IndexPrice, MarkPrice
            // 'orderFilter': 'Order' or 'StopOrder'
            // 'mmp': false // market maker protection
        };
        const isMarket = lowerCaseType === 'market';
        const isLimit = lowerCaseType === 'limit';
        if (isLimit !== undefined) {
            request['orderPrice'] = this.priceToPrecision (symbol, price);
        }
        const exchangeSpecificParam = this.safeString (params, 'time_in_force');
        const timeInForce = this.safeStringLower (params, 'timeInForce');
        const postOnly = this.isPostOnly (isMarket, exchangeSpecificParam === 'PostOnly', params);
        if (postOnly) {
            request['time_in_force'] = 'PostOnly';
        } else if (timeInForce === 'gtc') {
            request['time_in_force'] = 'GoodTillCancel';
        } else if (timeInForce === 'fok') {
            request['time_in_force'] = 'FillOrKill';
        } else if (timeInForce === 'ioc') {
            request['time_in_force'] = 'ImmediateOrCancel';
        }
        if (market['swap']) {
            const triggerPrice = this.safeValue2 (params, 'stopPrice', 'triggerPrice');
            const stopLossPrice = this.safeValue (params, 'stopLossPrice', triggerPrice);
            const isStopLossOrder = stopLossPrice !== undefined;
            const takeProfitPrice = this.safeValue (params, 'takeProfitPrice');
            const isTakeProfitOrder = takeProfitPrice !== undefined;
            const isStopOrder = isStopLossOrder || isTakeProfitOrder;
            if (isStopOrder) {
                request['orderFilter'] = 'StopOrder';
                request['trigger_by'] = 'LastPrice';
                const stopPx = isStopLossOrder ? stopLossPrice : takeProfitPrice;
                const preciseStopPrice = this.priceToPrecision (symbol, stopPx);
                request['triggerPrice'] = preciseStopPrice;
                const delta = this.numberToString (market['precision']['price']);
                request['basePrice'] = isStopLossOrder ? Precise.stringSub (preciseStopPrice, delta) : Precise.stringAdd (preciseStopPrice, delta);
            } else {
                request['orderFilter'] = 'Order';
            }
        }
        const clientOrderId = this.safeString (params, 'clientOrderId');
        if (clientOrderId !== undefined) {
            request['orderLinkId'] = clientOrderId;
        } else if (market['option']) {
            // mandatory field for options
            request['orderLinkId'] = this.uuid16 ();
        }
        params = this.omit (params, [ 'stopPrice', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId' ]);
        const method = market['option'] ? 'privatePostOptionUsdcOpenapiPrivateV1PlaceOrder' : 'privatePostPerpetualUsdcOpenapiPrivateV1PlaceOrder';
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         "retCode":0,
        //         "retMsg":"",
        //         "result":{
        //            "orderId":"34450a59-325e-4296-8af0-63c7c524ae33",
        //            "orderLinkId":"",
        //            "mmp":false,
        //            "symbol":"BTCPERP",
        //            "orderType":"Limit",
        //            "side":"Buy",
        //            "orderQty":"0.00100000",
        //            "orderPrice":"20000.00",
        //            "iv":"0",
        //            "timeInForce":"GoodTillCancel",
        //            "orderStatus":"Created",
        //            "createdAt":"1652261746007873",
        //            "basePrice":"0.00",
        //            "triggerPrice":"0.00",
        //            "takeProfit":"0.00",
        //            "stopLoss":"0.00",
        //            "slTriggerBy":"UNKNOWN",
        //            "tpTriggerBy":"UNKNOWN"
        //     }
        //
        const order = this.safeValue (response, 'result', {});
        return this.parseOrder (order);
    }

    async createContractOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (price === undefined && type === 'limit') {
            throw new ArgumentsRequired (this.id + ' createOrder requires a price argument for limit orders');
        }
        amount = this.amountToPrecision (symbol, amount);
        amount = market['linear'] ? parseFloat (amount) : parseInt (amount);
        const lowerCaseType = type.toLowerCase ();
        const request = {
            'symbol': market['id'],
            'side': this.capitalize (side),
            'order_type': this.capitalize (lowerCaseType), // limit
            'time_in_force': 'GoodTillCancel', // ImmediateOrCancel, FillOrKill, PostOnly
            'qty': amount,
            // 'take_profit': 123.45, // take profit price, only take effect upon opening the position
            // 'stop_loss': 123.45, // stop loss price, only take effect upon opening the position
            // 'reduce_only': false, // reduce only, required for linear orders
            // when creating a closing order, bybit recommends a True value for
            //  close_on_trigger to avoid failing due to insufficient available margin
            // 'close_on_trigger': false, required for linear orders
            // 'order_link_id': 'string', // unique client order id, max 36 characters
            // 'tp_trigger_by': 'LastPrice', // IndexPrice, MarkPrice
            // 'sl_trigger_by': 'LastPrice', // IndexPrice, MarkPrice
            // conditional orders ---------------------------------------------
            // base_price is used to compare with the value of stop_px, to decide
            // whether your conditional order will be triggered by crossing trigger
            // price from upper side or lower side, mainly used to identify the
            // expected direction of the current conditional order
            // 'base_price': 123.45, // required for conditional orders
            // 'stop_px': 123.45, // trigger price, required for conditional orders
            // 'trigger_by': 'LastPrice', // IndexPrice, MarkPrice
        };
        if (market['future']) {
            const positionIdx = this.safeInteger (params, 'position_idx', 0); // 0 One-Way Mode, 1 Buy-side, 2 Sell-side
            request['position_idx'] = positionIdx;
            params = this.omit (params, 'position_idx');
        }
        if (market['linear']) {
            request['reduce_only'] = this.safeValue2 (params, 'reduce_only', 'reduceOnly', false);
            request['close_on_trigger'] = false;
        }
        const isMarket = lowerCaseType === 'market';
        const isLimit = lowerCaseType === 'limit';
        if (isLimit) {
            if (price === undefined) {
                throw new ExchangeError (this.id + ' createOrder() requires price argument for limit orders');
            }
            request['price'] = parseFloat (this.priceToPrecision (symbol, price));
        }
        const exchangeSpecificParam = this.safeString (params, 'time_in_force');
        const timeInForce = this.safeStringLower (params, 'timeInForce');
        const postOnly = this.isPostOnly (isMarket, exchangeSpecificParam === 'PostOnly', params);
        if (postOnly) {
            request['time_in_force'] = 'PostOnly';
        } else if (timeInForce === 'gtc') {
            request['time_in_force'] = 'GoodTillCancel';
        } else if (timeInForce === 'fok') {
            request['time_in_force'] = 'FillOrKill';
        } else if (timeInForce === 'ioc') {
            request['time_in_force'] = 'ImmediateOrCancel';
        }
        const triggerPrice = this.safeValue2 (params, 'stopPrice', 'triggerPrice');
        const stopLossPrice = this.safeValue (params, 'stopLossPrice', triggerPrice);
        const isStopLossOrder = stopLossPrice !== undefined;
        const takeProfitPrice = this.safeValue (params, 'takeProfitPrice');
        const isTakeProfitOrder = takeProfitPrice !== undefined;
        const isStopOrder = isStopLossOrder || isTakeProfitOrder;
        if (isStopOrder) {
            request['trigger_by'] = 'LastPrice';
            const stopPx = isStopLossOrder ? stopLossPrice : takeProfitPrice;
            const preciseStopPrice = this.priceToPrecision (symbol, stopPx);
            request['stop_px'] = parseFloat (preciseStopPrice);
            const delta = this.numberToString (market['precision']['price']);
            const basePriceString = isStopLossOrder ? Precise.stringSub (preciseStopPrice, delta) : Precise.stringAdd (preciseStopPrice, delta);
            request['base_price'] = parseFloat (basePriceString);
        }
        const clientOrderId = this.safeString (params, 'clientOrderId');
        if (clientOrderId !== undefined) {
            request['order_link_id'] = clientOrderId;
        }
        params = this.omit (params, [ 'stop_px', 'stopPrice', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'reduceOnly', 'clientOrderId' ]);
        let method = undefined;
        if (market['future']) {
            method = isStopOrder ? 'privatePostFuturesPrivateStopOrderCreate' : 'privatePostFuturesPrivateOrderCreate';
        } else if (market['linear']) {
            method = isStopOrder ? 'privatePostPrivateLinearStopOrderCreate' : 'privatePostPrivateLinearOrderCreate';
        } else {
            // inverse swaps
            method = isStopOrder ? 'privatePostV2PrivateStopOrderCreate' : 'privatePostV2PrivateOrderCreate';
        }
        const response = await this[method] (this.extend (request, params));
        //
        //    {
        //        "ret_code":0,
        //        "ret_msg":"OK",
        //        "ext_code":"",
        //        "ext_info":"",
        //        "result":{
        //           "order_id":"f016f912-68c2-4da9-a289-1bb9b62b5c3b",
        //           "user_id":24478789,
        //           "symbol":"LTCUSDT",
        //           "side":"Buy",
        //           "order_type":"Market",
        //           "price":79.72,
        //           "qty":1,
        //           "time_in_force":"ImmediateOrCancel",
        //           "order_status":"Created",
        //           "last_exec_price":0,
        //           "cum_exec_qty":0,
        //           "cum_exec_value":0,
        //           "cum_exec_fee":0,
        //           "reduce_only":false,
        //           "close_on_trigger":false,
        //           "order_link_id":"",
        //           "created_time":"2022-05-11T13:56:29Z",
        //           "updated_time":"2022-05-11T13:56:29Z",
        //           "take_profit":0,
        //           "stop_loss":0,
        //           "tp_trigger_by":"UNKNOWN",
        //           "sl_trigger_by":"UNKNOWN",
        //           "position_idx":1
        //        },
        //        "time_now":"1652277389.122038",
        //        "rate_limit_status":98,
        //        "rate_limit_reset_ms":1652277389119,
        //        "rate_limit":100
        //    }
        //
        const order = this.safeValue (response, 'result', {});
        return this.parseOrder (order, market);
    }

    async editUsdcOrder (id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'symbol': market['id'],
            'orderId': id,
        };
        if (amount !== undefined) {
            request['orderQty'] = this.amountToPrecision (symbol, amount);
        }
        if (price !== undefined) {
            request['orderPrice'] = this.priceToPrecision (symbol, price);
        }
        const method = market['option'] ? 'privatePostOptionUsdcOpenApiPrivateV1ReplaceOrder' : 'privatePostPerpetualUsdcOpenApiPrivateV1ReplaceOrder';
        const response = await this[method] (this.extend (request, params));
        //
        //    {
        //        "retCode": 0,
        //        "retMsg": "OK",
        //        "result": {
        //            "outRequestId": "",
        //            "symbol": "BTC-13MAY22-40000-C",
        //            "orderId": "8c65df91-91fc-461d-9b14-786379ef138c",
        //            "orderLinkId": "AAAAA41133"
        //        },
        //        "retExtMap": {}
        //   }
        //
        return {
            'info': response,
            'id': id,
        };
    }

    async editContractOrder (id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' editOrder() requires an symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            // 'order_id': id, // only for non-conditional orders
            'symbol': market['id'],
            // 'p_r_qty': this.amountToPrecision (symbol, amount), // new order quantity, optional
            // 'p_r_price' this.priceToprecision (symbol, price), // new order price, optional
            // ----------------------------------------------------------------
            // conditional orders
            // 'stop_order_id': id, // only for conditional orders
            // 'p_r_trigger_price': 123.45, // new trigger price also known as stop_px
        };
        const orderType = this.safeString (params, 'orderType');
        const isStop = this.safeValue (params, 'stop', false);
        const isConditionalOrder = isStop || (orderType === 'stop' || orderType === 'conditional');
        params = this.omit (params, [ 'orderType', 'stop' ]);
        const idKey = isConditionalOrder ? 'stop_order_id' : 'order_id';
        request[idKey] = id;
        if (amount !== undefined) {
            request['p_r_qty'] = this.amountToPrecision (symbol, amount);
        }
        if (price !== undefined) {
            request['p_r_price'] = this.priceToPrecision (symbol, price);
        }
        let method = undefined;
        if (market['linear']) {
            method = isConditionalOrder ? 'privatePostPrivateLinearStopOrderReplace' : 'privatePostPrivateLinearOrderReplace';
        } else if (market['future']) {
            method = isConditionalOrder ? 'privatePostFuturesPrivateStopOrderReplace' : 'privatePostFuturesPrivateOrderReplace';
        } else {
            // inverse swaps
            method = isConditionalOrder ? 'privatePostV2PrivateSpotOrderReplace' : 'privatePostV2PrivateOrderReplace';
        }
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "ok",
        //         "ext_code": "",
        //         "result": { "order_id": "efa44157-c355-4a98-b6d6-1d846a936b93" },
        //         "time_now": "1539778407.210858",
        //         "rate_limit_status": 99, // remaining number of accesses in one minute
        //         "rate_limit_reset_ms": 1580885703683,
        //         "rate_limit": 100
        //     }
        //
        // conditional orders
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "ok",
        //         "ext_code": "",
        //         "result": { "stop_order_id": "378a1bbc-a93a-4e75-87f4-502ea754ba36" },
        //         "ext_info": null,
        //         "time_now": "1577475760.604942",
        //         "rate_limit_status": 96,
        //         "rate_limit_reset_ms": 1577475760612,
        //         "rate_limit": "100"
        //     }
        //
        const result = this.safeValue (response, 'result', {});
        return {
            'info': response,
            'id': this.safeString2 (result, 'order_id', 'stop_order_id'),
            'order_id': this.safeString (result, 'order_id'),
            'stop_order_id': this.safeString (result, 'stop_order_id'),
        };
    }

    async editOrder (id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' editOrder() requires an symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const isUsdcSettled = (market['settle'] === 'USDC');
        if (market['spot']) {
            throw new NotSupported (this.id + ' editOrder() does not support spot markets');
        } else if (isUsdcSettled) {
            return await this.editUsdcOrder (id, symbol, type, side, amount, price, params);
        } else {
            return await this.editContractOrder (id, symbol, type, side, amount, price, params);
        }
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        /**
         * @method
         * @name bybit#cancelOrder
         * @description cancels an open order
         * @param {str} id order id
         * @param {str} symbol unified symbol of the market the order was made in
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
         */
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'symbol': market['id'],
            // 'order_link_id': 'string', // one of order_id, stop_order_id or order_link_id is required
            // regular orders ---------------------------------------------
            // 'order_id': id, // one of order_id or order_link_id is required for regular orders
            // conditional orders ---------------------------------------------
            // 'stop_order_id': id, // one of stop_order_id or order_link_id is required for conditional orders
            // spot orders
            // 'orderId': id
        };
        const orderType = this.safeStringLower (params, 'orderType');
        const isStop = this.safeValue (params, 'stop', false);
        const isConditional = isStop || (orderType === 'stop') || (orderType === 'conditional');
        params = this.omit (params, [ 'orderType', 'stop' ]);
        const isUsdcSettled = market['settle'] === 'USDC';
        let method = undefined;
        if (market['spot']) {
            method = 'privateDeleteSpotV1Order';
            request['orderId'] = id;
        } else if (isUsdcSettled) {
            request['orderId'] = id;
            if (market['option']) {
                method = 'privatePostOptionUsdcOpenapiPrivateV1CancelOrder';
            } else {
                method = 'privatePostPerpetualUsdcOpenapiPrivateV1CancelOrder';
                request['orderFilter'] = isConditional ? 'StopOrder' : 'Order';
            }
        } else if (market['linear']) {
            // linear futures and linear swaps
            method = isConditional ? 'privatePostPrivateLinearStopOrderCancel' : 'privatePostPrivateLinearOrderCancel';
        } else if (market['swap']) {
            // inverse swaps
            method = isConditional ? 'privatePostV2PrivateStopOrderCancel' : 'privatePostV2PrivateOrderCancel';
        } else {
            // inverse futures
            method = isConditional ? 'privatePostFuturesPrivateStopOrderCancel' : 'privatePostFuturesPrivateOrderCancel';
        }
        if (market['contract'] && !isUsdcSettled) {
            if (!isConditional) {
                request['order_id'] = id;
            } else {
                request['stop_order_id'] = id;
            }
        }
        const response = await this[method] (this.extend (request, params));
        // spot order
        //    {
        //        "ret_code":0,
        //        "ret_msg":"",
        //        "ext_code":null,
        //        "ext_info":null,
        //        "result":{
        //           "accountId":"24478790",
        //           "symbol":"LTCUSDT",
        //           "orderLinkId":"1652192399682",
        //           "orderId":"1153067855569315072",
        //           "transactTime":"1652192399866",
        //           "price":"50",
        //           "origQty":"0.2",
        //           "executedQty":"0",
        //           "status":"NEW",
        //           "timeInForce":"GTC",
        //           "type":"LIMIT",
        //           "side":"BUY"
        //        }
        //    }
        // linear
        //    {
        //        "ret_code":0,
        //        "ret_msg":"OK",
        //        "ext_code":"",
        //        "ext_info":"",
        //        "result":{
        //           "order_id":"f5103487-f7f9-48d3-a26d-b74a3a53d3d3"
        //        },
        //        "time_now":"1652192814.880473",
        //        "rate_limit_status":99,
        //        "rate_limit_reset_ms":1652192814876,
        //        "rate_limit":100
        //     }
        const result = this.safeValue (response, 'result', {});
        return this.parseOrder (result, market);
    }

    async cancelAllOrders (symbol = undefined, params = {}) {
        /**
         * @method
         * @name bybit#cancelAllOrders
         * @description cancel all open orders
         * @param {str|undefined} symbol unified market symbol, only orders in the market of this symbol are cancelled when symbol is not undefined
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
         */
        await this.loadMarkets ();
        let market = undefined;
        let isUsdcSettled = undefined;
        if (symbol !== undefined) {
            market = this.market (symbol);
            isUsdcSettled = market['settle'] === 'USDC';
        } else {
            let settle = this.safeString (this.options, 'defaultSettle');
            settle = this.safeString2 (params, 'settle', 'defaultSettle', settle);
            params = this.omit (params, [ 'settle', 'defaultSettle' ]);
            isUsdcSettled = (settle === 'USDC');
        }
        let type = undefined;
        [ type, params ] = this.handleMarketTypeAndParams ('cancelAllOrders', market, params);
        if (!isUsdcSettled && symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' cancelAllOrders() requires a symbol argument for ' + type + ' markets');
        }
        const request = {};
        if (!isUsdcSettled) {
            request['symbol'] = market['id'];
        }
        const orderType = this.safeStringLower (params, 'orderType');
        const isStop = this.safeValue (params, 'stop', false);
        const isConditional = isStop || (orderType === 'stop') || (orderType === 'conditional');
        params = this.omit (params, [ 'stop', 'orderType' ]);
        let method = undefined;
        if (type === 'spot') {
            method = 'privateDeleteSpotOrderBatchCancel';
        } else if (isUsdcSettled) {
            method = (type === 'option') ? 'privatePostOptionUsdcOpenapiPrivateV1CancelAll' : 'privatePostPerpetualUsdcOpenapiPrivateV1CancelAll';
        } else if (type === 'future') {
            method = isConditional ? 'privatePostFuturesPrivateStopOrderCancelAll' : 'privatePostFuturesPrivateOrderCancelAll';
        } else if (market['linear']) {
            // linear swap
            method = isConditional ? 'privatePostPrivateLinearStopOrderCancelAll' : 'privatePostPrivateLinearOrderCancelAll';
        } else {
            // inverse swap
            method = isConditional ? 'privatePostV2PrivateStopOrderCancelAll' : 'privatePostV2PrivateOrderCancelAll';
        }
        const response = await this[method] (this.extend (request, params));
        // spot
        //    {
        //        "ret_code": 0,
        //        "ret_msg": "",
        //        "ext_code": null,
        //        "ext_info": null,
        //        "result": {
        //            "success": true
        //        }
        //    }
        //
        // linear swap
        //   {
        //       "ret_code":0,
        //       "ret_msg":"OK",
        //       "ext_code":"",
        //       "ext_info":"",
        //       "result":[
        //          "49d9ee94-303b-4bcf-959b-9e5d215e4973"
        //       ],
        //       "time_now":"1652182444.015560",
        //       "rate_limit_status":90,
        //       "rate_limit_reset_ms":1652182444010,
        //       "rate_limit":100
        //    }
        //
        // conditional futures
        //    {
        //        "ret_code":0,
        //        "ret_msg":"OK",
        //        "ext_code":"",
        //        "ext_info":"",
        //        "result":[
        //           {
        //              "clOrdID":"a14aea1e-9148-4a34-871a-f935f7cdb654",
        //              "user_id":24478789,
        //              "symbol":"ETHUSDM22",
        //              "side":"Buy",
        //              "order_type":"Limit",
        //              "price":"2001",
        //              "qty":10,
        //              "time_in_force":"GoodTillCancel",
        //              "create_type":"CreateByStopOrder",
        //              "cancel_type":"CancelByUser",
        //              "order_status":"",
        //              "leaves_value":"0",
        //              "created_at":"2022-05-10T11:43:29.705138839Z",
        //              "updated_at":"2022-05-10T11:43:37.988493739Z",
        //              "cross_status":"Deactivated",
        //              "cross_seq":-1,
        //              "stop_order_type":"Stop",
        //              "trigger_by":"LastPrice",
        //              "base_price":"2410.65",
        //              "trail_value":"0",
        //              "expected_direction":"Falling"
        //           }
        //        ],
        //        "time_now":"1652183017.988764",
        //        "rate_limit_status":97,
        //        "rate_limit_reset_ms":1652183017986,
        //        "rate_limit":100
        //    }
        //
        const result = this.safeValue (response, 'result', []);
        if (!Array.isArray (result)) {
            return response;
        }
        return this.parseOrders (result, market);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOrders
         * @description fetches information on multiple orders made by the user
         * @param {str} symbol unified market symbol of the market orders were made in
         * @param {int|undefined} since the earliest time in ms to fetch orders for
         * @param {int|undefined} limit the maximum number of  orde structures to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure
         */
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (market['spot'] || (market['settle'] === 'USDC')) {
            throw new NotSupported (this.id + ' fetchOrders() does not support ' + market['type'] + ' markets or USDC markets, use exchange.fetchOpenOrders () and exchange.fetchClosedOrders () instead');
        }
        let method = undefined;
        const isStop = this.safeValue (params, 'stop', false);
        const orderType = this.safeStringLower (params, 'orderType');
        const stopOrderId = this.safeString (params, 'stop_order_id'); // might want to filter by id
        const isConditionalOrder = isStop || (stopOrderId !== undefined) || (orderType === 'stop' || orderType === 'conditional');
        params = this.omit (params, [ 'orderType', 'stop', 'orderType' ]);
        if (market['linear']) {
            method = isConditionalOrder ? 'privateGetPrivateLinearStopOrderList' : 'privateGetPrivateLinearOrderList';
        } else if (market['future']) {
            method = isConditionalOrder ? 'privateGetFuturesPrivateStopOrderList' : 'privateGetFuturesPrivateOrderList';
        } else {
            // inverse swap
            method = isConditionalOrder ? 'privateGetV2PrivateStopOrderList' : 'privateGetV2PrivateOrderList';
        }
        const request = {
            'symbol': market['id'],
            // 'order_id': 'string'
            // 'order_link_id': 'string', // unique client order id, max 36 characters
            // 'symbol': market['id'], // default BTCUSD
            // 'order': 'desc', // asc
            // 'page': 1,
            // 'limit': 20, // max 50
            // 'order_status': 'Created,New'
            // conditional orders ---------------------------------------------
            // 'stop_order_id': 'string',
            // 'stop_order_status': 'Untriggered',
        };
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this[method] (this.extend (request, params));
        //
        // linear swap
        //
        //     {
        //         "ret_code":"0",
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":{
        //            "current_page":"1",
        //            "data":[
        //               {
        //                  "order_id":"68ab115d-cdbc-4c38-adc0-b2fbc60136ab",
        //                  "user_id":"24478789",
        //                  "symbol":"LTCUSDT",
        //                  "side":"Sell",
        //                  "order_type":"Market",
        //                  "price":"94.72",
        //                  "qty":"0.1",
        //                  "time_in_force":"ImmediateOrCancel",
        //                  "order_status":"Filled",
        //                  "last_exec_price":"99.65",
        //                  "cum_exec_qty":"0.1",
        //                  "cum_exec_value":"9.965",
        //                  "cum_exec_fee":"0.005979",
        //                  "reduce_only":true,
        //                  "close_on_trigger":true,
        //                  "order_link_id":"",
        //                  "created_time":"2022-05-05T15:15:34Z",
        //                  "updated_time":"2022-05-05T15:15:34Z",
        //                  "take_profit":"0",
        //                  "stop_loss":"0",
        //                  "tp_trigger_by":"UNKNOWN",
        //                  "sl_trigger_by":"UNKNOWN"
        //               }
        //            ]
        //         },
        //         "time_now":"1652106664.857572",
        //         "rate_limit_status":"598",
        //         "rate_limit_reset_ms":"1652106664856",
        //         "rate_limit":"600"
        //     }
        //
        //
        // conditional orders
        //
        //     {
        //         "ret_code":"0",
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":{
        //            "current_page":"1",
        //            "last_page":"0",
        //            "data":[
        //               {
        //                  "user_id":"24478789",
        //                  "stop_order_id":"68e996af-fa55-4ca1-830e-4bf68ffbff3e",
        //                  "symbol":"LTCUSDT",
        //                  "side":"Buy",
        //                  "order_type":"Limit",
        //                  "price":"86",
        //                  "qty":"0.1",
        //                  "time_in_force":"GoodTillCancel",
        //                  "order_status":"Untriggered",
        //                  "trigger_price":"86",
        //                  "order_link_id":"",
        //                  "created_time":"2022-05-09T14:36:36Z",
        //                  "updated_time":"2022-05-09T14:36:36Z",
        //                  "take_profit":"0",
        //                  "stop_loss":"0",
        //                  "trigger_by":"LastPrice",
        //                  "base_price":"86.96",
        //                  "tp_trigger_by":"UNKNOWN",
        //                  "sl_trigger_by":"UNKNOWN",
        //                  "reduce_only":false,
        //                  "close_on_trigger":false
        //               }
        //            ]
        //         },
        //         "time_now":"1652107028.148177",
        //         "rate_limit_status":"598",
        //         "rate_limit_reset_ms":"1652107028146",
        //         "rate_limit":"600"
        //     }
        //
        const result = this.safeValue (response, 'result', {});
        const data = this.safeValue (result, 'data', []);
        return this.parseOrders (data, market, since, limit);
    }

    async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchClosedOrders
         * @description fetches information on multiple closed orders made by the user
         * @param {str|undefined} symbol unified market symbol of the market orders were made in
         * @param {int|undefined} since the earliest time in ms to fetch orders for
         * @param {int|undefined} limit the maximum number of  orde structures to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure
         */
        let market = undefined;
        let isUsdcSettled = undefined;
        if (symbol !== undefined) {
            market = this.market (symbol);
            isUsdcSettled = market['settle'] === 'USDC';
        } else {
            let settle = this.safeString (this.options, 'defaultSettle');
            settle = this.safeString2 (params, 'settle', 'defaultSettle', settle);
            params = this.omit (params, [ 'settle', 'defaultSettle' ]);
            isUsdcSettled = settle === 'USDC';
        }
        let type = undefined;
        [ type, params ] = this.handleMarketTypeAndParams ('fetchClosedOrders', market, params);
        if ((type === 'swap' || type === 'future') && !isUsdcSettled) {
            if (symbol === undefined) {
                throw new ArgumentsRequired (this.id + ' fetchClosedOrders requires a symbol argument for ' + symbol + ' markets');
            }
            const type = this.safeStringLower (params, 'orderType');
            const isStop = this.safeValue (params, 'stop', false);
            const isConditional = isStop || (type === 'stop') || (type === 'conditional');
            params = this.omit (params, [ 'orderType', 'stop' ]);
            let defaultStatuses = undefined;
            if (!isConditional) {
                defaultStatuses = [
                    'Rejected',
                    'Filled',
                    'Cancelled',
                ];
            } else {
                // conditional orders
                defaultStatuses = [
                    'Active',
                    'Triggered',
                    'Cancelled',
                    'Rejected',
                    'Deactivated',
                ];
            }
            const closeStatus = defaultStatuses.join (',');
            const status = this.safeString2 (params, 'order_status', 'status', closeStatus);
            params = this.omit (params, [ 'order_status', 'status' ]);
            params['order_status'] = status;
            return await this.fetchOrders (symbol, since, limit, params);
        }
        const request = {};
        let method = undefined;
        if (type === 'spot') {
            method = 'privateGetSpotV1HistoryOrders';
        } else {
            // usdc
            method = 'privatePostOptionUsdcOpenapiPrivateV1QueryOrderHistory';
            request['category'] = (type === 'swap') ? 'perpetual' : 'option';
        }
        const orders = await this[method] (this.extend (request, params));
        let result = this.safeValue (orders, 'result', []);
        if (!Array.isArray (result)) {
            result = this.safeValue (result, 'dataList', []);
        }
        return this.parseOrders (result, market, since, limit);
    }

    async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOpenOrders
         * @description fetch all unfilled currently open orders
         * @param {str|undefined} symbol unified market symbol
         * @param {int|undefined} since the earliest time in ms to fetch open orders for
         * @param {int|undefined} limit the maximum number of  open orders structures to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
         */
        let market = undefined;
        let isUsdcSettled = undefined;
        if (symbol !== undefined) {
            market = this.market (symbol);
            isUsdcSettled = market['settle'] === 'USDC';
        } else {
            let settle = this.safeString (this.options, 'defaultSettle');
            settle = this.safeString2 (params, 'settle', 'defaultSettle', settle);
            params = this.omit (params, [ 'settle', 'defaultSettle' ]);
            isUsdcSettled = settle === 'USDC';
        }
        let type = undefined;
        [ type, params ] = this.handleMarketTypeAndParams ('fetchOpenOrders', market, params);
        const request = {};
        let method = undefined;
        if ((type === 'swap' || type === 'future') && !isUsdcSettled) {
            if (symbol === undefined) {
                throw new ArgumentsRequired (this.id + ' fetchOpenOrders requires a symbol argument for ' + symbol + ' markets');
            }
            request['symbol'] = market['id'];
            const type = this.safeStringLower (params, 'orderType');
            const isStop = this.safeValue (params, 'stop', false);
            const isConditional = isStop || (type === 'stop') || (type === 'conditional');
            params = this.omit (params, [ 'stop', 'orderType' ]);
            if (market['future']) {
                method = isConditional ? 'privateGetFuturesPrivateStopOrder' : 'privateGetFuturesPrivateOrder';
            } else if (market['linear']) {
                method = isConditional ? 'privateGetPrivateLinearStopOrderSearch' : 'privateGetPrivateLinearOrderSearch';
            } else {
                // inverse swap
                method = isConditional ? 'privateGetV2PrivateStopOrder' : 'privateGetV2PrivateOrder';
            }
        } else if (type === 'spot') {
            method = 'privateGetSpotV1OpenOrders';
        } else {
            // usdc
            method = 'privatePostOptionUsdcOpenapiPrivateV1QueryActiveOrders';
            request['category'] = (type === 'swap') ? 'perpetual' : 'option';
        }
        const orders = await this[method] (this.extend (request, params));
        let result = this.safeValue (orders, 'result', []);
        if (!Array.isArray (result)) {
            const dataList = this.safeValue (result, 'dataList');
            if (dataList === undefined) {
                return this.parseOrder (result, market);
            }
            result = dataList;
        }
        // {
        //     "ret_code":0,
        //     "ret_msg":"",
        //     "ext_code":null,
        //     "ext_info":null,
        //     "result":[
        //        {
        //           "accountId":"24478790",
        //           "exchangeId":"301",
        //           "symbol":"LTCUSDT",
        //           "symbolName":"LTCUSDT",
        //           "orderLinkId":"1652115972506",
        //           "orderId":"1152426740986003968",
        //           "price":"50",
        //           "origQty":"0.2",
        //           "executedQty":"0",
        //           "cummulativeQuoteQty":"0",
        //           "avgPrice":"0",
        //           "status":"NEW",
        //           "timeInForce":"GTC",
        //           "type":"LIMIT",
        //           "side":"BUY",
        //           "stopPrice":"0.0",
        //           "icebergQty":"0.0",
        //           "time":"1652115973053",
        //           "updateTime":"1652115973063",
        //           "isWorking":true
        //        }
        //     ]
        //  }
        return this.parseOrders (result, market, since, limit);
    }

    async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOrderTrades
         * @description fetch all the trades made from a single order
         * @param {str} id order id
         * @param {str|undefined} symbol unified market symbol
         * @param {int|undefined} since the earliest time in ms to fetch trades for
         * @param {int|undefined} limit the maximum number of trades to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html#trade-structure}
         */
        const request = {
            'order_id': id,
        };
        return await this.fetchMyTrades (symbol, since, limit, this.extend (request, params));
    }

    async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchMyTrades
         * @description fetch all trades made by the user
         * @param {str} symbol unified market symbol
         * @param {int|undefined} since the earliest time in ms to fetch trades for
         * @param {int|undefined} limit the maximum number of trades structures to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html#trade-structure}
         */
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument');
        }
        await this.loadMarkets ();
        const request = {
            // 'order_id': 'f185806b-b801-40ff-adec-52289370ed62', // if not provided will return user's trading records
            // 'symbol': market['id'],
            // 'start_time': parseInt (since / 1000),
            // 'page': 1,
            // 'limit' 20, // max 50
        };
        let market = undefined;
        const orderId = this.safeString (params, 'order_id');
        if (orderId !== undefined) {
            request['order_id'] = orderId;
            params = this.omit (params, 'order_id');
        }
        market = this.market (symbol);
        const isUsdcSettled = market['settle'] === 'USDC';
        if (isUsdcSettled) {
            throw new NotSupported (this.id + ' fetchMyTrades() is not supported for market ' + symbol);
        }
        request['symbol'] = market['id'];
        if (since !== undefined) {
            request['start_time'] = since;
        }
        if (limit !== undefined) {
            request['limit'] = limit; // default 20, max 50
        }
        let method = undefined;
        if (market['spot']) {
            method = 'privateGetSpotV1MyTrades';
        } else if (market['future']) {
            method = 'privateGetFuturesPrivateExecutionList';
        } else {
            // linear and inverse swaps
            method = market['linear'] ? 'privateGetPrivateLinearTradeExecutionList' : 'privateGetV2PrivateExecutionList';
        }
        const response = await this[method] (this.extend (request, params));
        //
        // spot
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "",
        //         "ext_code": null,
        //         "ext_info": null,
        //         "result": [
        //            {
        //                 "id": "931975237315196160",
        //                 "symbol": "BTCUSDT",
        //                 "symbolName": "BTCUSDT",
        //                 "orderId": "931975236946097408",
        //                 "ticketId": "1057753175328833537",
        //                 "matchOrderId": "931975113180558592",
        //                 "price": "20000.00001",
        //                 "qty": "0.01",
        //                 "commission": "0.02000000001",
        //                 "commissionAsset": "USDT",
        //                 "time": "1625836105890",
        //                 "isBuyer": false,
        //                 "isMaker": false,
        //                 "fee": {
        //                     "feeTokenId": "USDT",
        //                     "feeTokenName": "USDT",
        //                     "fee": "0.02000000001"
        //                 },
        //                 "feeTokenId": "USDT",
        //                 "feeAmount": "0.02000000001",
        //                 "makerRebate": "0"
        //            }
        //         ]
        //     }
        //
        // inverse
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "OK",
        //         "ext_code": "",
        //         "ext_info": "",
        //         "result": {
        //             "order_id": "Abandoned!!", // Abandoned!!
        //             "trade_list": [
        //                 {
        //                     "closed_size": 0,
        //                     "cross_seq": 277136382,
        //                     "exec_fee": "0.0000001",
        //                     "exec_id": "256e5ef8-abfe-5772-971b-f944e15e0d68",
        //                     "exec_price": "8178.5",
        //                     "exec_qty": 1,
        //                     "exec_time": "1571676941.70682",
        //                     "exec_type": "Trade", //Exec Type Enum
        //                     "exec_value": "0.00012227",
        //                     "fee_rate": "0.00075",
        //                     "last_liquidity_ind": "RemovedLiquidity", //Liquidity Enum
        //                     "leaves_qty": 0,
        //                     "nth_fill": 2,
        //                     "order_id": "7ad50cb1-9ad0-4f74-804b-d82a516e1029",
        //                     "order_link_id": "",
        //                     "order_price": "8178",
        //                     "order_qty": 1,
        //                     "order_type": "Market", //Order Type Enum
        //                     "side": "Buy", //Side Enum
        //                     "symbol": "BTCUSD", //Symbol Enum
        //                     "user_id": 1
        //                 }
        //             ]
        //         },
        //         "time_now": "1577483699.281488",
        //         "rate_limit_status": 118,
        //         "rate_limit_reset_ms": 1577483699244737,
        //         "rate_limit": 120
        //     }
        //
        // linear
        //
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK",
        //         "ext_code":"",
        //         "ext_info":"",
        //         "result":{
        //             "current_page":1,
        //             "data":[
        //                 {
        //                     "order_id":"b59418ec-14d4-4ef9-b9f4-721d5d576974",
        //                     "order_link_id":"",
        //                     "side":"Sell",
        //                     "symbol":"BTCUSDT",
        //                     "exec_id":"0327284d-faec-5191-bd89-acc5b4fafda9",
        //                     "price":0.5,
        //                     "order_price":0.5,
        //                     "order_qty":0.01,
        //                     "order_type":"Market",
        //                     "fee_rate":0.00075,
        //                     "exec_price":9709.5,
        //                     "exec_type":"Trade",
        //                     "exec_qty":0.01,
        //                     "exec_fee":0.07282125,
        //                     "exec_value":97.095,
        //                     "leaves_qty":0,
        //                     "closed_size":0.01,
        //                     "last_liquidity_ind":"RemovedLiquidity",
        //                     "trade_time":1591648052,
        //                     "trade_time_ms":1591648052861
        //                 }
        //             ]
        //         },
        //         "time_now":"1591736501.979264",
        //         "rate_limit_status":119,
        //         "rate_limit_reset_ms":1591736501974,
        //         "rate_limit":120
        //     }
        //
        let result = this.safeValue (response, 'result', {});
        if (!Array.isArray (result)) {
            result = this.safeValue2 (result, 'trade_list', 'data', []);
        }
        return this.parseTrades (result, market, since, limit);
    }

    parseDepositAddress (depositAddress, currency = undefined) {
        //
        //     {
        //         chain_type: 'Arbitrum One',
        //         address_deposit: '0x83a127952d266A6eA306c40Ac62A4a70668FE3BE',
        //         tag_deposit: '',
        //         chain: 'ARBI'
        //     }
        //
        const address = this.safeString (depositAddress, 'address_deposit');
        const tag = this.safeString (depositAddress, 'tag_deposit');
        const code = this.safeString (currency, 'code');
        const chain = this.safeString (depositAddress, 'chain');
        this.checkAddress (address);
        return {
            'currency': code,
            'address': address,
            'tag': tag,
            'network': chain,
            'info': depositAddress,
        };
    }

    async fetchDepositAddressesByNetwork (code, params = {}) {
        /**
         * @method
         * @name bybit#fetchDepositAddressesByNetwork
         * @description fetch a dictionary of addresses for a currency, indexed by network
         * @param {str} code unified currency code of the currency for the deposit address
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a dictionary of [address structures]{@link https://docs.ccxt.com/en/latest/manual.html#address-structure} indexed by the network
         */
        await this.loadMarkets ();
        let currency = this.currency (code);
        const request = {
            'coin': currency['id'],
        };
        const response = await this.privateGetAssetV1PrivateDepositAddress (this.extend (request, params));
        //
        //     {
        //         ret_code: '0',
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         result: {
        //             coin: 'ETH',
        //             chains: [
        //                 {
        //                     chain_type: 'Arbitrum One',
        //                     address_deposit: 'bybitisthebest',
        //                     tag_deposit: '',
        //                     chain: 'ARBI'
        //                 }
        //             ]
        //         },
        //         ext_info: null,
        //         time_now: '1653141635426'
        //     }
        //
        const result = this.safeValue (response, 'result', []);
        const chains = this.safeValue (result, 'chains', []);
        const coin = this.safeString (result, 'coin');
        currency = this.currency (coin);
        const parsed = this.parseDepositAddresses (chains, [ code ], false, {
            'currency': currency['id'],
        });
        return this.indexBy (parsed, 'network');
    }

    async fetchDepositAddress (code, params = {}) {
        /**
         * @method
         * @name bybit#fetchDepositAddress
         * @description fetch the deposit address for a currency associated with this account
         * @param {str} code unified currency code
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} an [address structure]{@link https://docs.ccxt.com/en/latest/manual.html#address-structure}
         */
        const rawNetwork = this.safeStringUpper (params, 'network');
        const networks = this.safeValue (this.options, 'networks', {});
        const network = this.safeString (networks, rawNetwork, rawNetwork);
        params = this.omit (params, 'network');
        const response = await this.fetchDepositAddressesByNetwork (code, params);
        let result = undefined;
        if (network === undefined) {
            result = this.safeValue (response, code);
            if (result === undefined) {
                const alias = this.safeString (networks, code, code);
                result = this.safeValue (response, alias);
                if (result === undefined) {
                    const defaultNetwork = this.safeString (this.options, 'defaultNetwork', 'ERC20');
                    result = this.safeValue (response, defaultNetwork);
                    if (result === undefined) {
                        const values = Object.values (response);
                        result = this.safeValue (values, 0);
                        if (result === undefined) {
                            throw new InvalidAddress (this.id + ' fetchDepositAddress() cannot find deposit address for ' + code);
                        }
                    }
                }
            }
            return result;
        }
        result = this.safeValue (response, network);
        if (result === undefined) {
            throw new InvalidAddress (this.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code);
        }
        return result;
    }

    async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchDeposits
         * @description fetch all deposits made to an account
         * @param {str|undefined} code unified currency code
         * @param {int|undefined} since the earliest time in ms to fetch deposits for
         * @param {int|undefined} limit the maximum number of deposits structures to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
         */
        await this.loadMarkets ();
        const request = {
            // 'coin': currency['id'],
            // 'currency': currency['id'], // alias
            // 'start_date': this.iso8601 (since),
            // 'end_date': this.iso8601 (till),
            'wallet_fund_type': 'Deposit', // Deposit, Withdraw, RealisedPNL, Commission, Refund, Prize, ExchangeOrderWithdraw, ExchangeOrderDeposit
            // 'page': 1,
            // 'limit': 20, // max 50
        };
        let currency = undefined;
        if (code !== undefined) {
            currency = this.currency (code);
            request['coin'] = currency['id'];
        }
        if (since !== undefined) {
            request['start_date'] = this.yyyymmdd (since);
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        // Currently only works for deposits prior to 2021-07-15
        // will be updated soon
        const response = await this.privateGetV2PrivateWalletFundRecords (this.extend (request, params));
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "ok",
        //         "ext_code": "",
        //         "result": {
        //             "data": [
        //                 {
        //                     "id": 234467,
        //                     "user_id": 1,
        //                     "coin": "BTC",
        //                     "wallet_id": 27913,
        //                     "type": "Realized P&L",
        //                     "amount": "-0.00000006",
        //                     "tx_id": "",
        //                     "address": "BTCUSD",
        //                     "wallet_balance": "0.03000330",
        //                     "exec_time": "2019-12-09T00:00:25.000Z",
        //                     "cross_seq": 0
        //                 }
        //             ]
        //         },
        //         "ext_info": null,
        //         "time_now": "1577481867.115552",
        //         "rate_limit_status": 119,
        //         "rate_limit_reset_ms": 1577481867122,
        //         "rate_limit": 120
        //     }
        //
        const result = this.safeValue (response, 'result', {});
        const data = this.safeValue (result, 'data', []);
        return this.parseTransactions (data, currency, since, limit, { 'type': 'deposit' });
    }

    async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchWithdrawals
         * @description fetch all withdrawals made from an account
         * @param {str} code unified currency code
         * @param {int|undefined} since the earliest time in ms to fetch withdrawals for
         * @param {int|undefined} limit the maximum number of withdrawals structures to retrieve
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
         */
        await this.loadMarkets ();
        const request = {
            // 'coin': currency['id'],
            // 'start_date': this.iso8601 (since),
            // 'end_date': this.iso8601 (till),
            // 'status': 'Pending', // ToBeConfirmed, UnderReview, Pending, Success, CancelByUser, Reject, Expire
            // 'page': 1,
            // 'limit': 20, // max 50
        };
        let currency = undefined;
        if (code !== undefined) {
            currency = this.currency (code);
            request['coin'] = currency['id'];
        }
        if (since !== undefined) {
            request['start_date'] = this.yyyymmdd (since);
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this.privateGetV2PrivateWalletWithdrawList (this.extend (request, params));
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "ok",
        //         "ext_code": "",
        //         "result": {
        //             "data": [
        //                 {
        //                     "id": 137,
        //                     "user_id": 1,
        //                     "coin": "XRP", // Coin Enum
        //                     "status": "Pending", // Withdraw Status Enum
        //                     "amount": "20.00000000",
        //                     "fee": "0.25000000",
        //                     "address": "rH7H595XYEVTEHU2FySYsWnmfACBnZS9zM",
        //                     "tx_id": "",
        //                     "submited_at": "2019-06-11T02:20:24.000Z",
        //                     "updated_at": "2019-06-11T02:20:24.000Z"
        //                 },
        //             ],
        //             "current_page": 1,
        //             "last_page": 1
        //         },
        //         "ext_info": null,
        //         "time_now": "1577482295.125488",
        //         "rate_limit_status": 119,
        //         "rate_limit_reset_ms": 1577482295132,
        //         "rate_limit": 120
        //     }
        //
        const result = this.safeValue (response, 'result', {});
        const data = this.safeValue (result, 'data', []);
        return this.parseTransactions (data, currency, since, limit, { 'type': 'withdrawal' });
    }

    parseTransactionStatus (status) {
        const statuses = {
            'ToBeConfirmed': 'pending',
            'UnderReview': 'pending',
            'Pending': 'pending',
            'Success': 'ok',
            'CancelByUser': 'canceled',
            'Reject': 'rejected',
            'Expire': 'expired',
        };
        return this.safeString (statuses, status, status);
    }

    parseTransaction (transaction, currency = undefined) {
        //
        // fetchWithdrawals
        //
        //     {
        //         "id": 137,
        //         "user_id": 1,
        //         "coin": "XRP", // Coin Enum
        //         "status": "Pending", // Withdraw Status Enum
        //         "amount": "20.00000000",
        //         "fee": "0.25000000",
        //         "address": "rH7H595XYEVTEHU2FySYsWnmfACBnZS9zM",
        //         "tx_id": "",
        //         "submited_at": "2019-06-11T02:20:24.000Z",
        //         "updated_at": "2019-06-11T02:20:24.000Z"
        //     }
        //
        // fetchDeposits ledger entries
        //
        //     {
        //         "id": 234467,
        //         "user_id": 1,
        //         "coin": "BTC",
        //         "wallet_id": 27913,
        //         "type": "Realized P&L",
        //         "amount": "-0.00000006",
        //         "tx_id": "",
        //         "address": "BTCUSD",
        //         "wallet_balance": "0.03000330",
        //         "exec_time": "2019-12-09T00:00:25.000Z",
        //         "cross_seq": 0
        //     }
        //
        const currencyId = this.safeString (transaction, 'coin');
        const code = this.safeCurrencyCode (currencyId, currency);
        const timestamp = this.parse8601 (this.safeString2 (transaction, 'submited_at', 'exec_time'));
        const updated = this.parse8601 (this.safeString (transaction, 'updated_at'));
        const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
        const address = this.safeString (transaction, 'address');
        const feeCost = this.safeNumber (transaction, 'fee');
        const type = this.safeStringLower (transaction, 'type');
        let fee = undefined;
        if (feeCost !== undefined) {
            fee = {
                'cost': feeCost,
                'currency': code,
            };
        }
        return {
            'info': transaction,
            'id': this.safeString (transaction, 'id'),
            'txid': this.safeString (transaction, 'tx_id'),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'network': undefined,
            'address': address,
            'addressTo': undefined,
            'addressFrom': undefined,
            'tag': undefined,
            'tagTo': undefined,
            'tagFrom': undefined,
            'type': type,
            'amount': this.safeNumber (transaction, 'amount'),
            'currency': code,
            'status': status,
            'updated': updated,
            'fee': fee,
        };
    }

    async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchLedger
         * @description fetch the history of changes, actions done by the user or operations that altered balance of the user
         * @param {str|undefined} code unified currency code, default is undefined
         * @param {int|undefined} since timestamp in ms of the earliest ledger entry, default is undefined
         * @param {int|undefined} limit max number of ledger entrys to return, default is undefined
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a [ledger structure]{@link https://docs.ccxt.com/en/latest/manual.html#ledger-structure}
         */
        await this.loadMarkets ();
        const request = {
            // 'coin': currency['id'],
            // 'currency': currency['id'], // alias
            // 'start_date': this.iso8601 (since),
            // 'end_date': this.iso8601 (till),
            // 'wallet_fund_type': 'Deposit', // Withdraw, RealisedPNL, Commission, Refund, Prize, ExchangeOrderWithdraw, ExchangeOrderDeposit
            // 'page': 1,
            // 'limit': 20, // max 50
        };
        let currency = undefined;
        if (code !== undefined) {
            currency = this.currency (code);
            request['coin'] = currency['id'];
        }
        if (since !== undefined) {
            request['start_date'] = this.yyyymmdd (since);
        }
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this.privateGetV2PrivateWalletFundRecords (this.extend (request, params));
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "ok",
        //         "ext_code": "",
        //         "result": {
        //             "data": [
        //                 {
        //                     "id": 234467,
        //                     "user_id": 1,
        //                     "coin": "BTC",
        //                     "wallet_id": 27913,
        //                     "type": "Realized P&L",
        //                     "amount": "-0.00000006",
        //                     "tx_id": "",
        //                     "address": "BTCUSD",
        //                     "wallet_balance": "0.03000330",
        //                     "exec_time": "2019-12-09T00:00:25.000Z",
        //                     "cross_seq": 0
        //                 }
        //             ]
        //         },
        //         "ext_info": null,
        //         "time_now": "1577481867.115552",
        //         "rate_limit_status": 119,
        //         "rate_limit_reset_ms": 1577481867122,
        //         "rate_limit": 120
        //     }
        //
        const result = this.safeValue (response, 'result', {});
        const data = this.safeValue (result, 'data', []);
        return this.parseLedger (data, currency, since, limit);
    }

    parseLedgerEntry (item, currency = undefined) {
        //
        //     {
        //         "id": 234467,
        //         "user_id": 1,
        //         "coin": "BTC",
        //         "wallet_id": 27913,
        //         "type": "Realized P&L",
        //         "amount": "-0.00000006",
        //         "tx_id": "",
        //         "address": "BTCUSD",
        //         "wallet_balance": "0.03000330",
        //         "exec_time": "2019-12-09T00:00:25.000Z",
        //         "cross_seq": 0
        //     }
        //
        const currencyId = this.safeString (item, 'coin');
        const code = this.safeCurrencyCode (currencyId, currency);
        const amount = this.safeNumber (item, 'amount');
        const after = this.safeNumber (item, 'wallet_balance');
        const direction = (amount < 0) ? 'out' : 'in';
        let before = undefined;
        if (after !== undefined && amount !== undefined) {
            const difference = (direction === 'out') ? amount : -amount;
            before = this.sum (after, difference);
        }
        const timestamp = this.parse8601 (this.safeString (item, 'exec_time'));
        const type = this.parseLedgerEntryType (this.safeString (item, 'type'));
        const id = this.safeString (item, 'id');
        const referenceId = this.safeString (item, 'tx_id');
        return {
            'id': id,
            'currency': code,
            'account': this.safeString (item, 'wallet_id'),
            'referenceAccount': undefined,
            'referenceId': referenceId,
            'status': undefined,
            'amount': amount,
            'before': before,
            'after': after,
            'fee': undefined,
            'direction': direction,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'type': type,
            'info': item,
        };
    }

    parseLedgerEntryType (type) {
        const types = {
            'Deposit': 'transaction',
            'Withdraw': 'transaction',
            'RealisedPNL': 'trade',
            'Commission': 'fee',
            'Refund': 'cashback',
            'Prize': 'prize', // ?
            'ExchangeOrderWithdraw': 'transaction',
            'ExchangeOrderDeposit': 'transaction',
        };
        return this.safeString (types, type, type);
    }

    async withdraw (code, amount, address, tag = undefined, params = {}) {
        /**
         * @method
         * @name bybit#withdraw
         * @description make a withdrawal
         * @param {str} code unified currency code
         * @param {float} amount the amount to withdraw
         * @param {str} address the address to withdraw to
         * @param {str|undefined} tag
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a [transaction structure]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure}
         */
        [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
        await this.loadMarkets ();
        this.checkAddress (address);
        const currency = this.currency (code);
        const request = {
            'coin': currency['id'],
            'amount': this.numberToString (amount),
            'address': address,
        };
        if (tag !== undefined) {
            request['tag'] = tag;
        }
        const networks = this.safeValue (this.options, 'networks', {});
        let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
        network = this.safeStringUpper (networks, network, network); // handle ERC20>ETH alias
        if (network !== undefined) {
            request['chain'] = network;
            params = this.omit (params, 'network');
        }
        const response = await this.privatePostAssetV1PrivateWithdraw (this.extend (request, params));
        //
        //     {
        //         "ret_code":0,
        //         "ret_msg":"OK"
        //         "ext_code":"",
        //         "result":{
        //             "id":"bybitistheone"
        //         },
        //         "ext_info":null,
        //         "time_now":1653149296617
        //     }
        //
        const result = this.safeValue (response, 'result', {});
        return this.parseTransaction (result, currency);
    }

    async fetchPositions (symbols = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchPositions
         * @description fetch all open positions
         * @param {[str]|undefined} symbols list of unified market symbols
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {[dict]} a list of [position structure]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
         */
        await this.loadMarkets ();
        const request = {};
        let market = undefined;
        let type = undefined;
        let isLinear = undefined;
        let isUsdcSettled = undefined;
        if (Array.isArray (symbols)) {
            const length = symbols.length;
            if (length !== 1) {
                throw new ArgumentsRequired (this.id + ' fetchPositions() takes an array with exactly one symbol');
            }
            const symbol = this.safeString (symbols, 0);
            market = this.market (symbol);
            type = market['type'];
            isLinear = market['linear'];
            isUsdcSettled = market['settle'] === 'USDC';
            request['symbol'] = market['id'];
        } else {
            // market undefined
            [ type, params ] = this.handleMarketTypeAndParams ('fetchPositions', undefined, params);
            const options = this.safeValue (this.options, 'fetchPositions', {});
            const defaultSubType = this.safeString (this.options, 'defaultSubType', 'linear');
            let subType = this.safeString (options, 'subType', defaultSubType);
            subType = this.safeString (params, 'subType', subType);
            isLinear = (subType === 'linear');
            let defaultSettle = this.safeString (this.options, 'defaultSettle');
            defaultSettle = this.safeString2 (params, 'settle', 'defaultSettle', defaultSettle);
            isUsdcSettled = (defaultSettle === 'USDC');
        }
        params = this.omit (params, [ 'settle', 'defaultSettle', 'subType' ]);
        let method = undefined;
        if (isUsdcSettled) {
            method = 'privatePostOptionUsdcOpenapiPrivateV1QueryPosition';
            request['category'] = (type === 'option') ? 'OPTION' : 'PERPETUAL';
        } else if (type === 'future') {
            method = 'privateGetFuturesPrivatePositionList';
        } else if (isLinear) {
            method = 'privateGetPrivateLinearPositionList';
        } else {
            // inverse swaps
            method = 'privateGetV2PrivatePositionList';
        }
        let response = await this[method] (this.extend (request, params));
        if ((typeof response === 'string') && this.isJsonEncodedObject (response)) {
            response = JSON.parse (response);
        }
        //
        //     {
        //         ret_code: 0,
        //         ret_msg: 'OK',
        //         ext_code: '',
        //         ext_info: '',
        //         result: [] or {} depending on the request
        //     }
        //
        let result = this.safeValue (response, 'result', {});
        // usdc contracts
        if ('dataList' in result) {
            result = this.safeValue (result, 'dataList', []);
        }
        let positions = undefined;
        if (!Array.isArray (result)) {
            positions = [ result ];
        } else {
            positions = result;
        }
        const results = [];
        for (let i = 0; i < positions.length; i++) {
            let rawPosition = positions[i];
            if (('data' in rawPosition) && ('is_valid' in rawPosition)) {
                // futures only
                rawPosition = this.safeValue (rawPosition, 'data');
            }
            results.push (this.parsePosition (rawPosition, market));
        }
        return this.filterByArray (results, 'symbol', symbols, false);
    }

    parsePosition (position, market = undefined) {
        //
        // linear swap
        //
        //    {
        //        "user_id":"24478789",
        //        "symbol":"LTCUSDT",
        //        "side":"Buy",
        //        "size":"0.1",
        //        "position_value":"7.083",
        //        "entry_price":"70.83",
        //        "liq_price":"0.01",
        //        "bust_price":"0.01",
        //        "leverage":"1",
        //        "auto_add_margin":"0",
        //        "is_isolated":false,
        //        "position_margin":"13.8407674",
        //        "occ_closing_fee":"6e-07",
        //        "realised_pnl":"-0.0042498",
        //        "cum_realised_pnl":"-0.159232",
        //        "free_qty":"-0.1",
        //        "tp_sl_mode":"Full",
        //        "unrealised_pnl":"0.008",
        //        "deleverage_indicator":"2",
        //        "risk_id":"71",
        //        "stop_loss":"0",
        //        "take_profit":"0",
        //        "trailing_stop":"0",
        //        "position_idx":"1",
        //        "mode":"BothSide"
        //    }
        //
        // inverse swap / future
        //    {
        //        "id":0,
        //        "position_idx":0,
        //        "mode":0,
        //        "user_id":24478789,
        //        "risk_id":11,
        //        "symbol":"ETHUSD",
        //        "side":"Buy",
        //        "size":10, // USD amount
        //        "position_value":"0.0047808",
        //        "entry_price":"2091.70013387",
        //        "is_isolated":false,
        //        "auto_add_margin":1,
        //        "leverage":"10",
        //        "effective_leverage":"0.9",
        //        "position_margin":"0.00048124",
        //        "liq_price":"992.75",
        //        "bust_price":"990.4",
        //        "occ_closing_fee":"0.00000606",
        //        "occ_funding_fee":"0",
        //        "take_profit":"0",
        //        "stop_loss":"0",
        //        "trailing_stop":"0",
        //        "position_status":"Normal",
        //        "deleverage_indicator":3,
        //        "oc_calc_data":"{\"blq\":0,\"slq\":0,\"bmp\":0,\"smp\":0,\"fq\":-10,\"bv2c\":0.10126,\"sv2c\":0.10114}",
        //        "order_margin":"0",
        //        "wallet_balance":"0.0053223",
        //        "realised_pnl":"-0.00000287",
        //        "unrealised_pnl":0.00001847,
        //        "cum_realised_pnl":"-0.00001611",
        //        "cross_seq":8301155878,
        //        "position_seq":0,
        //        "created_at":"2022-05-05T15:06:17.949997224Z",
        //        "updated_at":"2022-05-13T13:40:29.793570924Z",
        //        "tp_sl_mode":"Full"
        //    }
        //
        // usdc
        //    {
        //       "symbol":"BTCPERP",
        //       "leverage":"1.00",
        //       "occClosingFee":"0.0000",
        //       "liqPrice":"",
        //       "positionValue":"30.8100",
        //       "takeProfit":"0.0",
        //       "riskId":"10001",
        //       "trailingStop":"0.0000",
        //       "unrealisedPnl":"0.0000",
        //       "createdAt":"1652451795305",
        //       "markPrice":"30809.41",
        //       "cumRealisedPnl":"0.0000",
        //       "positionMM":"0.1541",
        //       "positionIM":"30.8100",
        //       "updatedAt":"1652451795305",
        //       "tpSLMode":"UNKNOWN",
        //       "side":"Buy",
        //       "bustPrice":"",
        //       "deleverageIndicator":"0",
        //       "entryPrice":"30810.0",
        //       "size":"0.001",
        //       "sessionRPL":"0.0000",
        //       "positionStatus":"NORMAL",
        //       "sessionUPL":"-0.0006",
        //       "stopLoss":"0.0",
        //       "orderMargin":"0.0000",
        //       "sessionAvgPrice":"30810.0"
        //    }
        //
        const contract = this.safeString (position, 'symbol');
        market = this.safeMarket (contract, market);
        const size = this.safeString (position, 'size');
        let side = this.safeString (position, 'side');
        side = (side === 'Buy') ? 'long' : 'short';
        const notional = this.safeString2 (position, 'position_value', 'positionValue');
        const unrealisedPnl = this.omitZero (this.safeString2 (position, 'unrealised_pnl', 'unrealisedPnl'));
        let initialMarginString = this.safeString (position, 'positionIM');
        const maintenanceMarginString = this.safeString (position, 'positionMM');
        let timestamp = this.parse8601 (this.safeString (position, 'updated_at'));
        if (timestamp === undefined) {
            timestamp = this.safeInteger (position, 'createdAt');
        }
        const isIsolated = this.safeValue (position, 'is_isolated', false); // if not present it is cross
        const marginMode = isIsolated ? 'isolated' : 'cross';
        let collateralString = this.safeString (position, 'position_margin');
        const entryPrice = this.omitZero (this.safeString2 (position, 'entry_price', 'entryPrice'));
        const liquidationPrice = this.omitZero (this.safeString2 (position, 'liq_price', 'liqPrice'));
        const leverage = this.safeString (position, 'leverage');
        if (market['settle'] === 'USDT') {
            // Initial Margin = Contract size x Entry Price / Leverage
            initialMarginString = Precise.stringDiv (Precise.stringMul (size, entryPrice), leverage);
        } else if (market['inverse']) {
            // Initial Margin = Contracts / ( Entry Price x Leverage )
            initialMarginString = Precise.stringDiv (size, Precise.stringMul (entryPrice, leverage));
            if (!isIsolated) {
                collateralString = this.safeString (position, 'wallet_balance');
            }
        }
        const percentage = Precise.stringMul (Precise.stringDiv (unrealisedPnl, initialMarginString), '100');
        return {
            'info': position,
            'symbol': market['symbol'],
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'initialMargin': this.parseNumber (initialMarginString),
            'initialMarginPercentage': this.parseNumber (Precise.stringDiv (initialMarginString, notional)),
            'maintenanceMargin': maintenanceMarginString,
            'maintenanceMarginPercentage': undefined,
            'entryPrice': this.parseNumber (entryPrice),
            'notional': this.parseNumber (notional),
            'leverage': this.parseNumber (leverage),
            'unrealizedPnl': this.parseNumber (unrealisedPnl),
            'contracts': this.parseNumber (size), // in USD for inverse swaps
            'contractSize': this.safeNumber (market, 'contractSize'),
            'marginRatio': undefined,
            'liquidationPrice': this.parseNumber (liquidationPrice),
            'markPrice': this.safeNumber (position, 'markPrice'),
            'collateral': this.parseNumber (collateralString),
            'marginMode': marginMode,
            'side': side,
            'percentage': this.parseNumber (percentage),
        };
    }

    async setMarginMode (marginMode, symbol = undefined, params = {}) {
        /**
         * @method
         * @name bybit#setMarginMode
         * @description set margin mode to 'cross' or 'isolated'
         * @param {str} marginMode 'cross' or 'isolated'
         * @param {str} symbol unified market symbol
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} response from the exchange
         */
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' setMarginMode() requires a symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (market['settle'] === 'USDC') {
            throw new NotSupported (this.id + ' setMarginMode() does not support market ' + symbol + '');
        }
        marginMode = marginMode.toUpperCase ();
        if ((marginMode !== 'ISOLATED') && (marginMode !== 'CROSS')) {
            throw new BadRequest (this.id + ' setMarginMode() marginMode must be either isolated or cross');
        }
        const leverage = this.safeNumber (params, 'leverage');
        let sellLeverage = undefined;
        let buyLeverage = undefined;
        if (leverage === undefined) {
            sellLeverage = this.safeNumber2 (params, 'sell_leverage', 'sellLeverage');
            buyLeverage = this.safeNumber2 (params, 'buy_leverage', 'buyLeverage');
            if (sellLeverage === undefined || buyLeverage === undefined) {
                throw new ArgumentsRequired (this.id + ' setMarginMode() requires a leverage parameter or sell_leverage and buy_leverage parameters');
            }
            params = this.omit (params, [ 'buy_leverage', 'sell_leverage', 'sellLeverage', 'buyLeverage' ]);
        } else {
            params = this.omit (params, 'leverage');
            sellLeverage = leverage;
            buyLeverage = leverage;
        }
        const isIsolated = (marginMode === 'ISOLATED');
        const request = {
            'symbol': market['id'],
            'is_isolated': isIsolated,
            'buy_leverage': leverage,
            'sell_leverage': leverage,
        };
        let method = undefined;
        if (market['future']) {
            method = 'privatePostFuturesPrivatePositionSwitchIsolated';
        } else if (market['inverse']) {
            method = 'privatePostV2PrivatePositionSwitchIsolated';
        } else {
            // linear
            method = 'privatePostPrivateLinearPositionSwitchIsolated';
        }
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "OK",
        //         "ext_code": "",
        //         "ext_info": "",
        //         "result": null,
        //         "time_now": "1585881597.006026",
        //         "rate_limit_status": 74,
        //         "rate_limit_reset_ms": 1585881597004,
        //         "rate_limit": 75
        //     }
        //
        return response;
    }

    async setLeverage (leverage, symbol = undefined, params = {}) {
        /**
         * @method
         * @name bybit#setLeverage
         * @description set the level of leverage for a market
         * @param {float} leverage the rate of leverage
         * @param {str} symbol unified market symbol
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} response from the exchange
         */
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        // WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS
        // AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS
        const isUsdcSettled = market['settle'] === 'USDC';
        let method = undefined;
        if (isUsdcSettled) {
            method = 'privatePostPerpetualUsdcOpenapiPrivateV1PositionLeverageSave';
        } else if (market['future']) {
            method = 'privatePostFuturesPrivatePositionLeverageSave';
        } else if (market['linear']) {
            method = 'privatePostPrivateLinearPositionSetLeverage';
        } else {
            // inverse swaps
            method = 'privatePostV2PrivatePositionLeverageSave';
        }
        const request = {
            'symbol': market['id'],
        };
        leverage = isUsdcSettled ? leverage.toString () : parseInt (leverage);
        const isLinearSwap = market['swap'] && market['linear'];
        const requiresBuyAndSellLeverage = !isUsdcSettled && (isLinearSwap || market['future']);
        if (requiresBuyAndSellLeverage) {
            const buyLeverage = this.safeNumber (params, 'buy_leverage');
            const sellLeverage = this.safeNumber (params, 'sell_leverage');
            if (buyLeverage !== undefined && sellLeverage !== undefined) {
                if ((buyLeverage < 1) || (buyLeverage > 100) || (sellLeverage < 1) || (sellLeverage > 100)) {
                    throw new BadRequest (this.id + ' setLeverage() leverage should be between 1 and 100');
                }
            } else {
                request['buy_leverage'] = leverage;
                request['sell_leverage'] = leverage;
            }
        } else {
            // requires leverage
            request['leverage'] = leverage;
        }
        if ((leverage < 1) || (leverage > 100)) {
            throw new BadRequest (this.id + ' setLeverage() leverage should be between 1 and 100');
        }
        return await this[method] (this.extend (request, params));
    }

    async setPositionMode (hedged, symbol = undefined, params = {}) {
        if (symbol === undefined) {
            throw new ArgumentsRequired (this.id + ' setPositionMode() requires a symbol argument');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        if (market['settle'] === 'USDC') {
            throw new NotSupported (this.id + ' setPositionMode() does not support market ' + symbol);
        }
        if (market['inverse'] && !market['future']) {
            throw new BadRequest (this.id + ' setPositionMode() must be either a linear swap or an inverse future');
        }
        let method = undefined;
        let mode = undefined;
        if (market['future']) {
            method = 'privatePostFuturesPrivatePositionSwitchMode';
            if (hedged) {
                mode = '3';
            } else {
                mode = '0';
            }
        } else {
            // linear
            method = 'privatePostPrivateLinearPositionSwitchMode';
            if (hedged) {
                mode = 'BothSide';
            } else {
                mode = 'MergedSingle';
            }
        }
        const request = {
            'symbol': market['id'],
            'mode': mode,
        };
        const response = await this[method] (this.extend (request, params));
        //
        //     {
        //         "ret_code": 0,
        //         "ret_msg": "ok",
        //         "ext_code": "",
        //         "result": null,
        //         "ext_info": null,
        //         "time_now": "1577477968.175013",
        //         "rate_limit_status": 74,
        //         "rate_limit_reset_ms": 1577477968183,
        //         "rate_limit": 75
        //     }
        //
        return response;
    }

    async fetchOpenInterestHistory (symbol, timeframe = '1h', since = undefined, limit = undefined, params = {}) {
        /**
         * @method
         * @name bybit#fetchOpenInterestHistory
         * @description Gets the total amount of unsettled contracts. In other words, the total number of contracts held in open positions
         * @param {str} symbol Unified market symbol
         * @param {str} timeframe "5m", 15m, 30m, 1h, 4h, 1d
         * @param {int} since Not used by Bybit
         * @param {int} limit The number of open interest structures to return. Max 200, default 50
         * @param {dict} params Exchange specific parameters
         * @returns An array of open interest structures
         */
        if (timeframe === '1m') {
            throw new BadRequest (this.id + 'fetchOpenInterestHistory cannot use the 1m timeframe');
        }
        await this.loadMarkets ();
        const market = this.market (symbol);
        const request = {
            'symbol': market['id'],
            'period': timeframe,
        };
        if (limit !== undefined) {
            request['limit'] = limit;
        }
        const response = await this.publicGetV2PublicOpenInterest (this.extend (request, params));
        //
        //    {
        //        "ret_code": 0,
        //        "ret_msg": "OK",
        //        "ext_code": "",
        //        "ext_info": "",
        //        "result": [
        //            {
        //                "open_interest": 805604444,
        //                "timestamp": 1645056000,
        //                "symbol": "BTCUSD"
        //            },
        //            ...
        //        ],
        //        "time_now": "1645085118.727358"
        //    }
        //
        const result = this.safeValue (response, 'result');
        return this.parseOpenInterests (result, market, since, limit);
    }

    parseOpenInterest (interest, market = undefined) {
        //
        //    {
        //        "open_interest": 805604444,
        //        "timestamp": 1645056000,
        //        "symbol": "BTCUSD"
        //    }
        //
        const id = this.safeString (interest, 'symbol');
        market = this.safeMarket (id, market);
        const timestamp = this.safeTimestamp (interest, 'timestamp');
        const numContracts = this.safeString (interest, 'open_interest');
        const contractSize = this.safeString (market, 'contractSize');
        return {
            'symbol': this.safeSymbol (id),
            'baseVolume': Precise.stringMul (numContracts, contractSize),
            'quoteVolume': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'info': interest,
        };
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = this.implodeHostname (this.urls['api'][api]) + '/' + path;
        if (api === 'public') {
            if (Object.keys (params).length) {
                url += '?' + this.rawencode (params);
            }
        } else if (api === 'private') {
            this.checkRequiredCredentials ();
            const isOpenapi = url.indexOf ('openapi') >= 0;
            const timestamp = this.milliseconds ().toString ();
            if (isOpenapi) {
                if (Object.keys (params).length) {
                    body = this.json (params);
                } else {
                    // this fix for PHP is required otherwise it generates
                    // '[]' on empty arrays even when forced to use objects
                    body = '{}';
                }
                const payload = timestamp + this.apiKey + body;
                const signature = this.hmac (this.encode (payload), this.encode (this.secret), 'sha256', 'hex');
                headers = {
                    'Content-Type': 'application/json',
                    'X-BAPI-API-KEY': this.apiKey,
                    'X-BAPI-TIMESTAMP': timestamp,
                    'X-BAPI-SIGN': signature,
                };
            } else {
                const query = this.extend (params, {
                    'api_key': this.apiKey,
                    'recv_window': this.options['recvWindow'],
                    'timestamp': timestamp,
                });
                const sortedQuery = this.keysort (query);
                const auth = this.rawencode (sortedQuery);
                const signature = this.hmac (this.encode (auth), this.encode (this.secret));
                if (method === 'POST') {
                    const isSpot = url.indexOf ('spot') >= 0;
                    const extendedQuery = this.extend (query, {
                        'sign': signature,
                    });
                    if (isSpot) {
                        body = this.urlencode (extendedQuery);
                        headers = {
                            'Content-Type': 'application/x-www-form-urlencoded',
                        };
                    } else {
                        body = this.json (extendedQuery);
                        headers = {
                            'Content-Type': 'application/json',
                        };
                        const brokerId = this.safeString (this.options, 'brokerId');
                        if (brokerId !== undefined) {
                            headers['Referer'] = brokerId;
                        }
                    }
                } else {
                    url += '?' + this.urlencode (sortedQuery) + '&sign=' + signature;
                }
            }
        }
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }

    handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
        if (!response) {
            return; // fallback to default error handler
        }
        //
        //     {
        //         ret_code: 10001,
        //         ret_msg: 'ReadMapCB: expect { or n, but found \u0000, error ' +
        //         'found in #0 byte of ...||..., bigger context ' +
        //         '...||...',
        //         ext_code: '',
        //         ext_info: '',
        //         result: null,
        //         time_now: '1583934106.590436'
        //     }
        //
        //     {
        //         "retCode":10001,
        //         "retMsg":"symbol params err",
        //         "result":{"symbol":"","bid":"","bidIv":"","bidSize":"","ask":"","askIv":"","askSize":"","lastPrice":"","openInterest":"","indexPrice":"","markPrice":"","markPriceIv":"","change24h":"","high24h":"","low24h":"","volume24h":"","turnover24h":"","totalVolume":"","totalTurnover":"","fundingRate":"","predictedFundingRate":"","nextFundingTime":"","countdownHour":"0","predictedDeliveryPrice":"","underlyingPrice":"","delta":"","gamma":"","vega":"","theta":""}
        //     }
        //
        const errorCode = this.safeString2 (response, 'ret_code', 'retCode');
        if (errorCode !== '0') {
            if (errorCode === '30084') {
                // not an error
                // https://github.com/ccxt/ccxt/issues/11268
                // https://github.com/ccxt/ccxt/pull/11624
                // POST https://api.bybit.com/v2/private/position/switch-isolated 200 OK
                // {"ret_code":30084,"ret_msg":"Isolated not modified","ext_code":"","ext_info":"","result":null,"time_now":"1642005219.937988","rate_limit_status":73,"rate_limit_reset_ms":1642005219894,"rate_limit":75}
                return undefined;
            }
            const feedback = this.id + ' ' + body;
            this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
            this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
            throw new ExchangeError (feedback); // unknown message
        }
    }

    async fetchMarketLeverageTiers (symbol, params = {}) {
        /**
         * @method
         * @name bybit#fetchMarketLeverageTiers
         * @description retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes for a single market
         * @param {str} symbol unified market symbol
         * @param {dict} params extra parameters specific to the bybit api endpoint
         * @returns {dict} a [leverage tiers structure]{@link https://docs.ccxt.com/en/latest/manual.html#leverage-tiers-structure}
         */
        await this.loadMarkets ();
        const request = {};
        let market = undefined;
        market = this.market (symbol);
        if (market['spot'] || market['option']) {
            throw new BadRequest (this.id + ' fetchMarketLeverageTiers() symbol does not support market ' + symbol);
        }
        request['symbol'] = market['id'];
        const isUsdcSettled = market['settle'] === 'USDC';
        let method = undefined;
        if (isUsdcSettled) {
            method = 'publicGetPerpetualUsdcOpenapiPublicV1RiskLimitList';
        } else if (market['linear']) {
            method = 'publicGetPublicLinearRiskLimit';
        } else {
            method = 'publicGetV2PublicRiskLimitList';
        }
        const response = await this[method] (this.extend (request, params));
        //
        //  publicLinearGetRiskLimit
        //    {
        //        ret_code: '0',
        //        ret_msg: 'OK',
        //        ext_code: '',
        //        ext_info: '',
        //        result: [
        //            {
        //                id: '11',
        //                symbol: 'ETHUSDT',
        //                limit: '800000',
        //                maintain_margin: '0.01',
        //                starting_margin: '0.02',
        //                section: [
        //                    '1',  '2',  '3',
        //                    '5',  '10', '15',
        //                    '25'
        //                ],
        //                is_lowest_risk: '1',
        //                created_at: '2022-02-04 23:30:33.555252',
        //                updated_at: '2022-02-04 23:30:33.555254',
        //                max_leverage: '50'
        //            },
        //            ...
        //        ]
        //    }
        //
        //  v2PublicGetRiskLimitList
        //    {
        //        ret_code: '0',
        //        ret_msg: 'OK',
        //        ext_code: '',
        //        ext_info: '',
        //        result: [
        //            {
        //                id: '180',
        //                is_lowest_risk: '0',
        //                section: [
        //                  '1', '2', '3',
        //                  '4', '5', '7',
        //                  '8', '9'
        //                ],
        //                symbol: 'ETHUSDH22',
        //                limit: '30000',
        //                max_leverage: '9',
        //                starting_margin: '11',
        //                maintain_margin: '5.5',
        //                coin: 'ETH',
        //                created_at: '2021-04-22T15:00:00Z',
        //                updated_at: '2021-04-22T15:00:00Z'
        //            },
        //        ],
        //        time_now: '1644017569.683191'
        //    }
        //
        const result = this.safeValue (response, 'result');
        return this.parseMarketLeverageTiers (result, market);
    }

    parseMarketLeverageTiers (info, market) {
        //
        //    Linear
        //    [
        //        {
        //            id: '11',
        //            symbol: 'ETHUSDT',
        //            limit: '800000',
        //            maintain_margin: '0.01',
        //            starting_margin: '0.02',
        //            section: [
        //                '1',  '2',  '3',
        //                '5',  '10', '15',
        //                '25'
        //            ],
        //            is_lowest_risk: '1',
        //            created_at: '2022-02-04 23:30:33.555252',
        //            updated_at: '2022-02-04 23:30:33.555254',
        //            max_leverage: '50'
        //        },
        //        ...
        //    ]
        //
        //    Inverse
        //    [
        //        {
        //            id: '180',
        //            is_lowest_risk: '0',
        //            section: [
        //                '1', '2', '3',
        //                '4', '5', '7',
        //                '8', '9'
        //            ],
        //            symbol: 'ETHUSDH22',
        //            limit: '30000',
        //            max_leverage: '9',
        //            starting_margin: '11',
        //            maintain_margin: '5.5',
        //            coin: 'ETH',
        //            created_at: '2021-04-22T15:00:00Z',
        //            updated_at: '2021-04-22T15:00:00Z'
        //        }
        //        ...
        //    ]
        //
        // usdc swap
        //
        //    {
        //        "riskId":"10001",
        //        "symbol":"BTCPERP",
        //        "limit":"1000000",
        //        "startingMargin":"0.0100",
        //        "maintainMargin":"0.0050",
        //        "isLowestRisk":true,
        //        "section":[
        //           "1",
        //           "2",
        //           "3",
        //           "5",
        //           "10",
        //           "25",
        //           "50",
        //           "100"
        //        ],
        //        "maxLeverage":"100.00"
        //    }
        //
        let minNotional = 0;
        const tiers = [];
        for (let i = 0; i < info.length; i++) {
            const item = info[i];
            const maxNotional = this.safeNumber (item, 'limit');
            tiers.push ({
                'tier': this.sum (i, 1),
                'currency': market['base'],
                'minNotional': minNotional,
                'maxNotional': maxNotional,
                'maintenanceMarginRate': this.safeNumber2 (item, 'maintain_margin', 'maintainMargin'),
                'maxLeverage': this.safeNumber2 (item, 'max_leverage', 'maxLeverage'),
                'info': item,
            });
            minNotional = maxNotional;
        }
        return tiers;
    }
};