ccxt-ir 4.3.46.0.3__py2.py3-none-any.whl → 4.5.0__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccxt/__init__.py +39 -35
- ccxt/abantether.py +8 -8
- ccxt/abstract/alpaca.py +4 -0
- ccxt/abstract/apex.py +31 -0
- ccxt/abstract/bigone.py +1 -1
- ccxt/abstract/binance.py +106 -48
- ccxt/abstract/binancecoinm.py +106 -48
- ccxt/abstract/binanceus.py +141 -83
- ccxt/abstract/binanceusdm.py +106 -48
- ccxt/abstract/bingx.py +50 -1
- ccxt/abstract/bitbank.py +5 -0
- ccxt/abstract/bitfinex.py +136 -65
- ccxt/abstract/bitflyer.py +1 -0
- ccxt/abstract/bitget.py +67 -0
- ccxt/abstract/bitmart.py +19 -1
- ccxt/abstract/bitopro.py +1 -0
- ccxt/abstract/bitrue.py +68 -68
- ccxt/abstract/bitstamp.py +1 -0
- ccxt/abstract/blofin.py +30 -0
- ccxt/abstract/btcbox.py +2 -0
- ccxt/abstract/bybit.py +28 -13
- ccxt/abstract/cex.py +28 -29
- ccxt/abstract/coinbaseexchange.py +1 -0
- ccxt/abstract/coinbaseinternational.py +1 -1
- ccxt/abstract/cryptocom.py +16 -0
- ccxt/abstract/cryptomus.py +20 -0
- ccxt/abstract/defx.py +69 -0
- ccxt/abstract/deribit.py +1 -0
- ccxt/abstract/derive.py +117 -0
- ccxt/abstract/digifinex.py +1 -0
- ccxt/abstract/ellipx.py +25 -0
- ccxt/abstract/foxbit.py +26 -0
- ccxt/abstract/gate.py +19 -0
- ccxt/abstract/gateio.py +19 -0
- ccxt/abstract/gemini.py +1 -0
- ccxt/abstract/hibachi.py +26 -0
- ccxt/abstract/hyperliquid.py +1 -1
- ccxt/abstract/independentreserve.py +6 -0
- ccxt/abstract/kraken.py +1 -0
- ccxt/abstract/krakenfutures.py +4 -0
- ccxt/abstract/kucoin.py +10 -0
- ccxt/abstract/kucoinfutures.py +18 -0
- ccxt/abstract/lbank.py +2 -1
- ccxt/abstract/luno.py +1 -0
- ccxt/abstract/mexc.py +2 -0
- ccxt/abstract/modetrade.py +119 -0
- ccxt/abstract/myokx.py +349 -0
- ccxt/abstract/oceanex.py +5 -0
- ccxt/abstract/okx.py +25 -0
- ccxt/abstract/okxus.py +349 -0
- ccxt/abstract/onetrading.py +0 -12
- ccxt/abstract/paradex.py +23 -0
- ccxt/abstract/phemex.py +2 -0
- ccxt/abstract/poloniex.py +36 -0
- ccxt/abstract/tradeogre.py +3 -1
- ccxt/abstract/upbit.py +51 -34
- ccxt/abstract/whitebit.py +16 -0
- ccxt/abstract/woo.py +64 -6
- ccxt/abstract/xt.py +10 -5
- ccxt/afratether.py +7 -7
- ccxt/alpaca.py +828 -51
- ccxt/apex.py +1875 -0
- ccxt/arzinja.py +7 -7
- ccxt/arzplus.py +9 -9
- ccxt/ascendex.py +501 -306
- ccxt/async_support/__init__.py +39 -35
- ccxt/async_support/abantether.py +8 -8
- ccxt/async_support/afratether.py +9 -9
- ccxt/async_support/alpaca.py +828 -51
- ccxt/async_support/apex.py +1875 -0
- ccxt/async_support/arzinja.py +10 -10
- ccxt/async_support/arzplus.py +12 -12
- ccxt/async_support/ascendex.py +502 -306
- ccxt/async_support/base/exchange.py +303 -89
- ccxt/async_support/base/ws/cache.py +9 -3
- ccxt/async_support/base/ws/client.py +173 -38
- ccxt/async_support/base/ws/future.py +25 -37
- ccxt/async_support/bequant.py +5 -3
- ccxt/async_support/bigone.py +279 -144
- ccxt/async_support/binance.py +2347 -1158
- ccxt/async_support/binancecoinm.py +9 -3
- ccxt/async_support/binanceus.py +17 -3
- ccxt/async_support/binanceusdm.py +9 -4
- ccxt/async_support/bingx.py +2962 -920
- ccxt/async_support/bit2c.py +147 -27
- ccxt/async_support/bitbank.py +151 -23
- ccxt/async_support/bitbns.py +104 -30
- ccxt/async_support/bitfinex.py +3291 -1113
- ccxt/async_support/bitflyer.py +202 -27
- ccxt/async_support/bitget.py +3683 -1538
- ccxt/async_support/bithumb.py +195 -38
- ccxt/async_support/bitimen.py +12 -12
- ccxt/async_support/bitir.py +38 -38
- ccxt/async_support/bitmart.py +1288 -350
- ccxt/async_support/bitmex.py +260 -75
- ccxt/async_support/bitopro.py +262 -62
- ccxt/async_support/bitpin.py +17 -16
- ccxt/async_support/bitrue.py +459 -290
- ccxt/async_support/bitso.py +199 -54
- ccxt/async_support/bitstamp.py +230 -96
- ccxt/async_support/bitteam.py +167 -25
- ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
- ccxt/async_support/bitvavo.py +213 -49
- ccxt/async_support/blockchaincom.py +160 -46
- ccxt/async_support/blofin.py +502 -120
- ccxt/async_support/btcalpha.py +169 -31
- ccxt/async_support/btcbox.py +292 -23
- ccxt/async_support/btcmarkets.py +211 -58
- ccxt/async_support/btcturk.py +161 -38
- ccxt/async_support/bybit.py +1775 -1030
- ccxt/async_support/cex.py +1440 -1303
- ccxt/async_support/coinbase.py +724 -212
- ccxt/async_support/coinbaseadvanced.py +2 -1
- ccxt/async_support/coinbaseexchange.py +388 -89
- ccxt/async_support/coinbaseinternational.py +412 -57
- ccxt/async_support/coincatch.py +177 -78
- ccxt/async_support/coincheck.py +135 -19
- ccxt/async_support/coinex.py +606 -232
- ccxt/async_support/coinmate.py +189 -63
- ccxt/async_support/coinmetro.py +195 -54
- ccxt/async_support/coinone.py +158 -51
- ccxt/async_support/coinsph.py +336 -61
- ccxt/async_support/coinspot.py +151 -52
- ccxt/async_support/cryptocom.py +661 -111
- ccxt/async_support/cryptomus.py +1137 -0
- ccxt/async_support/defx.py +2071 -0
- ccxt/async_support/delta.py +299 -99
- ccxt/async_support/deribit.py +348 -126
- ccxt/async_support/derive.py +2572 -0
- ccxt/async_support/digifinex.py +430 -214
- ccxt/async_support/ellipx.py +2029 -0
- ccxt/async_support/eterex.py +10 -10
- ccxt/async_support/excoino.py +31 -31
- ccxt/async_support/exir.py +14 -14
- ccxt/async_support/exmo.py +344 -131
- ccxt/async_support/exnovin.py +10 -10
- ccxt/async_support/farhadexchange.py +12 -12
- ccxt/async_support/fmfwio.py +2 -1
- ccxt/async_support/foxbit.py +1935 -0
- ccxt/async_support/gate.py +1351 -529
- ccxt/async_support/gateio.py +2 -1
- ccxt/async_support/gemini.py +144 -39
- ccxt/async_support/hashkey.py +152 -109
- ccxt/async_support/hibachi.py +2080 -0
- ccxt/async_support/hitbtc.py +395 -167
- ccxt/async_support/hitobit.py +12 -12
- ccxt/async_support/hollaex.py +307 -119
- ccxt/async_support/htx.py +851 -383
- ccxt/async_support/huobi.py +2 -1
- ccxt/async_support/hyperliquid.py +1848 -536
- ccxt/async_support/independentreserve.py +288 -15
- ccxt/async_support/indodax.py +190 -33
- ccxt/async_support/jibitex.py +12 -12
- ccxt/async_support/kraken.py +795 -351
- ccxt/async_support/krakenfutures.py +214 -62
- ccxt/async_support/kucoin.py +715 -396
- ccxt/async_support/kucoinfutures.py +652 -89
- ccxt/async_support/latoken.py +217 -113
- ccxt/async_support/lbank.py +425 -97
- ccxt/async_support/luno.py +382 -35
- ccxt/async_support/mercado.py +113 -6
- ccxt/async_support/mexc.py +874 -437
- ccxt/async_support/modetrade.py +2818 -0
- ccxt/async_support/myokx.py +54 -0
- ccxt/async_support/ndax.py +221 -64
- ccxt/async_support/nobitex.py +31 -37
- ccxt/async_support/novadax.py +190 -34
- ccxt/async_support/oceanex.py +217 -28
- ccxt/async_support/okcoin.py +253 -145
- ccxt/async_support/okexchange.py +11 -11
- ccxt/async_support/okx.py +1088 -351
- ccxt/async_support/okxus.py +54 -0
- ccxt/async_support/ompfinex.py +25 -24
- ccxt/async_support/onetrading.py +213 -392
- ccxt/async_support/oxfun.py +245 -166
- ccxt/async_support/p2b.py +151 -29
- ccxt/async_support/paradex.py +562 -49
- ccxt/async_support/paymium.py +82 -19
- ccxt/async_support/phemex.py +713 -172
- ccxt/async_support/poloniex.py +1602 -283
- ccxt/async_support/probit.py +224 -95
- ccxt/async_support/ramzinex.py +30 -27
- ccxt/async_support/sarmayex.py +9 -9
- ccxt/async_support/sarrafex.py +13 -13
- ccxt/async_support/tabdeal.py +14 -13
- ccxt/async_support/tetherland.py +9 -9
- ccxt/async_support/timex.py +210 -51
- ccxt/async_support/tokocrypto.py +167 -47
- ccxt/async_support/tradeogre.py +266 -31
- ccxt/async_support/twox.py +9 -9
- ccxt/async_support/ubitex.py +12 -12
- ccxt/async_support/upbit.py +568 -165
- ccxt/async_support/vertex.py +160 -32
- ccxt/async_support/wallex.py +12 -12
- ccxt/async_support/wavesexchange.py +165 -30
- ccxt/async_support/whitebit.py +975 -127
- ccxt/async_support/woo.py +1918 -1016
- ccxt/async_support/woofipro.py +433 -141
- ccxt/async_support/xt.py +649 -193
- ccxt/async_support/yobit.py +195 -70
- ccxt/async_support/zaif.py +91 -15
- ccxt/async_support/zonda.py +151 -36
- ccxt/base/decimal_to_precision.py +14 -10
- ccxt/base/errors.py +49 -18
- ccxt/base/exchange.py +1556 -450
- ccxt/base/precise.py +10 -0
- ccxt/base/types.py +114 -6
- ccxt/bequant.py +5 -3
- ccxt/bigone.py +279 -144
- ccxt/binance.py +2347 -1158
- ccxt/binancecoinm.py +9 -3
- ccxt/binanceus.py +17 -3
- ccxt/binanceusdm.py +9 -4
- ccxt/bingx.py +2962 -920
- ccxt/bit2c.py +147 -27
- ccxt/bitbank.py +151 -23
- ccxt/bitbns.py +104 -30
- ccxt/bitfinex.py +3290 -1113
- ccxt/bitflyer.py +202 -27
- ccxt/bitget.py +3683 -1538
- ccxt/bithumb.py +194 -38
- ccxt/bitimen.py +9 -9
- ccxt/bitir.py +35 -35
- ccxt/bitmart.py +1288 -350
- ccxt/bitmex.py +260 -75
- ccxt/bitopro.py +262 -62
- ccxt/bitpin.py +15 -14
- ccxt/bitrue.py +459 -290
- ccxt/bitso.py +199 -54
- ccxt/bitstamp.py +230 -96
- ccxt/bitteam.py +167 -25
- ccxt/{huobijp.py → bittrade.py} +158 -30
- ccxt/bitvavo.py +213 -49
- ccxt/blockchaincom.py +160 -46
- ccxt/blofin.py +502 -120
- ccxt/btcalpha.py +169 -31
- ccxt/btcbox.py +291 -23
- ccxt/btcmarkets.py +211 -58
- ccxt/btcturk.py +161 -38
- ccxt/bybit.py +1775 -1030
- ccxt/cex.py +1439 -1303
- ccxt/coinbase.py +724 -212
- ccxt/coinbaseadvanced.py +2 -1
- ccxt/coinbaseexchange.py +388 -89
- ccxt/coinbaseinternational.py +412 -57
- ccxt/coincatch.py +177 -78
- ccxt/coincheck.py +135 -19
- ccxt/coinex.py +606 -232
- ccxt/coinmate.py +189 -63
- ccxt/coinmetro.py +194 -54
- ccxt/coinone.py +158 -51
- ccxt/coinsph.py +336 -61
- ccxt/coinspot.py +151 -52
- ccxt/cryptocom.py +661 -111
- ccxt/cryptomus.py +1137 -0
- ccxt/defx.py +2070 -0
- ccxt/delta.py +299 -99
- ccxt/deribit.py +348 -126
- ccxt/derive.py +2571 -0
- ccxt/digifinex.py +430 -214
- ccxt/ellipx.py +2029 -0
- ccxt/eterex.py +7 -7
- ccxt/excoino.py +29 -29
- ccxt/exir.py +11 -11
- ccxt/exmo.py +343 -131
- ccxt/exnovin.py +8 -8
- ccxt/farhadexchange.py +10 -10
- ccxt/fmfwio.py +2 -1
- ccxt/foxbit.py +1935 -0
- ccxt/gate.py +1351 -529
- ccxt/gateio.py +2 -1
- ccxt/gemini.py +144 -39
- ccxt/hashkey.py +152 -109
- ccxt/hibachi.py +2079 -0
- ccxt/hitbtc.py +395 -167
- ccxt/hitobit.py +9 -9
- ccxt/hollaex.py +307 -119
- ccxt/htx.py +851 -383
- ccxt/huobi.py +2 -1
- ccxt/hyperliquid.py +1848 -536
- ccxt/independentreserve.py +287 -15
- ccxt/indodax.py +190 -33
- ccxt/jibitex.py +9 -9
- ccxt/kraken.py +794 -351
- ccxt/krakenfutures.py +214 -62
- ccxt/kucoin.py +715 -396
- ccxt/kucoinfutures.py +652 -89
- ccxt/latoken.py +217 -113
- ccxt/lbank.py +425 -97
- ccxt/luno.py +382 -35
- ccxt/mercado.py +113 -6
- ccxt/mexc.py +873 -437
- ccxt/modetrade.py +2818 -0
- ccxt/myokx.py +54 -0
- ccxt/ndax.py +221 -64
- ccxt/nobitex.py +29 -35
- ccxt/novadax.py +190 -34
- ccxt/oceanex.py +217 -28
- ccxt/okcoin.py +253 -145
- ccxt/okexchange.py +9 -9
- ccxt/okx.py +1088 -351
- ccxt/okxus.py +54 -0
- ccxt/ompfinex.py +22 -21
- ccxt/onetrading.py +213 -392
- ccxt/oxfun.py +245 -166
- ccxt/p2b.py +151 -29
- ccxt/paradex.py +562 -49
- ccxt/paymium.py +82 -19
- ccxt/phemex.py +712 -172
- ccxt/poloniex.py +1601 -283
- ccxt/pro/__init__.py +76 -17
- ccxt/pro/alpaca.py +21 -6
- ccxt/pro/apex.py +984 -0
- ccxt/pro/ascendex.py +58 -10
- ccxt/pro/bequant.py +6 -1
- ccxt/pro/binance.py +728 -156
- ccxt/pro/binancecoinm.py +6 -2
- ccxt/pro/binanceus.py +8 -4
- ccxt/pro/binanceusdm.py +7 -2
- ccxt/pro/bingx.py +333 -142
- ccxt/pro/bitfinex.py +727 -262
- ccxt/pro/bitget.py +570 -79
- ccxt/pro/bithumb.py +20 -6
- ccxt/pro/bitmart.py +216 -87
- ccxt/pro/bitmex.py +47 -9
- ccxt/pro/bitopro.py +26 -14
- ccxt/pro/bitrue.py +22 -22
- ccxt/pro/bitstamp.py +54 -21
- ccxt/pro/{huobijp.py → bittrade.py} +7 -6
- ccxt/pro/bitvavo.py +191 -67
- ccxt/pro/blockchaincom.py +21 -8
- ccxt/pro/blofin.py +9 -1
- ccxt/pro/bybit.py +632 -245
- ccxt/pro/cex.py +59 -24
- ccxt/pro/coinbase.py +102 -73
- ccxt/pro/coinbaseadvanced.py +2 -1
- ccxt/pro/coinbaseexchange.py +8 -8
- ccxt/pro/coinbaseinternational.py +181 -25
- ccxt/pro/coincatch.py +6 -7
- ccxt/pro/coincheck.py +11 -6
- ccxt/pro/coinex.py +967 -665
- ccxt/pro/coinone.py +16 -9
- ccxt/pro/cryptocom.py +448 -45
- ccxt/pro/defx.py +831 -0
- ccxt/pro/deribit.py +150 -14
- ccxt/pro/derive.py +704 -0
- ccxt/pro/exmo.py +239 -6
- ccxt/pro/gate.py +623 -65
- ccxt/pro/gateio.py +2 -1
- ccxt/pro/gemini.py +27 -11
- ccxt/pro/hashkey.py +2 -2
- ccxt/pro/hitbtc.py +196 -91
- ccxt/pro/hollaex.py +23 -7
- ccxt/pro/htx.py +51 -14
- ccxt/pro/huobi.py +2 -1
- ccxt/pro/hyperliquid.py +591 -27
- ccxt/pro/independentreserve.py +9 -6
- ccxt/pro/kraken.py +640 -320
- ccxt/pro/krakenfutures.py +62 -35
- ccxt/pro/kucoin.py +267 -46
- ccxt/pro/kucoinfutures.py +165 -21
- ccxt/pro/lbank.py +102 -21
- ccxt/pro/luno.py +12 -8
- ccxt/pro/mexc.py +877 -111
- ccxt/pro/modetrade.py +1271 -0
- ccxt/pro/myokx.py +38 -0
- ccxt/pro/ndax.py +15 -2
- ccxt/pro/okcoin.py +23 -4
- ccxt/pro/okx.py +573 -98
- ccxt/pro/okxus.py +38 -0
- ccxt/pro/onetrading.py +30 -13
- ccxt/pro/oxfun.py +131 -27
- ccxt/pro/p2b.py +88 -22
- ccxt/pro/paradex.py +3 -3
- ccxt/pro/phemex.py +75 -21
- ccxt/pro/poloniex.py +124 -41
- ccxt/pro/probit.py +87 -80
- ccxt/pro/tradeogre.py +272 -0
- ccxt/pro/upbit.py +152 -12
- ccxt/pro/vertex.py +8 -3
- ccxt/pro/whitebit.py +58 -5
- ccxt/pro/woo.py +228 -37
- ccxt/pro/woofipro.py +106 -18
- ccxt/pro/xt.py +111 -5
- ccxt/probit.py +224 -95
- ccxt/protobuf/__init__.py +0 -0
- ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
- ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
- ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
- ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
- ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
- ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
- ccxt/protobuf/mexc/__init__.py +0 -0
- ccxt/ramzinex.py +28 -25
- ccxt/sarmayex.py +7 -7
- ccxt/sarrafex.py +10 -10
- ccxt/static_dependencies/__init__.py +1 -1
- ccxt/static_dependencies/lark/py.typed +0 -0
- ccxt/static_dependencies/marshmallow/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
- ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
- ccxt/tabdeal.py +12 -11
- ccxt/test/tests_async.py +261 -57
- ccxt/test/tests_helpers.py +1 -3
- ccxt/test/tests_init.py +4 -3
- ccxt/test/tests_sync.py +261 -57
- ccxt/tetherland.py +7 -7
- ccxt/timex.py +210 -51
- ccxt/tokocrypto.py +167 -47
- ccxt/tradeogre.py +266 -31
- ccxt/twox.py +7 -7
- ccxt/ubitex.py +9 -9
- ccxt/upbit.py +568 -165
- ccxt/vertex.py +160 -32
- ccxt/wallex.py +9 -9
- ccxt/wavesexchange.py +165 -30
- ccxt/whitebit.py +975 -127
- ccxt/woo.py +1917 -1016
- ccxt/woofipro.py +432 -141
- ccxt/xt.py +649 -193
- ccxt/yobit.py +194 -70
- ccxt/zaif.py +91 -15
- ccxt/zonda.py +151 -36
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
- ccxt_ir-4.5.0.dist-info/RECORD +743 -0
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
- ccxt/__test__.py +0 -7
- ccxt/abstract/ace.py +0 -15
- ccxt/abstract/bitbay.py +0 -53
- ccxt/abstract/bitcoincom.py +0 -115
- ccxt/abstract/bitfinex2.py +0 -139
- ccxt/abstract/bitpanda.py +0 -35
- ccxt/abstract/bl3p.py +0 -19
- ccxt/abstract/coinlist.py +0 -54
- ccxt/abstract/currencycom.py +0 -68
- ccxt/abstract/hitbtc3.py +0 -115
- ccxt/abstract/idex.py +0 -26
- ccxt/abstract/kuna.py +0 -182
- ccxt/abstract/lykke.py +0 -29
- ccxt/abstract/poloniexfutures.py +0 -48
- ccxt/abstract/wazirx.py +0 -30
- ccxt/ace.py +0 -1012
- ccxt/async_support/ace.py +0 -1012
- ccxt/async_support/base/ws/aiohttp_client.py +0 -125
- ccxt/async_support/base/ws/fast_client.py +0 -96
- ccxt/async_support/bitbay.py +0 -17
- ccxt/async_support/bitcoincom.py +0 -17
- ccxt/async_support/bitfinex2.py +0 -3552
- ccxt/async_support/bitpanda.py +0 -16
- ccxt/async_support/bl3p.py +0 -485
- ccxt/async_support/coinlist.py +0 -2243
- ccxt/async_support/currencycom.py +0 -1950
- ccxt/async_support/hitbtc3.py +0 -16
- ccxt/async_support/idex.py +0 -1766
- ccxt/async_support/kuna.py +0 -1841
- ccxt/async_support/lykke.py +0 -1270
- ccxt/async_support/poloniexfutures.py +0 -1717
- ccxt/async_support/wazirx.py +0 -1224
- ccxt/bitbay.py +0 -17
- ccxt/bitcoincom.py +0 -17
- ccxt/bitfinex2.py +0 -3552
- ccxt/bitpanda.py +0 -16
- ccxt/bl3p.py +0 -485
- ccxt/coinlist.py +0 -2243
- ccxt/currencycom.py +0 -1950
- ccxt/hitbtc3.py +0 -16
- ccxt/idex.py +0 -1766
- ccxt/kuna.py +0 -1841
- ccxt/lykke.py +0 -1270
- ccxt/poloniexfutures.py +0 -1717
- ccxt/pro/bitcoincom.py +0 -34
- ccxt/pro/bitfinex2.py +0 -1083
- ccxt/pro/bitpanda.py +0 -15
- ccxt/pro/currencycom.py +0 -536
- ccxt/pro/idex.py +0 -672
- ccxt/pro/poloniexfutures.py +0 -990
- ccxt/pro/wazirx.py +0 -749
- ccxt/test/base/__init__.py +0 -29
- ccxt/test/base/test_account.py +0 -26
- ccxt/test/base/test_balance.py +0 -56
- ccxt/test/base/test_borrow_interest.py +0 -35
- ccxt/test/base/test_borrow_rate.py +0 -32
- ccxt/test/base/test_calculate_fee.py +0 -51
- ccxt/test/base/test_crypto.py +0 -127
- ccxt/test/base/test_currency.py +0 -76
- ccxt/test/base/test_datetime.py +0 -109
- ccxt/test/base/test_decimal_to_precision.py +0 -392
- ccxt/test/base/test_deep_extend.py +0 -68
- ccxt/test/base/test_deposit_withdrawal.py +0 -50
- ccxt/test/base/test_exchange_datetime_functions.py +0 -76
- ccxt/test/base/test_funding_rate_history.py +0 -29
- ccxt/test/base/test_last_price.py +0 -31
- ccxt/test/base/test_ledger_entry.py +0 -45
- ccxt/test/base/test_ledger_item.py +0 -48
- ccxt/test/base/test_leverage_tier.py +0 -33
- ccxt/test/base/test_liquidation.py +0 -50
- ccxt/test/base/test_margin_mode.py +0 -24
- ccxt/test/base/test_margin_modification.py +0 -35
- ccxt/test/base/test_market.py +0 -193
- ccxt/test/base/test_number.py +0 -411
- ccxt/test/base/test_ohlcv.py +0 -33
- ccxt/test/base/test_open_interest.py +0 -32
- ccxt/test/base/test_order.py +0 -64
- ccxt/test/base/test_order_book.py +0 -69
- ccxt/test/base/test_position.py +0 -60
- ccxt/test/base/test_shared_methods.py +0 -353
- ccxt/test/base/test_status.py +0 -24
- ccxt/test/base/test_throttle.py +0 -126
- ccxt/test/base/test_ticker.py +0 -92
- ccxt/test/base/test_trade.py +0 -47
- ccxt/test/base/test_trading_fee.py +0 -26
- ccxt/test/base/test_transaction.py +0 -39
- ccxt/test/test_async.py +0 -1649
- ccxt/test/test_sync.py +0 -1648
- ccxt/wazirx.py +0 -1224
- ccxt_ir-4.3.46.0.3.dist-info/RECORD +0 -773
- /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
- {ccxt_ir-4.3.46.0.3.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/bybit.py
CHANGED
|
@@ -6,15 +6,18 @@
|
|
|
6
6
|
from ccxt.base.exchange import Exchange
|
|
7
7
|
from ccxt.abstract.bybit import ImplicitAPI
|
|
8
8
|
import hashlib
|
|
9
|
-
from ccxt.base.types import Balances, CrossBorrowRate, Currencies, Currency, Greeks, Int, Leverage, LeverageTier, LeverageTiers,
|
|
9
|
+
from ccxt.base.types import Any, Balances, BorrowInterest, Conversion, CrossBorrowRate, Currencies, Currency, DepositAddress, FundingHistory, Greeks, Int, LedgerEntry, Leverage, LeverageTier, LeverageTiers, Liquidation, LongShortRatio, Market, Num, Option, OptionChain, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFeeInterface, TradingFees, Transaction, MarketInterface, TransferEntry
|
|
10
10
|
from typing import List
|
|
11
11
|
from ccxt.base.errors import ExchangeError
|
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
|
13
13
|
from ccxt.base.errors import PermissionDenied
|
|
14
|
+
from ccxt.base.errors import AccountSuspended
|
|
14
15
|
from ccxt.base.errors import ArgumentsRequired
|
|
15
16
|
from ccxt.base.errors import BadRequest
|
|
17
|
+
from ccxt.base.errors import BadSymbol
|
|
16
18
|
from ccxt.base.errors import NoChange
|
|
17
19
|
from ccxt.base.errors import MarginModeAlreadySet
|
|
20
|
+
from ccxt.base.errors import ManualInteractionNeeded
|
|
18
21
|
from ccxt.base.errors import InsufficientFunds
|
|
19
22
|
from ccxt.base.errors import InvalidOrder
|
|
20
23
|
from ccxt.base.errors import OrderNotFound
|
|
@@ -28,7 +31,7 @@ from ccxt.base.precise import Precise
|
|
|
28
31
|
|
|
29
32
|
class bybit(Exchange, ImplicitAPI):
|
|
30
33
|
|
|
31
|
-
def describe(self):
|
|
34
|
+
def describe(self) -> Any:
|
|
32
35
|
return self.deep_extend(super(bybit, self).describe(), {
|
|
33
36
|
'id': 'bybit',
|
|
34
37
|
'name': 'Bybit',
|
|
@@ -48,11 +51,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
48
51
|
'option': True,
|
|
49
52
|
'borrowCrossMargin': True,
|
|
50
53
|
'cancelAllOrders': True,
|
|
54
|
+
'cancelAllOrdersAfter': True,
|
|
51
55
|
'cancelOrder': True,
|
|
52
56
|
'cancelOrders': True,
|
|
53
57
|
'cancelOrdersForSymbols': True,
|
|
54
58
|
'closeAllPositions': False,
|
|
55
59
|
'closePosition': False,
|
|
60
|
+
'createConvertTrade': True,
|
|
56
61
|
'createMarketBuyOrderWithCost': True,
|
|
57
62
|
'createMarketSellOrderWithCost': True,
|
|
58
63
|
'createOrder': True,
|
|
@@ -68,7 +73,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
68
73
|
'createTrailingAmountOrder': True,
|
|
69
74
|
'createTriggerOrder': True,
|
|
70
75
|
'editOrder': True,
|
|
76
|
+
'editOrders': True,
|
|
77
|
+
'fetchAllGreeks': True,
|
|
71
78
|
'fetchBalance': True,
|
|
79
|
+
'fetchBidsAsks': 'emulated',
|
|
72
80
|
'fetchBorrowInterest': False, # temporarily disabled, doesn't work
|
|
73
81
|
'fetchBorrowRateHistories': False,
|
|
74
82
|
'fetchBorrowRateHistory': False,
|
|
@@ -76,6 +84,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
76
84
|
'fetchCanceledOrders': True,
|
|
77
85
|
'fetchClosedOrder': True,
|
|
78
86
|
'fetchClosedOrders': True,
|
|
87
|
+
'fetchConvertCurrencies': True,
|
|
88
|
+
'fetchConvertQuote': True,
|
|
89
|
+
'fetchConvertTrade': True,
|
|
90
|
+
'fetchConvertTradeHistory': True,
|
|
79
91
|
'fetchCrossBorrowRate': True,
|
|
80
92
|
'fetchCrossBorrowRates': False,
|
|
81
93
|
'fetchCurrencies': True,
|
|
@@ -87,7 +99,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
87
99
|
'fetchDepositWithdrawFee': 'emulated',
|
|
88
100
|
'fetchDepositWithdrawFees': True,
|
|
89
101
|
'fetchFundingHistory': True,
|
|
90
|
-
'fetchFundingRate':
|
|
102
|
+
'fetchFundingRate': 'emulated', # emulated in exchange
|
|
91
103
|
'fetchFundingRateHistory': True,
|
|
92
104
|
'fetchFundingRates': True,
|
|
93
105
|
'fetchGreeks': True,
|
|
@@ -97,6 +109,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
97
109
|
'fetchLedger': True,
|
|
98
110
|
'fetchLeverage': True,
|
|
99
111
|
'fetchLeverageTiers': True,
|
|
112
|
+
'fetchLongShortRatio': False,
|
|
113
|
+
'fetchLongShortRatioHistory': True,
|
|
100
114
|
'fetchMarginAdjustmentHistory': False,
|
|
101
115
|
'fetchMarketLeverageTiers': True,
|
|
102
116
|
'fetchMarkets': True,
|
|
@@ -111,7 +125,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
111
125
|
'fetchOpenOrders': True,
|
|
112
126
|
'fetchOption': True,
|
|
113
127
|
'fetchOptionChain': True,
|
|
114
|
-
'fetchOrder':
|
|
128
|
+
'fetchOrder': True,
|
|
115
129
|
'fetchOrderBook': True,
|
|
116
130
|
'fetchOrders': False,
|
|
117
131
|
'fetchOrderTrades': True,
|
|
@@ -163,7 +177,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
163
177
|
'public': 'https://api-testnet.{hostname}',
|
|
164
178
|
'private': 'https://api-testnet.{hostname}',
|
|
165
179
|
},
|
|
166
|
-
'logo': 'https://
|
|
180
|
+
'logo': 'https://github.com/user-attachments/assets/97a5d0b3-de10-423d-90e1-6620960025ed',
|
|
167
181
|
'api': {
|
|
168
182
|
'spot': 'https://api.{hostname}',
|
|
169
183
|
'futures': 'https://api.{hostname}',
|
|
@@ -243,16 +257,23 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
243
257
|
'v5/spot-lever-token/reference': 5,
|
|
244
258
|
# spot margin trade
|
|
245
259
|
'v5/spot-margin-trade/data': 5,
|
|
260
|
+
'v5/spot-margin-trade/collateral': 5,
|
|
246
261
|
'v5/spot-cross-margin-trade/data': 5,
|
|
247
262
|
'v5/spot-cross-margin-trade/pledge-token': 5,
|
|
248
263
|
'v5/spot-cross-margin-trade/borrow-token': 5,
|
|
264
|
+
# crypto loan
|
|
265
|
+
'v5/crypto-loan/collateral-data': 5,
|
|
266
|
+
'v5/crypto-loan/loanable-data': 5,
|
|
249
267
|
# institutional lending
|
|
250
268
|
'v5/ins-loan/product-infos': 5,
|
|
251
269
|
'v5/ins-loan/ensure-tokens-convert': 5,
|
|
270
|
+
# earn
|
|
271
|
+
'v5/earn/product': 5,
|
|
252
272
|
},
|
|
253
273
|
},
|
|
254
274
|
'private': {
|
|
255
275
|
'get': {
|
|
276
|
+
'v5/market/instruments-info': 5,
|
|
256
277
|
# Legacy inverse swap
|
|
257
278
|
'v2/private/wallet/fund/records': 25, # 120 per minute = 2 per second => cost = 50 / 2 = 25
|
|
258
279
|
# spot
|
|
@@ -340,7 +361,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
340
361
|
'v5/account/contract-transaction-log': 1,
|
|
341
362
|
'v5/account/smp-group': 1,
|
|
342
363
|
'v5/account/mmp-state': 5,
|
|
364
|
+
'v5/account/withdrawal': 5,
|
|
343
365
|
# asset
|
|
366
|
+
'v5/asset/exchange/query-coin-list': 0.5, # 100/s => cost = 50 / 100 = 0.5
|
|
367
|
+
'v5/asset/exchange/convert-result-query': 0.5, # 100/s => cost = 50 / 100 = 0.5
|
|
368
|
+
'v5/asset/exchange/query-convert-history': 0.5, # 100/s => cost = 50 / 100 = 0.5
|
|
344
369
|
'v5/asset/exchange/order-record': 5, # 10/s => cost = 50 / 10 = 5
|
|
345
370
|
'v5/asset/delivery-record': 5,
|
|
346
371
|
'v5/asset/settlement-record': 5,
|
|
@@ -369,14 +394,24 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
369
394
|
'v5/user/aff-customer-info': 5,
|
|
370
395
|
'v5/user/del-submember': 5,
|
|
371
396
|
'v5/user/submembers': 5,
|
|
397
|
+
# affilate
|
|
398
|
+
'v5/affiliate/aff-user-list': 5,
|
|
372
399
|
# spot leverage token
|
|
373
400
|
'v5/spot-lever-token/order-record': 1, # 50/s => cost = 50 / 50 = 1
|
|
374
401
|
# spot margin trade
|
|
402
|
+
'v5/spot-margin-trade/interest-rate-history': 5,
|
|
375
403
|
'v5/spot-margin-trade/state': 5,
|
|
376
404
|
'v5/spot-cross-margin-trade/loan-info': 1, # 50/s => cost = 50 / 50 = 1
|
|
377
405
|
'v5/spot-cross-margin-trade/account': 1, # 50/s => cost = 50 / 50 = 1
|
|
378
406
|
'v5/spot-cross-margin-trade/orders': 1, # 50/s => cost = 50 / 50 = 1
|
|
379
407
|
'v5/spot-cross-margin-trade/repay-history': 1, # 50/s => cost = 50 / 50 = 1
|
|
408
|
+
# crypto loan
|
|
409
|
+
'v5/crypto-loan/borrowable-collateralisable-number': 5,
|
|
410
|
+
'v5/crypto-loan/ongoing-orders': 5,
|
|
411
|
+
'v5/crypto-loan/repayment-history': 5,
|
|
412
|
+
'v5/crypto-loan/borrow-history': 5,
|
|
413
|
+
'v5/crypto-loan/max-collateral-amount': 5,
|
|
414
|
+
'v5/crypto-loan/adjustment-history': 5,
|
|
380
415
|
# institutional lending
|
|
381
416
|
'v5/ins-loan/product-infos': 5,
|
|
382
417
|
'v5/ins-loan/ensure-tokens-convert': 5,
|
|
@@ -388,27 +423,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
388
423
|
'v5/lending/history-order': 5,
|
|
389
424
|
'v5/lending/account': 5,
|
|
390
425
|
# broker
|
|
391
|
-
'v5/broker/earning-record': 5,
|
|
426
|
+
'v5/broker/earning-record': 5, # deprecated
|
|
392
427
|
'v5/broker/earnings-info': 5,
|
|
393
428
|
'v5/broker/account-info': 5,
|
|
394
429
|
'v5/broker/asset/query-sub-member-deposit-record': 10,
|
|
430
|
+
# earn
|
|
431
|
+
'v5/earn/order': 5,
|
|
432
|
+
'v5/earn/position': 5,
|
|
395
433
|
},
|
|
396
434
|
'post': {
|
|
397
|
-
# Legacy option USDC
|
|
398
|
-
'option/usdc/openapi/private/v1/place-order': 2.5,
|
|
399
|
-
'option/usdc/openapi/private/v1/replace-order': 2.5,
|
|
400
|
-
'option/usdc/openapi/private/v1/cancel-order': 2.5,
|
|
401
|
-
'option/usdc/openapi/private/v1/cancel-all': 2.5,
|
|
402
|
-
'option/usdc/openapi/private/v1/query-active-orders': 2.5,
|
|
403
|
-
'option/usdc/openapi/private/v1/query-order-history': 2.5,
|
|
404
|
-
'option/usdc/openapi/private/v1/execution-list': 2.5,
|
|
405
|
-
'option/usdc/openapi/private/v1/query-position': 2.5,
|
|
406
|
-
# Legacy perpetual swap USDC
|
|
407
|
-
'perpetual/usdc/openapi/private/v1/place-order': 2.5,
|
|
408
|
-
'perpetual/usdc/openapi/private/v1/replace-order': 2.5,
|
|
409
|
-
'perpetual/usdc/openapi/private/v1/cancel-order': 2.5,
|
|
410
|
-
'perpetual/usdc/openapi/private/v1/cancel-all': 2.5,
|
|
411
|
-
'perpetual/usdc/openapi/private/v1/position/leverage/save': 2.5,
|
|
412
435
|
# spot
|
|
413
436
|
'spot/v3/private/order': 2.5,
|
|
414
437
|
'spot/v3/private/cancel-order': 2.5,
|
|
@@ -499,6 +522,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
499
522
|
'v5/account/mmp-modify': 5,
|
|
500
523
|
'v5/account/mmp-reset': 5,
|
|
501
524
|
# asset
|
|
525
|
+
'v5/asset/exchange/quote-apply': 1, # 50/s
|
|
526
|
+
'v5/asset/exchange/convert-execute': 1, # 50/s
|
|
502
527
|
'v5/asset/transfer/inter-transfer': 50, # 1/s => cost = 50 / 1 = 50
|
|
503
528
|
'v5/asset/transfer/save-transfer-sub-member': 150, # 1/3/s => cost = 50 / 1/3 = 150
|
|
504
529
|
'v5/asset/transfer/universal-transfer': 10, # 5/s => cost = 50 / 5 = 10
|
|
@@ -522,6 +547,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
522
547
|
'v5/spot-cross-margin-trade/loan': 2.5, # 20/s => cost = 50 / 20 = 2.5
|
|
523
548
|
'v5/spot-cross-margin-trade/repay': 2.5, # 20/s => cost = 50 / 20 = 2.5
|
|
524
549
|
'v5/spot-cross-margin-trade/switch': 2.5, # 20/s => cost = 50 / 20 = 2.5
|
|
550
|
+
# crypto loan
|
|
551
|
+
'v5/crypto-loan/borrow': 5,
|
|
552
|
+
'v5/crypto-loan/repay': 5,
|
|
553
|
+
'v5/crypto-loan/adjust-ltv': 5,
|
|
525
554
|
# institutional lending
|
|
526
555
|
'v5/ins-loan/association-uid': 5,
|
|
527
556
|
# c2c lending
|
|
@@ -532,6 +561,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
532
561
|
'v5/account/set-collateral-switch-batch': 5,
|
|
533
562
|
# demo trading
|
|
534
563
|
'v5/account/demo-apply-money': 5,
|
|
564
|
+
# broker
|
|
565
|
+
'v5/broker/award/info': 5,
|
|
566
|
+
'v5/broker/award/distribute-award': 5,
|
|
567
|
+
'v5/broker/award/distribution-record': 5,
|
|
568
|
+
# earn
|
|
569
|
+
'v5/earn/place-order': 5,
|
|
535
570
|
},
|
|
536
571
|
},
|
|
537
572
|
},
|
|
@@ -565,7 +600,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
565
600
|
'10005': PermissionDenied, # permission denied for current apikey
|
|
566
601
|
'10006': RateLimitExceeded, # too many requests
|
|
567
602
|
'10007': AuthenticationError, # api_key not found in your request parameters
|
|
568
|
-
'10008':
|
|
603
|
+
'10008': AccountSuspended, # User had been banned
|
|
569
604
|
'10009': AuthenticationError, # IP had been banned
|
|
570
605
|
'10010': PermissionDenied, # request ip mismatch
|
|
571
606
|
'10014': BadRequest, # Request is duplicate
|
|
@@ -653,6 +688,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
653
688
|
'110071': ExchangeError, # Sorry, we're revamping the Unified Margin Account! Currently, new upgrades are not supported. If you have any questions, please contact our 24/7 customer support.
|
|
654
689
|
'110072': InvalidOrder, # OrderLinkedID is duplicate
|
|
655
690
|
'110073': ExchangeError, # Set margin mode failed
|
|
691
|
+
'110092': InvalidOrder, # expect Rising, but trigger_price[XXXXX] <= current[XXXXX]
|
|
692
|
+
'110093': InvalidOrder, # expect Falling, but trigger_price[XXXXX] >= current[XXXXX]
|
|
693
|
+
'110094': InvalidOrder, # Order notional value below the lower limit
|
|
656
694
|
'130006': InvalidOrder, # {"ret_code":130006,"ret_msg":"The number of contracts exceeds maximum limit allowed: too large","ext_code":"","ext_info":"","result":null,"time_now":"1658397095.099030","rate_limit_status":99,"rate_limit_reset_ms":1658397095097,"rate_limit":100}
|
|
657
695
|
'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} | {"ret_code":130021,"ret_msg":"oc_diff[1707966351], new_oc[1707966351] with ob[....]+AB[....]","ext_code":"","ext_info":"","result":null,"time_now":"1658395300.872766","rate_limit_status":99,"rate_limit_reset_ms":1658395300855,"rate_limit":100} caused issues/9149#issuecomment-1146559498
|
|
658
696
|
'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}
|
|
@@ -765,8 +803,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
765
803
|
'140069': PermissionDenied, # Do not allow OTC lending users to trade
|
|
766
804
|
'140070': InvalidOrder, # ETP symbols are not allowed to be traded
|
|
767
805
|
'170001': ExchangeError, # Internal error.
|
|
768
|
-
'170007': RequestTimeout, # Timeout waiting for response from backend server.
|
|
769
806
|
'170005': InvalidOrder, # Too many new orders; current limit is %s orders per %s.
|
|
807
|
+
'170007': RequestTimeout, # Timeout waiting for response from backend server.
|
|
808
|
+
'170010': InvalidOrder, # Purchase failed: Exceed the maximum position limit of leveraged tokens, the current available limit is %s USDT
|
|
809
|
+
'170011': InvalidOrder, # "Purchase failed: Exceed the maximum position limit of innovation tokens,
|
|
810
|
+
'170019': InvalidOrder, # the current available limit is replaceKey0 USDT"
|
|
770
811
|
'170031': ExchangeError, # The feature has been suspended
|
|
771
812
|
'170032': ExchangeError, # Network error. Please try again later
|
|
772
813
|
'170033': InsufficientFunds, # margin Insufficient account balance
|
|
@@ -779,6 +820,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
779
820
|
'170116': InvalidOrder, # Invalid orderType.
|
|
780
821
|
'170117': InvalidOrder, # Invalid side.
|
|
781
822
|
'170121': InvalidOrder, # Invalid symbol.
|
|
823
|
+
'170124': InvalidOrder, # Order amount too large.
|
|
782
824
|
'170130': BadRequest, # Data sent for paramter '%s' is not valid.
|
|
783
825
|
'170131': InsufficientFunds, # Balance insufficient
|
|
784
826
|
'170132': InvalidOrder, # Order price too high.
|
|
@@ -789,7 +831,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
789
831
|
'170137': InvalidOrder, # Order volume decimal too long
|
|
790
832
|
'170139': InvalidOrder, # Order has been filled.
|
|
791
833
|
'170140': InvalidOrder, # Transaction amount lower than the minimum.
|
|
792
|
-
'170124': InvalidOrder, # Order amount too large.
|
|
793
834
|
'170141': InvalidOrder, # Duplicate clientOrderId
|
|
794
835
|
'170142': InvalidOrder, # Order has been canceled
|
|
795
836
|
'170143': InvalidOrder, # Cannot be found on order book
|
|
@@ -814,6 +855,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
814
855
|
'170198': InvalidOrder, # Your order quantity to sell is too large. The filled price may deviate significantly from the market price. Please try again
|
|
815
856
|
'170199': InvalidOrder, # Your order quantity to buy is too large. The filled price may deviate significantly from the nav. Please try again.
|
|
816
857
|
'170200': InvalidOrder, # Your order quantity to sell is too large. The filled price may deviate significantly from the nav. Please try again.
|
|
858
|
+
'170201': PermissionDenied, # Your account has been restricted for trades. If you have any questions, please email us at support@bybit.com
|
|
859
|
+
'170202': InvalidOrder, # Invalid orderFilter parameter.
|
|
860
|
+
'170203': InvalidOrder, # Please enter the TP/SL price.
|
|
861
|
+
'170204': InvalidOrder, # trigger price cannot be higher than 110% price.
|
|
862
|
+
'170206': InvalidOrder, # trigger price cannot be lower than 90% of qty.
|
|
863
|
+
'170210': InvalidOrder, # New order rejected.
|
|
864
|
+
'170213': OrderNotFound, # Order does not exist.
|
|
865
|
+
'170217': InvalidOrder, # Only LIMIT-MAKER order is supported for the current pair.
|
|
866
|
+
'170218': InvalidOrder, # The LIMIT-MAKER order is rejected due to invalid price.
|
|
817
867
|
'170221': BadRequest, # This coin does not exist.
|
|
818
868
|
'170222': RateLimitExceeded, # Too many hasattr(self, requests) time frame.
|
|
819
869
|
'170223': InsufficientFunds, # Your Spot Account with Institutional Lending triggers an alert or liquidation.
|
|
@@ -823,18 +873,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
823
873
|
'170228': InvalidOrder, # The purchase amount of each order exceeds the estimated maximum purchase amount.
|
|
824
874
|
'170229': InvalidOrder, # The sell quantity per order exceeds the estimated maximum sell quantity.
|
|
825
875
|
'170234': ExchangeError, # System Error
|
|
826
|
-
'
|
|
827
|
-
'170213': OrderNotFound, # Order does not exist.
|
|
828
|
-
'170217': InvalidOrder, # Only LIMIT-MAKER order is supported for the current pair.
|
|
829
|
-
'170218': InvalidOrder, # The LIMIT-MAKER order is rejected due to invalid price.
|
|
830
|
-
'170010': InvalidOrder, # Purchase failed: Exceed the maximum position limit of leveraged tokens, the current available limit is %s USDT
|
|
831
|
-
'170011': InvalidOrder, # "Purchase failed: Exceed the maximum position limit of innovation tokens,
|
|
832
|
-
'170019': InvalidOrder, # the current available limit is replaceKey0 USDT"
|
|
833
|
-
'170201': PermissionDenied, # Your account has been restricted for trades. If you have any questions, please email us at support@bybit.com
|
|
834
|
-
'170202': InvalidOrder, # Invalid orderFilter parameter.
|
|
835
|
-
'170203': InvalidOrder, # Please enter the TP/SL price.
|
|
836
|
-
'170204': InvalidOrder, # trigger price cannot be higher than 110% price.
|
|
837
|
-
'170206': InvalidOrder, # trigger price cannot be lower than 90% of qty.
|
|
876
|
+
'170241': ManualInteractionNeeded, # To proceed with trading, users must read through and confirm that they fully understand the project's risk disclosure document.
|
|
838
877
|
'175000': InvalidOrder, # The serialNum is already in use.
|
|
839
878
|
'175001': InvalidOrder, # Daily purchase limit has been exceeded. Please try again later.
|
|
840
879
|
'175002': InvalidOrder, # There's a large number of purchase orders. Please try again later.
|
|
@@ -987,6 +1026,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
987
1026
|
'3200300': InsufficientFunds, # {"retCode":3200300,"retMsg":"Insufficient margin balance.","result":null,"retExtMap":{}}
|
|
988
1027
|
},
|
|
989
1028
|
'broad': {
|
|
1029
|
+
'Not supported symbols': BadSymbol, # {"retCode":10001,"retMsg":"Not supported symbols","result":{},"retExtInfo":{},"time":1726147060461}
|
|
990
1030
|
'Request timeout': RequestTimeout, # {"retCode":10016,"retMsg":"Request timeout, please try again later","result":{},"retExtInfo":{},"time":1675307914985}
|
|
991
1031
|
'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}
|
|
992
1032
|
'invalid api_key': AuthenticationError, # {"ret_code":10003,"ret_msg":"invalid api_key","ext_code":"","ext_info":"","result":null,"time_now":"1599547085.415797"}
|
|
@@ -998,15 +1038,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
998
1038
|
},
|
|
999
1039
|
'precisionMode': TICK_SIZE,
|
|
1000
1040
|
'options': {
|
|
1001
|
-
'
|
|
1041
|
+
'usePrivateInstrumentsInfo': False,
|
|
1002
1042
|
'enableDemoTrading': False,
|
|
1003
|
-
'fetchMarkets':
|
|
1004
|
-
|
|
1005
|
-
'method': 'privatePostV5OrderCreate', # 'privatePostV5PositionTradingStop'
|
|
1043
|
+
'fetchMarkets': {
|
|
1044
|
+
'types': ['spot', 'linear', 'inverse', 'option'],
|
|
1006
1045
|
},
|
|
1007
1046
|
'enableUnifiedMargin': None,
|
|
1008
1047
|
'enableUnifiedAccount': None,
|
|
1009
|
-
'
|
|
1048
|
+
'unifiedMarginStatus': None,
|
|
1049
|
+
'createMarketBuyOrderRequiresPrice': False, # only True for classic accounts
|
|
1010
1050
|
'createUnifiedMarginAccount': False,
|
|
1011
1051
|
'defaultType': 'swap', # 'swap', 'future', 'option', 'spot'
|
|
1012
1052
|
'defaultSubType': 'linear', # 'linear', 'inverse'
|
|
@@ -1043,8 +1083,78 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1043
1083
|
'ERC20': 'ETH',
|
|
1044
1084
|
'TRC20': 'TRX',
|
|
1045
1085
|
'BEP20': 'BSC',
|
|
1086
|
+
'SOL': 'SOL',
|
|
1087
|
+
'ACA': 'ACA',
|
|
1088
|
+
'ADA': 'ADA',
|
|
1089
|
+
'ALGO': 'ALGO',
|
|
1090
|
+
'APT': 'APTOS',
|
|
1091
|
+
'AR': 'AR',
|
|
1092
|
+
'ARBONE': 'ARBI',
|
|
1093
|
+
'AVAXC': 'CAVAX',
|
|
1094
|
+
'AVAXX': 'XAVAX',
|
|
1095
|
+
'ATOM': 'ATOM',
|
|
1096
|
+
'BCH': 'BCH',
|
|
1097
|
+
'BEP2': 'BNB',
|
|
1098
|
+
'CHZ': 'CHZ',
|
|
1099
|
+
'DCR': 'DCR',
|
|
1100
|
+
'DGB': 'DGB',
|
|
1101
|
+
'DOGE': 'DOGE',
|
|
1102
|
+
'DOT': 'DOT',
|
|
1103
|
+
'EGLD': 'EGLD',
|
|
1104
|
+
'EOS': 'EOS',
|
|
1105
|
+
'ETC': 'ETC',
|
|
1106
|
+
'ETHF': 'ETHF',
|
|
1107
|
+
'ETHW': 'ETHW',
|
|
1108
|
+
'FIL': 'FIL',
|
|
1109
|
+
'STEP': 'FITFI',
|
|
1110
|
+
'FLOW': 'FLOW',
|
|
1111
|
+
'FTM': 'FTM',
|
|
1112
|
+
'GLMR': 'GLMR',
|
|
1113
|
+
'HBAR': 'HBAR',
|
|
1114
|
+
'HNT': 'HNT',
|
|
1115
|
+
'ICP': 'ICP',
|
|
1116
|
+
'ICX': 'ICX',
|
|
1117
|
+
'KDA': 'KDA',
|
|
1118
|
+
'KLAY': 'KLAY',
|
|
1119
|
+
'KMA': 'KMA',
|
|
1120
|
+
'KSM': 'KSM',
|
|
1121
|
+
'LTC': 'LTC',
|
|
1122
|
+
# 'TERRA': 'LUNANEW',
|
|
1123
|
+
# 'TERRACLASSIC': 'LUNA',
|
|
1124
|
+
'MATIC': 'MATIC',
|
|
1125
|
+
'MINA': 'MINA',
|
|
1126
|
+
'MOVR': 'MOVR',
|
|
1127
|
+
'NEAR': 'NEAR',
|
|
1128
|
+
'NEM': 'NEM',
|
|
1129
|
+
'OASYS': 'OAS',
|
|
1130
|
+
'OASIS': 'ROSE',
|
|
1046
1131
|
'OMNI': 'OMNI',
|
|
1047
|
-
'
|
|
1132
|
+
'ONE': 'ONE',
|
|
1133
|
+
'OPTIMISM': 'OP',
|
|
1134
|
+
'POKT': 'POKT',
|
|
1135
|
+
'QTUM': 'QTUM',
|
|
1136
|
+
'RVN': 'RVN',
|
|
1137
|
+
'SC': 'SC',
|
|
1138
|
+
'SCRT': 'SCRT',
|
|
1139
|
+
'STX': 'STX',
|
|
1140
|
+
'THETA': 'THETA',
|
|
1141
|
+
'TON': 'TON',
|
|
1142
|
+
'WAVES': 'WAVES',
|
|
1143
|
+
'WAX': 'WAXP',
|
|
1144
|
+
'XDC': 'XDC',
|
|
1145
|
+
'XEC': 'XEC',
|
|
1146
|
+
'XLM': 'XLM',
|
|
1147
|
+
'XRP': 'XRP',
|
|
1148
|
+
'XTZ': 'XTZ',
|
|
1149
|
+
'XYM': 'XYM',
|
|
1150
|
+
'ZEN': 'ZEN',
|
|
1151
|
+
'ZIL': 'ZIL',
|
|
1152
|
+
'ZKSYNC': 'ZKSYNC',
|
|
1153
|
+
# todo: uncomment after consensus
|
|
1154
|
+
# 'CADUCEUS': 'CMP',
|
|
1155
|
+
# 'KON': 'KON', # konpay, "konchain"
|
|
1156
|
+
# 'AURORA': 'AURORA',
|
|
1157
|
+
# 'BITCOINGOLD': 'BTG',
|
|
1048
1158
|
},
|
|
1049
1159
|
'networksById': {
|
|
1050
1160
|
'ETH': 'ERC20',
|
|
@@ -1065,6 +1175,113 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1065
1175
|
'4h': '4h',
|
|
1066
1176
|
'1d': '1d',
|
|
1067
1177
|
},
|
|
1178
|
+
'useMarkPriceForPositionCollateral': False, # use mark price for position collateral
|
|
1179
|
+
},
|
|
1180
|
+
'features': {
|
|
1181
|
+
'default': {
|
|
1182
|
+
'sandbox': True,
|
|
1183
|
+
'createOrder': {
|
|
1184
|
+
'marginMode': False,
|
|
1185
|
+
'triggerPrice': True,
|
|
1186
|
+
'triggerPriceType': {
|
|
1187
|
+
'last': True,
|
|
1188
|
+
'mark': True,
|
|
1189
|
+
'index': True,
|
|
1190
|
+
},
|
|
1191
|
+
'triggerDirection': True,
|
|
1192
|
+
'stopLossPrice': True,
|
|
1193
|
+
'takeProfitPrice': True,
|
|
1194
|
+
'attachedStopLossTakeProfit': {
|
|
1195
|
+
'triggerPriceType': {
|
|
1196
|
+
'last': True,
|
|
1197
|
+
'mark': True,
|
|
1198
|
+
'index': True,
|
|
1199
|
+
},
|
|
1200
|
+
'price': True,
|
|
1201
|
+
},
|
|
1202
|
+
'timeInForce': {
|
|
1203
|
+
'IOC': True,
|
|
1204
|
+
'FOK': True,
|
|
1205
|
+
'PO': True,
|
|
1206
|
+
'GTD': False,
|
|
1207
|
+
},
|
|
1208
|
+
'hedged': True,
|
|
1209
|
+
'selfTradePrevention': True, # todo: implement
|
|
1210
|
+
'trailing': True,
|
|
1211
|
+
'iceberg': False,
|
|
1212
|
+
'leverage': False,
|
|
1213
|
+
'marketBuyRequiresPrice': False,
|
|
1214
|
+
'marketBuyByCost': True,
|
|
1215
|
+
},
|
|
1216
|
+
'createOrders': {
|
|
1217
|
+
'max': 10,
|
|
1218
|
+
},
|
|
1219
|
+
'fetchMyTrades': {
|
|
1220
|
+
'marginMode': False,
|
|
1221
|
+
'limit': 100,
|
|
1222
|
+
'daysBack': 365 * 2, # 2 years
|
|
1223
|
+
'untilDays': 7, # days between start-end
|
|
1224
|
+
'symbolRequired': False,
|
|
1225
|
+
},
|
|
1226
|
+
'fetchOrder': {
|
|
1227
|
+
'marginMode': False,
|
|
1228
|
+
'trigger': True,
|
|
1229
|
+
'trailing': False,
|
|
1230
|
+
'symbolRequired': True,
|
|
1231
|
+
},
|
|
1232
|
+
'fetchOpenOrders': {
|
|
1233
|
+
'marginMode': False,
|
|
1234
|
+
'limit': 50,
|
|
1235
|
+
'trigger': True,
|
|
1236
|
+
'trailing': False,
|
|
1237
|
+
'symbolRequired': False,
|
|
1238
|
+
},
|
|
1239
|
+
'fetchOrders': None,
|
|
1240
|
+
'fetchClosedOrders': {
|
|
1241
|
+
'marginMode': False,
|
|
1242
|
+
'limit': 50,
|
|
1243
|
+
'daysBack': 365 * 2, # 2 years
|
|
1244
|
+
'daysBackCanceled': 1,
|
|
1245
|
+
'untilDays': 7,
|
|
1246
|
+
'trigger': True,
|
|
1247
|
+
'trailing': False,
|
|
1248
|
+
'symbolRequired': False,
|
|
1249
|
+
},
|
|
1250
|
+
'fetchOHLCV': {
|
|
1251
|
+
'limit': 1000,
|
|
1252
|
+
},
|
|
1253
|
+
'editOrders': {
|
|
1254
|
+
'max': 10,
|
|
1255
|
+
},
|
|
1256
|
+
},
|
|
1257
|
+
'spot': {
|
|
1258
|
+
'extends': 'default',
|
|
1259
|
+
'createOrder': {
|
|
1260
|
+
'triggerPriceType': None,
|
|
1261
|
+
'triggerDirection': False,
|
|
1262
|
+
'attachedStopLossTakeProfit': {
|
|
1263
|
+
'triggerPriceType': None,
|
|
1264
|
+
'price': True,
|
|
1265
|
+
},
|
|
1266
|
+
'marketBuyRequiresPrice': True,
|
|
1267
|
+
},
|
|
1268
|
+
},
|
|
1269
|
+
'swap': {
|
|
1270
|
+
'linear': {
|
|
1271
|
+
'extends': 'default',
|
|
1272
|
+
},
|
|
1273
|
+
'inverse': {
|
|
1274
|
+
'extends': 'default',
|
|
1275
|
+
},
|
|
1276
|
+
},
|
|
1277
|
+
'future': {
|
|
1278
|
+
'linear': {
|
|
1279
|
+
'extends': 'default',
|
|
1280
|
+
},
|
|
1281
|
+
'inverse': {
|
|
1282
|
+
'extends': 'default',
|
|
1283
|
+
},
|
|
1284
|
+
},
|
|
1068
1285
|
},
|
|
1069
1286
|
'fees': {
|
|
1070
1287
|
'trading': {
|
|
@@ -1083,21 +1300,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1083
1300
|
},
|
|
1084
1301
|
})
|
|
1085
1302
|
|
|
1086
|
-
def set_sandbox_mode(self, enable: bool):
|
|
1087
|
-
"""
|
|
1088
|
-
enables or disables sandbox mode
|
|
1089
|
-
:param boolean [enable]: True if demo trading should be enabled, False otherwise
|
|
1090
|
-
"""
|
|
1091
|
-
super(bybit, self).set_sandbox_mode(enable)
|
|
1092
|
-
self.options['sandboxMode'] = enable
|
|
1093
|
-
|
|
1094
1303
|
def enable_demo_trading(self, enable: bool):
|
|
1095
1304
|
"""
|
|
1096
1305
|
enables or disables demo trading mode
|
|
1097
|
-
|
|
1306
|
+
https://bybit-exchange.github.io/docs/v5/demo
|
|
1098
1307
|
:param boolean [enable]: True if demo trading should be enabled, False otherwise
|
|
1099
1308
|
"""
|
|
1100
|
-
if self.
|
|
1309
|
+
if self.isSandboxModeEnabled:
|
|
1101
1310
|
raise NotSupported(self.id + ' demo trading does not support in sandbox environment')
|
|
1102
1311
|
# enable demo trading in bybit, see: https://bybit-exchange.github.io/docs/v5/demo
|
|
1103
1312
|
if enable:
|
|
@@ -1114,7 +1323,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1114
1323
|
|
|
1115
1324
|
def add_pagination_cursor_to_result(self, response):
|
|
1116
1325
|
result = self.safe_dict(response, 'result', {})
|
|
1117
|
-
data = self.
|
|
1326
|
+
data = self.safe_list_n(result, ['list', 'rows', 'data', 'dataList'], [])
|
|
1118
1327
|
paginationCursor = self.safe_string_2(result, 'nextPageCursor', 'cursor')
|
|
1119
1328
|
dataLength = len(data)
|
|
1120
1329
|
if (paginationCursor is not None) and (dataLength > 0):
|
|
@@ -1125,9 +1334,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1125
1334
|
|
|
1126
1335
|
def is_unified_enabled(self, params={}):
|
|
1127
1336
|
"""
|
|
1337
|
+
|
|
1338
|
+
https://bybit-exchange.github.io/docs/v5/user/apikey-info#http-request
|
|
1339
|
+
https://bybit-exchange.github.io/docs/v5/account/account-info
|
|
1340
|
+
|
|
1128
1341
|
returns [enableUnifiedMargin, enableUnifiedAccount] so the user can check if unified account is enabled
|
|
1342
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1343
|
+
:returns any: [enableUnifiedMargin, enableUnifiedAccount]
|
|
1129
1344
|
"""
|
|
1130
|
-
# The API key of user id must own one of permissions will be allowed to call following API endpoints
|
|
1345
|
+
# The API key of user id must own one of permissions will be allowed to call following API endpoints:
|
|
1131
1346
|
# SUB UID: "Account Transfer"
|
|
1132
1347
|
# MASTER UID: "Account Transfer", "Subaccount Transfer", "Withdrawal"
|
|
1133
1348
|
enableUnifiedMargin = self.safe_bool(self.options, 'enableUnifiedMargin')
|
|
@@ -1138,8 +1353,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1138
1353
|
# so we're assuming UTA is enabled
|
|
1139
1354
|
self.options['enableUnifiedMargin'] = False
|
|
1140
1355
|
self.options['enableUnifiedAccount'] = True
|
|
1356
|
+
self.options['unifiedMarginStatus'] = 6
|
|
1141
1357
|
return [self.options['enableUnifiedMargin'], self.options['enableUnifiedAccount']]
|
|
1142
|
-
|
|
1358
|
+
rawPromises = [self.privateGetV5UserQueryApi(params), self.privateGetV5AccountInfo(params)]
|
|
1359
|
+
promises = rawPromises
|
|
1360
|
+
response = promises[0]
|
|
1361
|
+
accountInfo = promises[1]
|
|
1143
1362
|
#
|
|
1144
1363
|
# {
|
|
1145
1364
|
# "retCode": 0,
|
|
@@ -1179,19 +1398,44 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1179
1398
|
# "retExtInfo": {},
|
|
1180
1399
|
# "time": 1676891757649
|
|
1181
1400
|
# }
|
|
1401
|
+
# account info
|
|
1402
|
+
# {
|
|
1403
|
+
# "retCode": 0,
|
|
1404
|
+
# "retMsg": "OK",
|
|
1405
|
+
# "result": {
|
|
1406
|
+
# "marginMode": "REGULAR_MARGIN",
|
|
1407
|
+
# "updatedTime": "1697078946000",
|
|
1408
|
+
# "unifiedMarginStatus": 4,
|
|
1409
|
+
# "dcpStatus": "OFF",
|
|
1410
|
+
# "timeWindow": 10,
|
|
1411
|
+
# "smpGroup": 0,
|
|
1412
|
+
# "isMasterTrader": False,
|
|
1413
|
+
# "spotHedgingStatus": "OFF"
|
|
1414
|
+
# }
|
|
1415
|
+
# }
|
|
1182
1416
|
#
|
|
1183
1417
|
result = self.safe_dict(response, 'result', {})
|
|
1418
|
+
accountResult = self.safe_dict(accountInfo, 'result', {})
|
|
1184
1419
|
self.options['enableUnifiedMargin'] = self.safe_integer(result, 'unified') == 1
|
|
1185
1420
|
self.options['enableUnifiedAccount'] = self.safe_integer(result, 'uta') == 1
|
|
1421
|
+
self.options['unifiedMarginStatus'] = self.safe_integer(accountResult, 'unifiedMarginStatus', 6) # default to uta 2.0 pro if not found
|
|
1186
1422
|
return [self.options['enableUnifiedMargin'], self.options['enableUnifiedAccount']]
|
|
1187
1423
|
|
|
1188
1424
|
def upgrade_unified_trade_account(self, params={}):
|
|
1425
|
+
"""
|
|
1426
|
+
upgrades the account to unified trade account *warning* self is irreversible
|
|
1427
|
+
|
|
1428
|
+
https://bybit-exchange.github.io/docs/v5/account/upgrade-unified-account
|
|
1429
|
+
|
|
1430
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1431
|
+
:returns any: nothing
|
|
1432
|
+
"""
|
|
1189
1433
|
return self.privatePostV5AccountUpgradeToUta(params)
|
|
1190
1434
|
|
|
1191
1435
|
def create_expired_option_market(self, symbol: str):
|
|
1192
1436
|
# support expired option contracts
|
|
1193
|
-
quote =
|
|
1194
|
-
settle =
|
|
1437
|
+
quote = None
|
|
1438
|
+
settle = None
|
|
1195
1439
|
optionParts = symbol.split('-')
|
|
1196
1440
|
symbolBase = symbol.split('/')
|
|
1197
1441
|
base = None
|
|
@@ -1199,13 +1443,36 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1199
1443
|
if symbol.find('/') > -1:
|
|
1200
1444
|
base = self.safe_string(symbolBase, 0)
|
|
1201
1445
|
expiry = self.safe_string(optionParts, 1)
|
|
1446
|
+
symbolQuoteAndSettle = self.safe_string(symbolBase, 1)
|
|
1447
|
+
splitQuote = symbolQuoteAndSettle.split(':')
|
|
1448
|
+
quoteAndSettle = self.safe_string(splitQuote, 0)
|
|
1449
|
+
quote = quoteAndSettle
|
|
1450
|
+
settle = quoteAndSettle
|
|
1202
1451
|
else:
|
|
1203
1452
|
base = self.safe_string(optionParts, 0)
|
|
1204
1453
|
expiry = self.convert_market_id_expire_date(self.safe_string(optionParts, 1))
|
|
1454
|
+
if symbol.endswith('-USDT'):
|
|
1455
|
+
quote = 'USDT'
|
|
1456
|
+
settle = 'USDT'
|
|
1457
|
+
else:
|
|
1458
|
+
quote = 'USDC'
|
|
1459
|
+
settle = 'USDC'
|
|
1205
1460
|
strike = self.safe_string(optionParts, 2)
|
|
1206
1461
|
optionType = self.safe_string(optionParts, 3)
|
|
1207
1462
|
datetime = self.convert_expire_date(expiry)
|
|
1208
1463
|
timestamp = self.parse8601(datetime)
|
|
1464
|
+
amountPrecision = None
|
|
1465
|
+
pricePrecision = None
|
|
1466
|
+
# hard coded amount and price precisions from fetchOptionMarkets
|
|
1467
|
+
if base == 'BTC':
|
|
1468
|
+
amountPrecision = self.parse_number('0.01')
|
|
1469
|
+
pricePrecision = self.parse_number('5')
|
|
1470
|
+
elif base == 'ETH':
|
|
1471
|
+
amountPrecision = self.parse_number('0.1')
|
|
1472
|
+
pricePrecision = self.parse_number('0.1')
|
|
1473
|
+
elif base == 'SOL':
|
|
1474
|
+
amountPrecision = self.parse_number('1')
|
|
1475
|
+
pricePrecision = self.parse_number('0.01')
|
|
1209
1476
|
return {
|
|
1210
1477
|
'id': base + '-' + self.convert_expire_date_to_market_id_date(expiry) + '-' + strike + '-' + optionType,
|
|
1211
1478
|
'symbol': base + '/' + quote + ':' + settle + '-' + expiry + '-' + strike + '-' + optionType,
|
|
@@ -1225,14 +1492,14 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1225
1492
|
'option': True,
|
|
1226
1493
|
'margin': False,
|
|
1227
1494
|
'contract': True,
|
|
1228
|
-
'contractSize':
|
|
1495
|
+
'contractSize': self.parse_number('1'),
|
|
1229
1496
|
'expiry': timestamp,
|
|
1230
1497
|
'expiryDatetime': datetime,
|
|
1231
1498
|
'optionType': 'call' if (optionType == 'C') else 'put',
|
|
1232
1499
|
'strike': self.parse_number(strike),
|
|
1233
1500
|
'precision': {
|
|
1234
|
-
'amount':
|
|
1235
|
-
'price':
|
|
1501
|
+
'amount': amountPrecision,
|
|
1502
|
+
'price': pricePrecision,
|
|
1236
1503
|
},
|
|
1237
1504
|
'limits': {
|
|
1238
1505
|
'amount': {
|
|
@@ -1267,10 +1534,38 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1267
1534
|
return [type, params]
|
|
1268
1535
|
return [subType, params]
|
|
1269
1536
|
|
|
1270
|
-
def
|
|
1537
|
+
def get_amount(self, symbol: str, amount: float):
|
|
1538
|
+
# some markets like options might not have the precision available
|
|
1539
|
+
# and we shouldn't crash in those cases
|
|
1540
|
+
market = self.market(symbol)
|
|
1541
|
+
emptyPrecisionAmount = (market['precision']['amount'] is None)
|
|
1542
|
+
amountString = self.number_to_string(amount)
|
|
1543
|
+
if not emptyPrecisionAmount and (amountString != '0'):
|
|
1544
|
+
return self.amount_to_precision(symbol, amount)
|
|
1545
|
+
return amountString
|
|
1546
|
+
|
|
1547
|
+
def get_price(self, symbol: str, price: str):
|
|
1548
|
+
if price is None:
|
|
1549
|
+
return price
|
|
1550
|
+
market = self.market(symbol)
|
|
1551
|
+
emptyPrecisionPrice = (market['precision']['price'] is None)
|
|
1552
|
+
if not emptyPrecisionPrice:
|
|
1553
|
+
return self.price_to_precision(symbol, price)
|
|
1554
|
+
return price
|
|
1555
|
+
|
|
1556
|
+
def get_cost(self, symbol: str, cost: str):
|
|
1557
|
+
market = self.market(symbol)
|
|
1558
|
+
emptyPrecisionPrice = (market['precision']['price'] is None)
|
|
1559
|
+
if not emptyPrecisionPrice:
|
|
1560
|
+
return self.cost_to_precision(symbol, cost)
|
|
1561
|
+
return cost
|
|
1562
|
+
|
|
1563
|
+
def fetch_time(self, params={}) -> Int:
|
|
1271
1564
|
"""
|
|
1272
1565
|
fetches the current integer timestamp in milliseconds from the exchange server
|
|
1273
|
-
|
|
1566
|
+
|
|
1567
|
+
https://bybit-exchange.github.io/docs/v5/market/time
|
|
1568
|
+
|
|
1274
1569
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1275
1570
|
:returns int: the current integer timestamp in milliseconds from the exchange server
|
|
1276
1571
|
"""
|
|
@@ -1292,7 +1587,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1292
1587
|
def fetch_currencies(self, params={}) -> Currencies:
|
|
1293
1588
|
"""
|
|
1294
1589
|
fetches all available currencies on an exchange
|
|
1295
|
-
|
|
1590
|
+
|
|
1591
|
+
https://bybit-exchange.github.io/docs/v5/asset/coin-info
|
|
1592
|
+
|
|
1296
1593
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1297
1594
|
:returns dict: an associative dictionary of currencies
|
|
1298
1595
|
"""
|
|
@@ -1341,92 +1638,81 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1341
1638
|
name = self.safe_string(currency, 'name')
|
|
1342
1639
|
chains = self.safe_list(currency, 'chains', [])
|
|
1343
1640
|
networks: dict = {}
|
|
1344
|
-
minPrecision = None
|
|
1345
|
-
minWithdrawFeeString = None
|
|
1346
|
-
minWithdrawString = None
|
|
1347
|
-
minDepositString = None
|
|
1348
|
-
deposit = False
|
|
1349
|
-
withdraw = False
|
|
1350
1641
|
for j in range(0, len(chains)):
|
|
1351
1642
|
chain = chains[j]
|
|
1352
1643
|
networkId = self.safe_string(chain, 'chain')
|
|
1353
1644
|
networkCode = self.network_id_to_code(networkId)
|
|
1354
|
-
precision = self.parse_number(self.parse_precision(self.safe_string(chain, 'minAccuracy')))
|
|
1355
|
-
minPrecision = precision if (minPrecision is None) else min(minPrecision, precision)
|
|
1356
|
-
depositAllowed = self.safe_integer(chain, 'chainDeposit') == 1
|
|
1357
|
-
deposit = depositAllowed if (depositAllowed) else deposit
|
|
1358
|
-
withdrawAllowed = self.safe_integer(chain, 'chainWithdraw') == 1
|
|
1359
|
-
withdraw = withdrawAllowed if (withdrawAllowed) else withdraw
|
|
1360
|
-
withdrawFeeString = self.safe_string(chain, 'withdrawFee')
|
|
1361
|
-
if withdrawFeeString is not None:
|
|
1362
|
-
minWithdrawFeeString = withdrawFeeString if (minWithdrawFeeString is None) else Precise.string_min(withdrawFeeString, minWithdrawFeeString)
|
|
1363
|
-
minNetworkWithdrawString = self.safe_string(chain, 'withdrawMin')
|
|
1364
|
-
if minNetworkWithdrawString is not None:
|
|
1365
|
-
minWithdrawString = minNetworkWithdrawString if (minWithdrawString is None) else Precise.string_min(minNetworkWithdrawString, minWithdrawString)
|
|
1366
|
-
minNetworkDepositString = self.safe_string(chain, 'depositMin')
|
|
1367
|
-
if minNetworkDepositString is not None:
|
|
1368
|
-
minDepositString = minNetworkDepositString if (minDepositString is None) else Precise.string_min(minNetworkDepositString, minDepositString)
|
|
1369
1645
|
networks[networkCode] = {
|
|
1370
1646
|
'info': chain,
|
|
1371
1647
|
'id': networkId,
|
|
1372
1648
|
'network': networkCode,
|
|
1373
|
-
'active':
|
|
1374
|
-
'deposit':
|
|
1375
|
-
'withdraw':
|
|
1376
|
-
'fee': self.
|
|
1377
|
-
'precision':
|
|
1649
|
+
'active': None,
|
|
1650
|
+
'deposit': self.safe_integer(chain, 'chainDeposit') == 1,
|
|
1651
|
+
'withdraw': self.safe_integer(chain, 'chainWithdraw') == 1,
|
|
1652
|
+
'fee': self.safe_number(chain, 'withdrawFee'),
|
|
1653
|
+
'precision': self.parse_number(self.parse_precision(self.safe_string(chain, 'minAccuracy'))),
|
|
1378
1654
|
'limits': {
|
|
1379
1655
|
'withdraw': {
|
|
1380
|
-
'min': self.
|
|
1656
|
+
'min': self.safe_number(chain, 'withdrawMin'),
|
|
1381
1657
|
'max': None,
|
|
1382
1658
|
},
|
|
1383
1659
|
'deposit': {
|
|
1384
|
-
'min': self.
|
|
1660
|
+
'min': self.safe_number(chain, 'depositMin'),
|
|
1385
1661
|
'max': None,
|
|
1386
1662
|
},
|
|
1387
1663
|
},
|
|
1388
1664
|
}
|
|
1389
|
-
result[code] = {
|
|
1665
|
+
result[code] = self.safe_currency_structure({
|
|
1390
1666
|
'info': currency,
|
|
1391
1667
|
'code': code,
|
|
1392
1668
|
'id': currencyId,
|
|
1393
1669
|
'name': name,
|
|
1394
|
-
'active':
|
|
1395
|
-
'deposit':
|
|
1396
|
-
'withdraw':
|
|
1397
|
-
'fee':
|
|
1398
|
-
'precision':
|
|
1670
|
+
'active': None,
|
|
1671
|
+
'deposit': None,
|
|
1672
|
+
'withdraw': None,
|
|
1673
|
+
'fee': None,
|
|
1674
|
+
'precision': None,
|
|
1399
1675
|
'limits': {
|
|
1400
1676
|
'amount': {
|
|
1401
1677
|
'min': None,
|
|
1402
1678
|
'max': None,
|
|
1403
1679
|
},
|
|
1404
1680
|
'withdraw': {
|
|
1405
|
-
'min':
|
|
1681
|
+
'min': None,
|
|
1406
1682
|
'max': None,
|
|
1407
1683
|
},
|
|
1408
1684
|
'deposit': {
|
|
1409
|
-
'min':
|
|
1685
|
+
'min': None,
|
|
1410
1686
|
'max': None,
|
|
1411
1687
|
},
|
|
1412
1688
|
},
|
|
1413
1689
|
'networks': networks,
|
|
1414
|
-
|
|
1690
|
+
'type': 'crypto', # atm exchange api provides only cryptos
|
|
1691
|
+
})
|
|
1415
1692
|
return result
|
|
1416
1693
|
|
|
1417
1694
|
def fetch_markets(self, params={}) -> List[Market]:
|
|
1418
1695
|
"""
|
|
1419
1696
|
retrieves data on all markets for bybit
|
|
1420
|
-
|
|
1697
|
+
|
|
1698
|
+
https://bybit-exchange.github.io/docs/v5/market/instrument
|
|
1699
|
+
|
|
1421
1700
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1422
1701
|
:returns dict[]: an array of objects representing market data
|
|
1423
1702
|
"""
|
|
1424
1703
|
if self.options['adjustForTimeDifference']:
|
|
1425
1704
|
self.load_time_difference()
|
|
1426
1705
|
promisesUnresolved = []
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1706
|
+
types = None
|
|
1707
|
+
defaultTypes = ['spot', 'linear', 'inverse', 'option']
|
|
1708
|
+
fetchMarketsOptions = self.safe_dict(self.options, 'fetchMarkets')
|
|
1709
|
+
if fetchMarketsOptions is not None:
|
|
1710
|
+
types = self.safe_list(fetchMarketsOptions, 'types', defaultTypes)
|
|
1711
|
+
else:
|
|
1712
|
+
# for backward-compatibility
|
|
1713
|
+
types = self.safe_list(self.options, 'fetchMarkets', defaultTypes)
|
|
1714
|
+
for i in range(0, len(types)):
|
|
1715
|
+
marketType = types[i]
|
|
1430
1716
|
if marketType == 'spot':
|
|
1431
1717
|
promisesUnresolved.append(self.fetch_spot_markets(params))
|
|
1432
1718
|
elif marketType == 'linear':
|
|
@@ -1452,11 +1738,16 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1452
1738
|
derivativeMarkets = self.array_concat(futureMarkets, optionMarkets)
|
|
1453
1739
|
return self.array_concat(spotMarkets, derivativeMarkets)
|
|
1454
1740
|
|
|
1455
|
-
def fetch_spot_markets(self, params):
|
|
1741
|
+
def fetch_spot_markets(self, params) -> List[Market]:
|
|
1456
1742
|
request: dict = {
|
|
1457
1743
|
'category': 'spot',
|
|
1458
1744
|
}
|
|
1459
|
-
|
|
1745
|
+
usePrivateInstrumentsInfo = self.safe_bool(self.options, 'usePrivateInstrumentsInfo', False)
|
|
1746
|
+
response: dict = None
|
|
1747
|
+
if usePrivateInstrumentsInfo:
|
|
1748
|
+
response = self.privateGetV5MarketInstrumentsInfo(self.extend(request, params))
|
|
1749
|
+
else:
|
|
1750
|
+
response = self.publicGetV5MarketInstrumentsInfo(self.extend(request, params))
|
|
1460
1751
|
#
|
|
1461
1752
|
# {
|
|
1462
1753
|
# "retCode": 0,
|
|
@@ -1562,17 +1853,33 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1562
1853
|
}))
|
|
1563
1854
|
return result
|
|
1564
1855
|
|
|
1565
|
-
def fetch_future_markets(self, params):
|
|
1856
|
+
def fetch_future_markets(self, params) -> List[Market]:
|
|
1566
1857
|
params = self.extend(params)
|
|
1567
1858
|
params['limit'] = 1000 # minimize number of requests
|
|
1568
|
-
|
|
1859
|
+
preLaunchMarkets = []
|
|
1860
|
+
usePrivateInstrumentsInfo = self.safe_bool(self.options, 'usePrivateInstrumentsInfo', False)
|
|
1861
|
+
response: dict = None
|
|
1862
|
+
if usePrivateInstrumentsInfo:
|
|
1863
|
+
response = self.privateGetV5MarketInstrumentsInfo(params)
|
|
1864
|
+
else:
|
|
1865
|
+
linearPromises = [
|
|
1866
|
+
self.publicGetV5MarketInstrumentsInfo(params),
|
|
1867
|
+
self.publicGetV5MarketInstrumentsInfo(self.extend(params, {'status': 'PreLaunch'})),
|
|
1868
|
+
]
|
|
1869
|
+
promises = linearPromises
|
|
1870
|
+
response = self.safe_dict(promises, 0, {})
|
|
1871
|
+
preLaunchMarkets = self.safe_dict(promises, 1, {})
|
|
1569
1872
|
data = self.safe_dict(response, 'result', {})
|
|
1570
1873
|
markets = self.safe_list(data, 'list', [])
|
|
1571
1874
|
paginationCursor = self.safe_string(data, 'nextPageCursor')
|
|
1572
1875
|
if paginationCursor is not None:
|
|
1573
1876
|
while(paginationCursor is not None):
|
|
1574
1877
|
params['cursor'] = paginationCursor
|
|
1575
|
-
responseInner =
|
|
1878
|
+
responseInner: dict = None
|
|
1879
|
+
if usePrivateInstrumentsInfo:
|
|
1880
|
+
responseInner = self.privateGetV5MarketInstrumentsInfo(params)
|
|
1881
|
+
else:
|
|
1882
|
+
responseInner = self.publicGetV5MarketInstrumentsInfo(params)
|
|
1576
1883
|
dataNew = self.safe_dict(responseInner, 'result', {})
|
|
1577
1884
|
rawMarkets = self.safe_list(dataNew, 'list', [])
|
|
1578
1885
|
rawMarketsLength = len(rawMarkets)
|
|
@@ -1624,6 +1931,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1624
1931
|
# "time": 1672712495660
|
|
1625
1932
|
# }
|
|
1626
1933
|
#
|
|
1934
|
+
preLaunchData = self.safe_dict(preLaunchMarkets, 'result', {})
|
|
1935
|
+
preLaunchMarketsList = self.safe_list(preLaunchData, 'list', [])
|
|
1936
|
+
markets = self.array_concat(markets, preLaunchMarketsList)
|
|
1627
1937
|
result = []
|
|
1628
1938
|
category = self.safe_string(data, 'category')
|
|
1629
1939
|
for i in range(0, len(markets)):
|
|
@@ -1725,11 +2035,16 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1725
2035
|
}))
|
|
1726
2036
|
return result
|
|
1727
2037
|
|
|
1728
|
-
def fetch_option_markets(self, params):
|
|
2038
|
+
def fetch_option_markets(self, params) -> List[Market]:
|
|
1729
2039
|
request: dict = {
|
|
1730
2040
|
'category': 'option',
|
|
1731
2041
|
}
|
|
1732
|
-
|
|
2042
|
+
usePrivateInstrumentsInfo = self.safe_bool(self.options, 'usePrivateInstrumentsInfo', False)
|
|
2043
|
+
response: dict = None
|
|
2044
|
+
if usePrivateInstrumentsInfo:
|
|
2045
|
+
response = self.privateGetV5MarketInstrumentsInfo(self.extend(request, params))
|
|
2046
|
+
else:
|
|
2047
|
+
response = self.publicGetV5MarketInstrumentsInfo(self.extend(request, params))
|
|
1733
2048
|
data = self.safe_dict(response, 'result', {})
|
|
1734
2049
|
markets = self.safe_list(data, 'list', [])
|
|
1735
2050
|
if self.options['loadAllOptions']:
|
|
@@ -1738,7 +2053,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1738
2053
|
if paginationCursor is not None:
|
|
1739
2054
|
while(paginationCursor is not None):
|
|
1740
2055
|
request['cursor'] = paginationCursor
|
|
1741
|
-
responseInner =
|
|
2056
|
+
responseInner: dict = None
|
|
2057
|
+
if usePrivateInstrumentsInfo:
|
|
2058
|
+
responseInner = self.privateGetV5MarketInstrumentsInfo(self.extend(request, params))
|
|
2059
|
+
else:
|
|
2060
|
+
responseInner = self.publicGetV5MarketInstrumentsInfo(self.extend(request, params))
|
|
1742
2061
|
dataNew = self.safe_dict(responseInner, 'result', {})
|
|
1743
2062
|
rawMarkets = self.safe_list(dataNew, 'list', [])
|
|
1744
2063
|
rawMarketsLength = len(rawMarkets)
|
|
@@ -1799,6 +2118,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1799
2118
|
strike = self.safe_string(splitId, 2)
|
|
1800
2119
|
optionLetter = self.safe_string(splitId, 3)
|
|
1801
2120
|
isActive = (status == 'Trading')
|
|
2121
|
+
isInverse = base == settle
|
|
1802
2122
|
if isActive or (self.options['loadAllOptions']) or (self.options['loadExpiredOptions']):
|
|
1803
2123
|
result.append(self.safe_market_structure({
|
|
1804
2124
|
'id': id,
|
|
@@ -1810,6 +2130,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1810
2130
|
'quoteId': quoteId,
|
|
1811
2131
|
'settleId': settleId,
|
|
1812
2132
|
'type': 'option',
|
|
2133
|
+
'subType': None,
|
|
1813
2134
|
'spot': False,
|
|
1814
2135
|
'margin': False,
|
|
1815
2136
|
'swap': False,
|
|
@@ -1817,11 +2138,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1817
2138
|
'option': True,
|
|
1818
2139
|
'active': isActive,
|
|
1819
2140
|
'contract': True,
|
|
1820
|
-
'linear':
|
|
1821
|
-
'inverse':
|
|
2141
|
+
'linear': not isInverse,
|
|
2142
|
+
'inverse': isInverse,
|
|
1822
2143
|
'taker': self.safe_number(market, 'takerFee', self.parse_number('0.0006')),
|
|
1823
2144
|
'maker': self.safe_number(market, 'makerFee', self.parse_number('0.0001')),
|
|
1824
|
-
'contractSize': self.
|
|
2145
|
+
'contractSize': self.parse_number('1'),
|
|
1825
2146
|
'expiry': expiry,
|
|
1826
2147
|
'expiryDatetime': self.iso8601(expiry),
|
|
1827
2148
|
'strike': self.parse_number(strike),
|
|
@@ -1967,13 +2288,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1967
2288
|
'average': None,
|
|
1968
2289
|
'baseVolume': baseVolume,
|
|
1969
2290
|
'quoteVolume': quoteVolume,
|
|
2291
|
+
'markPrice': self.safe_string(ticker, 'markPrice'),
|
|
2292
|
+
'indexPrice': self.safe_string(ticker, 'indexPrice'),
|
|
1970
2293
|
'info': ticker,
|
|
1971
2294
|
}, market)
|
|
1972
2295
|
|
|
1973
2296
|
def fetch_ticker(self, symbol: str, params={}) -> Ticker:
|
|
1974
2297
|
"""
|
|
1975
2298
|
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
|
1976
|
-
|
|
2299
|
+
|
|
2300
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
|
2301
|
+
|
|
1977
2302
|
:param str symbol: unified symbol of the market to fetch the ticker for
|
|
1978
2303
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
1979
2304
|
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
@@ -1987,15 +2312,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
1987
2312
|
# 'baseCoin': '', Base coin. For option only
|
|
1988
2313
|
# 'expDate': '', Expiry date. e.g., 25DEC22. For option only
|
|
1989
2314
|
}
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
if market['option']:
|
|
1994
|
-
request['category'] = 'option'
|
|
1995
|
-
elif market['linear']:
|
|
1996
|
-
request['category'] = 'linear'
|
|
1997
|
-
elif market['inverse']:
|
|
1998
|
-
request['category'] = 'inverse'
|
|
2315
|
+
category = None
|
|
2316
|
+
category, params = self.get_bybit_type('fetchTicker', market, params)
|
|
2317
|
+
request['category'] = category
|
|
1999
2318
|
response = self.publicGetV5MarketTickers(self.extend(request, params))
|
|
2000
2319
|
#
|
|
2001
2320
|
# {
|
|
@@ -2043,13 +2362,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2043
2362
|
def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
|
|
2044
2363
|
"""
|
|
2045
2364
|
fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
|
|
2046
|
-
|
|
2365
|
+
|
|
2366
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
|
2367
|
+
|
|
2047
2368
|
:param str[] symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
|
2048
2369
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
2049
2370
|
:param str [params.subType]: *contract only* 'linear', 'inverse'
|
|
2371
|
+
:param str [params.baseCoin]: *option only* base coin, default is 'BTC'
|
|
2050
2372
|
:returns dict: an array of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
2051
2373
|
"""
|
|
2052
2374
|
self.load_markets()
|
|
2375
|
+
code = self.safe_string_n(params, ['code', 'currency', 'baseCoin'])
|
|
2053
2376
|
market = None
|
|
2054
2377
|
parsedSymbols = None
|
|
2055
2378
|
if symbols is not None:
|
|
@@ -2071,27 +2394,26 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2071
2394
|
currentType = market['type']
|
|
2072
2395
|
elif market['type'] != currentType:
|
|
2073
2396
|
raise BadRequest(self.id + ' fetchTickers can only accept a list of symbols of the same type')
|
|
2397
|
+
if market['option']:
|
|
2398
|
+
if code is not None and code != market['base']:
|
|
2399
|
+
raise BadRequest(self.id + ' fetchTickers the base currency must be the same for all symbols, self endpoint only supports one base currency at a time. Read more about it here: https://bybit-exchange.github.io/docs/v5/market/tickers')
|
|
2400
|
+
if code is None:
|
|
2401
|
+
code = market['base']
|
|
2402
|
+
params = self.omit(params, ['code', 'currency'])
|
|
2074
2403
|
parsedSymbols.append(market['symbol'])
|
|
2075
2404
|
request: dict = {
|
|
2076
2405
|
# 'symbol': market['id'],
|
|
2077
2406
|
# 'baseCoin': '', # Base coin. For option only
|
|
2078
2407
|
# 'expDate': '', # Expiry date. e.g., 25DEC22. For option only
|
|
2079
2408
|
}
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
# with higher priority and only default to spot, if `subType` is not set in params
|
|
2085
|
-
passedSubType = self.safe_string(params, 'subType')
|
|
2086
|
-
subType = None
|
|
2087
|
-
subType, params = self.handle_sub_type_and_params('fetchTickers', market, params, 'linear')
|
|
2088
|
-
# only if passedSubType is None, then use spot
|
|
2089
|
-
if type == 'spot' and passedSubType is None:
|
|
2090
|
-
request['category'] = 'spot'
|
|
2091
|
-
elif type == 'swap' or type == 'future' or subType is not None:
|
|
2092
|
-
request['category'] = subType
|
|
2093
|
-
elif type == 'option':
|
|
2409
|
+
category = None
|
|
2410
|
+
category, params = self.get_bybit_type('fetchTickers', market, params)
|
|
2411
|
+
request['category'] = category
|
|
2412
|
+
if category == 'option':
|
|
2094
2413
|
request['category'] = 'option'
|
|
2414
|
+
if code is None:
|
|
2415
|
+
code = 'BTC'
|
|
2416
|
+
request['baseCoin'] = code
|
|
2095
2417
|
response = self.publicGetV5MarketTickers(self.extend(request, params))
|
|
2096
2418
|
#
|
|
2097
2419
|
# {
|
|
@@ -2135,6 +2457,20 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2135
2457
|
tickerList = self.safe_list(result, 'list', [])
|
|
2136
2458
|
return self.parse_tickers(tickerList, parsedSymbols)
|
|
2137
2459
|
|
|
2460
|
+
def fetch_bids_asks(self, symbols: Strings = None, params={}) -> Tickers:
|
|
2461
|
+
"""
|
|
2462
|
+
fetches the bid and ask price and volume for multiple markets
|
|
2463
|
+
|
|
2464
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
|
2465
|
+
|
|
2466
|
+
:param str[]|None symbols: unified symbols of the markets to fetch the bids and asks for, all markets are returned if not assigned
|
|
2467
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
2468
|
+
:param str [params.subType]: *contract only* 'linear', 'inverse'
|
|
2469
|
+
:param str [params.baseCoin]: *option only* base coin, default is 'BTC'
|
|
2470
|
+
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
|
2471
|
+
"""
|
|
2472
|
+
return self.fetch_tickers(symbols, params)
|
|
2473
|
+
|
|
2138
2474
|
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
|
2139
2475
|
#
|
|
2140
2476
|
# [
|
|
@@ -2160,10 +2496,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2160
2496
|
def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
|
2161
2497
|
"""
|
|
2162
2498
|
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2499
|
+
|
|
2500
|
+
https://bybit-exchange.github.io/docs/v5/market/kline
|
|
2501
|
+
https://bybit-exchange.github.io/docs/v5/market/mark-kline
|
|
2502
|
+
https://bybit-exchange.github.io/docs/v5/market/index-kline
|
|
2503
|
+
https://bybit-exchange.github.io/docs/v5/market/preimum-index-kline
|
|
2504
|
+
|
|
2167
2505
|
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
|
2168
2506
|
:param str timeframe: the length of time each candle represents
|
|
2169
2507
|
:param int [since]: timestamp in ms of the earliest candle to fetch
|
|
@@ -2258,7 +2596,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2258
2596
|
ohlcvs = self.safe_list(result, 'list', [])
|
|
2259
2597
|
return self.parse_ohlcvs(ohlcvs, market, timeframe, since, limit)
|
|
2260
2598
|
|
|
2261
|
-
def parse_funding_rate(self, ticker, market: Market = None):
|
|
2599
|
+
def parse_funding_rate(self, ticker, market: Market = None) -> FundingRate:
|
|
2600
|
+
#
|
|
2262
2601
|
# {
|
|
2263
2602
|
# "symbol": "BTCUSDT",
|
|
2264
2603
|
# "bidPrice": "19255",
|
|
@@ -2291,6 +2630,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2291
2630
|
fundingTimestamp = self.safe_integer(ticker, 'nextFundingTime')
|
|
2292
2631
|
markPrice = self.safe_number(ticker, 'markPrice')
|
|
2293
2632
|
indexPrice = self.safe_number(ticker, 'indexPrice')
|
|
2633
|
+
info = self.safe_dict(self.safe_market(marketId, market, None, 'swap'), 'info')
|
|
2634
|
+
fundingInterval = self.safe_integer(info, 'fundingInterval')
|
|
2635
|
+
intervalString = None
|
|
2636
|
+
if fundingInterval is not None:
|
|
2637
|
+
interval = self.parse_to_int(fundingInterval / 60)
|
|
2638
|
+
intervalString = str(interval) + 'h'
|
|
2294
2639
|
return {
|
|
2295
2640
|
'info': ticker,
|
|
2296
2641
|
'symbol': symbol,
|
|
@@ -2309,15 +2654,18 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2309
2654
|
'previousFundingRate': None,
|
|
2310
2655
|
'previousFundingTimestamp': None,
|
|
2311
2656
|
'previousFundingDatetime': None,
|
|
2657
|
+
'interval': intervalString,
|
|
2312
2658
|
}
|
|
2313
2659
|
|
|
2314
|
-
def fetch_funding_rates(self, symbols: Strings = None, params={}):
|
|
2660
|
+
def fetch_funding_rates(self, symbols: Strings = None, params={}) -> FundingRates:
|
|
2315
2661
|
"""
|
|
2316
2662
|
fetches funding rates for multiple markets
|
|
2317
|
-
|
|
2663
|
+
|
|
2664
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
|
2665
|
+
|
|
2318
2666
|
:param str[] symbols: unified symbols of the markets to fetch the funding rates for, all market funding rates are returned if not assigned
|
|
2319
2667
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
2320
|
-
:returns dict:
|
|
2668
|
+
:returns dict[]: a list of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-structure>`
|
|
2321
2669
|
"""
|
|
2322
2670
|
self.load_markets()
|
|
2323
2671
|
market = None
|
|
@@ -2373,22 +2721,19 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2373
2721
|
# "time": 1663670053454
|
|
2374
2722
|
# }
|
|
2375
2723
|
#
|
|
2376
|
-
|
|
2724
|
+
data = self.safe_dict(response, 'result', {})
|
|
2725
|
+
tickerList = self.safe_list(data, 'list', [])
|
|
2377
2726
|
timestamp = self.safe_integer(response, 'time')
|
|
2378
|
-
tickerList = self.safe_value(tickerList, 'list')
|
|
2379
|
-
fundingRates: dict = {}
|
|
2380
2727
|
for i in range(0, len(tickerList)):
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
ticker = self.parse_funding_rate(tickerList[i], None)
|
|
2384
|
-
symbol = ticker['symbol']
|
|
2385
|
-
fundingRates[symbol] = ticker
|
|
2386
|
-
return self.filter_by_array(fundingRates, 'symbol', symbols)
|
|
2728
|
+
tickerList[i]['timestamp'] = timestamp # will be removed inside the parser
|
|
2729
|
+
return self.parse_funding_rates(tickerList, symbols)
|
|
2387
2730
|
|
|
2388
2731
|
def fetch_funding_rate_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
2389
2732
|
"""
|
|
2390
2733
|
fetches historical funding rate prices
|
|
2391
|
-
|
|
2734
|
+
|
|
2735
|
+
https://bybit-exchange.github.io/docs/v5/market/history-fund-rate
|
|
2736
|
+
|
|
2392
2737
|
:param str symbol: unified symbol of the market to fetch the funding rate history for
|
|
2393
2738
|
:param int [since]: timestamp in ms of the earliest funding rate to fetch
|
|
2394
2739
|
:param int [limit]: the maximum amount of `funding rate structures <https://docs.ccxt.com/#/?id=funding-rate-history-structure>` to fetch
|
|
@@ -2640,7 +2985,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2640
2985
|
def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
2641
2986
|
"""
|
|
2642
2987
|
get the list of most recent trades for a particular symbol
|
|
2643
|
-
|
|
2988
|
+
|
|
2989
|
+
https://bybit-exchange.github.io/docs/v5/market/recent-trade
|
|
2990
|
+
|
|
2644
2991
|
:param str symbol: unified symbol of the market to fetch trades for
|
|
2645
2992
|
:param int [since]: timestamp in ms of the earliest trade to fetch
|
|
2646
2993
|
:param int [limit]: the maximum amount of trades to fetch
|
|
@@ -2695,7 +3042,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2695
3042
|
def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
|
2696
3043
|
"""
|
|
2697
3044
|
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
|
2698
|
-
|
|
3045
|
+
|
|
3046
|
+
https://bybit-exchange.github.io/docs/v5/market/orderbook
|
|
3047
|
+
|
|
2699
3048
|
:param str symbol: unified symbol of the market to fetch the order book for
|
|
2700
3049
|
:param int [limit]: the maximum amount of order book entries to return
|
|
2701
3050
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -2864,7 +3213,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2864
3213
|
'datetime': self.iso8601(timestamp),
|
|
2865
3214
|
}
|
|
2866
3215
|
responseResult = self.safe_dict(response, 'result', {})
|
|
2867
|
-
currencyList = self.
|
|
3216
|
+
currencyList = self.safe_list_n(responseResult, ['loanAccountList', 'list', 'balance'])
|
|
2868
3217
|
if currencyList is None:
|
|
2869
3218
|
# usdc wallet
|
|
2870
3219
|
code = 'USDC'
|
|
@@ -2886,7 +3235,16 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2886
3235
|
if (loan is not None) and (interest is not None):
|
|
2887
3236
|
account['debt'] = Precise.string_add(loan, interest)
|
|
2888
3237
|
account['total'] = self.safe_string(coinEntry, 'walletBalance')
|
|
2889
|
-
|
|
3238
|
+
free = self.safe_string_2(coinEntry, 'availableToWithdraw', 'free')
|
|
3239
|
+
if free is not None:
|
|
3240
|
+
account['free'] = free
|
|
3241
|
+
else:
|
|
3242
|
+
locked = self.safe_string(coinEntry, 'locked', '0')
|
|
3243
|
+
totalPositionIm = self.safe_string(coinEntry, 'totalPositionIM', '0')
|
|
3244
|
+
totalOrderIm = self.safe_string(coinEntry, 'totalOrderIM', '0')
|
|
3245
|
+
totalUsed = Precise.string_add(locked, totalPositionIm)
|
|
3246
|
+
totalUsed = Precise.string_add(totalUsed, totalOrderIm)
|
|
3247
|
+
account['used'] = totalUsed
|
|
2890
3248
|
# account['used'] = self.safe_string(coinEntry, 'locked')
|
|
2891
3249
|
currencyId = self.safe_string(coinEntry, 'coin')
|
|
2892
3250
|
code = self.safe_currency_code(currencyId)
|
|
@@ -2908,11 +3266,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2908
3266
|
def fetch_balance(self, params={}) -> Balances:
|
|
2909
3267
|
"""
|
|
2910
3268
|
query for balance and get the amount of funds available for trading or funds locked in orders
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
3269
|
+
|
|
3270
|
+
https://bybit-exchange.github.io/docs/v5/spot-margin-normal/account-info
|
|
3271
|
+
https://bybit-exchange.github.io/docs/v5/asset/all-balance
|
|
3272
|
+
https://bybit-exchange.github.io/docs/v5/account/wallet-balance
|
|
3273
|
+
|
|
2914
3274
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
2915
|
-
:param str [params.type]: wallet type, ['spot', 'swap', '
|
|
3275
|
+
:param str [params.type]: wallet type, ['spot', 'swap', 'funding']
|
|
2916
3276
|
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
|
2917
3277
|
"""
|
|
2918
3278
|
self.load_markets()
|
|
@@ -2920,14 +3280,29 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2920
3280
|
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
2921
3281
|
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
2922
3282
|
type = None
|
|
3283
|
+
# don't use getBybitType here
|
|
2923
3284
|
type, params = self.handle_market_type_and_params('fetchBalance', None, params)
|
|
3285
|
+
subType = None
|
|
3286
|
+
subType, params = self.handle_sub_type_and_params('fetchBalance', None, params)
|
|
3287
|
+
if (type == 'swap') or (type == 'future'):
|
|
3288
|
+
type = subType
|
|
3289
|
+
lowercaseRawType = type.lower() if (type is not None) else None
|
|
2924
3290
|
isSpot = (type == 'spot')
|
|
2925
|
-
|
|
3291
|
+
isLinear = (type == 'linear')
|
|
3292
|
+
isInverse = (type == 'inverse')
|
|
3293
|
+
isFunding = (lowercaseRawType == 'fund') or (lowercaseRawType == 'funding')
|
|
2926
3294
|
if isUnifiedAccount:
|
|
2927
|
-
|
|
2928
|
-
|
|
3295
|
+
unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 6)
|
|
3296
|
+
if unifiedMarginStatus < 5:
|
|
3297
|
+
# it's not uta.20 where inverse are unified
|
|
3298
|
+
if isInverse:
|
|
3299
|
+
type = 'contract'
|
|
3300
|
+
else:
|
|
3301
|
+
type = 'unified'
|
|
3302
|
+
else:
|
|
3303
|
+
type = 'unified' # uta.20 where inverse are unified
|
|
2929
3304
|
else:
|
|
2930
|
-
if
|
|
3305
|
+
if isLinear or isInverse:
|
|
2931
3306
|
type = 'contract'
|
|
2932
3307
|
accountTypes = self.safe_dict(self.options, 'accountsByType', {})
|
|
2933
3308
|
unifiedType = self.safe_string_upper(accountTypes, type, type)
|
|
@@ -2936,10 +3311,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
2936
3311
|
response = None
|
|
2937
3312
|
if isSpot and (marginMode is not None):
|
|
2938
3313
|
response = self.privateGetV5SpotCrossMarginTradeAccount(self.extend(request, params))
|
|
2939
|
-
elif
|
|
3314
|
+
elif isFunding:
|
|
2940
3315
|
# use self endpoint only we have no other choice
|
|
2941
3316
|
# because it requires transfer permission
|
|
2942
|
-
request['accountType'] =
|
|
3317
|
+
request['accountType'] = 'FUND'
|
|
2943
3318
|
response = self.privateGetV5AssetTransferQueryAccountCoinsBalance(self.extend(request, params))
|
|
2944
3319
|
else:
|
|
2945
3320
|
request['accountType'] = unifiedType
|
|
@@ -3183,13 +3558,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3183
3558
|
if code is not None:
|
|
3184
3559
|
if code != '0':
|
|
3185
3560
|
category = self.safe_string(order, 'category')
|
|
3186
|
-
|
|
3561
|
+
inferredMarketType = 'spot' if (category == 'spot') else 'contract'
|
|
3187
3562
|
return self.safe_order({
|
|
3188
3563
|
'info': order,
|
|
3189
3564
|
'status': 'rejected',
|
|
3190
3565
|
'id': self.safe_string(order, 'orderId'),
|
|
3191
3566
|
'clientOrderId': self.safe_string(order, 'orderLinkId'),
|
|
3192
|
-
'symbol': self.safe_symbol(self.safe_string(order, 'symbol'), None, None,
|
|
3567
|
+
'symbol': self.safe_symbol(self.safe_string(order, 'symbol'), None, None, inferredMarketType),
|
|
3193
3568
|
})
|
|
3194
3569
|
marketId = self.safe_string(order, 'symbol')
|
|
3195
3570
|
isContract = ('tpslMode' in order)
|
|
@@ -3201,11 +3576,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3201
3576
|
market = self.safe_market(marketId, market, None, marketType)
|
|
3202
3577
|
symbol = market['symbol']
|
|
3203
3578
|
timestamp = self.safe_integer_2(order, 'createdTime', 'createdAt')
|
|
3579
|
+
marketUnit = self.safe_string(order, 'marketUnit', 'baseCoin')
|
|
3204
3580
|
id = self.safe_string(order, 'orderId')
|
|
3205
3581
|
type = self.safe_string_lower(order, 'orderType')
|
|
3206
3582
|
price = self.safe_string(order, 'price')
|
|
3207
|
-
amount =
|
|
3208
|
-
cost =
|
|
3583
|
+
amount: Str = None
|
|
3584
|
+
cost: Str = None
|
|
3585
|
+
if marketUnit == 'baseCoin':
|
|
3586
|
+
amount = self.safe_string(order, 'qty')
|
|
3587
|
+
cost = self.safe_string(order, 'cumExecValue')
|
|
3588
|
+
else:
|
|
3589
|
+
cost = self.safe_string(order, 'cumExecValue')
|
|
3209
3590
|
filled = self.safe_string(order, 'cumExecQty')
|
|
3210
3591
|
remaining = self.safe_string(order, 'leavesQty')
|
|
3211
3592
|
lastTradeTimestamp = self.safe_integer_2(order, 'updatedTime', 'updatedAt')
|
|
@@ -3230,7 +3611,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3230
3611
|
else:
|
|
3231
3612
|
feeCurrencyCode = market['base'] if market['inverse'] else market['settle']
|
|
3232
3613
|
fee = {
|
|
3233
|
-
'cost': feeCostString,
|
|
3614
|
+
'cost': self.parse_number(feeCostString),
|
|
3234
3615
|
'currency': feeCurrencyCode,
|
|
3235
3616
|
}
|
|
3236
3617
|
clientOrderId = self.safe_string(order, 'orderLinkId')
|
|
@@ -3239,29 +3620,29 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3239
3620
|
avgPrice = self.omit_zero(self.safe_string(order, 'avgPrice'))
|
|
3240
3621
|
rawTimeInForce = self.safe_string(order, 'timeInForce')
|
|
3241
3622
|
timeInForce = self.parse_time_in_force(rawTimeInForce)
|
|
3242
|
-
|
|
3623
|
+
triggerPrice = self.omit_zero(self.safe_string(order, 'triggerPrice'))
|
|
3243
3624
|
reduceOnly = self.safe_bool(order, 'reduceOnly')
|
|
3244
3625
|
takeProfitPrice = self.omit_zero(self.safe_string(order, 'takeProfit'))
|
|
3245
3626
|
stopLossPrice = self.omit_zero(self.safe_string(order, 'stopLoss'))
|
|
3246
3627
|
triggerDirection = self.safe_string(order, 'triggerDirection')
|
|
3247
3628
|
isAscending = (triggerDirection == '1')
|
|
3248
|
-
isStopOrderType2 = (
|
|
3629
|
+
isStopOrderType2 = (triggerPrice is not None) and reduceOnly
|
|
3249
3630
|
if (stopLossPrice is None) and isStopOrderType2:
|
|
3250
3631
|
# check if order is stop order type 2 - stopLossPrice
|
|
3251
3632
|
if isAscending and (side == 'buy'):
|
|
3252
3633
|
# stopLoss order against short position
|
|
3253
|
-
stopLossPrice =
|
|
3634
|
+
stopLossPrice = triggerPrice
|
|
3254
3635
|
if not isAscending and (side == 'sell'):
|
|
3255
3636
|
# stopLoss order against a long position
|
|
3256
|
-
stopLossPrice =
|
|
3637
|
+
stopLossPrice = triggerPrice
|
|
3257
3638
|
if (takeProfitPrice is None) and isStopOrderType2:
|
|
3258
3639
|
# check if order is stop order type 2 - takeProfitPrice
|
|
3259
3640
|
if isAscending and (side == 'sell'):
|
|
3260
3641
|
# takeprofit order against a long position
|
|
3261
|
-
takeProfitPrice =
|
|
3642
|
+
takeProfitPrice = triggerPrice
|
|
3262
3643
|
if not isAscending and (side == 'buy'):
|
|
3263
3644
|
# takeprofit order against a short position
|
|
3264
|
-
takeProfitPrice =
|
|
3645
|
+
takeProfitPrice = triggerPrice
|
|
3265
3646
|
return self.safe_order({
|
|
3266
3647
|
'info': order,
|
|
3267
3648
|
'id': id,
|
|
@@ -3277,8 +3658,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3277
3658
|
'reduceOnly': self.safe_bool(order, 'reduceOnly'),
|
|
3278
3659
|
'side': side,
|
|
3279
3660
|
'price': price,
|
|
3280
|
-
'
|
|
3281
|
-
'triggerPrice': stopPrice,
|
|
3661
|
+
'triggerPrice': triggerPrice,
|
|
3282
3662
|
'takeProfitPrice': takeProfitPrice,
|
|
3283
3663
|
'stopLossPrice': stopLossPrice,
|
|
3284
3664
|
'amount': amount,
|
|
@@ -3291,10 +3671,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3291
3671
|
'trades': None,
|
|
3292
3672
|
}, market)
|
|
3293
3673
|
|
|
3294
|
-
def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
|
|
3674
|
+
def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}) -> Order:
|
|
3295
3675
|
"""
|
|
3296
|
-
:see: https://bybit-exchange.github.io/docs/v5/order/create-order
|
|
3297
3676
|
create a market buy order by providing the symbol and cost
|
|
3677
|
+
|
|
3678
|
+
https://bybit-exchange.github.io/docs/v5/order/create-order
|
|
3679
|
+
|
|
3298
3680
|
:param str symbol: unified symbol of the market to create an order in
|
|
3299
3681
|
:param float cost: how much you want to trade in units of the quote currency
|
|
3300
3682
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -3304,12 +3686,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3304
3686
|
market = self.market(symbol)
|
|
3305
3687
|
if not market['spot']:
|
|
3306
3688
|
raise NotSupported(self.id + ' createMarketBuyOrderWithCost() supports spot orders only')
|
|
3307
|
-
|
|
3689
|
+
req = {
|
|
3690
|
+
'cost': cost,
|
|
3691
|
+
}
|
|
3692
|
+
return self.create_order(symbol, 'market', 'buy', -1, None, self.extend(req, params))
|
|
3308
3693
|
|
|
3309
|
-
def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
|
|
3694
|
+
def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}) -> Order:
|
|
3310
3695
|
"""
|
|
3311
|
-
:see: https://bybit-exchange.github.io/docs/v5/order/create-order
|
|
3312
3696
|
create a market sell order by providing the symbol and cost
|
|
3697
|
+
|
|
3698
|
+
https://bybit-exchange.github.io/docs/v5/order/create-order
|
|
3699
|
+
|
|
3313
3700
|
:param str symbol: unified symbol of the market to create an order in
|
|
3314
3701
|
:param float cost: how much you want to trade in units of the quote currency
|
|
3315
3702
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -3323,27 +3710,33 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3323
3710
|
market = self.market(symbol)
|
|
3324
3711
|
if not market['spot']:
|
|
3325
3712
|
raise NotSupported(self.id + ' createMarketSellOrderWithCost() supports spot orders only')
|
|
3326
|
-
|
|
3713
|
+
req = {
|
|
3714
|
+
'cost': cost,
|
|
3715
|
+
}
|
|
3716
|
+
return self.create_order(symbol, 'market', 'sell', -1, None, self.extend(req, params))
|
|
3327
3717
|
|
|
3328
|
-
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
|
3718
|
+
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}) -> Order:
|
|
3329
3719
|
"""
|
|
3330
3720
|
create a trade order
|
|
3331
|
-
|
|
3332
|
-
|
|
3721
|
+
|
|
3722
|
+
https://bybit-exchange.github.io/docs/v5/order/create-order
|
|
3723
|
+
https://bybit-exchange.github.io/docs/v5/position/trading-stop
|
|
3724
|
+
|
|
3333
3725
|
:param str symbol: unified symbol of the market to create an order in
|
|
3334
3726
|
:param str type: 'market' or 'limit'
|
|
3335
3727
|
:param str side: 'buy' or 'sell'
|
|
3336
3728
|
:param float amount: how much of currency you want to trade in units of base currency
|
|
3337
|
-
:param float [price]: the price at which the order is to be
|
|
3729
|
+
:param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
|
3338
3730
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
3339
3731
|
:param str [params.timeInForce]: "GTC", "IOC", "FOK"
|
|
3340
3732
|
:param bool [params.postOnly]: True or False whether the order is post-only
|
|
3341
3733
|
:param bool [params.reduceOnly]: True or False whether the order is reduce-only
|
|
3342
|
-
:param str [params.positionIdx]: *contracts only*
|
|
3343
|
-
:param
|
|
3734
|
+
:param str [params.positionIdx]: *contracts only* 0 for one-way mode, 1 buy side of hedged mode, 2 sell side of hedged mode
|
|
3735
|
+
:param bool [params.hedged]: *contracts only* True for hedged mode, False for one way mode, default is False
|
|
3736
|
+
:param int [params.isLeverage]: *unified spot only* False then spot trading True then margin trading
|
|
3344
3737
|
:param str [params.tpslMode]: *contract only* 'full' or 'partial'
|
|
3345
3738
|
:param str [params.mmp]: *option only* market maker protection
|
|
3346
|
-
:param str [params.triggerDirection]: *contract only* the direction for trigger orders, '
|
|
3739
|
+
:param str [params.triggerDirection]: *contract only* the direction for trigger orders, 'ascending' or 'descending'
|
|
3347
3740
|
:param float [params.triggerPrice]: The price at which a trigger order is triggered at
|
|
3348
3741
|
:param float [params.stopLossPrice]: The price at which a stop loss order is triggered at
|
|
3349
3742
|
:param float [params.takeProfitPrice]: The price at which a take profit order is triggered at
|
|
@@ -3357,18 +3750,24 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3357
3750
|
"""
|
|
3358
3751
|
self.load_markets()
|
|
3359
3752
|
market = self.market(symbol)
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
3363
|
-
if isUsdcSettled and not isUnifiedAccount:
|
|
3364
|
-
return self.create_usdc_order(symbol, type, side, amount, price, params)
|
|
3753
|
+
parts = self.is_unified_enabled()
|
|
3754
|
+
enableUnifiedAccount = parts[1]
|
|
3365
3755
|
trailingAmount = self.safe_string_2(params, 'trailingAmount', 'trailingStop')
|
|
3756
|
+
stopLossPrice = self.safe_string(params, 'stopLossPrice')
|
|
3757
|
+
takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
|
|
3366
3758
|
isTrailingAmountOrder = trailingAmount is not None
|
|
3759
|
+
isStopLoss = stopLossPrice is not None
|
|
3760
|
+
isTakeProfit = takeProfitPrice is not None
|
|
3367
3761
|
orderRequest = self.create_order_request(symbol, type, side, amount, price, params, enableUnifiedAccount)
|
|
3368
|
-
|
|
3369
|
-
|
|
3762
|
+
defaultMethod = None
|
|
3763
|
+
if (isTrailingAmountOrder or isStopLoss or isTakeProfit) and not market['spot']:
|
|
3764
|
+
defaultMethod = 'privatePostV5PositionTradingStop'
|
|
3765
|
+
else:
|
|
3766
|
+
defaultMethod = 'privatePostV5OrderCreate'
|
|
3767
|
+
method = None
|
|
3768
|
+
method, params = self.handle_option_and_params(params, 'createOrder', 'method', defaultMethod)
|
|
3370
3769
|
response = None
|
|
3371
|
-
if
|
|
3770
|
+
if method == 'privatePostV5PositionTradingStop':
|
|
3372
3771
|
response = self.privatePostV5PositionTradingStop(orderRequest)
|
|
3373
3772
|
else:
|
|
3374
3773
|
response = self.privatePostV5OrderCreate(orderRequest) # already extended inside createOrderRequest
|
|
@@ -3393,8 +3792,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3393
3792
|
lowerCaseType = type.lower()
|
|
3394
3793
|
if (price is None) and (lowerCaseType == 'limit'):
|
|
3395
3794
|
raise ArgumentsRequired(self.id + ' createOrder requires a price argument for limit orders')
|
|
3396
|
-
defaultMethod = None
|
|
3397
|
-
defaultMethod, params = self.handle_option_and_params(params, 'createOrder', 'method', 'privatePostV5OrderCreate')
|
|
3398
3795
|
request: dict = {
|
|
3399
3796
|
'symbol': market['id'],
|
|
3400
3797
|
# 'side': self.capitalize(side),
|
|
@@ -3420,6 +3817,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3420
3817
|
# Valid for option only.
|
|
3421
3818
|
# 'orderIv': '0', # Implied volatility; parameters are passed according to the real value; for example, for 10%, 0.1 is passed
|
|
3422
3819
|
}
|
|
3820
|
+
hedged = self.safe_bool(params, 'hedged', False)
|
|
3821
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly')
|
|
3423
3822
|
triggerPrice = self.safe_value_2(params, 'triggerPrice', 'stopPrice')
|
|
3424
3823
|
stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice')
|
|
3425
3824
|
takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
|
|
@@ -3436,25 +3835,34 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3436
3835
|
isMarket = lowerCaseType == 'market'
|
|
3437
3836
|
isLimit = lowerCaseType == 'limit'
|
|
3438
3837
|
isBuy = side == 'buy'
|
|
3439
|
-
|
|
3838
|
+
defaultMethod = None
|
|
3839
|
+
if (isTrailingAmountOrder or isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not market['spot']:
|
|
3840
|
+
defaultMethod = 'privatePostV5PositionTradingStop'
|
|
3841
|
+
else:
|
|
3842
|
+
defaultMethod = 'privatePostV5OrderCreate'
|
|
3843
|
+
method = None
|
|
3844
|
+
method, params = self.handle_option_and_params(params, 'createOrder', 'method', defaultMethod)
|
|
3845
|
+
isAlternativeEndpoint = method == 'privatePostV5PositionTradingStop'
|
|
3846
|
+
amountString = self.get_amount(symbol, amount)
|
|
3847
|
+
priceString = self.get_price(symbol, self.number_to_string(price)) if (price is not None) else None
|
|
3440
3848
|
if isTrailingAmountOrder or isAlternativeEndpoint:
|
|
3441
3849
|
if isStopLoss or isTakeProfit or isTriggerOrder or market['spot']:
|
|
3442
3850
|
raise InvalidOrder(self.id + ' the API endpoint used only supports contract trailingAmount, stopLossPrice and takeProfitPrice orders')
|
|
3443
3851
|
if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
|
|
3444
3852
|
if isStopLossTriggerOrder:
|
|
3445
|
-
request['stopLoss'] = self.
|
|
3853
|
+
request['stopLoss'] = self.get_price(symbol, stopLossTriggerPrice)
|
|
3446
3854
|
if isLimit:
|
|
3447
3855
|
request['tpslMode'] = 'Partial'
|
|
3448
3856
|
request['slOrderType'] = 'Limit'
|
|
3449
|
-
request['slLimitPrice'] =
|
|
3450
|
-
request['slSize'] =
|
|
3857
|
+
request['slLimitPrice'] = priceString
|
|
3858
|
+
request['slSize'] = amountString
|
|
3451
3859
|
elif isTakeProfitTriggerOrder:
|
|
3452
|
-
request['takeProfit'] = self.
|
|
3860
|
+
request['takeProfit'] = self.get_price(symbol, takeProfitTriggerPrice)
|
|
3453
3861
|
if isLimit:
|
|
3454
3862
|
request['tpslMode'] = 'Partial'
|
|
3455
3863
|
request['tpOrderType'] = 'Limit'
|
|
3456
|
-
request['tpLimitPrice'] =
|
|
3457
|
-
request['tpSize'] =
|
|
3864
|
+
request['tpLimitPrice'] = priceString
|
|
3865
|
+
request['tpSize'] = amountString
|
|
3458
3866
|
else:
|
|
3459
3867
|
request['side'] = self.capitalize(side)
|
|
3460
3868
|
request['orderType'] = self.capitalize(lowerCaseType)
|
|
@@ -3482,15 +3890,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3482
3890
|
# mandatory field for options
|
|
3483
3891
|
request['orderLinkId'] = self.uuid16()
|
|
3484
3892
|
if isLimit:
|
|
3485
|
-
request['price'] =
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
request['category'] = 'linear'
|
|
3490
|
-
elif market['inverse']:
|
|
3491
|
-
request['category'] = 'inverse'
|
|
3492
|
-
elif market['option']:
|
|
3493
|
-
request['category'] = 'option'
|
|
3893
|
+
request['price'] = priceString
|
|
3894
|
+
category = None
|
|
3895
|
+
category, params = self.get_bybit_type('createOrderRequest', market, params)
|
|
3896
|
+
request['category'] = category
|
|
3494
3897
|
cost = self.safe_string(params, 'cost')
|
|
3495
3898
|
params = self.omit(params, 'cost')
|
|
3496
3899
|
# if the cost is inferable, let's keep the old logic and ignore marketUnit, to minimize the impact of the changes
|
|
@@ -3503,36 +3906,37 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3503
3906
|
if cost is not None:
|
|
3504
3907
|
orderCost = cost
|
|
3505
3908
|
else:
|
|
3506
|
-
amountString = self.number_to_string(amount)
|
|
3507
|
-
priceString = self.number_to_string(price)
|
|
3508
3909
|
quoteAmount = Precise.string_mul(amountString, priceString)
|
|
3509
3910
|
orderCost = quoteAmount
|
|
3510
|
-
request['qty'] = self.
|
|
3911
|
+
request['qty'] = self.get_cost(symbol, orderCost)
|
|
3511
3912
|
else:
|
|
3512
3913
|
request['marketUnit'] = 'baseCoin'
|
|
3513
|
-
request['qty'] =
|
|
3914
|
+
request['qty'] = amountString
|
|
3514
3915
|
elif market['spot'] and (type == 'market') and (side == 'buy'):
|
|
3515
3916
|
# classic accounts
|
|
3516
3917
|
# for market buy it requires the amount of quote currency to spend
|
|
3517
3918
|
createMarketBuyOrderRequiresPrice = True
|
|
3518
|
-
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice'
|
|
3919
|
+
createMarketBuyOrderRequiresPrice, params = self.handle_option_and_params(params, 'createOrder', 'createMarketBuyOrderRequiresPrice')
|
|
3519
3920
|
if createMarketBuyOrderRequiresPrice:
|
|
3520
3921
|
if (price is None) and (cost is None):
|
|
3521
3922
|
raise InvalidOrder(self.id + ' createOrder() requires the price argument for market buy orders to calculate the total cost to spend(amount * price), alternatively set the createMarketBuyOrderRequiresPrice option or param to False and pass the cost to spend in the amount argument')
|
|
3522
3923
|
else:
|
|
3523
|
-
|
|
3524
|
-
priceString = self.number_to_string(price)
|
|
3525
|
-
quoteAmount = Precise.string_mul(amountString, priceString)
|
|
3924
|
+
quoteAmount = Precise.string_mul(self.number_to_string(amount), priceString)
|
|
3526
3925
|
costRequest = cost if (cost is not None) else quoteAmount
|
|
3527
|
-
request['qty'] = self.
|
|
3926
|
+
request['qty'] = self.get_cost(symbol, costRequest)
|
|
3528
3927
|
else:
|
|
3529
|
-
|
|
3928
|
+
if cost is not None:
|
|
3929
|
+
request['qty'] = self.get_cost(symbol, self.number_to_string(cost))
|
|
3930
|
+
elif price is not None:
|
|
3931
|
+
request['qty'] = self.get_cost(symbol, Precise.string_mul(amountString, priceString))
|
|
3932
|
+
else:
|
|
3933
|
+
request['qty'] = amountString
|
|
3530
3934
|
else:
|
|
3531
3935
|
if not isTrailingAmountOrder and not isAlternativeEndpoint:
|
|
3532
|
-
request['qty'] =
|
|
3936
|
+
request['qty'] = amountString
|
|
3533
3937
|
if isTrailingAmountOrder:
|
|
3534
3938
|
if trailingTriggerPrice is not None:
|
|
3535
|
-
request['activePrice'] = self.
|
|
3939
|
+
request['activePrice'] = self.get_price(symbol, trailingTriggerPrice)
|
|
3536
3940
|
request['trailingStop'] = trailingAmount
|
|
3537
3941
|
elif isTriggerOrder and not isAlternativeEndpoint:
|
|
3538
3942
|
triggerDirection = self.safe_string(params, 'triggerDirection')
|
|
@@ -3542,43 +3946,51 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3542
3946
|
raise NotSupported(self.id + ' createOrder() : trigger order does not support triggerDirection for spot markets yet')
|
|
3543
3947
|
else:
|
|
3544
3948
|
if triggerDirection is None:
|
|
3545
|
-
raise ArgumentsRequired(self.id + ' stop/trigger orders require a triggerDirection parameter, either "
|
|
3546
|
-
isAsending = ((triggerDirection == 'above') or (triggerDirection == '1'))
|
|
3949
|
+
raise ArgumentsRequired(self.id + ' stop/trigger orders require a triggerDirection parameter, either "ascending" or "descending" to determine the direction of the trigger.')
|
|
3950
|
+
isAsending = ((triggerDirection == 'ascending') or (triggerDirection == 'above') or (triggerDirection == '1'))
|
|
3547
3951
|
request['triggerDirection'] = 1 if isAsending else 2
|
|
3548
|
-
request['triggerPrice'] = self.
|
|
3952
|
+
request['triggerPrice'] = self.get_price(symbol, triggerPrice)
|
|
3549
3953
|
elif (isStopLossTriggerOrder or isTakeProfitTriggerOrder) and not isAlternativeEndpoint:
|
|
3550
3954
|
if isBuy:
|
|
3551
3955
|
request['triggerDirection'] = 1 if isStopLossTriggerOrder else 2
|
|
3552
3956
|
else:
|
|
3553
3957
|
request['triggerDirection'] = 2 if isStopLossTriggerOrder else 1
|
|
3554
3958
|
triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
|
|
3555
|
-
request['triggerPrice'] = self.
|
|
3959
|
+
request['triggerPrice'] = self.get_price(symbol, triggerPrice)
|
|
3556
3960
|
request['reduceOnly'] = True
|
|
3557
3961
|
if (isStopLoss or isTakeProfit) and not isAlternativeEndpoint:
|
|
3558
3962
|
if isStopLoss:
|
|
3559
3963
|
slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
|
|
3560
|
-
request['stopLoss'] = self.
|
|
3964
|
+
request['stopLoss'] = self.get_price(symbol, slTriggerPrice)
|
|
3561
3965
|
slLimitPrice = self.safe_value(stopLoss, 'price')
|
|
3562
3966
|
if slLimitPrice is not None:
|
|
3563
3967
|
request['tpslMode'] = 'Partial'
|
|
3564
3968
|
request['slOrderType'] = 'Limit'
|
|
3565
|
-
request['slLimitPrice'] = self.
|
|
3969
|
+
request['slLimitPrice'] = self.get_price(symbol, slLimitPrice)
|
|
3566
3970
|
if isTakeProfit:
|
|
3567
3971
|
tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
|
|
3568
|
-
request['takeProfit'] = self.
|
|
3972
|
+
request['takeProfit'] = self.get_price(symbol, tpTriggerPrice)
|
|
3569
3973
|
tpLimitPrice = self.safe_value(takeProfit, 'price')
|
|
3570
3974
|
if tpLimitPrice is not None:
|
|
3571
3975
|
request['tpslMode'] = 'Partial'
|
|
3572
3976
|
request['tpOrderType'] = 'Limit'
|
|
3573
|
-
request['tpLimitPrice'] = self.
|
|
3574
|
-
|
|
3977
|
+
request['tpLimitPrice'] = self.get_price(symbol, tpLimitPrice)
|
|
3978
|
+
if not market['spot'] and hedged:
|
|
3979
|
+
if reduceOnly:
|
|
3980
|
+
params = self.omit(params, 'reduceOnly')
|
|
3981
|
+
side = 'sell' if (side == 'buy') else 'buy'
|
|
3982
|
+
request['positionIdx'] = 1 if (side == 'buy') else 2
|
|
3983
|
+
params = self.omit(params, ['stopPrice', 'timeInForce', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId', 'triggerPrice', 'stopLoss', 'takeProfit', 'trailingAmount', 'trailingTriggerPrice', 'hedged'])
|
|
3575
3984
|
return self.extend(request, params)
|
|
3576
3985
|
|
|
3577
|
-
def create_orders(self, orders: List[OrderRequest], params={}):
|
|
3986
|
+
def create_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
|
|
3578
3987
|
"""
|
|
3579
3988
|
create a list of trade orders
|
|
3580
|
-
|
|
3989
|
+
|
|
3990
|
+
https://bybit-exchange.github.io/docs/v5/order/batch-place
|
|
3991
|
+
|
|
3581
3992
|
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
|
3993
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
3582
3994
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
3583
3995
|
"""
|
|
3584
3996
|
self.load_markets()
|
|
@@ -3594,15 +4006,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3594
4006
|
side = self.safe_string(rawOrder, 'side')
|
|
3595
4007
|
amount = self.safe_value(rawOrder, 'amount')
|
|
3596
4008
|
price = self.safe_value(rawOrder, 'price')
|
|
3597
|
-
orderParams = self.
|
|
4009
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
|
3598
4010
|
orderRequest = self.create_order_request(marketId, type, side, amount, price, orderParams, isUta)
|
|
4011
|
+
del orderRequest['category']
|
|
3599
4012
|
ordersRequests.append(orderRequest)
|
|
3600
4013
|
symbols = self.market_symbols(orderSymbols, None, False, True, True)
|
|
3601
4014
|
market = self.market(symbols[0])
|
|
4015
|
+
unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 6)
|
|
3602
4016
|
category = None
|
|
3603
4017
|
category, params = self.get_bybit_type('createOrders', market, params)
|
|
3604
|
-
if category == 'inverse':
|
|
3605
|
-
raise NotSupported(self.id + ' createOrders does not allow inverse orders')
|
|
4018
|
+
if (category == 'inverse') and (unifiedMarginStatus < 5):
|
|
4019
|
+
raise NotSupported(self.id + ' createOrders does not allow inverse orders for non UTA2.0 account')
|
|
3606
4020
|
request: dict = {
|
|
3607
4021
|
'category': category,
|
|
3608
4022
|
'request': ordersRequests,
|
|
@@ -3657,165 +4071,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3657
4071
|
#
|
|
3658
4072
|
return self.parse_orders(data)
|
|
3659
4073
|
|
|
3660
|
-
def create_usdc_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
|
3661
|
-
self.load_markets()
|
|
3662
|
-
market = self.market(symbol)
|
|
3663
|
-
if type == 'market':
|
|
3664
|
-
raise NotSupported(self.id + ' createOrder does not allow market orders for ' + symbol + ' markets')
|
|
3665
|
-
lowerCaseType = type.lower()
|
|
3666
|
-
if (price is None) and (lowerCaseType == 'limit'):
|
|
3667
|
-
raise ArgumentsRequired(self.id + ' createOrder requires a price argument for limit orders')
|
|
3668
|
-
request: dict = {
|
|
3669
|
-
'symbol': market['id'],
|
|
3670
|
-
'side': self.capitalize(side),
|
|
3671
|
-
'orderType': self.capitalize(lowerCaseType), # limit or market
|
|
3672
|
-
'timeInForce': 'GoodTillCancel', # ImmediateOrCancel, FillOrKill, PostOnly
|
|
3673
|
-
'orderQty': self.amount_to_precision(symbol, amount),
|
|
3674
|
-
# 'takeProfit': 123.45, # take profit price, only take effect upon opening the position
|
|
3675
|
-
# 'stopLoss': 123.45, # stop loss price, only take effect upon opening the position
|
|
3676
|
-
# 'reduceOnly': False, # reduce only, required for linear orders
|
|
3677
|
-
# when creating a closing order, bybit recommends a True value for
|
|
3678
|
-
# closeOnTrigger to avoid failing due to insufficient available margin
|
|
3679
|
-
# 'closeOnTrigger': False, required for linear orders
|
|
3680
|
-
# 'orderLinkId': 'string', # unique client order id, max 36 characters
|
|
3681
|
-
# 'triggerPrice': 123.45, # trigger price, required for conditional orders
|
|
3682
|
-
# 'trigger_by': 'MarkPrice', # IndexPrice, MarkPrice
|
|
3683
|
-
# 'tptriggerby': 'MarkPrice', # IndexPrice, MarkPrice
|
|
3684
|
-
# 'slTriggerBy': 'MarkPrice', # IndexPrice, MarkPrice
|
|
3685
|
-
# 'orderFilter': 'Order' or 'StopOrder'
|
|
3686
|
-
# 'mmp': False # market maker protection
|
|
3687
|
-
}
|
|
3688
|
-
isMarket = lowerCaseType == 'market'
|
|
3689
|
-
isLimit = lowerCaseType == 'limit'
|
|
3690
|
-
if isLimit is not None:
|
|
3691
|
-
request['orderPrice'] = self.price_to_precision(symbol, price)
|
|
3692
|
-
exchangeSpecificParam = self.safe_string(params, 'time_in_force')
|
|
3693
|
-
timeInForce = self.safe_string_lower(params, 'timeInForce')
|
|
3694
|
-
postOnly = self.is_post_only(isMarket, exchangeSpecificParam == 'PostOnly', params)
|
|
3695
|
-
if postOnly:
|
|
3696
|
-
request['time_in_force'] = 'PostOnly'
|
|
3697
|
-
elif timeInForce == 'gtc':
|
|
3698
|
-
request['time_in_force'] = 'GoodTillCancel'
|
|
3699
|
-
elif timeInForce == 'fok':
|
|
3700
|
-
request['time_in_force'] = 'FillOrKill'
|
|
3701
|
-
elif timeInForce == 'ioc':
|
|
3702
|
-
request['time_in_force'] = 'ImmediateOrCancel'
|
|
3703
|
-
if market['swap']:
|
|
3704
|
-
triggerPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
|
|
3705
|
-
stopLossTriggerPrice = self.safe_value(params, 'stopLossPrice', triggerPrice)
|
|
3706
|
-
takeProfitTriggerPrice = self.safe_value(params, 'takeProfitPrice')
|
|
3707
|
-
stopLoss = self.safe_value(params, 'stopLoss')
|
|
3708
|
-
takeProfit = self.safe_value(params, 'takeProfit')
|
|
3709
|
-
isStopLossTriggerOrder = stopLossTriggerPrice is not None
|
|
3710
|
-
isTakeProfitTriggerOrder = takeProfitTriggerPrice is not None
|
|
3711
|
-
isStopLoss = stopLoss is not None
|
|
3712
|
-
isTakeProfit = takeProfit is not None
|
|
3713
|
-
isStopOrder = isStopLossTriggerOrder or isTakeProfitTriggerOrder
|
|
3714
|
-
if isStopOrder:
|
|
3715
|
-
request['orderFilter'] = 'StopOrder'
|
|
3716
|
-
request['trigger_by'] = 'LastPrice'
|
|
3717
|
-
stopPx = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
|
|
3718
|
-
preciseStopPrice = self.price_to_precision(symbol, stopPx)
|
|
3719
|
-
request['triggerPrice'] = preciseStopPrice
|
|
3720
|
-
delta = self.number_to_string(market['precision']['price'])
|
|
3721
|
-
request['basePrice'] = Precise.string_sub(preciseStopPrice, delta) if isStopLossTriggerOrder else Precise.string_add(preciseStopPrice, delta)
|
|
3722
|
-
elif isStopLoss or isTakeProfit:
|
|
3723
|
-
if isStopLoss:
|
|
3724
|
-
slTriggerPrice = self.safe_value_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
|
|
3725
|
-
request['stopLoss'] = self.price_to_precision(symbol, slTriggerPrice)
|
|
3726
|
-
if isTakeProfit:
|
|
3727
|
-
tpTriggerPrice = self.safe_value_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
|
|
3728
|
-
request['takeProfit'] = self.price_to_precision(symbol, tpTriggerPrice)
|
|
3729
|
-
else:
|
|
3730
|
-
request['orderFilter'] = 'Order'
|
|
3731
|
-
clientOrderId = self.safe_string(params, 'clientOrderId')
|
|
3732
|
-
if clientOrderId is not None:
|
|
3733
|
-
request['orderLinkId'] = clientOrderId
|
|
3734
|
-
elif market['option']:
|
|
3735
|
-
# mandatory field for options
|
|
3736
|
-
request['orderLinkId'] = self.uuid16()
|
|
3737
|
-
params = self.omit(params, ['stopPrice', 'timeInForce', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'postOnly', 'clientOrderId'])
|
|
3738
|
-
response = None
|
|
3739
|
-
if market['option']:
|
|
3740
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1PlaceOrder(self.extend(request, params))
|
|
3741
|
-
else:
|
|
3742
|
-
response = self.privatePostPerpetualUsdcOpenapiPrivateV1PlaceOrder(self.extend(request, params))
|
|
3743
|
-
#
|
|
3744
|
-
# {
|
|
3745
|
-
# "retCode":0,
|
|
3746
|
-
# "retMsg":"",
|
|
3747
|
-
# "result":{
|
|
3748
|
-
# "orderId":"34450a59-325e-4296-8af0-63c7c524ae33",
|
|
3749
|
-
# "orderLinkId":"",
|
|
3750
|
-
# "mmp":false,
|
|
3751
|
-
# "symbol":"BTCPERP",
|
|
3752
|
-
# "orderType":"Limit",
|
|
3753
|
-
# "side":"Buy",
|
|
3754
|
-
# "orderQty":"0.00100000",
|
|
3755
|
-
# "orderPrice":"20000.00",
|
|
3756
|
-
# "iv":"0",
|
|
3757
|
-
# "timeInForce":"GoodTillCancel",
|
|
3758
|
-
# "orderStatus":"Created",
|
|
3759
|
-
# "createdAt":"1652261746007873",
|
|
3760
|
-
# "basePrice":"0.00",
|
|
3761
|
-
# "triggerPrice":"0.00",
|
|
3762
|
-
# "takeProfit":"0.00",
|
|
3763
|
-
# "stopLoss":"0.00",
|
|
3764
|
-
# "slTriggerBy":"UNKNOWN",
|
|
3765
|
-
# "tpTriggerBy":"UNKNOWN"
|
|
3766
|
-
# }
|
|
3767
|
-
#
|
|
3768
|
-
order = self.safe_dict(response, 'result', {})
|
|
3769
|
-
return self.parse_order(order, market)
|
|
3770
|
-
|
|
3771
|
-
def edit_usdc_order(self, id, symbol, type, side, amount=None, price=None, params={}):
|
|
3772
|
-
self.load_markets()
|
|
3773
|
-
market = self.market(symbol)
|
|
3774
|
-
request: dict = {
|
|
3775
|
-
'symbol': market['id'],
|
|
3776
|
-
'orderId': id,
|
|
3777
|
-
}
|
|
3778
|
-
if amount is not None:
|
|
3779
|
-
request['orderQty'] = self.amount_to_precision(symbol, amount)
|
|
3780
|
-
if price is not None:
|
|
3781
|
-
request['orderPrice'] = self.price_to_precision(symbol, price)
|
|
3782
|
-
response = None
|
|
3783
|
-
if market['option']:
|
|
3784
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
|
|
3785
|
-
else:
|
|
3786
|
-
isStop = self.safe_bool_2(params, 'stop', 'trigger', False)
|
|
3787
|
-
triggerPrice = self.safe_value_2(params, 'stopPrice', 'triggerPrice')
|
|
3788
|
-
stopLossPrice = self.safe_value(params, 'stopLossPrice')
|
|
3789
|
-
isStopLossOrder = stopLossPrice is not None
|
|
3790
|
-
takeProfitPrice = self.safe_value(params, 'takeProfitPrice')
|
|
3791
|
-
isTakeProfitOrder = takeProfitPrice is not None
|
|
3792
|
-
isStopOrder = isStopLossOrder or isTakeProfitOrder or isStop
|
|
3793
|
-
if isStopOrder:
|
|
3794
|
-
request['orderFilter'] = 'StopOrder' if isStop else 'Order'
|
|
3795
|
-
if triggerPrice is not None:
|
|
3796
|
-
request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
|
|
3797
|
-
if stopLossPrice is not None:
|
|
3798
|
-
request['stopLoss'] = self.price_to_precision(symbol, stopLossPrice)
|
|
3799
|
-
if takeProfitPrice is not None:
|
|
3800
|
-
request['takeProfit'] = self.price_to_precision(symbol, takeProfitPrice)
|
|
3801
|
-
params = self.omit(params, ['stop', 'stopPrice', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice'])
|
|
3802
|
-
response = self.privatePostPerpetualUsdcOpenapiPrivateV1ReplaceOrder(self.extend(request, params))
|
|
3803
|
-
#
|
|
3804
|
-
# {
|
|
3805
|
-
# "retCode": 0,
|
|
3806
|
-
# "retMsg": "OK",
|
|
3807
|
-
# "result": {
|
|
3808
|
-
# "outRequestId": "",
|
|
3809
|
-
# "symbol": "BTC-13MAY22-40000-C",
|
|
3810
|
-
# "orderId": "8c65df91-91fc-461d-9b14-786379ef138c",
|
|
3811
|
-
# "orderLinkId": "AAAAA41133"
|
|
3812
|
-
# },
|
|
3813
|
-
# "retExtMap": {}
|
|
3814
|
-
# }
|
|
3815
|
-
#
|
|
3816
|
-
result = self.safe_dict(response, 'result', {})
|
|
3817
|
-
return self.parse_order(result, market)
|
|
3818
|
-
|
|
3819
4074
|
def edit_order_request(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
|
|
3820
4075
|
market = self.market(symbol)
|
|
3821
4076
|
request: dict = {
|
|
@@ -3831,20 +4086,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3831
4086
|
# Valid for option only.
|
|
3832
4087
|
# 'orderIv': '0', # Implied volatility; parameters are passed according to the real value; for example, for 10%, 0.1 is passed
|
|
3833
4088
|
}
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
|
|
3837
|
-
request['category'] = 'linear'
|
|
3838
|
-
elif market['inverse']:
|
|
3839
|
-
request['category'] = 'inverse'
|
|
3840
|
-
elif market['option']:
|
|
3841
|
-
request['category'] = 'option'
|
|
4089
|
+
category = None
|
|
4090
|
+
category, params = self.get_bybit_type('editOrderRequest', market, params)
|
|
4091
|
+
request['category'] = category
|
|
3842
4092
|
if amount is not None:
|
|
3843
|
-
request['qty'] = self.
|
|
4093
|
+
request['qty'] = self.get_amount(symbol, amount)
|
|
3844
4094
|
if price is not None:
|
|
3845
|
-
request['price'] = self.
|
|
3846
|
-
if amount is not None:
|
|
3847
|
-
request['qty'] = self.amount_to_precision(symbol, amount)
|
|
4095
|
+
request['price'] = self.get_price(symbol, self.number_to_string(price))
|
|
3848
4096
|
triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
|
|
3849
4097
|
stopLossTriggerPrice = self.safe_string(params, 'stopLossPrice')
|
|
3850
4098
|
takeProfitTriggerPrice = self.safe_string(params, 'takeProfitPrice')
|
|
@@ -3857,20 +4105,20 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3857
4105
|
if isStopLossTriggerOrder or isTakeProfitTriggerOrder:
|
|
3858
4106
|
triggerPrice = stopLossTriggerPrice if isStopLossTriggerOrder else takeProfitTriggerPrice
|
|
3859
4107
|
if triggerPrice is not None:
|
|
3860
|
-
triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.
|
|
4108
|
+
triggerPriceRequest = triggerPrice if (triggerPrice == '0') else self.get_price(symbol, triggerPrice)
|
|
3861
4109
|
request['triggerPrice'] = triggerPriceRequest
|
|
3862
4110
|
triggerBy = self.safe_string(params, 'triggerBy', 'LastPrice')
|
|
3863
4111
|
request['triggerBy'] = triggerBy
|
|
3864
4112
|
if isStopLoss or isTakeProfit:
|
|
3865
4113
|
if isStopLoss:
|
|
3866
4114
|
slTriggerPrice = self.safe_string_2(stopLoss, 'triggerPrice', 'stopPrice', stopLoss)
|
|
3867
|
-
stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.
|
|
4115
|
+
stopLossRequest = slTriggerPrice if (slTriggerPrice == '0') else self.get_price(symbol, slTriggerPrice)
|
|
3868
4116
|
request['stopLoss'] = stopLossRequest
|
|
3869
4117
|
slTriggerBy = self.safe_string(params, 'slTriggerBy', 'LastPrice')
|
|
3870
4118
|
request['slTriggerBy'] = slTriggerBy
|
|
3871
4119
|
if isTakeProfit:
|
|
3872
4120
|
tpTriggerPrice = self.safe_string_2(takeProfit, 'triggerPrice', 'stopPrice', takeProfit)
|
|
3873
|
-
takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.
|
|
4121
|
+
takeProfitRequest = tpTriggerPrice if (tpTriggerPrice == '0') else self.get_price(symbol, tpTriggerPrice)
|
|
3874
4122
|
request['takeProfit'] = takeProfitRequest
|
|
3875
4123
|
tpTriggerBy = self.safe_string(params, 'tpTriggerBy', 'LastPrice')
|
|
3876
4124
|
request['tpTriggerBy'] = tpTriggerBy
|
|
@@ -3880,18 +4128,20 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3880
4128
|
params = self.omit(params, ['stopPrice', 'stopLossPrice', 'takeProfitPrice', 'triggerPrice', 'clientOrderId', 'stopLoss', 'takeProfit'])
|
|
3881
4129
|
return request
|
|
3882
4130
|
|
|
3883
|
-
def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
|
|
4131
|
+
def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}) -> Order:
|
|
3884
4132
|
"""
|
|
3885
4133
|
edit a trade order
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
4134
|
+
|
|
4135
|
+
https://bybit-exchange.github.io/docs/v5/order/amend-order
|
|
4136
|
+
https://bybit-exchange.github.io/docs/derivatives/unified/replace-order
|
|
4137
|
+
https://bybit-exchange.github.io/docs/api-explorer/derivatives/trade/contract/replace-order
|
|
4138
|
+
|
|
3889
4139
|
:param str id: cancel order id
|
|
3890
4140
|
:param str symbol: unified symbol of the market to create an order in
|
|
3891
4141
|
:param str type: 'market' or 'limit'
|
|
3892
4142
|
:param str side: 'buy' or 'sell'
|
|
3893
4143
|
:param float amount: how much of currency you want to trade in units of base currency
|
|
3894
|
-
:param float price: the price at which the order is to be
|
|
4144
|
+
:param float price: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
|
|
3895
4145
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
3896
4146
|
:param float [params.triggerPrice]: The price that a trigger order is triggered at
|
|
3897
4147
|
:param float [params.stopLossPrice]: The price that a stop loss order is triggered at
|
|
@@ -3908,12 +4158,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3908
4158
|
self.load_markets()
|
|
3909
4159
|
if symbol is None:
|
|
3910
4160
|
raise ArgumentsRequired(self.id + ' editOrder() requires a symbol argument')
|
|
3911
|
-
market = self.market(symbol)
|
|
3912
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
3913
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
3914
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
3915
|
-
if isUsdcSettled and not isUnifiedAccount:
|
|
3916
|
-
return self.edit_usdc_order(id, symbol, type, side, amount, price, params)
|
|
3917
4161
|
request = self.edit_order_request(id, symbol, type, side, amount, price, params)
|
|
3918
4162
|
response = self.privatePostV5OrderAmend(self.extend(request, params))
|
|
3919
4163
|
#
|
|
@@ -3934,41 +4178,90 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3934
4178
|
'id': self.safe_string(result, 'orderId'),
|
|
3935
4179
|
})
|
|
3936
4180
|
|
|
3937
|
-
def
|
|
3938
|
-
|
|
3939
|
-
|
|
4181
|
+
def edit_orders(self, orders: List[OrderRequest], params={}) -> List[Order]:
|
|
4182
|
+
"""
|
|
4183
|
+
edit a list of trade orders
|
|
4184
|
+
|
|
4185
|
+
https://bybit-exchange.github.io/docs/v5/order/batch-amend
|
|
4186
|
+
|
|
4187
|
+
:param Array orders: list of orders to create, each object should contain the parameters required by createOrder, namely symbol, type, side, amount, price and params
|
|
4188
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4189
|
+
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
4190
|
+
"""
|
|
3940
4191
|
self.load_markets()
|
|
3941
|
-
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
3945
|
-
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
4192
|
+
ordersRequests = []
|
|
4193
|
+
orderSymbols = []
|
|
4194
|
+
for i in range(0, len(orders)):
|
|
4195
|
+
rawOrder = orders[i]
|
|
4196
|
+
symbol = self.safe_string(rawOrder, 'symbol')
|
|
4197
|
+
orderSymbols.append(symbol)
|
|
4198
|
+
id = self.safe_string(rawOrder, 'id')
|
|
4199
|
+
type = self.safe_string(rawOrder, 'type')
|
|
4200
|
+
side = self.safe_string(rawOrder, 'side')
|
|
4201
|
+
amount = self.safe_value(rawOrder, 'amount')
|
|
4202
|
+
price = self.safe_value(rawOrder, 'price')
|
|
4203
|
+
orderParams = self.safe_dict(rawOrder, 'params', {})
|
|
4204
|
+
orderRequest = self.edit_order_request(id, symbol, type, side, amount, price, orderParams)
|
|
4205
|
+
del orderRequest['category']
|
|
4206
|
+
ordersRequests.append(orderRequest)
|
|
4207
|
+
orderSymbols = self.market_symbols(orderSymbols, None, False, True, True)
|
|
4208
|
+
market = self.market(orderSymbols[0])
|
|
4209
|
+
unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 6)
|
|
4210
|
+
category = None
|
|
4211
|
+
category, params = self.get_bybit_type('editOrders', market, params)
|
|
4212
|
+
if (category == 'inverse') and (unifiedMarginStatus < 5):
|
|
4213
|
+
raise NotSupported(self.id + ' editOrders does not allow inverse orders for non UTA2.0 account')
|
|
4214
|
+
request: dict = {
|
|
4215
|
+
'category': category,
|
|
4216
|
+
'request': ordersRequests,
|
|
4217
|
+
}
|
|
4218
|
+
response = self.privatePostV5OrderAmendBatch(self.extend(request, params))
|
|
4219
|
+
result = self.safe_dict(response, 'result', {})
|
|
4220
|
+
data = self.safe_list(result, 'list', [])
|
|
4221
|
+
retInfo = self.safe_dict(response, 'retExtInfo', {})
|
|
4222
|
+
codes = self.safe_list(retInfo, 'list', [])
|
|
4223
|
+
# self.extend the error with the unsuccessful orders
|
|
4224
|
+
for i in range(0, len(codes)):
|
|
4225
|
+
code = codes[i]
|
|
4226
|
+
retCode = self.safe_integer(code, 'code')
|
|
4227
|
+
if retCode != 0:
|
|
4228
|
+
data[i] = self.extend(data[i], code)
|
|
3957
4229
|
#
|
|
3958
|
-
#
|
|
3959
|
-
#
|
|
3960
|
-
#
|
|
3961
|
-
#
|
|
3962
|
-
#
|
|
3963
|
-
#
|
|
3964
|
-
#
|
|
3965
|
-
#
|
|
3966
|
-
#
|
|
3967
|
-
#
|
|
3968
|
-
#
|
|
4230
|
+
# {
|
|
4231
|
+
# "retCode": 0,
|
|
4232
|
+
# "retMsg": "OK",
|
|
4233
|
+
# "result": {
|
|
4234
|
+
# "list": [
|
|
4235
|
+
# {
|
|
4236
|
+
# "category": "option",
|
|
4237
|
+
# "symbol": "ETH-30DEC22-500-C",
|
|
4238
|
+
# "orderId": "b551f227-7059-4fb5-a6a6-699c04dbd2f2",
|
|
4239
|
+
# "orderLinkId": ""
|
|
4240
|
+
# },
|
|
4241
|
+
# {
|
|
4242
|
+
# "category": "option",
|
|
4243
|
+
# "symbol": "ETH-30DEC22-700-C",
|
|
4244
|
+
# "orderId": "fa6a595f-1a57-483f-b9d3-30e9c8235a52",
|
|
4245
|
+
# "orderLinkId": ""
|
|
4246
|
+
# }
|
|
4247
|
+
# ]
|
|
4248
|
+
# },
|
|
4249
|
+
# "retExtInfo": {
|
|
4250
|
+
# "list": [
|
|
4251
|
+
# {
|
|
4252
|
+
# "code": 0,
|
|
4253
|
+
# "msg": "OK"
|
|
4254
|
+
# },
|
|
4255
|
+
# {
|
|
4256
|
+
# "code": 0,
|
|
4257
|
+
# "msg": "OK"
|
|
4258
|
+
# }
|
|
4259
|
+
# ]
|
|
4260
|
+
# },
|
|
4261
|
+
# "time": 1672222808060
|
|
4262
|
+
# }
|
|
3969
4263
|
#
|
|
3970
|
-
|
|
3971
|
-
return self.parse_order(result, market)
|
|
4264
|
+
return self.parse_orders(data)
|
|
3972
4265
|
|
|
3973
4266
|
def cancel_order_request(self, id: str, symbol: Str = None, params={}):
|
|
3974
4267
|
market = self.market(symbol)
|
|
@@ -3981,29 +4274,27 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
3981
4274
|
}
|
|
3982
4275
|
if market['spot']:
|
|
3983
4276
|
# only works for spot market
|
|
3984
|
-
|
|
4277
|
+
isTrigger = self.safe_bool_2(params, 'stop', 'trigger', False)
|
|
3985
4278
|
params = self.omit(params, ['stop', 'trigger'])
|
|
3986
|
-
request['orderFilter'] = 'StopOrder' if
|
|
4279
|
+
request['orderFilter'] = 'StopOrder' if isTrigger else 'Order'
|
|
3987
4280
|
if id is not None: # The user can also use argument params["orderLinkId"]
|
|
3988
4281
|
request['orderId'] = id
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
request['category'] = 'linear'
|
|
3993
|
-
elif market['inverse']:
|
|
3994
|
-
request['category'] = 'inverse'
|
|
3995
|
-
elif market['option']:
|
|
3996
|
-
request['category'] = 'option'
|
|
4282
|
+
category = None
|
|
4283
|
+
category, params = self.get_bybit_type('cancelOrderRequest', market, params)
|
|
4284
|
+
request['category'] = category
|
|
3997
4285
|
return self.extend(request, params)
|
|
3998
4286
|
|
|
3999
|
-
def cancel_order(self, id: str, symbol: Str = None, params={}):
|
|
4287
|
+
def cancel_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
4000
4288
|
"""
|
|
4001
4289
|
cancels an open order
|
|
4002
|
-
|
|
4290
|
+
|
|
4291
|
+
https://bybit-exchange.github.io/docs/v5/order/cancel-order
|
|
4292
|
+
|
|
4003
4293
|
:param str id: order id
|
|
4004
4294
|
:param str symbol: unified symbol of the market the order was made in
|
|
4005
4295
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4006
|
-
:param boolean [params.
|
|
4296
|
+
:param boolean [params.trigger]: *spot only* whether the order is a trigger order
|
|
4297
|
+
:param boolean [params.stop]: alias for trigger
|
|
4007
4298
|
:param str [params.orderFilter]: *spot only* 'Order' or 'StopOrder' or 'tpslOrder'
|
|
4008
4299
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
4009
4300
|
"""
|
|
@@ -4011,11 +4302,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4011
4302
|
raise ArgumentsRequired(self.id + ' cancelOrder() requires a symbol argument')
|
|
4012
4303
|
self.load_markets()
|
|
4013
4304
|
market = self.market(symbol)
|
|
4014
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
4015
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
4016
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
4017
|
-
if isUsdcSettled and not isUnifiedAccount:
|
|
4018
|
-
return self.cancel_usdc_order(id, symbol, params)
|
|
4019
4305
|
requestExtended = self.cancel_order_request(id, symbol, params)
|
|
4020
4306
|
response = self.privatePostV5OrderCancel(requestExtended)
|
|
4021
4307
|
#
|
|
@@ -4033,10 +4319,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4033
4319
|
result = self.safe_dict(response, 'result', {})
|
|
4034
4320
|
return self.parse_order(result, market)
|
|
4035
4321
|
|
|
4036
|
-
def cancel_orders(self, ids, symbol: Str = None, params={}):
|
|
4322
|
+
def cancel_orders(self, ids, symbol: Str = None, params={}) -> List[Order]:
|
|
4037
4323
|
"""
|
|
4038
4324
|
cancel multiple orders
|
|
4039
|
-
|
|
4325
|
+
|
|
4326
|
+
https://bybit-exchange.github.io/docs/v5/order/batch-cancel
|
|
4327
|
+
|
|
4040
4328
|
:param str[] ids: order ids
|
|
4041
4329
|
:param str symbol: unified symbol of the market the order was made in
|
|
4042
4330
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -4047,6 +4335,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4047
4335
|
raise ArgumentsRequired(self.id + ' cancelOrders() requires a symbol argument')
|
|
4048
4336
|
self.load_markets()
|
|
4049
4337
|
market = self.market(symbol)
|
|
4338
|
+
types = self.is_unified_enabled()
|
|
4339
|
+
enableUnifiedAccount = types[1]
|
|
4340
|
+
if not enableUnifiedAccount:
|
|
4341
|
+
raise NotSupported(self.id + ' cancelOrders() supports UTA accounts only')
|
|
4050
4342
|
category = None
|
|
4051
4343
|
category, params = self.get_bybit_type('cancelOrders', market, params)
|
|
4052
4344
|
if category == 'inverse':
|
|
@@ -4108,17 +4400,54 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4108
4400
|
row = self.safe_list(result, 'list', [])
|
|
4109
4401
|
return self.parse_orders(row, market)
|
|
4110
4402
|
|
|
4403
|
+
def cancel_all_orders_after(self, timeout: Int, params={}):
|
|
4404
|
+
"""
|
|
4405
|
+
dead man's switch, cancel all orders after the given timeout
|
|
4406
|
+
|
|
4407
|
+
https://bybit-exchange.github.io/docs/v5/order/dcp
|
|
4408
|
+
|
|
4409
|
+
:param number timeout: time in milliseconds
|
|
4410
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4411
|
+
:param str [params.product]: OPTIONS, DERIVATIVES, SPOT, default is 'DERIVATIVES'
|
|
4412
|
+
:returns dict: the api result
|
|
4413
|
+
"""
|
|
4414
|
+
self.load_markets()
|
|
4415
|
+
request: dict = {
|
|
4416
|
+
'timeWindow': self.parse_to_int(timeout / 1000),
|
|
4417
|
+
}
|
|
4418
|
+
type: Str = None
|
|
4419
|
+
type, params = self.handle_market_type_and_params('cancelAllOrdersAfter', None, params, 'swap')
|
|
4420
|
+
productMap = {
|
|
4421
|
+
'spot': 'SPOT',
|
|
4422
|
+
'swap': 'DERIVATIVES',
|
|
4423
|
+
'option': 'OPTIONS',
|
|
4424
|
+
}
|
|
4425
|
+
product = self.safe_string(productMap, type, type)
|
|
4426
|
+
request['product'] = product
|
|
4427
|
+
response = self.privatePostV5OrderDisconnectedCancelAll(self.extend(request, params))
|
|
4428
|
+
#
|
|
4429
|
+
# {
|
|
4430
|
+
# "retCode": 0,
|
|
4431
|
+
# "retMsg": "success"
|
|
4432
|
+
# }
|
|
4433
|
+
#
|
|
4434
|
+
return response
|
|
4435
|
+
|
|
4111
4436
|
def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
|
|
4112
4437
|
"""
|
|
4113
4438
|
cancel multiple orders for multiple symbols
|
|
4114
|
-
|
|
4115
|
-
|
|
4116
|
-
|
|
4439
|
+
|
|
4440
|
+
https://bybit-exchange.github.io/docs/v5/order/batch-cancel
|
|
4441
|
+
|
|
4442
|
+
:param CancellationRequest[] orders: list of order ids with symbol, example [{"id": "a", "symbol": "BTC/USDT"}, {"id": "b", "symbol": "ETH/USDT"}]
|
|
4117
4443
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4118
|
-
:param str[] [params.clientOrderIds]: client order ids
|
|
4119
4444
|
:returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
4120
4445
|
"""
|
|
4121
4446
|
self.load_markets()
|
|
4447
|
+
types = self.is_unified_enabled()
|
|
4448
|
+
enableUnifiedAccount = types[1]
|
|
4449
|
+
if not enableUnifiedAccount:
|
|
4450
|
+
raise NotSupported(self.id + ' cancelOrdersForSymbols() supports UTA accounts only')
|
|
4122
4451
|
ordersRequests = []
|
|
4123
4452
|
category = None
|
|
4124
4453
|
for i in range(0, len(orders)):
|
|
@@ -4186,54 +4515,16 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4186
4515
|
row = self.safe_list(result, 'list', [])
|
|
4187
4516
|
return self.parse_orders(row, None)
|
|
4188
4517
|
|
|
4189
|
-
def cancel_all_usdc_orders(self, symbol: Str = None, params={}):
|
|
4190
|
-
if symbol is None:
|
|
4191
|
-
raise ArgumentsRequired(self.id + ' cancelAllUsdcOrders() requires a symbol argument')
|
|
4192
|
-
self.load_markets()
|
|
4193
|
-
market = self.market(symbol)
|
|
4194
|
-
request: dict = {
|
|
4195
|
-
'symbol': market['id'],
|
|
4196
|
-
}
|
|
4197
|
-
response = None
|
|
4198
|
-
if market['option']:
|
|
4199
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1CancelAll(self.extend(request, params))
|
|
4200
|
-
else:
|
|
4201
|
-
isStop = self.safe_bool_2(params, 'stop', 'trigger', False)
|
|
4202
|
-
if isStop:
|
|
4203
|
-
request['orderFilter'] = 'StopOrder'
|
|
4204
|
-
else:
|
|
4205
|
-
request['orderFilter'] = 'Order'
|
|
4206
|
-
params = self.omit(params, ['stop', 'trigger'])
|
|
4207
|
-
response = self.privatePostPerpetualUsdcOpenapiPrivateV1CancelAll(self.extend(request, params))
|
|
4208
|
-
#
|
|
4209
|
-
# {
|
|
4210
|
-
# "retCode": 0,
|
|
4211
|
-
# "retMsg": "OK",
|
|
4212
|
-
# "retExtMap": {},
|
|
4213
|
-
# "result": [
|
|
4214
|
-
# {
|
|
4215
|
-
# "outRequestId": "cancelAll-290119-1652176443114-0",
|
|
4216
|
-
# "symbol": "BTC-13MAY22-40000-C",
|
|
4217
|
-
# "orderId": "fa6cd740-56ed-477d-9385-90ccbfee49ca",
|
|
4218
|
-
# "orderLinkId": "",
|
|
4219
|
-
# "errorCode": 0,
|
|
4220
|
-
# "errorDesc": ""
|
|
4221
|
-
# }
|
|
4222
|
-
# ]
|
|
4223
|
-
# }
|
|
4224
|
-
#
|
|
4225
|
-
result = self.safe_value(response, 'result', [])
|
|
4226
|
-
if not isinstance(result, list):
|
|
4227
|
-
return response
|
|
4228
|
-
return self.parse_orders(result, market)
|
|
4229
|
-
|
|
4230
4518
|
def cancel_all_orders(self, symbol: Str = None, params={}):
|
|
4231
4519
|
"""
|
|
4232
4520
|
cancel all open orders
|
|
4233
|
-
|
|
4521
|
+
|
|
4522
|
+
https://bybit-exchange.github.io/docs/v5/order/cancel-all
|
|
4523
|
+
|
|
4234
4524
|
:param str symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
|
|
4235
4525
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4236
|
-
:param boolean [params.
|
|
4526
|
+
:param boolean [params.trigger]: True if trigger order
|
|
4527
|
+
:param boolean [params.stop]: alias for trigger
|
|
4237
4528
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4238
4529
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4239
4530
|
:param str [params.baseCoin]: Base coin. Supports linear, inverse & option
|
|
@@ -4247,9 +4538,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4247
4538
|
request: dict = {}
|
|
4248
4539
|
if symbol is not None:
|
|
4249
4540
|
market = self.market(symbol)
|
|
4250
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
4251
|
-
if isUsdcSettled and not isUnifiedAccount:
|
|
4252
|
-
return self.cancel_all_usdc_orders(symbol, params)
|
|
4253
4541
|
request['symbol'] = market['id']
|
|
4254
4542
|
type = None
|
|
4255
4543
|
type, params = self.get_bybit_type('cancelAllOrders', market, params)
|
|
@@ -4261,9 +4549,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4261
4549
|
if symbol is None and baseCoin is None:
|
|
4262
4550
|
defaultSettle = self.safe_string(self.options, 'defaultSettle', 'USDT')
|
|
4263
4551
|
request['settleCoin'] = self.safe_string(params, 'settleCoin', defaultSettle)
|
|
4264
|
-
|
|
4552
|
+
isTrigger = self.safe_bool_2(params, 'stop', 'trigger', False)
|
|
4265
4553
|
params = self.omit(params, ['stop', 'trigger'])
|
|
4266
|
-
if
|
|
4554
|
+
if isTrigger:
|
|
4267
4555
|
request['orderFilter'] = 'StopOrder'
|
|
4268
4556
|
response = self.privatePostV5OrderCancelAll(self.extend(request, params))
|
|
4269
4557
|
#
|
|
@@ -4297,95 +4585,16 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4297
4585
|
result = self.safe_dict(response, 'result', {})
|
|
4298
4586
|
orders = self.safe_list(result, 'list')
|
|
4299
4587
|
if not isinstance(orders, list):
|
|
4300
|
-
return response
|
|
4588
|
+
return [self.safe_order({'info': response})]
|
|
4301
4589
|
return self.parse_orders(orders, market)
|
|
4302
4590
|
|
|
4303
|
-
def
|
|
4304
|
-
self.load_markets()
|
|
4305
|
-
market = None
|
|
4306
|
-
request: dict = {
|
|
4307
|
-
# 'category': '', # Type. PERPETUAL, OPTION
|
|
4308
|
-
# 'symbol': '', # Contract name
|
|
4309
|
-
# 'baseCoin': '', # Base currency
|
|
4310
|
-
# 'orderId': '', # Order ID
|
|
4311
|
-
# 'orderLinkId': '', # Custom ID used for cross-platform strategy remarks; a max. of 32 characters
|
|
4312
|
-
# 'orderStatus': '', # Order status
|
|
4313
|
-
# 'orderFilter': '', # refer to Order Filter
|
|
4314
|
-
# 'direction': '', # prev: prev page, next: next page.
|
|
4315
|
-
# 'limit': 0, # Limit for data size per page, max size is 50. Default 20 pieces of data per page
|
|
4316
|
-
# 'cursor': '', # API pass-through
|
|
4317
|
-
}
|
|
4318
|
-
if symbol is not None:
|
|
4319
|
-
market = self.market(symbol)
|
|
4320
|
-
request['symbol'] = market['id']
|
|
4321
|
-
type = None
|
|
4322
|
-
type, params = self.handle_market_type_and_params('fetchOrders', market, params)
|
|
4323
|
-
if type == 'swap':
|
|
4324
|
-
request['category'] = 'PERPETUAL'
|
|
4325
|
-
else:
|
|
4326
|
-
request['category'] = 'OPTION'
|
|
4327
|
-
isStop = self.safe_bool_2(params, 'stop', 'trigger', False)
|
|
4328
|
-
params = self.omit(params, ['stop', 'trigger'])
|
|
4329
|
-
if isStop:
|
|
4330
|
-
request['orderFilter'] = 'StopOrder'
|
|
4331
|
-
if limit is not None:
|
|
4332
|
-
request['limit'] = limit
|
|
4333
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1QueryOrderHistory(self.extend(request, params))
|
|
4334
|
-
#
|
|
4335
|
-
# {
|
|
4336
|
-
# "result": {
|
|
4337
|
-
# "cursor": "640034d1-97ec-4382-9983-694898c03ba3%3A1640854950675%2C640034d1-97ec-4382-9983-694898c03ba3%3A1640854950675",
|
|
4338
|
-
# "resultTotalSize": 1,
|
|
4339
|
-
# "dataList": [
|
|
4340
|
-
# {
|
|
4341
|
-
# "symbol": "ETHPERP",
|
|
4342
|
-
# "orderType": "Limit",
|
|
4343
|
-
# "orderLinkId": "",
|
|
4344
|
-
# "orderId": "c04ad17d-ca85-45d1-859e-561e7236f6db",
|
|
4345
|
-
# "cancelType": "UNKNOWN",
|
|
4346
|
-
# "stopOrderType": "UNKNOWN",
|
|
4347
|
-
# "orderStatus": "Filled",
|
|
4348
|
-
# "updateTimeStamp": "1666178097006",
|
|
4349
|
-
# "takeProfit": "0.0000",
|
|
4350
|
-
# "cumExecValue": "12.9825",
|
|
4351
|
-
# "createdAt": "1666178096996",
|
|
4352
|
-
# "blockTradeId": "",
|
|
4353
|
-
# "orderPnl": "",
|
|
4354
|
-
# "price": "1300.0",
|
|
4355
|
-
# "tpTriggerBy": "UNKNOWN",
|
|
4356
|
-
# "timeInForce": "GoodTillCancel",
|
|
4357
|
-
# "updatedAt": "1666178097006",
|
|
4358
|
-
# "basePrice": "",
|
|
4359
|
-
# "realisedPnl": "0.0000",
|
|
4360
|
-
# "side": "Buy",
|
|
4361
|
-
# "triggerPrice": "0.0",
|
|
4362
|
-
# "cumExecFee": "0.0078",
|
|
4363
|
-
# "leavesQty": "0.000",
|
|
4364
|
-
# "cashFlow": "",
|
|
4365
|
-
# "slTriggerBy": "UNKNOWN",
|
|
4366
|
-
# "iv": "",
|
|
4367
|
-
# "closeOnTrigger": "UNKNOWN",
|
|
4368
|
-
# "cumExecQty": "0.010",
|
|
4369
|
-
# "reduceOnly": 0,
|
|
4370
|
-
# "qty": "0.010",
|
|
4371
|
-
# "stopLoss": "0.0000",
|
|
4372
|
-
# "triggerBy": "UNKNOWN",
|
|
4373
|
-
# "orderIM": ""
|
|
4374
|
-
# }
|
|
4375
|
-
# ]
|
|
4376
|
-
# },
|
|
4377
|
-
# "retCode": 0,
|
|
4378
|
-
# "retMsg": "Success."
|
|
4379
|
-
# }
|
|
4380
|
-
#
|
|
4381
|
-
result = self.safe_dict(response, 'result', {})
|
|
4382
|
-
data = self.safe_list(result, 'dataList', [])
|
|
4383
|
-
return self.parse_orders(data, market, since, limit)
|
|
4384
|
-
|
|
4385
|
-
def fetch_order_classic(self, id: str, symbol: Str = None, params={}):
|
|
4591
|
+
def fetch_order_classic(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
4386
4592
|
"""
|
|
4387
4593
|
fetches information on an order made by the user *classic accounts only*
|
|
4388
|
-
|
|
4594
|
+
|
|
4595
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
4596
|
+
|
|
4597
|
+
:param str id: the order id
|
|
4389
4598
|
:param str symbol: unified symbol of the market the order was made in
|
|
4390
4599
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4391
4600
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
@@ -4403,7 +4612,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4403
4612
|
length = len(result)
|
|
4404
4613
|
if length == 0:
|
|
4405
4614
|
isTrigger = self.safe_bool_n(params, ['trigger', 'stop'], False)
|
|
4406
|
-
extra = '' if isTrigger else 'If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4615
|
+
extra = '' if isTrigger else ' If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4407
4616
|
raise OrderNotFound('Order ' + str(id) + ' was not found.' + extra)
|
|
4408
4617
|
if length > 1:
|
|
4409
4618
|
raise InvalidOrder(self.id + ' returned more than one order')
|
|
@@ -4411,28 +4620,106 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4411
4620
|
|
|
4412
4621
|
def fetch_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
4413
4622
|
"""
|
|
4414
|
-
|
|
4415
|
-
|
|
4623
|
+
classic accounts only/ spot not supported* fetches information on an order made by the user *classic accounts only*
|
|
4624
|
+
|
|
4625
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
4626
|
+
|
|
4627
|
+
:param str id: the order id
|
|
4416
4628
|
:param str symbol: unified symbol of the market the order was made in
|
|
4417
4629
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4630
|
+
:param dict [params.acknowledged]: to suppress the warning, set to True
|
|
4418
4631
|
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
|
4419
4632
|
"""
|
|
4420
|
-
|
|
4421
|
-
enableUnifiedAccount = self.
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4633
|
+
self.load_markets()
|
|
4634
|
+
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
4635
|
+
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
4636
|
+
if not isUnifiedAccount:
|
|
4637
|
+
return self.fetch_order_classic(id, symbol, params)
|
|
4638
|
+
acknowledge = False
|
|
4639
|
+
acknowledge, params = self.handle_option_and_params(params, 'fetchOrder', 'acknowledged')
|
|
4640
|
+
if not acknowledge:
|
|
4641
|
+
raise ArgumentsRequired(self.id + ' fetchOrder() can only access an order if it is in last 500 orders(of any status) for your account. Set params["acknowledged"] = True to hide self warning. Alternatively, we suggest to use fetchOpenOrder or fetchClosedOrder')
|
|
4642
|
+
market = self.market(symbol)
|
|
4643
|
+
marketType = None
|
|
4644
|
+
marketType, params = self.get_bybit_type('fetchOrder', market, params)
|
|
4645
|
+
request: dict = {
|
|
4646
|
+
'symbol': market['id'],
|
|
4647
|
+
'orderId': id,
|
|
4648
|
+
'category': marketType,
|
|
4649
|
+
}
|
|
4650
|
+
isTrigger = None
|
|
4651
|
+
isTrigger, params = self.handle_param_bool_2(params, 'trigger', 'stop', False)
|
|
4652
|
+
if isTrigger:
|
|
4653
|
+
request['orderFilter'] = 'StopOrder'
|
|
4654
|
+
response = self.privateGetV5OrderRealtime(self.extend(request, params))
|
|
4655
|
+
#
|
|
4656
|
+
# {
|
|
4657
|
+
# "retCode": 0,
|
|
4658
|
+
# "retMsg": "OK",
|
|
4659
|
+
# "result": {
|
|
4660
|
+
# "nextPageCursor": "1321052653536515584%3A1672217748287%2C1321052653536515584%3A1672217748287",
|
|
4661
|
+
# "category": "spot",
|
|
4662
|
+
# "list": [
|
|
4663
|
+
# {
|
|
4664
|
+
# "symbol": "ETHUSDT",
|
|
4665
|
+
# "orderType": "Limit",
|
|
4666
|
+
# "orderLinkId": "1672217748277652",
|
|
4667
|
+
# "orderId": "1321052653536515584",
|
|
4668
|
+
# "cancelType": "UNKNOWN",
|
|
4669
|
+
# "avgPrice": "",
|
|
4670
|
+
# "stopOrderType": "tpslOrder",
|
|
4671
|
+
# "lastPriceOnCreated": "",
|
|
4672
|
+
# "orderStatus": "Cancelled",
|
|
4673
|
+
# "takeProfit": "",
|
|
4674
|
+
# "cumExecValue": "0",
|
|
4675
|
+
# "triggerDirection": 0,
|
|
4676
|
+
# "isLeverage": "0",
|
|
4677
|
+
# "rejectReason": "",
|
|
4678
|
+
# "price": "1000",
|
|
4679
|
+
# "orderIv": "",
|
|
4680
|
+
# "createdTime": "1672217748287",
|
|
4681
|
+
# "tpTriggerBy": "",
|
|
4682
|
+
# "positionIdx": 0,
|
|
4683
|
+
# "timeInForce": "GTC",
|
|
4684
|
+
# "leavesValue": "500",
|
|
4685
|
+
# "updatedTime": "1672217748287",
|
|
4686
|
+
# "side": "Buy",
|
|
4687
|
+
# "triggerPrice": "1500",
|
|
4688
|
+
# "cumExecFee": "0",
|
|
4689
|
+
# "leavesQty": "0",
|
|
4690
|
+
# "slTriggerBy": "",
|
|
4691
|
+
# "closeOnTrigger": False,
|
|
4692
|
+
# "cumExecQty": "0",
|
|
4693
|
+
# "reduceOnly": False,
|
|
4694
|
+
# "qty": "0.5",
|
|
4695
|
+
# "stopLoss": "",
|
|
4696
|
+
# "triggerBy": "1192.5"
|
|
4697
|
+
# }
|
|
4698
|
+
# ]
|
|
4699
|
+
# },
|
|
4700
|
+
# "retExtInfo": {},
|
|
4701
|
+
# "time": 1672219526294
|
|
4702
|
+
# }
|
|
4703
|
+
#
|
|
4704
|
+
result = self.safe_dict(response, 'result', {})
|
|
4705
|
+
innerList = self.safe_list(result, 'list', [])
|
|
4706
|
+
if len(innerList) == 0:
|
|
4707
|
+
extra = '' if isTrigger else ' If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4708
|
+
raise OrderNotFound('Order ' + str(id) + ' was not found.' + extra)
|
|
4709
|
+
order = self.safe_dict(innerList, 0, {})
|
|
4710
|
+
return self.parse_order(order, market)
|
|
4425
4711
|
|
|
4426
4712
|
def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
4427
4713
|
res = self.is_unified_enabled()
|
|
4428
4714
|
"""
|
|
4429
4715
|
*classic accounts only/ spot not supported* fetches information on multiple orders made by the user *classic accounts only/ spot not supported*
|
|
4430
|
-
|
|
4716
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
4431
4717
|
:param str symbol: unified market symbol of the market orders were made in
|
|
4432
4718
|
:param int [since]: the earliest time in ms to fetch orders for
|
|
4433
4719
|
:param int [limit]: the maximum number of order structures to retrieve
|
|
4434
4720
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4435
|
-
:param boolean [params.
|
|
4721
|
+
:param boolean [params.trigger]: True if trigger order
|
|
4722
|
+
:param boolean [params.stop]: alias for trigger
|
|
4436
4723
|
:param str [params.type]: market type, ['swap', 'option']
|
|
4437
4724
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4438
4725
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
@@ -4448,12 +4735,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4448
4735
|
def fetch_orders_classic(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
4449
4736
|
"""
|
|
4450
4737
|
fetches information on multiple orders made by the user *classic accounts only*
|
|
4451
|
-
|
|
4738
|
+
|
|
4739
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
4740
|
+
|
|
4452
4741
|
:param str symbol: unified market symbol of the market orders were made in
|
|
4453
4742
|
:param int [since]: the earliest time in ms to fetch orders for
|
|
4454
4743
|
:param int [limit]: the maximum number of order structures to retrieve
|
|
4455
4744
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4456
|
-
:param boolean [params.
|
|
4745
|
+
:param boolean [params.trigger]: True if trigger order
|
|
4746
|
+
:param boolean [params.stop]: alias for trigger
|
|
4457
4747
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4458
4748
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4459
4749
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
@@ -4466,25 +4756,19 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4466
4756
|
paginate, params = self.handle_option_and_params(params, 'fetchOrders', 'paginate')
|
|
4467
4757
|
if paginate:
|
|
4468
4758
|
return self.fetch_paginated_call_cursor('fetchOrders', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 50)
|
|
4469
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
4470
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
4471
4759
|
request: dict = {}
|
|
4472
4760
|
market = None
|
|
4473
|
-
isUsdcSettled = False
|
|
4474
4761
|
if symbol is not None:
|
|
4475
4762
|
market = self.market(symbol)
|
|
4476
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
4477
4763
|
request['symbol'] = market['id']
|
|
4478
4764
|
type = None
|
|
4479
4765
|
type, params = self.get_bybit_type('fetchOrders', market, params)
|
|
4480
|
-
if ((type == 'option') or isUsdcSettled) and not isUnifiedAccount:
|
|
4481
|
-
return self.fetch_usdc_orders(symbol, since, limit, params)
|
|
4482
4766
|
if type == 'spot':
|
|
4483
4767
|
raise NotSupported(self.id + ' fetchOrders() is not supported for spot markets')
|
|
4484
4768
|
request['category'] = type
|
|
4485
|
-
|
|
4769
|
+
isTrigger = self.safe_bool_n(params, ['trigger', 'stop'], False)
|
|
4486
4770
|
params = self.omit(params, ['trigger', 'stop'])
|
|
4487
|
-
if
|
|
4771
|
+
if isTrigger:
|
|
4488
4772
|
request['orderFilter'] = 'StopOrder'
|
|
4489
4773
|
if limit is not None:
|
|
4490
4774
|
request['limit'] = limit
|
|
@@ -4549,14 +4833,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4549
4833
|
data = self.add_pagination_cursor_to_result(response)
|
|
4550
4834
|
return self.parse_orders(data, market, since, limit)
|
|
4551
4835
|
|
|
4552
|
-
def fetch_closed_order(self, id: str, symbol: Str = None, params={}):
|
|
4836
|
+
def fetch_closed_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
4553
4837
|
"""
|
|
4554
4838
|
fetches information on a closed order made by the user
|
|
4555
|
-
|
|
4839
|
+
|
|
4840
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
4841
|
+
|
|
4556
4842
|
:param str id: order id
|
|
4557
4843
|
:param str [symbol]: unified symbol of the market the order was made in
|
|
4558
4844
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4559
|
-
:param boolean [params.
|
|
4845
|
+
:param boolean [params.trigger]: set to True for fetching a closed trigger order
|
|
4846
|
+
:param boolean [params.stop]: alias for trigger
|
|
4560
4847
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4561
4848
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4562
4849
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
@@ -4570,20 +4857,23 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4570
4857
|
length = len(result)
|
|
4571
4858
|
if length == 0:
|
|
4572
4859
|
isTrigger = self.safe_bool_n(params, ['trigger', 'stop'], False)
|
|
4573
|
-
extra = '' if isTrigger else 'If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4860
|
+
extra = '' if isTrigger else ' If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4574
4861
|
raise OrderNotFound('Order ' + str(id) + ' was not found.' + extra)
|
|
4575
4862
|
if length > 1:
|
|
4576
4863
|
raise InvalidOrder(self.id + ' returned more than one order')
|
|
4577
4864
|
return self.safe_value(result, 0)
|
|
4578
4865
|
|
|
4579
|
-
def fetch_open_order(self, id: str, symbol: Str = None, params={}):
|
|
4866
|
+
def fetch_open_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
|
4580
4867
|
"""
|
|
4581
4868
|
fetches information on an open order made by the user
|
|
4582
|
-
|
|
4869
|
+
|
|
4870
|
+
https://bybit-exchange.github.io/docs/v5/order/open-order
|
|
4871
|
+
|
|
4583
4872
|
:param str id: order id
|
|
4584
4873
|
:param str [symbol]: unified symbol of the market the order was made in
|
|
4585
4874
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4586
|
-
:param boolean [params.
|
|
4875
|
+
:param boolean [params.trigger]: set to True for fetching an open trigger order
|
|
4876
|
+
:param boolean [params.stop]: alias for trigger
|
|
4587
4877
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4588
4878
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4589
4879
|
:param str [params.baseCoin]: Base coin. Supports linear, inverse & option
|
|
@@ -4599,7 +4889,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4599
4889
|
length = len(result)
|
|
4600
4890
|
if length == 0:
|
|
4601
4891
|
isTrigger = self.safe_bool_n(params, ['trigger', 'stop'], False)
|
|
4602
|
-
extra = '' if isTrigger else 'If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4892
|
+
extra = '' if isTrigger else ' If you are trying to fetch SL/TP conditional order, you might try setting params["trigger"] = True'
|
|
4603
4893
|
raise OrderNotFound('Order ' + str(id) + ' was not found.' + extra)
|
|
4604
4894
|
if length > 1:
|
|
4605
4895
|
raise InvalidOrder(self.id + ' returned more than one order')
|
|
@@ -4608,12 +4898,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4608
4898
|
def fetch_canceled_and_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
4609
4899
|
"""
|
|
4610
4900
|
fetches information on multiple canceled and closed orders made by the user
|
|
4611
|
-
|
|
4901
|
+
|
|
4902
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
4903
|
+
|
|
4612
4904
|
:param str [symbol]: unified market symbol of the market orders were made in
|
|
4613
4905
|
:param int [since]: the earliest time in ms to fetch orders for
|
|
4614
4906
|
:param int [limit]: the maximum number of order structures to retrieve
|
|
4615
4907
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4616
|
-
:param boolean [params.
|
|
4908
|
+
:param boolean [params.trigger]: set to True for fetching trigger orders
|
|
4909
|
+
:param boolean [params.stop]: alias for trigger
|
|
4617
4910
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4618
4911
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4619
4912
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
@@ -4626,23 +4919,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4626
4919
|
paginate, params = self.handle_option_and_params(params, 'fetchCanceledAndClosedOrders', 'paginate')
|
|
4627
4920
|
if paginate:
|
|
4628
4921
|
return self.fetch_paginated_call_cursor('fetchCanceledAndClosedOrders', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 50)
|
|
4629
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
4630
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
4631
4922
|
request: dict = {}
|
|
4632
4923
|
market = None
|
|
4633
|
-
isUsdcSettled = False
|
|
4634
4924
|
if symbol is not None:
|
|
4635
4925
|
market = self.market(symbol)
|
|
4636
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
4637
4926
|
request['symbol'] = market['id']
|
|
4638
4927
|
type = None
|
|
4639
4928
|
type, params = self.get_bybit_type('fetchCanceledAndClosedOrders', market, params)
|
|
4640
|
-
if ((type == 'option') or isUsdcSettled) and not isUnifiedAccount:
|
|
4641
|
-
return self.fetch_usdc_orders(symbol, since, limit, params)
|
|
4642
4929
|
request['category'] = type
|
|
4643
|
-
|
|
4930
|
+
isTrigger = self.safe_bool_n(params, ['trigger', 'stop'], False)
|
|
4644
4931
|
params = self.omit(params, ['trigger', 'stop'])
|
|
4645
|
-
if
|
|
4932
|
+
if isTrigger:
|
|
4646
4933
|
request['orderFilter'] = 'StopOrder'
|
|
4647
4934
|
if limit is not None:
|
|
4648
4935
|
request['limit'] = limit
|
|
@@ -4710,12 +4997,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4710
4997
|
def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
4711
4998
|
"""
|
|
4712
4999
|
fetches information on multiple closed orders made by the user
|
|
4713
|
-
|
|
5000
|
+
|
|
5001
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
5002
|
+
|
|
4714
5003
|
:param str [symbol]: unified market symbol of the market orders were made in
|
|
4715
5004
|
:param int [since]: the earliest time in ms to fetch orders for
|
|
4716
5005
|
:param int [limit]: the maximum number of order structures to retrieve
|
|
4717
5006
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4718
|
-
:param boolean [params.
|
|
5007
|
+
:param boolean [params.trigger]: set to True for fetching closed trigger orders
|
|
5008
|
+
:param boolean [params.stop]: alias for trigger
|
|
4719
5009
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4720
5010
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4721
5011
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
@@ -4729,15 +5019,18 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4729
5019
|
}
|
|
4730
5020
|
return self.fetch_canceled_and_closed_orders(symbol, since, limit, self.extend(request, params))
|
|
4731
5021
|
|
|
4732
|
-
def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
5022
|
+
def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
4733
5023
|
"""
|
|
4734
5024
|
fetches information on multiple canceled orders made by the user
|
|
4735
|
-
|
|
5025
|
+
|
|
5026
|
+
https://bybit-exchange.github.io/docs/v5/order/order-list
|
|
5027
|
+
|
|
4736
5028
|
:param str [symbol]: unified market symbol of the market orders were made in
|
|
4737
5029
|
:param int [since]: timestamp in ms of the earliest order, default is None
|
|
4738
5030
|
:param int [limit]: max number of orders to return, default is None
|
|
4739
5031
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4740
|
-
:param boolean [params.
|
|
5032
|
+
:param boolean [params.trigger]: True if trigger order
|
|
5033
|
+
:param boolean [params.stop]: alias for trigger
|
|
4741
5034
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4742
5035
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4743
5036
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
@@ -4751,72 +5044,35 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4751
5044
|
}
|
|
4752
5045
|
return self.fetch_canceled_and_closed_orders(symbol, since, limit, self.extend(request, params))
|
|
4753
5046
|
|
|
4754
|
-
def fetch_usdc_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
4755
|
-
self.load_markets()
|
|
4756
|
-
request: dict = {}
|
|
4757
|
-
market = None
|
|
4758
|
-
if symbol is not None:
|
|
4759
|
-
market = self.market(symbol)
|
|
4760
|
-
request['symbol'] = market['id']
|
|
4761
|
-
type = None
|
|
4762
|
-
type, params = self.handle_market_type_and_params('fetchUsdcOpenOrders', market, params)
|
|
4763
|
-
request['category'] = 'perpetual' if (type == 'swap') else 'option'
|
|
4764
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1QueryActiveOrders(self.extend(request, params))
|
|
4765
|
-
result = self.safe_dict(response, 'result', {})
|
|
4766
|
-
orders = self.safe_list(result, 'dataList', [])
|
|
4767
|
-
#
|
|
4768
|
-
# {
|
|
4769
|
-
# "retCode": 0,
|
|
4770
|
-
# "retMsg": "OK",
|
|
4771
|
-
# "result": {
|
|
4772
|
-
# "resultTotalSize": 1,
|
|
4773
|
-
# "cursor": "id%3D1662019818569%23df31e03b-fc00-4b4c-bd1c-b97fd72b5c5c",
|
|
4774
|
-
# "dataList": [
|
|
4775
|
-
# {
|
|
4776
|
-
# "orderId": "df31e03b-fc00-4b4c-bd1c-b97fd72b5c5c",
|
|
4777
|
-
# "orderLinkId": "",
|
|
4778
|
-
# "symbol": "BTC-2SEP22-18000-C",
|
|
4779
|
-
# "orderStatus": "New",
|
|
4780
|
-
# "orderPrice": "500",
|
|
4781
|
-
# "side": "Buy",
|
|
4782
|
-
# "remainingQty": "0.1",
|
|
4783
|
-
# "orderType": "Limit",
|
|
4784
|
-
# "qty": "0.1",
|
|
4785
|
-
# "iv": "0.0000",
|
|
4786
|
-
# "cancelType": "",
|
|
4787
|
-
# "updateTimestamp": "1662019818579"
|
|
4788
|
-
# }
|
|
4789
|
-
# ]
|
|
4790
|
-
# }
|
|
4791
|
-
# }
|
|
4792
|
-
#
|
|
4793
|
-
return self.parse_orders(orders, market, since, limit)
|
|
4794
|
-
|
|
4795
5047
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
|
4796
5048
|
"""
|
|
4797
5049
|
fetch all unfilled currently open orders
|
|
4798
|
-
|
|
5050
|
+
|
|
5051
|
+
https://bybit-exchange.github.io/docs/v5/order/open-order
|
|
5052
|
+
|
|
4799
5053
|
:param str symbol: unified market symbol
|
|
4800
5054
|
:param int [since]: the earliest time in ms to fetch open orders for
|
|
4801
5055
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
|
4802
5056
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
4803
|
-
:param boolean [params.
|
|
5057
|
+
:param boolean [params.trigger]: set to True for fetching open trigger orders
|
|
5058
|
+
:param boolean [params.stop]: alias for trigger
|
|
4804
5059
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
4805
5060
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
4806
5061
|
:param str [params.baseCoin]: Base coin. Supports linear, inverse & option
|
|
4807
5062
|
:param str [params.settleCoin]: Settle coin. Supports linear, inverse & option
|
|
4808
5063
|
:param str [params.orderFilter]: 'Order' or 'StopOrder' or 'tpslOrder'
|
|
5064
|
+
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
|
4809
5065
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
|
4810
5066
|
"""
|
|
4811
5067
|
self.load_markets()
|
|
4812
|
-
|
|
4813
|
-
|
|
5068
|
+
paginate = False
|
|
5069
|
+
paginate, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'paginate')
|
|
5070
|
+
if paginate:
|
|
5071
|
+
return self.fetch_paginated_call_cursor('fetchOpenOrders', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 50)
|
|
4814
5072
|
request: dict = {}
|
|
4815
5073
|
market = None
|
|
4816
|
-
isUsdcSettled = False
|
|
4817
5074
|
if symbol is not None:
|
|
4818
5075
|
market = self.market(symbol)
|
|
4819
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
4820
5076
|
request['symbol'] = market['id']
|
|
4821
5077
|
type = None
|
|
4822
5078
|
type, params = self.get_bybit_type('fetchOpenOrders', market, params)
|
|
@@ -4826,13 +5082,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4826
5082
|
defaultSettle = self.safe_string(self.options, 'defaultSettle', 'USDT')
|
|
4827
5083
|
settleCoin = self.safe_string(params, 'settleCoin', defaultSettle)
|
|
4828
5084
|
request['settleCoin'] = settleCoin
|
|
4829
|
-
isUsdcSettled = (settleCoin == 'USDC')
|
|
4830
|
-
if ((type == 'option') or isUsdcSettled) and not isUnifiedAccount:
|
|
4831
|
-
return self.fetch_usdc_open_orders(symbol, since, limit, params)
|
|
4832
5085
|
request['category'] = type
|
|
4833
|
-
|
|
5086
|
+
isTrigger = self.safe_bool_2(params, 'stop', 'trigger', False)
|
|
4834
5087
|
params = self.omit(params, ['stop', 'trigger'])
|
|
4835
|
-
if
|
|
5088
|
+
if isTrigger:
|
|
4836
5089
|
request['orderFilter'] = 'StopOrder'
|
|
4837
5090
|
if limit is not None:
|
|
4838
5091
|
request['limit'] = limit
|
|
@@ -4889,10 +5142,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4889
5142
|
data = self.add_pagination_cursor_to_result(response)
|
|
4890
5143
|
return self.parse_orders(data, market, since, limit)
|
|
4891
5144
|
|
|
4892
|
-
def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
5145
|
+
def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
4893
5146
|
"""
|
|
4894
5147
|
fetch all the trades made from a single order
|
|
4895
|
-
|
|
5148
|
+
|
|
5149
|
+
https://bybit-exchange.github.io/docs/v5/position/execution
|
|
5150
|
+
|
|
4896
5151
|
:param str id: order id
|
|
4897
5152
|
:param str symbol: unified market symbol
|
|
4898
5153
|
:param int [since]: the earliest time in ms to fetch trades for
|
|
@@ -4909,53 +5164,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4909
5164
|
params = self.omit(params, ['clientOrderId', 'orderLinkId'])
|
|
4910
5165
|
return self.fetch_my_trades(symbol, since, limit, self.extend(request, params))
|
|
4911
5166
|
|
|
4912
|
-
def
|
|
4913
|
-
self.load_markets()
|
|
4914
|
-
market = None
|
|
4915
|
-
request: dict = {}
|
|
4916
|
-
if symbol is not None:
|
|
4917
|
-
market = self.market(symbol)
|
|
4918
|
-
request['symbol'] = market['id']
|
|
4919
|
-
request['category'] = 'OPTION' if market['option'] else 'PERPETUAL'
|
|
4920
|
-
else:
|
|
4921
|
-
request['category'] = 'PERPETUAL'
|
|
4922
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1ExecutionList(self.extend(request, params))
|
|
4923
|
-
#
|
|
4924
|
-
# {
|
|
4925
|
-
# "result": {
|
|
4926
|
-
# "cursor": "29%3A1%2C28%3A1",
|
|
4927
|
-
# "resultTotalSize": 2,
|
|
4928
|
-
# "dataList": [
|
|
4929
|
-
# {
|
|
4930
|
-
# "symbol": "ETHPERP",
|
|
4931
|
-
# "orderLinkId": "",
|
|
4932
|
-
# "side": "Sell",
|
|
4933
|
-
# "orderId": "d83f8b4d-2f60-4e04-a64a-a3f207989dc6",
|
|
4934
|
-
# "execFee": "0.0210",
|
|
4935
|
-
# "feeRate": "0.000600",
|
|
4936
|
-
# "blockTradeId": "",
|
|
4937
|
-
# "tradeTime": "1669196423581",
|
|
4938
|
-
# "execPrice": "1161.45",
|
|
4939
|
-
# "lastLiquidityInd": "TAKER",
|
|
4940
|
-
# "execValue": "34.8435",
|
|
4941
|
-
# "execType": "Trade",
|
|
4942
|
-
# "execQty": "0.030",
|
|
4943
|
-
# "tradeId": "d9aa8590-9e6a-575e-a1be-d6261e6ed2e5"
|
|
4944
|
-
# }, ...
|
|
4945
|
-
# ]
|
|
4946
|
-
# },
|
|
4947
|
-
# "retCode": 0,
|
|
4948
|
-
# "retMsg": "Success."
|
|
4949
|
-
# }
|
|
4950
|
-
#
|
|
4951
|
-
result = self.safe_dict(response, 'result', {})
|
|
4952
|
-
dataList = self.safe_list(result, 'dataList', [])
|
|
4953
|
-
return self.parse_trades(dataList, market, since, limit)
|
|
4954
|
-
|
|
4955
|
-
def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
5167
|
+
def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
|
4956
5168
|
"""
|
|
4957
5169
|
fetch all trades made by the user
|
|
4958
|
-
|
|
5170
|
+
|
|
5171
|
+
https://bybit-exchange.github.io/docs/api-explorer/v5/position/execution
|
|
5172
|
+
|
|
4959
5173
|
:param str symbol: unified market symbol
|
|
4960
5174
|
:param int [since]: the earliest time in ms to fetch trades for
|
|
4961
5175
|
:param int [limit]: the maximum number of trades structures to retrieve
|
|
@@ -4970,21 +5184,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
4970
5184
|
paginate, params = self.handle_option_and_params(params, 'fetchMyTrades', 'paginate')
|
|
4971
5185
|
if paginate:
|
|
4972
5186
|
return self.fetch_paginated_call_cursor('fetchMyTrades', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 100)
|
|
4973
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
4974
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
4975
5187
|
request: dict = {
|
|
4976
5188
|
'execType': 'Trade',
|
|
4977
5189
|
}
|
|
4978
5190
|
market = None
|
|
4979
|
-
isUsdcSettled = False
|
|
4980
5191
|
if symbol is not None:
|
|
4981
5192
|
market = self.market(symbol)
|
|
4982
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
4983
5193
|
request['symbol'] = market['id']
|
|
4984
5194
|
type = None
|
|
4985
5195
|
type, params = self.get_bybit_type('fetchMyTrades', market, params)
|
|
4986
|
-
if ((type == 'option') or isUsdcSettled) and not isUnifiedAccount:
|
|
4987
|
-
return self.fetch_my_usdc_trades(symbol, since, limit, params)
|
|
4988
5196
|
request['category'] = type
|
|
4989
5197
|
if limit is not None:
|
|
4990
5198
|
request['limit'] = limit
|
|
@@ -5035,7 +5243,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5035
5243
|
trades = self.add_pagination_cursor_to_result(response)
|
|
5036
5244
|
return self.parse_trades(trades, market, since, limit)
|
|
5037
5245
|
|
|
5038
|
-
def parse_deposit_address(self, depositAddress, currency: Currency = None):
|
|
5246
|
+
def parse_deposit_address(self, depositAddress, currency: Currency = None) -> DepositAddress:
|
|
5039
5247
|
#
|
|
5040
5248
|
# {
|
|
5041
5249
|
# "chainType": "ERC20",
|
|
@@ -5047,20 +5255,21 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5047
5255
|
address = self.safe_string(depositAddress, 'addressDeposit')
|
|
5048
5256
|
tag = self.safe_string(depositAddress, 'tagDeposit')
|
|
5049
5257
|
code = self.safe_string(currency, 'code')
|
|
5050
|
-
chain = self.safe_string(depositAddress, 'chain')
|
|
5051
5258
|
self.check_address(address)
|
|
5052
5259
|
return {
|
|
5260
|
+
'info': depositAddress,
|
|
5053
5261
|
'currency': code,
|
|
5262
|
+
'network': self.network_id_to_code(self.safe_string(depositAddress, 'chain'), code),
|
|
5054
5263
|
'address': address,
|
|
5055
5264
|
'tag': tag,
|
|
5056
|
-
'network': chain,
|
|
5057
|
-
'info': depositAddress,
|
|
5058
5265
|
}
|
|
5059
5266
|
|
|
5060
|
-
def fetch_deposit_addresses_by_network(self, code: str, params={}):
|
|
5267
|
+
def fetch_deposit_addresses_by_network(self, code: str, params={}) -> List[DepositAddress]:
|
|
5061
5268
|
"""
|
|
5062
5269
|
fetch a dictionary of addresses for a currency, indexed by network
|
|
5063
|
-
|
|
5270
|
+
|
|
5271
|
+
https://bybit-exchange.github.io/docs/v5/asset/master-deposit-addr
|
|
5272
|
+
|
|
5064
5273
|
:param str code: unified currency code of the currency for the deposit address
|
|
5065
5274
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
5066
5275
|
:returns dict: a dictionary of `address structures <https://docs.ccxt.com/#/?id=address-structure>` indexed by the network
|
|
@@ -5070,6 +5279,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5070
5279
|
request: dict = {
|
|
5071
5280
|
'coin': currency['id'],
|
|
5072
5281
|
}
|
|
5282
|
+
networkCode = None
|
|
5283
|
+
networkCode, params = self.handle_network_code_and_params(params)
|
|
5284
|
+
if networkCode is not None:
|
|
5285
|
+
request['chainType'] = self.network_code_to_id(networkCode, code)
|
|
5073
5286
|
response = self.privateGetV5AssetDepositQueryAddress(self.extend(request, params))
|
|
5074
5287
|
#
|
|
5075
5288
|
# {
|
|
@@ -5099,60 +5312,35 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5099
5312
|
})
|
|
5100
5313
|
return self.index_by(parsed, 'network')
|
|
5101
5314
|
|
|
5102
|
-
def fetch_deposit_address(self, code: str, params={}):
|
|
5315
|
+
def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
|
|
5103
5316
|
"""
|
|
5104
5317
|
fetch the deposit address for a currency associated with self account
|
|
5105
|
-
|
|
5318
|
+
|
|
5319
|
+
https://bybit-exchange.github.io/docs/v5/asset/master-deposit-addr
|
|
5320
|
+
|
|
5106
5321
|
:param str code: unified currency code
|
|
5107
5322
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
5108
5323
|
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
|
5109
5324
|
"""
|
|
5110
5325
|
self.load_markets()
|
|
5111
|
-
networkCode, query = self.handle_network_code_and_params(params)
|
|
5112
|
-
networkId = self.network_code_to_id(networkCode)
|
|
5113
5326
|
currency = self.currency(code)
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
request['chainType'] = networkId
|
|
5119
|
-
response = self.privateGetV5AssetDepositQueryAddress(self.extend(request, query))
|
|
5120
|
-
#
|
|
5121
|
-
# {
|
|
5122
|
-
# "retCode": 0,
|
|
5123
|
-
# "retMsg": "success",
|
|
5124
|
-
# "result": {
|
|
5125
|
-
# "coin": "USDT",
|
|
5126
|
-
# "chains": [
|
|
5127
|
-
# {
|
|
5128
|
-
# "chainType": "ERC20",
|
|
5129
|
-
# "addressDeposit": "0xd9e1cd77afa0e50b452a62fbb68a3340602286c3",
|
|
5130
|
-
# "tagDeposit": "",
|
|
5131
|
-
# "chain": "ETH"
|
|
5132
|
-
# }
|
|
5133
|
-
# ]
|
|
5134
|
-
# },
|
|
5135
|
-
# "retExtInfo": {},
|
|
5136
|
-
# "time": 1672192792860
|
|
5137
|
-
# }
|
|
5138
|
-
#
|
|
5139
|
-
result = self.safe_dict(response, 'result', {})
|
|
5140
|
-
chains = self.safe_list(result, 'chains', [])
|
|
5141
|
-
chainsIndexedById = self.index_by(chains, 'chain')
|
|
5142
|
-
selectedNetworkId = self.select_network_id_from_raw_networks(code, networkCode, chainsIndexedById)
|
|
5143
|
-
addressObject = self.safe_dict(chainsIndexedById, selectedNetworkId, {})
|
|
5144
|
-
return self.parse_deposit_address(addressObject, currency)
|
|
5327
|
+
networkCode, paramsOmited = self.handle_network_code_and_params(params)
|
|
5328
|
+
indexedAddresses = self.fetch_deposit_addresses_by_network(code, paramsOmited)
|
|
5329
|
+
selectedNetworkCode = self.select_network_code_from_unified_networks(currency['code'], networkCode, indexedAddresses)
|
|
5330
|
+
return indexedAddresses[selectedNetworkCode]
|
|
5145
5331
|
|
|
5146
5332
|
def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
|
5147
5333
|
"""
|
|
5148
5334
|
fetch all deposits made to an account
|
|
5149
|
-
|
|
5335
|
+
|
|
5336
|
+
https://bybit-exchange.github.io/docs/v5/asset/deposit-record
|
|
5337
|
+
|
|
5150
5338
|
:param str code: unified currency code
|
|
5151
5339
|
:param int [since]: the earliest time in ms to fetch deposits for, default = 30 days before the current time
|
|
5152
5340
|
:param int [limit]: the maximum number of deposits structures to retrieve, default = 50, max = 50
|
|
5153
5341
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
5154
5342
|
:param int [params.until]: the latest time in ms to fetch deposits for, default = 30 days after since
|
|
5155
|
-
|
|
5343
|
+
EXCHANGE SPECIFIC PARAMETERS
|
|
5156
5344
|
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [availble parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
|
5157
5345
|
:param str [params.cursor]: used for pagination
|
|
5158
5346
|
:returns dict[]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
|
@@ -5210,7 +5398,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5210
5398
|
def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
|
|
5211
5399
|
"""
|
|
5212
5400
|
fetch all withdrawals made from an account
|
|
5213
|
-
|
|
5401
|
+
|
|
5402
|
+
https://bybit-exchange.github.io/docs/v5/asset/withdraw-record
|
|
5403
|
+
|
|
5214
5404
|
:param str code: unified currency code
|
|
5215
5405
|
:param int [since]: the earliest time in ms to fetch withdrawals for
|
|
5216
5406
|
:param int [limit]: the maximum number of withdrawals structures to retrieve
|
|
@@ -5380,17 +5570,26 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5380
5570
|
'comment': None,
|
|
5381
5571
|
}
|
|
5382
5572
|
|
|
5383
|
-
def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
5573
|
+
def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LedgerEntry]:
|
|
5384
5574
|
"""
|
|
5385
|
-
fetch the history of changes, actions done by the user or operations that altered balance of the user
|
|
5386
|
-
|
|
5387
|
-
|
|
5575
|
+
fetch the history of changes, actions done by the user or operations that altered the balance of the user
|
|
5576
|
+
|
|
5577
|
+
https://bybit-exchange.github.io/docs/v5/account/transaction-log
|
|
5578
|
+
https://bybit-exchange.github.io/docs/v5/account/contract-transaction-log
|
|
5579
|
+
|
|
5580
|
+
:param str [code]: unified currency code, default is None
|
|
5388
5581
|
:param int [since]: timestamp in ms of the earliest ledger entry, default is None
|
|
5389
|
-
:param int [limit]: max number of ledger
|
|
5582
|
+
:param int [limit]: max number of ledger entries to return, default is None
|
|
5390
5583
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
5391
|
-
:
|
|
5584
|
+
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times. See in the docs all the [available parameters](https://github.com/ccxt/ccxt/wiki/Manual#pagination-params)
|
|
5585
|
+
:param str [params.subType]: if inverse will use v5/account/contract-transaction-log
|
|
5586
|
+
:returns dict: a `ledger structure <https://docs.ccxt.com/#/?id=ledger>`
|
|
5392
5587
|
"""
|
|
5393
5588
|
self.load_markets()
|
|
5589
|
+
paginate = False
|
|
5590
|
+
paginate, params = self.handle_option_and_params(params, 'fetchLedger', 'paginate')
|
|
5591
|
+
if paginate:
|
|
5592
|
+
return self.fetch_paginated_call_cursor('fetchLedger', code, since, limit, params, 'nextPageCursor', 'cursor', None, 50)
|
|
5394
5593
|
request: dict = {
|
|
5395
5594
|
# 'coin': currency['id'],
|
|
5396
5595
|
# 'currency': currency['id'], # alias
|
|
@@ -5425,11 +5624,17 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5425
5624
|
request[currencyKey] = currency['id']
|
|
5426
5625
|
if limit is not None:
|
|
5427
5626
|
request['limit'] = limit
|
|
5627
|
+
subType = None
|
|
5628
|
+
subType, params = self.handle_sub_type_and_params('fetchLedger', None, params)
|
|
5428
5629
|
response = None
|
|
5429
5630
|
if enableUnified[1]:
|
|
5430
|
-
|
|
5631
|
+
unifiedMarginStatus = self.safe_integer(self.options, 'unifiedMarginStatus', 5) # 3/4 uta 1.0, 5/6 uta 2.0
|
|
5632
|
+
if subType == 'inverse' and (unifiedMarginStatus < 5):
|
|
5633
|
+
response = self.privateGetV5AccountContractTransactionLog(self.extend(request, params))
|
|
5634
|
+
else:
|
|
5635
|
+
response = self.privateGetV5AccountTransactionLog(self.extend(request, params))
|
|
5431
5636
|
else:
|
|
5432
|
-
response = self.
|
|
5637
|
+
response = self.privateGetV5AccountContractTransactionLog(self.extend(request, params))
|
|
5433
5638
|
#
|
|
5434
5639
|
# {
|
|
5435
5640
|
# "ret_code": 0,
|
|
@@ -5536,7 +5741,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5536
5741
|
data = self.add_pagination_cursor_to_result(response)
|
|
5537
5742
|
return self.parse_ledger(data, currency, since, limit)
|
|
5538
5743
|
|
|
5539
|
-
def parse_ledger_entry(self, item: dict, currency: Currency = None):
|
|
5744
|
+
def parse_ledger_entry(self, item: dict, currency: Currency = None) -> LedgerEntry:
|
|
5540
5745
|
#
|
|
5541
5746
|
# {
|
|
5542
5747
|
# "id": 234467,
|
|
@@ -5575,36 +5780,41 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5575
5780
|
#
|
|
5576
5781
|
currencyId = self.safe_string_2(item, 'coin', 'currency')
|
|
5577
5782
|
code = self.safe_currency_code(currencyId, currency)
|
|
5578
|
-
|
|
5579
|
-
|
|
5580
|
-
|
|
5783
|
+
currency = self.safe_currency(currencyId, currency)
|
|
5784
|
+
amountString = self.safe_string_2(item, 'amount', 'change')
|
|
5785
|
+
afterString = self.safe_string_2(item, 'wallet_balance', 'cashBalance')
|
|
5786
|
+
direction = 'out' if Precise.string_lt(amountString, '0') else 'in'
|
|
5581
5787
|
before = None
|
|
5582
|
-
|
|
5583
|
-
|
|
5584
|
-
|
|
5788
|
+
after = None
|
|
5789
|
+
amount = None
|
|
5790
|
+
if afterString is not None and amountString is not None:
|
|
5791
|
+
difference = amountString if (direction == 'out') else Precise.string_neg(amountString)
|
|
5792
|
+
before = self.parse_to_numeric(Precise.string_add(afterString, difference))
|
|
5793
|
+
after = self.parse_to_numeric(afterString)
|
|
5794
|
+
amount = self.parse_to_numeric(Precise.string_abs(amountString))
|
|
5585
5795
|
timestamp = self.parse8601(self.safe_string(item, 'exec_time'))
|
|
5586
5796
|
if timestamp is None:
|
|
5587
5797
|
timestamp = self.safe_integer(item, 'transactionTime')
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
'id': id,
|
|
5593
|
-
'currency': code,
|
|
5798
|
+
return self.safe_ledger_entry({
|
|
5799
|
+
'info': item,
|
|
5800
|
+
'id': self.safe_string(item, 'id'),
|
|
5801
|
+
'direction': direction,
|
|
5594
5802
|
'account': self.safe_string(item, 'wallet_id'),
|
|
5803
|
+
'referenceId': self.safe_string(item, 'tx_id'),
|
|
5595
5804
|
'referenceAccount': None,
|
|
5596
|
-
'
|
|
5597
|
-
'
|
|
5598
|
-
'amount':
|
|
5599
|
-
'before': self.parse_number(before),
|
|
5600
|
-
'after': self.parse_number(after),
|
|
5601
|
-
'fee': self.parse_number(self.safe_string(item, 'fee')),
|
|
5602
|
-
'direction': direction,
|
|
5805
|
+
'type': self.parse_ledger_entry_type(self.safe_string(item, 'type')),
|
|
5806
|
+
'currency': code,
|
|
5807
|
+
'amount': amount,
|
|
5603
5808
|
'timestamp': timestamp,
|
|
5604
5809
|
'datetime': self.iso8601(timestamp),
|
|
5605
|
-
'
|
|
5606
|
-
'
|
|
5607
|
-
|
|
5810
|
+
'before': before,
|
|
5811
|
+
'after': after,
|
|
5812
|
+
'status': 'ok',
|
|
5813
|
+
'fee': {
|
|
5814
|
+
'currency': code,
|
|
5815
|
+
'cost': self.safe_number(item, 'fee'),
|
|
5816
|
+
},
|
|
5817
|
+
}, currency)
|
|
5608
5818
|
|
|
5609
5819
|
def parse_ledger_entry_type(self, type):
|
|
5610
5820
|
types: dict = {
|
|
@@ -5631,10 +5841,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5631
5841
|
}
|
|
5632
5842
|
return self.safe_string(types, type, type)
|
|
5633
5843
|
|
|
5634
|
-
def withdraw(self, code: str, amount: float, address: str, tag=None, params={}):
|
|
5844
|
+
def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
|
|
5635
5845
|
"""
|
|
5636
5846
|
make a withdrawal
|
|
5637
|
-
|
|
5847
|
+
|
|
5848
|
+
https://bybit-exchange.github.io/docs/v5/asset/withdraw
|
|
5849
|
+
|
|
5638
5850
|
:param str code: unified currency code
|
|
5639
5851
|
:param float amount: the amount to withdraw
|
|
5640
5852
|
:param str address: the address to withdraw to
|
|
@@ -5643,6 +5855,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5643
5855
|
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
|
5644
5856
|
"""
|
|
5645
5857
|
tag, params = self.handle_withdraw_tag_and_params(tag, params)
|
|
5858
|
+
accountType = None
|
|
5859
|
+
accounts = self.is_unified_enabled()
|
|
5860
|
+
isUta = accounts[1]
|
|
5861
|
+
accountType, params = self.handle_option_and_params(params, 'withdraw', 'accountType', 'SPOT')
|
|
5862
|
+
if isUta:
|
|
5863
|
+
accountType = 'UTA'
|
|
5646
5864
|
self.load_markets()
|
|
5647
5865
|
self.check_address(address)
|
|
5648
5866
|
currency = self.currency(code)
|
|
@@ -5651,6 +5869,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5651
5869
|
'amount': self.number_to_string(amount),
|
|
5652
5870
|
'address': address,
|
|
5653
5871
|
'timestamp': self.milliseconds(),
|
|
5872
|
+
'accountType': accountType,
|
|
5654
5873
|
}
|
|
5655
5874
|
if tag is not None:
|
|
5656
5875
|
request['tag'] = tag
|
|
@@ -5673,10 +5892,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5673
5892
|
result = self.safe_dict(response, 'result', {})
|
|
5674
5893
|
return self.parse_transaction(result, currency)
|
|
5675
5894
|
|
|
5676
|
-
def fetch_position(self, symbol: str, params={}):
|
|
5895
|
+
def fetch_position(self, symbol: str, params={}) -> Position:
|
|
5677
5896
|
"""
|
|
5678
5897
|
fetch data on a single open contract trade position
|
|
5679
|
-
|
|
5898
|
+
|
|
5899
|
+
https://bybit-exchange.github.io/docs/v5/position
|
|
5900
|
+
|
|
5680
5901
|
:param str symbol: unified market symbol of the market the position is held in, default is None
|
|
5681
5902
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
5682
5903
|
:returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
|
@@ -5688,18 +5909,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5688
5909
|
request: dict = {
|
|
5689
5910
|
'symbol': market['id'],
|
|
5690
5911
|
}
|
|
5691
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
5692
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
5693
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
5694
5912
|
response = None
|
|
5695
5913
|
type = None
|
|
5696
5914
|
type, params = self.get_bybit_type('fetchPosition', market, params)
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1QueryPosition(self.extend(request, params))
|
|
5700
|
-
else:
|
|
5701
|
-
request['category'] = type
|
|
5702
|
-
response = self.privateGetV5PositionList(self.extend(request, params))
|
|
5915
|
+
request['category'] = type
|
|
5916
|
+
response = self.privateGetV5PositionList(self.extend(request, params))
|
|
5703
5917
|
#
|
|
5704
5918
|
# {
|
|
5705
5919
|
# "retCode": 0,
|
|
@@ -5749,88 +5963,26 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5749
5963
|
position['datetime'] = self.iso8601(timestamp)
|
|
5750
5964
|
return position
|
|
5751
5965
|
|
|
5752
|
-
def
|
|
5753
|
-
self.load_markets()
|
|
5754
|
-
request: dict = {}
|
|
5755
|
-
market = None
|
|
5756
|
-
if isinstance(symbols, list):
|
|
5757
|
-
length = len(symbols)
|
|
5758
|
-
if length != 1:
|
|
5759
|
-
raise ArgumentsRequired(self.id + ' fetchUsdcPositions() takes an array with exactly one symbol')
|
|
5760
|
-
symbol = self.safe_string(symbols, 0)
|
|
5761
|
-
market = self.market(symbol)
|
|
5762
|
-
request['symbol'] = market['id']
|
|
5763
|
-
elif symbols is not None:
|
|
5764
|
-
market = self.market(symbols)
|
|
5765
|
-
request['symbol'] = market['id']
|
|
5766
|
-
type = None
|
|
5767
|
-
type, params = self.get_bybit_type('fetchUsdcPositions', market, params)
|
|
5768
|
-
request['category'] = 'OPTION' if (type == 'option') else 'PERPETUAL'
|
|
5769
|
-
response = self.privatePostOptionUsdcOpenapiPrivateV1QueryPosition(self.extend(request, params))
|
|
5770
|
-
#
|
|
5771
|
-
# {
|
|
5772
|
-
# "result": {
|
|
5773
|
-
# "cursor": "BTC-31DEC21-24000-P%3A1640834421431%2CBTC-31DEC21-24000-P%3A1640834421431",
|
|
5774
|
-
# "resultTotalSize": 1,
|
|
5775
|
-
# "dataList": [
|
|
5776
|
-
# {
|
|
5777
|
-
# "symbol": "BTC-31DEC21-24000-P",
|
|
5778
|
-
# "leverage": "",
|
|
5779
|
-
# "occClosingFee": "",
|
|
5780
|
-
# "liqPrice": "",
|
|
5781
|
-
# "positionValue": "",
|
|
5782
|
-
# "takeProfit": "",
|
|
5783
|
-
# "riskId": "",
|
|
5784
|
-
# "trailingStop": "",
|
|
5785
|
-
# "unrealisedPnl": "",
|
|
5786
|
-
# "createdAt": "1640834421431",
|
|
5787
|
-
# "markPrice": "0.00",
|
|
5788
|
-
# "cumRealisedPnl": "",
|
|
5789
|
-
# "positionMM": "359.5271",
|
|
5790
|
-
# "positionIM": "467.0633",
|
|
5791
|
-
# "updatedAt": "1640834421431",
|
|
5792
|
-
# "tpSLMode": "",
|
|
5793
|
-
# "side": "Sell",
|
|
5794
|
-
# "bustPrice": "",
|
|
5795
|
-
# "deleverageIndicator": 0,
|
|
5796
|
-
# "entryPrice": "1.4",
|
|
5797
|
-
# "size": "-0.100",
|
|
5798
|
-
# "sessionRPL": "",
|
|
5799
|
-
# "positionStatus": "",
|
|
5800
|
-
# "sessionUPL": "",
|
|
5801
|
-
# "stopLoss": "",
|
|
5802
|
-
# "orderMargin": "",
|
|
5803
|
-
# "sessionAvgPrice": "1.5"
|
|
5804
|
-
# }
|
|
5805
|
-
# ]
|
|
5806
|
-
# },
|
|
5807
|
-
# "retCode": 0,
|
|
5808
|
-
# "retMsg": "Success."
|
|
5809
|
-
# }
|
|
5810
|
-
#
|
|
5811
|
-
result = self.safe_dict(response, 'result', {})
|
|
5812
|
-
positions = self.safe_list(result, 'dataList', [])
|
|
5813
|
-
results = []
|
|
5814
|
-
for i in range(0, len(positions)):
|
|
5815
|
-
rawPosition = positions[i]
|
|
5816
|
-
if ('data' in rawPosition) and ('is_valid' in rawPosition):
|
|
5817
|
-
# futures only
|
|
5818
|
-
rawPosition = self.safe_dict(rawPosition, 'data')
|
|
5819
|
-
results.append(self.parse_position(rawPosition, market))
|
|
5820
|
-
return self.filter_by_array_positions(results, 'symbol', symbols, False)
|
|
5821
|
-
|
|
5822
|
-
def fetch_positions(self, symbols: Strings = None, params={}):
|
|
5966
|
+
def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
|
|
5823
5967
|
"""
|
|
5824
5968
|
fetch all open positions
|
|
5825
|
-
|
|
5969
|
+
|
|
5970
|
+
https://bybit-exchange.github.io/docs/v5/position
|
|
5971
|
+
|
|
5826
5972
|
:param str[] symbols: list of unified market symbols
|
|
5827
5973
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
5828
5974
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
5829
5975
|
:param str [params.subType]: market subType, ['linear', 'inverse']
|
|
5830
5976
|
:param str [params.baseCoin]: Base coin. Supports linear, inverse & option
|
|
5831
5977
|
:param str [params.settleCoin]: Settle coin. Supports linear, inverse & option
|
|
5978
|
+
:param boolean [params.paginate]: default False, when True will automatically paginate by calling self endpoint multiple times
|
|
5832
5979
|
:returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
|
|
5833
5980
|
"""
|
|
5981
|
+
self.load_markets()
|
|
5982
|
+
paginate = False
|
|
5983
|
+
paginate, params = self.handle_option_and_params(params, 'fetchPositions', 'paginate')
|
|
5984
|
+
if paginate:
|
|
5985
|
+
return self.fetch_paginated_call_cursor('fetchPositions', symbols, None, None, params, 'nextPageCursor', 'cursor', None, 200)
|
|
5834
5986
|
symbol = None
|
|
5835
5987
|
if (symbols is not None) and isinstance(symbols, list):
|
|
5836
5988
|
symbolsLength = len(symbols)
|
|
@@ -5842,17 +5994,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5842
5994
|
elif symbols is not None:
|
|
5843
5995
|
symbol = symbols
|
|
5844
5996
|
symbols = [self.symbol(symbol)]
|
|
5845
|
-
self.load_markets()
|
|
5846
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
5847
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
5848
5997
|
request: dict = {}
|
|
5849
5998
|
market = None
|
|
5850
|
-
isUsdcSettled = False
|
|
5851
5999
|
if symbol is not None:
|
|
5852
6000
|
market = self.market(symbol)
|
|
5853
6001
|
symbol = market['symbol']
|
|
5854
6002
|
request['symbol'] = market['id']
|
|
5855
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
5856
6003
|
type = None
|
|
5857
6004
|
type, params = self.get_bybit_type('fetchPositions', market, params)
|
|
5858
6005
|
if type == 'linear' or type == 'inverse':
|
|
@@ -5862,13 +6009,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5862
6009
|
defaultSettle = self.safe_string(self.options, 'defaultSettle', 'USDT')
|
|
5863
6010
|
settleCoin = self.safe_string(params, 'settleCoin', defaultSettle)
|
|
5864
6011
|
request['settleCoin'] = settleCoin
|
|
5865
|
-
isUsdcSettled = (settleCoin == 'USDC')
|
|
5866
6012
|
else:
|
|
5867
6013
|
# inverse
|
|
5868
6014
|
if symbol is None and baseCoin is None:
|
|
5869
6015
|
request['category'] = 'inverse'
|
|
5870
|
-
if (
|
|
5871
|
-
|
|
6016
|
+
if self.safe_integer(params, 'limit') is None:
|
|
6017
|
+
request['limit'] = 200 # max limit
|
|
5872
6018
|
params = self.omit(params, ['type'])
|
|
5873
6019
|
request['category'] = type
|
|
5874
6020
|
response = self.privateGetV5PositionList(self.extend(request, params))
|
|
@@ -5917,7 +6063,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
5917
6063
|
results.append(self.parse_position(rawPosition))
|
|
5918
6064
|
return self.filter_by_array_positions(results, 'symbol', symbols, False)
|
|
5919
6065
|
|
|
5920
|
-
def parse_position(self, position: dict, market: Market = None):
|
|
6066
|
+
def parse_position(self, position: dict, market: Market = None) -> Position:
|
|
5921
6067
|
#
|
|
5922
6068
|
# linear swap
|
|
5923
6069
|
#
|
|
@@ -6082,12 +6228,14 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6082
6228
|
marginMode = 'isolated' if (tradeMode == 1) else 'cross'
|
|
6083
6229
|
collateralString = self.safe_string(position, 'positionBalance')
|
|
6084
6230
|
entryPrice = self.omit_zero(self.safe_string_n(position, ['entryPrice', 'avgPrice', 'avgEntryPrice']))
|
|
6231
|
+
markPrice = self.safe_string(position, 'markPrice')
|
|
6085
6232
|
liquidationPrice = self.omit_zero(self.safe_string(position, 'liqPrice'))
|
|
6086
6233
|
leverage = self.safe_string(position, 'leverage')
|
|
6087
6234
|
if liquidationPrice is not None:
|
|
6088
6235
|
if market['settle'] == 'USDC':
|
|
6089
6236
|
# (Entry price - Liq price) * Contracts + Maintenance Margin + (unrealised pnl) = Collateral
|
|
6090
|
-
|
|
6237
|
+
price = markPrice if self.safe_bool(self.options, 'useMarkPriceForPositionCollateral', False) else entryPrice
|
|
6238
|
+
difference = Precise.string_abs(Precise.string_sub(price, liquidationPrice))
|
|
6091
6239
|
collateralString = Precise.string_add(Precise.string_add(Precise.string_mul(difference, size), maintenanceMarginString), unrealisedPnl)
|
|
6092
6240
|
else:
|
|
6093
6241
|
bustPrice = self.safe_string(position, 'bustPrice')
|
|
@@ -6114,6 +6262,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6114
6262
|
initialMarginString = Precise.string_div(size, Precise.string_mul(entryPrice, leverage))
|
|
6115
6263
|
maintenanceMarginPercentage = Precise.string_div(maintenanceMarginString, notional)
|
|
6116
6264
|
marginRatio = Precise.string_div(maintenanceMarginString, collateralString, 4)
|
|
6265
|
+
positionIdx = self.safe_string(position, 'positionIdx')
|
|
6266
|
+
hedged = (positionIdx is not None) and (positionIdx != '0')
|
|
6117
6267
|
return self.safe_position({
|
|
6118
6268
|
'info': position,
|
|
6119
6269
|
'id': None,
|
|
@@ -6134,7 +6284,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6134
6284
|
'contractSize': self.safe_number(market, 'contractSize'),
|
|
6135
6285
|
'marginRatio': self.parse_number(marginRatio),
|
|
6136
6286
|
'liquidationPrice': self.parse_number(liquidationPrice),
|
|
6137
|
-
'markPrice': self.
|
|
6287
|
+
'markPrice': self.parse_number(markPrice),
|
|
6138
6288
|
'lastPrice': self.safe_number(position, 'avgExitPrice'),
|
|
6139
6289
|
'collateral': self.parse_number(collateralString),
|
|
6140
6290
|
'marginMode': marginMode,
|
|
@@ -6142,12 +6292,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6142
6292
|
'percentage': None,
|
|
6143
6293
|
'stopLossPrice': self.safe_number_2(position, 'stop_loss', 'stopLoss'),
|
|
6144
6294
|
'takeProfitPrice': self.safe_number_2(position, 'take_profit', 'takeProfit'),
|
|
6295
|
+
'hedged': hedged,
|
|
6145
6296
|
})
|
|
6146
6297
|
|
|
6147
6298
|
def fetch_leverage(self, symbol: str, params={}) -> Leverage:
|
|
6148
6299
|
"""
|
|
6149
6300
|
fetch the set leverage for a market
|
|
6150
|
-
|
|
6301
|
+
|
|
6302
|
+
https://bybit-exchange.github.io/docs/v5/position
|
|
6303
|
+
|
|
6151
6304
|
:param str symbol: unified market symbol
|
|
6152
6305
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
6153
6306
|
:returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
|
|
@@ -6171,8 +6324,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6171
6324
|
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
|
6172
6325
|
"""
|
|
6173
6326
|
set margin mode(account) or trade mode(symbol)
|
|
6174
|
-
|
|
6175
|
-
|
|
6327
|
+
|
|
6328
|
+
https://bybit-exchange.github.io/docs/v5/account/set-margin-mode
|
|
6329
|
+
https://bybit-exchange.github.io/docs/v5/position/cross-isolate
|
|
6330
|
+
|
|
6176
6331
|
:param str marginMode: account mode must be either [isolated, cross, portfolio], trade mode must be either [isolated, cross]
|
|
6177
6332
|
:param str symbol: unified market symbol of the market the position is held in, default is None
|
|
6178
6333
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -6250,10 +6405,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6250
6405
|
response = self.privatePostV5PositionSwitchIsolated(self.extend(request, params))
|
|
6251
6406
|
return response
|
|
6252
6407
|
|
|
6253
|
-
def set_leverage(self, leverage:
|
|
6408
|
+
def set_leverage(self, leverage: int, symbol: Str = None, params={}):
|
|
6254
6409
|
"""
|
|
6255
6410
|
set the level of leverage for a market
|
|
6256
|
-
|
|
6411
|
+
|
|
6412
|
+
https://bybit-exchange.github.io/docs/v5/position/leverage
|
|
6413
|
+
|
|
6257
6414
|
:param float leverage: the rate of leverage
|
|
6258
6415
|
:param str symbol: unified market symbol
|
|
6259
6416
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -6267,9 +6424,6 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6267
6424
|
market = self.market(symbol)
|
|
6268
6425
|
# WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS
|
|
6269
6426
|
# AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS
|
|
6270
|
-
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
6271
|
-
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
6272
|
-
isUsdcSettled = market['settle'] == 'USDC'
|
|
6273
6427
|
# engage in leverage setting
|
|
6274
6428
|
# we reuse the code here instead of having two methods
|
|
6275
6429
|
leverageString = self.number_to_string(leverage)
|
|
@@ -6278,26 +6432,23 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6278
6432
|
'buyLeverage': leverageString,
|
|
6279
6433
|
'sellLeverage': leverageString,
|
|
6280
6434
|
}
|
|
6281
|
-
|
|
6282
|
-
|
|
6283
|
-
|
|
6284
|
-
|
|
6435
|
+
request['buyLeverage'] = leverageString
|
|
6436
|
+
request['sellLeverage'] = leverageString
|
|
6437
|
+
if market['linear']:
|
|
6438
|
+
request['category'] = 'linear'
|
|
6439
|
+
elif market['inverse']:
|
|
6440
|
+
request['category'] = 'inverse'
|
|
6285
6441
|
else:
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
if market['linear']:
|
|
6289
|
-
request['category'] = 'linear'
|
|
6290
|
-
elif market['inverse']:
|
|
6291
|
-
request['category'] = 'inverse'
|
|
6292
|
-
else:
|
|
6293
|
-
raise NotSupported(self.id + ' setLeverage() only support linear and inverse market')
|
|
6294
|
-
response = self.privatePostV5PositionSetLeverage(self.extend(request, params))
|
|
6442
|
+
raise NotSupported(self.id + ' setLeverage() only support linear and inverse market')
|
|
6443
|
+
response = self.privatePostV5PositionSetLeverage(self.extend(request, params))
|
|
6295
6444
|
return response
|
|
6296
6445
|
|
|
6297
6446
|
def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
|
|
6298
6447
|
"""
|
|
6299
6448
|
set hedged to True or False for a market
|
|
6300
|
-
|
|
6449
|
+
|
|
6450
|
+
https://bybit-exchange.github.io/docs/v5/position/position-mode
|
|
6451
|
+
|
|
6301
6452
|
:param bool hedged:
|
|
6302
6453
|
:param str symbol: used for unified account with inverse market
|
|
6303
6454
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -6388,12 +6539,14 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6388
6539
|
data = self.add_pagination_cursor_to_result(response)
|
|
6389
6540
|
id = self.safe_string(result, 'symbol')
|
|
6390
6541
|
market = self.safe_market(id, market, None, 'contract')
|
|
6391
|
-
return self.
|
|
6542
|
+
return self.parse_open_interests_history(data, market, since, limit)
|
|
6392
6543
|
|
|
6393
6544
|
def fetch_open_interest(self, symbol: str, params={}):
|
|
6394
6545
|
"""
|
|
6395
6546
|
Retrieves the open interest of a derivative trading pair
|
|
6396
|
-
|
|
6547
|
+
|
|
6548
|
+
https://bybit-exchange.github.io/docs/v5/market/open-interest
|
|
6549
|
+
|
|
6397
6550
|
:param str symbol: Unified CCXT market symbol
|
|
6398
6551
|
:param dict [params]: exchange specific parameters
|
|
6399
6552
|
:param str [params.interval]: 5m, 15m, 30m, 1h, 4h, 1d
|
|
@@ -6449,7 +6602,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6449
6602
|
def fetch_open_interest_history(self, symbol: str, timeframe='1h', since: Int = None, limit: Int = None, params={}):
|
|
6450
6603
|
"""
|
|
6451
6604
|
Gets the total amount of unsettled contracts. In other words, the total number of contracts held in open positions
|
|
6452
|
-
|
|
6605
|
+
|
|
6606
|
+
https://bybit-exchange.github.io/docs/v5/market/open-interest
|
|
6607
|
+
|
|
6453
6608
|
:param str symbol: Unified market symbol
|
|
6454
6609
|
:param str timeframe: "5m", 15m, 30m, 1h, 4h, 1d
|
|
6455
6610
|
:param int [since]: Not used by Bybit
|
|
@@ -6459,12 +6614,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6459
6614
|
:returns: An array of open interest structures
|
|
6460
6615
|
"""
|
|
6461
6616
|
if timeframe == '1m':
|
|
6462
|
-
raise BadRequest(self.id + 'fetchOpenInterestHistory cannot use the 1m timeframe')
|
|
6617
|
+
raise BadRequest(self.id + ' fetchOpenInterestHistory cannot use the 1m timeframe')
|
|
6463
6618
|
self.load_markets()
|
|
6464
6619
|
paginate = self.safe_bool(params, 'paginate')
|
|
6465
6620
|
if paginate:
|
|
6466
6621
|
params = self.omit(params, 'paginate')
|
|
6467
|
-
|
|
6622
|
+
params['timeframe'] = timeframe
|
|
6623
|
+
return self.fetch_paginated_call_cursor('fetchOpenInterestHistory', symbol, since, limit, params, 'nextPageCursor', 'cursor', None, 200)
|
|
6468
6624
|
market = self.market(symbol)
|
|
6469
6625
|
if market['spot'] or market['option']:
|
|
6470
6626
|
raise BadRequest(self.id + ' fetchOpenInterestHistory() symbol does not support market ' + symbol)
|
|
@@ -6483,10 +6639,13 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6483
6639
|
# }
|
|
6484
6640
|
#
|
|
6485
6641
|
timestamp = self.safe_integer(interest, 'timestamp')
|
|
6486
|
-
|
|
6642
|
+
openInterest = self.safe_number_2(interest, 'open_interest', 'openInterest')
|
|
6643
|
+
# the openInterest is in the base asset for linear and quote asset for inverse
|
|
6644
|
+
amount = openInterest if market['linear'] else None
|
|
6645
|
+
value = openInterest if market['inverse'] else None
|
|
6487
6646
|
return self.safe_open_interest({
|
|
6488
6647
|
'symbol': market['symbol'],
|
|
6489
|
-
'openInterestAmount':
|
|
6648
|
+
'openInterestAmount': amount,
|
|
6490
6649
|
'openInterestValue': value,
|
|
6491
6650
|
'timestamp': timestamp,
|
|
6492
6651
|
'datetime': self.iso8601(timestamp),
|
|
@@ -6496,7 +6655,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6496
6655
|
def fetch_cross_borrow_rate(self, code: str, params={}) -> CrossBorrowRate:
|
|
6497
6656
|
"""
|
|
6498
6657
|
fetch the rate of interest to borrow a currency for margin trading
|
|
6499
|
-
|
|
6658
|
+
|
|
6659
|
+
https://bybit-exchange.github.io/docs/zh-TW/v5/spot-margin-normal/interest-quota
|
|
6660
|
+
|
|
6500
6661
|
:param str code: unified currency code
|
|
6501
6662
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
6502
6663
|
:returns dict: a `borrow rate structure <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
|
|
@@ -6536,21 +6697,33 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6536
6697
|
# "timestamp": 1666734490778
|
|
6537
6698
|
# }
|
|
6538
6699
|
#
|
|
6700
|
+
# fetchBorrowRateHistory
|
|
6701
|
+
# {
|
|
6702
|
+
# "timestamp": 1721469600000,
|
|
6703
|
+
# "currency": "USDC",
|
|
6704
|
+
# "hourlyBorrowRate": "0.000014621596",
|
|
6705
|
+
# "vipLevel": "No VIP"
|
|
6706
|
+
# }
|
|
6707
|
+
#
|
|
6539
6708
|
timestamp = self.safe_integer(info, 'timestamp')
|
|
6540
|
-
currencyId = self.
|
|
6709
|
+
currencyId = self.safe_string_2(info, 'coin', 'currency')
|
|
6710
|
+
hourlyBorrowRate = self.safe_number(info, 'hourlyBorrowRate')
|
|
6711
|
+
period = 3600000 if (hourlyBorrowRate is not None) else 86400000 # 1h or 1d
|
|
6541
6712
|
return {
|
|
6542
6713
|
'currency': self.safe_currency_code(currencyId, currency),
|
|
6543
|
-
'rate': self.safe_number(info, 'interestRate'),
|
|
6544
|
-
'period':
|
|
6714
|
+
'rate': self.safe_number(info, 'interestRate', hourlyBorrowRate),
|
|
6715
|
+
'period': period, # Daily
|
|
6545
6716
|
'timestamp': timestamp,
|
|
6546
6717
|
'datetime': self.iso8601(timestamp),
|
|
6547
6718
|
'info': info,
|
|
6548
6719
|
}
|
|
6549
6720
|
|
|
6550
|
-
def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
6721
|
+
def fetch_borrow_interest(self, code: Str = None, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[BorrowInterest]:
|
|
6551
6722
|
"""
|
|
6552
6723
|
fetch the interest owed by the user for borrowing currency for margin trading
|
|
6553
|
-
|
|
6724
|
+
|
|
6725
|
+
https://bybit-exchange.github.io/docs/zh-TW/v5/spot-margin-normal/account-info
|
|
6726
|
+
|
|
6554
6727
|
:param str code: unified currency code
|
|
6555
6728
|
:param str symbol: unified market symbol when fetch interest in isolated markets
|
|
6556
6729
|
:param number [since]: the earliest time in ms to fetch borrrow interest for
|
|
@@ -6591,7 +6764,56 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6591
6764
|
interest = self.parse_borrow_interests(rows, None)
|
|
6592
6765
|
return self.filter_by_currency_since_limit(interest, code, since, limit)
|
|
6593
6766
|
|
|
6594
|
-
def
|
|
6767
|
+
def fetch_borrow_rate_history(self, code: str, since: Int = None, limit: Int = None, params={}):
|
|
6768
|
+
"""
|
|
6769
|
+
retrieves a history of a currencies borrow interest rate at specific time slots
|
|
6770
|
+
|
|
6771
|
+
https://bybit-exchange.github.io/docs/v5/spot-margin-uta/historical-interest
|
|
6772
|
+
|
|
6773
|
+
:param str code: unified currency code
|
|
6774
|
+
:param int [since]: timestamp for the earliest borrow rate
|
|
6775
|
+
:param int [limit]: the maximum number of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>` to retrieve
|
|
6776
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
6777
|
+
:param int [params.until]: the latest time in ms to fetch entries for
|
|
6778
|
+
:returns dict[]: an array of `borrow rate structures <https://docs.ccxt.com/#/?id=borrow-rate-structure>`
|
|
6779
|
+
"""
|
|
6780
|
+
self.load_markets()
|
|
6781
|
+
currency = self.currency(code)
|
|
6782
|
+
request: dict = {
|
|
6783
|
+
'currency': currency['id'],
|
|
6784
|
+
}
|
|
6785
|
+
if since is None:
|
|
6786
|
+
since = self.milliseconds() - 86400000 * 30 # last 30 days
|
|
6787
|
+
request['startTime'] = since
|
|
6788
|
+
endTime = self.safe_integer_2(params, 'until', 'endTime')
|
|
6789
|
+
params = self.omit(params, ['until'])
|
|
6790
|
+
if endTime is None:
|
|
6791
|
+
endTime = since + 86400000 * 30 # since + 30 days
|
|
6792
|
+
request['endTime'] = endTime
|
|
6793
|
+
response = self.privateGetV5SpotMarginTradeInterestRateHistory(self.extend(request, params))
|
|
6794
|
+
#
|
|
6795
|
+
# {
|
|
6796
|
+
# "retCode": 0,
|
|
6797
|
+
# "retMsg": "OK",
|
|
6798
|
+
# "result": {
|
|
6799
|
+
# "list": [
|
|
6800
|
+
# {
|
|
6801
|
+
# "timestamp": 1721469600000,
|
|
6802
|
+
# "currency": "USDC",
|
|
6803
|
+
# "hourlyBorrowRate": "0.000014621596",
|
|
6804
|
+
# "vipLevel": "No VIP"
|
|
6805
|
+
# }
|
|
6806
|
+
# ]
|
|
6807
|
+
# },
|
|
6808
|
+
# "retExtInfo": "{}",
|
|
6809
|
+
# "time": 1721899048991
|
|
6810
|
+
# }
|
|
6811
|
+
#
|
|
6812
|
+
data = self.safe_dict(response, 'result')
|
|
6813
|
+
rows = self.safe_list(data, 'list', [])
|
|
6814
|
+
return self.parse_borrow_rate_history(rows, code, since, limit)
|
|
6815
|
+
|
|
6816
|
+
def parse_borrow_interest(self, info: dict, market: Market = None) -> BorrowInterest:
|
|
6595
6817
|
#
|
|
6596
6818
|
# {
|
|
6597
6819
|
# "tokenId": "BTC",
|
|
@@ -6603,21 +6825,23 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6603
6825
|
# },
|
|
6604
6826
|
#
|
|
6605
6827
|
return {
|
|
6828
|
+
'info': info,
|
|
6606
6829
|
'symbol': None,
|
|
6607
|
-
'marginMode': 'cross',
|
|
6608
6830
|
'currency': self.safe_currency_code(self.safe_string(info, 'tokenId')),
|
|
6609
6831
|
'interest': self.safe_number(info, 'interest'),
|
|
6610
6832
|
'interestRate': None,
|
|
6611
6833
|
'amountBorrowed': self.safe_number(info, 'loan'),
|
|
6834
|
+
'marginMode': 'cross',
|
|
6612
6835
|
'timestamp': None,
|
|
6613
6836
|
'datetime': None,
|
|
6614
|
-
'info': info,
|
|
6615
6837
|
}
|
|
6616
6838
|
|
|
6617
6839
|
def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
|
6618
6840
|
"""
|
|
6619
6841
|
transfer currency internally between wallets on the same account
|
|
6620
|
-
|
|
6842
|
+
|
|
6843
|
+
https://bybit-exchange.github.io/docs/v5/asset/create-inter-transfer
|
|
6844
|
+
|
|
6621
6845
|
:param str code: unified currency code
|
|
6622
6846
|
:param float amount: amount to transfer
|
|
6623
6847
|
:param str fromAccount: account to transfer from
|
|
@@ -6665,10 +6889,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6665
6889
|
'status': status,
|
|
6666
6890
|
})
|
|
6667
6891
|
|
|
6668
|
-
def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) ->
|
|
6892
|
+
def fetch_transfers(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[TransferEntry]:
|
|
6669
6893
|
"""
|
|
6670
6894
|
fetch a history of internal transfers made on an account
|
|
6671
|
-
|
|
6895
|
+
|
|
6896
|
+
https://bybit-exchange.github.io/docs/v5/asset/inter-transfer-list
|
|
6897
|
+
|
|
6672
6898
|
:param str code: unified currency code of the currency transferred
|
|
6673
6899
|
:param int [since]: the earliest time in ms to fetch transfers for
|
|
6674
6900
|
:param int [limit]: the maximum number of transfer structures to retrieve
|
|
@@ -6685,8 +6911,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6685
6911
|
currency = None
|
|
6686
6912
|
request: dict = {}
|
|
6687
6913
|
if code is not None:
|
|
6688
|
-
currency = self.
|
|
6689
|
-
request['coin'] = currency
|
|
6914
|
+
currency = self.safe_currency(code)
|
|
6915
|
+
request['coin'] = currency['id']
|
|
6690
6916
|
if since is not None:
|
|
6691
6917
|
request['startTime'] = since
|
|
6692
6918
|
if limit is not None:
|
|
@@ -6721,7 +6947,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6721
6947
|
def borrow_cross_margin(self, code: str, amount: float, params={}):
|
|
6722
6948
|
"""
|
|
6723
6949
|
create a loan to borrow margin
|
|
6724
|
-
|
|
6950
|
+
|
|
6951
|
+
https://bybit-exchange.github.io/docs/v5/spot-margin-normal/borrow
|
|
6952
|
+
|
|
6725
6953
|
:param str code: unified currency code of the currency to borrow
|
|
6726
6954
|
:param float amount: the amount to borrow
|
|
6727
6955
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -6755,7 +6983,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6755
6983
|
def repay_cross_margin(self, code: str, amount, params={}):
|
|
6756
6984
|
"""
|
|
6757
6985
|
repay borrowed margin and interest
|
|
6758
|
-
|
|
6986
|
+
|
|
6987
|
+
https://bybit-exchange.github.io/docs/v5/spot-margin-normal/repay
|
|
6988
|
+
|
|
6759
6989
|
:param str code: unified currency code of the currency to repay
|
|
6760
6990
|
:param float amount: the amount to repay
|
|
6761
6991
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
@@ -6786,15 +7016,15 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6786
7016
|
'amount': amount,
|
|
6787
7017
|
})
|
|
6788
7018
|
|
|
6789
|
-
def parse_margin_loan(self, info, currency: Currency = None):
|
|
7019
|
+
def parse_margin_loan(self, info, currency: Currency = None) -> dict:
|
|
6790
7020
|
#
|
|
6791
|
-
#
|
|
7021
|
+
# borrowCrossMargin
|
|
6792
7022
|
#
|
|
6793
7023
|
# {
|
|
6794
7024
|
# "transactId": "14143"
|
|
6795
7025
|
# }
|
|
6796
7026
|
#
|
|
6797
|
-
#
|
|
7027
|
+
# repayCrossMargin
|
|
6798
7028
|
#
|
|
6799
7029
|
# {
|
|
6800
7030
|
# "repayId": "12128"
|
|
@@ -6857,7 +7087,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6857
7087
|
'status': self.parse_transfer_status(self.safe_string(transfer, 'status')),
|
|
6858
7088
|
}
|
|
6859
7089
|
|
|
6860
|
-
def fetch_derivatives_market_leverage_tiers(self, symbol: str, params={}):
|
|
7090
|
+
def fetch_derivatives_market_leverage_tiers(self, symbol: str, params={}) -> List[LeverageTier]:
|
|
6861
7091
|
self.load_markets()
|
|
6862
7092
|
market = self.market(symbol)
|
|
6863
7093
|
request: dict = {
|
|
@@ -6898,7 +7128,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6898
7128
|
def fetch_market_leverage_tiers(self, symbol: str, params={}) -> List[LeverageTier]:
|
|
6899
7129
|
"""
|
|
6900
7130
|
retrieve information on the maximum leverage, and maintenance margin for trades of varying trade sizes for a single market
|
|
6901
|
-
|
|
7131
|
+
|
|
7132
|
+
https://bybit-exchange.github.io/docs/v5/market/risk-limit
|
|
7133
|
+
|
|
6902
7134
|
:param str symbol: unified market symbol
|
|
6903
7135
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
6904
7136
|
:returns dict: a `leverage tiers structure <https://docs.ccxt.com/#/?id=leverage-tiers-structure>`
|
|
@@ -6935,7 +7167,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6935
7167
|
def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
|
6936
7168
|
"""
|
|
6937
7169
|
fetch the trading fees for a market
|
|
6938
|
-
|
|
7170
|
+
|
|
7171
|
+
https://bybit-exchange.github.io/docs/v5/account/fee-rate
|
|
7172
|
+
|
|
6939
7173
|
:param str symbol: unified market symbol
|
|
6940
7174
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
6941
7175
|
:returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
|
|
@@ -6946,14 +7180,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6946
7180
|
'symbol': market['id'],
|
|
6947
7181
|
}
|
|
6948
7182
|
category = None
|
|
6949
|
-
|
|
6950
|
-
category = 'linear'
|
|
6951
|
-
elif market['inverse']:
|
|
6952
|
-
category = 'inverse'
|
|
6953
|
-
elif market['spot']:
|
|
6954
|
-
category = 'spot'
|
|
6955
|
-
else:
|
|
6956
|
-
category = 'option'
|
|
7183
|
+
category, params = self.get_bybit_type('fetchTradingFee', market, params)
|
|
6957
7184
|
request['category'] = category
|
|
6958
7185
|
response = self.privateGetV5AccountFeeRate(self.extend(request, params))
|
|
6959
7186
|
#
|
|
@@ -6981,7 +7208,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
6981
7208
|
def fetch_trading_fees(self, params={}) -> TradingFees:
|
|
6982
7209
|
"""
|
|
6983
7210
|
fetch the trading fees for multiple markets
|
|
6984
|
-
|
|
7211
|
+
|
|
7212
|
+
https://bybit-exchange.github.io/docs/v5/account/fee-rate
|
|
7213
|
+
|
|
6985
7214
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
6986
7215
|
:param str [params.type]: market type, ['swap', 'option', 'spot']
|
|
6987
7216
|
:returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
|
|
@@ -7018,7 +7247,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7018
7247
|
result[symbol] = fee
|
|
7019
7248
|
return result
|
|
7020
7249
|
|
|
7021
|
-
def parse_deposit_withdraw_fee(self, fee, currency: Currency = None):
|
|
7250
|
+
def parse_deposit_withdraw_fee(self, fee, currency: Currency = None) -> Any:
|
|
7022
7251
|
#
|
|
7023
7252
|
# {
|
|
7024
7253
|
# "name": "BTC",
|
|
@@ -7071,7 +7300,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7071
7300
|
def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
|
|
7072
7301
|
"""
|
|
7073
7302
|
fetch deposit and withdraw fees
|
|
7074
|
-
|
|
7303
|
+
|
|
7304
|
+
https://bybit-exchange.github.io/docs/v5/asset/coin-info
|
|
7305
|
+
|
|
7075
7306
|
:param str[] codes: list of unified currency codes
|
|
7076
7307
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7077
7308
|
:returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
|
|
@@ -7116,7 +7347,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7116
7347
|
def fetch_settlement_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
7117
7348
|
"""
|
|
7118
7349
|
fetches historical settlement records
|
|
7119
|
-
|
|
7350
|
+
|
|
7351
|
+
https://bybit-exchange.github.io/docs/v5/market/delivery-price
|
|
7352
|
+
|
|
7120
7353
|
:param str symbol: unified market symbol of the settlement history
|
|
7121
7354
|
:param int [since]: timestamp in ms
|
|
7122
7355
|
:param int [limit]: number of records
|
|
@@ -7167,7 +7400,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7167
7400
|
def fetch_my_settlement_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
7168
7401
|
"""
|
|
7169
7402
|
fetches historical settlement records of the user
|
|
7170
|
-
|
|
7403
|
+
|
|
7404
|
+
https://bybit-exchange.github.io/docs/v5/asset/delivery
|
|
7405
|
+
|
|
7171
7406
|
:param str symbol: unified market symbol of the settlement history
|
|
7172
7407
|
:param int [since]: timestamp in ms
|
|
7173
7408
|
:param int [limit]: number of records
|
|
@@ -7184,9 +7419,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7184
7419
|
request['symbol'] = market['id']
|
|
7185
7420
|
type = None
|
|
7186
7421
|
type, params = self.get_bybit_type('fetchMySettlementHistory', market, params)
|
|
7187
|
-
if type == 'spot'
|
|
7422
|
+
if type == 'spot':
|
|
7188
7423
|
raise NotSupported(self.id + ' fetchMySettlementHistory() is not supported for spot market')
|
|
7189
|
-
request['category'] =
|
|
7424
|
+
request['category'] = type
|
|
7190
7425
|
if limit is not None:
|
|
7191
7426
|
request['limit'] = limit
|
|
7192
7427
|
response = self.privateGetV5AssetDeliveryRecord(self.extend(request, params))
|
|
@@ -7288,7 +7523,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7288
7523
|
def fetch_volatility_history(self, code: str, params={}):
|
|
7289
7524
|
"""
|
|
7290
7525
|
fetch the historical volatility of an option market based on an underlying asset
|
|
7291
|
-
|
|
7526
|
+
|
|
7527
|
+
https://bybit-exchange.github.io/docs/v5/market/iv
|
|
7528
|
+
|
|
7292
7529
|
:param str code: unified currency code
|
|
7293
7530
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7294
7531
|
:param int [params.period]: the period in days to fetch the volatility for: 7,14,21,30,60,90,180,270
|
|
@@ -7341,7 +7578,9 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7341
7578
|
def fetch_greeks(self, symbol: str, params={}) -> Greeks:
|
|
7342
7579
|
"""
|
|
7343
7580
|
fetches an option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
|
|
7344
|
-
|
|
7581
|
+
|
|
7582
|
+
https://bybit-exchange.github.io/docs/api-explorer/v5/market/tickers
|
|
7583
|
+
|
|
7345
7584
|
:param str symbol: unified symbol of the market to fetch greeks for
|
|
7346
7585
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7347
7586
|
:returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
|
|
@@ -7402,6 +7641,75 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7402
7641
|
'datetime': self.iso8601(timestamp),
|
|
7403
7642
|
})
|
|
7404
7643
|
|
|
7644
|
+
def fetch_all_greeks(self, symbols: Strings = None, params={}) -> List[Greeks]:
|
|
7645
|
+
"""
|
|
7646
|
+
fetches all option contracts greeks, financial metrics used to measure the factors that affect the price of an options contract
|
|
7647
|
+
|
|
7648
|
+
https://bybit-exchange.github.io/docs/api-explorer/v5/market/tickers
|
|
7649
|
+
|
|
7650
|
+
:param str[] [symbols]: unified symbols of the markets to fetch greeks for, all markets are returned if not assigned
|
|
7651
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7652
|
+
:param str [params.baseCoin]: the baseCoin of the symbol, default is BTC
|
|
7653
|
+
:returns dict: a `greeks structure <https://docs.ccxt.com/#/?id=greeks-structure>`
|
|
7654
|
+
"""
|
|
7655
|
+
self.load_markets()
|
|
7656
|
+
symbols = self.market_symbols(symbols, None, True, True, True)
|
|
7657
|
+
baseCoin = self.safe_string(params, 'baseCoin', 'BTC')
|
|
7658
|
+
request: dict = {
|
|
7659
|
+
'category': 'option',
|
|
7660
|
+
'baseCoin': baseCoin,
|
|
7661
|
+
}
|
|
7662
|
+
market = None
|
|
7663
|
+
if symbols is not None:
|
|
7664
|
+
symbolsLength = len(symbols)
|
|
7665
|
+
if symbolsLength == 1:
|
|
7666
|
+
market = self.market(symbols[0])
|
|
7667
|
+
request['symbol'] = market['id']
|
|
7668
|
+
response = self.publicGetV5MarketTickers(self.extend(request, params))
|
|
7669
|
+
#
|
|
7670
|
+
# {
|
|
7671
|
+
# "retCode": 0,
|
|
7672
|
+
# "retMsg": "SUCCESS",
|
|
7673
|
+
# "result": {
|
|
7674
|
+
# "category": "option",
|
|
7675
|
+
# "list": [
|
|
7676
|
+
# {
|
|
7677
|
+
# "symbol": "BTC-26JAN24-39000-C",
|
|
7678
|
+
# "bid1Price": "3205",
|
|
7679
|
+
# "bid1Size": "7.1",
|
|
7680
|
+
# "bid1Iv": "0.5478",
|
|
7681
|
+
# "ask1Price": "3315",
|
|
7682
|
+
# "ask1Size": "1.98",
|
|
7683
|
+
# "ask1Iv": "0.5638",
|
|
7684
|
+
# "lastPrice": "3230",
|
|
7685
|
+
# "highPrice24h": "3255",
|
|
7686
|
+
# "lowPrice24h": "3200",
|
|
7687
|
+
# "markPrice": "3273.02263032",
|
|
7688
|
+
# "indexPrice": "36790.96",
|
|
7689
|
+
# "markIv": "0.5577",
|
|
7690
|
+
# "underlyingPrice": "37649.67254894",
|
|
7691
|
+
# "openInterest": "19.67",
|
|
7692
|
+
# "turnover24h": "170140.33875912",
|
|
7693
|
+
# "volume24h": "4.56",
|
|
7694
|
+
# "totalVolume": "22",
|
|
7695
|
+
# "totalTurnover": "789305",
|
|
7696
|
+
# "delta": "0.49640971",
|
|
7697
|
+
# "gamma": "0.00004131",
|
|
7698
|
+
# "vega": "69.08651675",
|
|
7699
|
+
# "theta": "-24.9443226",
|
|
7700
|
+
# "predictedDeliveryPrice": "0",
|
|
7701
|
+
# "change24h": "0.18532111"
|
|
7702
|
+
# }
|
|
7703
|
+
# ]
|
|
7704
|
+
# },
|
|
7705
|
+
# "retExtInfo": {},
|
|
7706
|
+
# "time": 1699584008326
|
|
7707
|
+
# }
|
|
7708
|
+
#
|
|
7709
|
+
result = self.safe_dict(response, 'result', {})
|
|
7710
|
+
data = self.safe_list(result, 'list', [])
|
|
7711
|
+
return self.parse_all_greeks(data, symbols)
|
|
7712
|
+
|
|
7405
7713
|
def parse_greeks(self, greeks: dict, market: Market = None) -> Greeks:
|
|
7406
7714
|
#
|
|
7407
7715
|
# {
|
|
@@ -7456,10 +7764,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7456
7764
|
'info': greeks,
|
|
7457
7765
|
}
|
|
7458
7766
|
|
|
7459
|
-
def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
7767
|
+
def fetch_my_liquidations(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
|
7460
7768
|
"""
|
|
7461
7769
|
retrieves the users liquidated positions
|
|
7462
|
-
|
|
7770
|
+
|
|
7771
|
+
https://bybit-exchange.github.io/docs/api-explorer/v5/position/execution
|
|
7772
|
+
|
|
7463
7773
|
:param str [symbol]: unified CCXT market symbol
|
|
7464
7774
|
:param int [since]: the earliest time in ms to fetch liquidations for
|
|
7465
7775
|
:param int [limit]: the maximum number of liquidation structures to retrieve
|
|
@@ -7533,7 +7843,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7533
7843
|
liquidations = self.add_pagination_cursor_to_result(response)
|
|
7534
7844
|
return self.parse_liquidations(liquidations, market, since, limit)
|
|
7535
7845
|
|
|
7536
|
-
def parse_liquidation(self, liquidation, market: Market = None):
|
|
7846
|
+
def parse_liquidation(self, liquidation, market: Market = None) -> Liquidation:
|
|
7537
7847
|
#
|
|
7538
7848
|
# {
|
|
7539
7849
|
# "symbol": "ETHPERP",
|
|
@@ -7571,7 +7881,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7571
7881
|
quoteValueString = Precise.string_mul(baseValueString, priceString)
|
|
7572
7882
|
return self.safe_liquidation({
|
|
7573
7883
|
'info': liquidation,
|
|
7574
|
-
'symbol': self.safe_symbol(marketId, market),
|
|
7884
|
+
'symbol': self.safe_symbol(marketId, market, None, 'contract'),
|
|
7575
7885
|
'contracts': self.parse_number(contractsString),
|
|
7576
7886
|
'contractSize': self.parse_number(contractSizeString),
|
|
7577
7887
|
'price': self.parse_number(priceString),
|
|
@@ -7610,8 +7920,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7610
7920
|
|
|
7611
7921
|
def fetch_leverage_tiers(self, symbols: Strings = None, params={}) -> LeverageTiers:
|
|
7612
7922
|
"""
|
|
7613
|
-
:see: https://bybit-exchange.github.io/docs/v5/market/risk-limit
|
|
7614
7923
|
retrieve information on the maximum leverage, for different trade sizes
|
|
7924
|
+
|
|
7925
|
+
https://bybit-exchange.github.io/docs/v5/market/risk-limit
|
|
7926
|
+
|
|
7615
7927
|
:param str[] [symbols]: a list of unified market symbols
|
|
7616
7928
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7617
7929
|
:param str [params.subType]: market subType, ['linear', 'inverse'], default is 'linear'
|
|
@@ -7626,11 +7938,11 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7626
7938
|
if market['spot']:
|
|
7627
7939
|
raise NotSupported(self.id + ' fetchLeverageTiers() is not supported for spot market')
|
|
7628
7940
|
symbol = market['symbol']
|
|
7629
|
-
data = self.get_leverage_tiers_paginated(symbol, self.extend({'paginate': True, 'paginationCalls':
|
|
7941
|
+
data = self.get_leverage_tiers_paginated(symbol, self.extend({'paginate': True, 'paginationCalls': 50}, params))
|
|
7630
7942
|
symbols = self.market_symbols(symbols)
|
|
7631
7943
|
return self.parse_leverage_tiers(data, symbols, 'symbol')
|
|
7632
7944
|
|
|
7633
|
-
def parse_leverage_tiers(self, response, symbols: Strings = None, marketIdKey=None):
|
|
7945
|
+
def parse_leverage_tiers(self, response, symbols: Strings = None, marketIdKey=None) -> LeverageTiers:
|
|
7634
7946
|
#
|
|
7635
7947
|
# [
|
|
7636
7948
|
# {
|
|
@@ -7684,6 +7996,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7684
7996
|
minNotional = self.safe_number(info[i - 1], 'riskLimitValue')
|
|
7685
7997
|
tiers.append({
|
|
7686
7998
|
'tier': self.safe_integer(tier, 'id'),
|
|
7999
|
+
'symbol': self.safe_symbol(marketId, market),
|
|
7687
8000
|
'currency': market['settle'],
|
|
7688
8001
|
'minNotional': minNotional,
|
|
7689
8002
|
'maxNotional': self.safe_number(tier, 'riskLimitValue'),
|
|
@@ -7693,10 +8006,12 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7693
8006
|
})
|
|
7694
8007
|
return tiers
|
|
7695
8008
|
|
|
7696
|
-
def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
|
8009
|
+
def fetch_funding_history(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[FundingHistory]:
|
|
7697
8010
|
"""
|
|
7698
8011
|
fetch the history of funding payments paid and received on self account
|
|
7699
|
-
|
|
8012
|
+
|
|
8013
|
+
https://bybit-exchange.github.io/docs/api-explorer/v5/position/execution
|
|
8014
|
+
|
|
7700
8015
|
:param str [symbol]: unified market symbol
|
|
7701
8016
|
:param int [since]: the earliest time in ms to fetch funding history for
|
|
7702
8017
|
:param int [limit]: the maximum number of funding history structures to retrieve
|
|
@@ -7732,7 +8047,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7732
8047
|
fundings = self.add_pagination_cursor_to_result(response)
|
|
7733
8048
|
return self.parse_incomes(fundings, market, since, limit)
|
|
7734
8049
|
|
|
7735
|
-
def parse_income(self, income, market: Market = None):
|
|
8050
|
+
def parse_income(self, income, market: Market = None) -> object:
|
|
7736
8051
|
#
|
|
7737
8052
|
# {
|
|
7738
8053
|
# "symbol": "XMRUSDT",
|
|
@@ -7780,14 +8095,16 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7780
8095
|
'timestamp': timestamp,
|
|
7781
8096
|
'datetime': self.iso8601(timestamp),
|
|
7782
8097
|
'id': self.safe_string(income, 'execId'),
|
|
7783
|
-
'amount': self.safe_number(income, '
|
|
8098
|
+
'amount': self.safe_number(income, 'execFee'),
|
|
7784
8099
|
'rate': self.safe_number(income, 'feeRate'),
|
|
7785
8100
|
}
|
|
7786
8101
|
|
|
7787
8102
|
def fetch_option(self, symbol: str, params={}) -> Option:
|
|
7788
8103
|
"""
|
|
7789
8104
|
fetches option data that is commonly found in an option chain
|
|
7790
|
-
|
|
8105
|
+
|
|
8106
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
|
8107
|
+
|
|
7791
8108
|
:param str symbol: unified market symbol
|
|
7792
8109
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7793
8110
|
:returns dict: an `option chain structure <https://docs.ccxt.com/#/?id=option-chain-structure>`
|
|
@@ -7847,8 +8164,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7847
8164
|
def fetch_option_chain(self, code: str, params={}) -> OptionChain:
|
|
7848
8165
|
"""
|
|
7849
8166
|
fetches data for an underlying asset that is commonly found in an option chain
|
|
7850
|
-
|
|
7851
|
-
|
|
8167
|
+
|
|
8168
|
+
https://bybit-exchange.github.io/docs/v5/market/tickers
|
|
8169
|
+
|
|
8170
|
+
:param str code: base currency to fetch an option chain for
|
|
7852
8171
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
7853
8172
|
:returns dict: a list of `option chain structures <https://docs.ccxt.com/#/?id=option-chain-structure>`
|
|
7854
8173
|
"""
|
|
@@ -7958,8 +8277,10 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
7958
8277
|
def fetch_positions_history(self, symbols: Strings = None, since: Int = None, limit: Int = None, params={}) -> List[Position]:
|
|
7959
8278
|
"""
|
|
7960
8279
|
fetches historical positions
|
|
7961
|
-
|
|
7962
|
-
|
|
8280
|
+
|
|
8281
|
+
https://bybit-exchange.github.io/docs/v5/position/close-pnl
|
|
8282
|
+
|
|
8283
|
+
:param str[] symbols: a list of unified market symbols
|
|
7963
8284
|
:param int [since]: timestamp in ms of the earliest position to fetch, params["until"] - since <= 7 days
|
|
7964
8285
|
:param int [limit]: the maximum amount of records to fetch, default=50, max=100
|
|
7965
8286
|
:param dict params: extra parameters specific to the exchange api endpoint
|
|
@@ -8028,6 +8349,428 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
8028
8349
|
positions = self.parse_positions(rawPositions, symbols, params)
|
|
8029
8350
|
return self.filter_by_since_limit(positions, since, limit)
|
|
8030
8351
|
|
|
8352
|
+
def fetch_convert_currencies(self, params={}) -> Currencies:
|
|
8353
|
+
"""
|
|
8354
|
+
fetches all available currencies that can be converted
|
|
8355
|
+
|
|
8356
|
+
https://bybit-exchange.github.io/docs/v5/asset/convert/convert-coin-list
|
|
8357
|
+
|
|
8358
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
8359
|
+
:param str [params.accountType]: eb_convert_uta, eb_convert_spot, eb_convert_funding, eb_convert_inverse, or eb_convert_contract
|
|
8360
|
+
:returns dict: an associative dictionary of currencies
|
|
8361
|
+
"""
|
|
8362
|
+
self.load_markets()
|
|
8363
|
+
accountType = None
|
|
8364
|
+
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
8365
|
+
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
8366
|
+
accountTypeDefault = 'eb_convert_uta' if isUnifiedAccount else 'eb_convert_spot'
|
|
8367
|
+
accountType, params = self.handle_option_and_params(params, 'fetchConvertCurrencies', 'accountType', accountTypeDefault)
|
|
8368
|
+
request: dict = {
|
|
8369
|
+
'accountType': accountType,
|
|
8370
|
+
}
|
|
8371
|
+
response = self.privateGetV5AssetExchangeQueryCoinList(self.extend(request, params))
|
|
8372
|
+
#
|
|
8373
|
+
# {
|
|
8374
|
+
# "retCode": 0,
|
|
8375
|
+
# "retMsg": "ok",
|
|
8376
|
+
# "result": {
|
|
8377
|
+
# "coins": [
|
|
8378
|
+
# {
|
|
8379
|
+
# "coin": "MATIC",
|
|
8380
|
+
# "fullName": "MATIC",
|
|
8381
|
+
# "icon": "https://s1.bycsi.com/app/assets/token/0552ae79c535c3095fa18f7b377dd2e9.svg",
|
|
8382
|
+
# "iconNight": "https://t1.bycsi.com/app/assets/token/f59301aef2d6ac2165c4c4603e672fb4.svg",
|
|
8383
|
+
# "accuracyLength": 8,
|
|
8384
|
+
# "coinType": "crypto",
|
|
8385
|
+
# "balance": "0",
|
|
8386
|
+
# "uBalance": "0",
|
|
8387
|
+
# "timePeriod": 0,
|
|
8388
|
+
# "singleFromMinLimit": "1.1",
|
|
8389
|
+
# "singleFromMaxLimit": "20001",
|
|
8390
|
+
# "singleToMinLimit": "0",
|
|
8391
|
+
# "singleToMaxLimit": "0",
|
|
8392
|
+
# "dailyFromMinLimit": "0",
|
|
8393
|
+
# "dailyFromMaxLimit": "0",
|
|
8394
|
+
# "dailyToMinLimit": "0",
|
|
8395
|
+
# "dailyToMaxLimit": "0",
|
|
8396
|
+
# "disableFrom": False,
|
|
8397
|
+
# "disableTo": False
|
|
8398
|
+
# },
|
|
8399
|
+
# ]
|
|
8400
|
+
# },
|
|
8401
|
+
# "retExtInfo": {},
|
|
8402
|
+
# "time": 1727256416250
|
|
8403
|
+
# }
|
|
8404
|
+
#
|
|
8405
|
+
result: dict = {}
|
|
8406
|
+
data = self.safe_dict(response, 'result', {})
|
|
8407
|
+
coins = self.safe_list(data, 'coins', [])
|
|
8408
|
+
for i in range(0, len(coins)):
|
|
8409
|
+
entry = coins[i]
|
|
8410
|
+
id = self.safe_string(entry, 'coin')
|
|
8411
|
+
disableFrom = self.safe_bool(entry, 'disableFrom')
|
|
8412
|
+
disableTo = self.safe_bool(entry, 'disableTo')
|
|
8413
|
+
inactive = (disableFrom or disableTo)
|
|
8414
|
+
code = self.safe_currency_code(id)
|
|
8415
|
+
result[code] = {
|
|
8416
|
+
'info': entry,
|
|
8417
|
+
'id': id,
|
|
8418
|
+
'code': code,
|
|
8419
|
+
'networks': None,
|
|
8420
|
+
'type': self.safe_string(entry, 'coinType'),
|
|
8421
|
+
'name': self.safe_string(entry, 'fullName'),
|
|
8422
|
+
'active': not inactive,
|
|
8423
|
+
'deposit': None,
|
|
8424
|
+
'withdraw': self.safe_number(entry, 'balance'),
|
|
8425
|
+
'fee': None,
|
|
8426
|
+
'precision': None,
|
|
8427
|
+
'limits': {
|
|
8428
|
+
'amount': {
|
|
8429
|
+
'min': self.safe_number(entry, 'singleFromMinLimit'),
|
|
8430
|
+
'max': self.safe_number(entry, 'singleFromMaxLimit'),
|
|
8431
|
+
},
|
|
8432
|
+
'withdraw': {
|
|
8433
|
+
'min': None,
|
|
8434
|
+
'max': None,
|
|
8435
|
+
},
|
|
8436
|
+
'deposit': {
|
|
8437
|
+
'min': None,
|
|
8438
|
+
'max': None,
|
|
8439
|
+
},
|
|
8440
|
+
},
|
|
8441
|
+
'created': None,
|
|
8442
|
+
}
|
|
8443
|
+
return result
|
|
8444
|
+
|
|
8445
|
+
def fetch_convert_quote(self, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
|
8446
|
+
"""
|
|
8447
|
+
fetch a quote for converting from one currency to another
|
|
8448
|
+
|
|
8449
|
+
https://bybit-exchange.github.io/docs/v5/asset/convert/apply-quote
|
|
8450
|
+
|
|
8451
|
+
:param str fromCode: the currency that you want to sell and convert from
|
|
8452
|
+
:param str toCode: the currency that you want to buy and convert into
|
|
8453
|
+
:param float [amount]: how much you want to trade in units of the from currency
|
|
8454
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
8455
|
+
:param str [params.accountType]: eb_convert_uta, eb_convert_spot, eb_convert_funding, eb_convert_inverse, or eb_convert_contract
|
|
8456
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
|
8457
|
+
"""
|
|
8458
|
+
self.load_markets()
|
|
8459
|
+
accountType = None
|
|
8460
|
+
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
8461
|
+
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
8462
|
+
accountTypeDefault = 'eb_convert_uta' if isUnifiedAccount else 'eb_convert_spot'
|
|
8463
|
+
accountType, params = self.handle_option_and_params(params, 'fetchConvertQuote', 'accountType', accountTypeDefault)
|
|
8464
|
+
request: dict = {
|
|
8465
|
+
'fromCoin': fromCode,
|
|
8466
|
+
'toCoin': toCode,
|
|
8467
|
+
'requestAmount': self.number_to_string(amount),
|
|
8468
|
+
'requestCoin': fromCode,
|
|
8469
|
+
'accountType': accountType,
|
|
8470
|
+
}
|
|
8471
|
+
response = self.privatePostV5AssetExchangeQuoteApply(self.extend(request, params))
|
|
8472
|
+
#
|
|
8473
|
+
# {
|
|
8474
|
+
# "retCode": 0,
|
|
8475
|
+
# "retMsg": "ok",
|
|
8476
|
+
# "result": {
|
|
8477
|
+
# "quoteTxId": "1010020692439481682687668224",
|
|
8478
|
+
# "exchangeRate": "0.000015330836780000",
|
|
8479
|
+
# "fromCoin": "USDT",
|
|
8480
|
+
# "fromCoinType": "crypto",
|
|
8481
|
+
# "toCoin": "BTC",
|
|
8482
|
+
# "toCoinType": "crypto",
|
|
8483
|
+
# "fromAmount": "10",
|
|
8484
|
+
# "toAmount": "0.000153308367800000",
|
|
8485
|
+
# "expiredTime": "1727257413353",
|
|
8486
|
+
# "requestId": ""
|
|
8487
|
+
# },
|
|
8488
|
+
# "retExtInfo": {},
|
|
8489
|
+
# "time": 1727257398375
|
|
8490
|
+
# }
|
|
8491
|
+
#
|
|
8492
|
+
data = self.safe_dict(response, 'result', {})
|
|
8493
|
+
fromCurrencyId = self.safe_string(data, 'fromCoin', fromCode)
|
|
8494
|
+
fromCurrency = self.currency(fromCurrencyId)
|
|
8495
|
+
toCurrencyId = self.safe_string(data, 'toCoin', toCode)
|
|
8496
|
+
toCurrency = self.currency(toCurrencyId)
|
|
8497
|
+
return self.parse_conversion(data, fromCurrency, toCurrency)
|
|
8498
|
+
|
|
8499
|
+
def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
|
|
8500
|
+
"""
|
|
8501
|
+
convert from one currency to another
|
|
8502
|
+
|
|
8503
|
+
https://bybit-exchange.github.io/docs/v5/asset/convert/confirm-quote
|
|
8504
|
+
|
|
8505
|
+
:param str id: the id of the trade that you want to make
|
|
8506
|
+
:param str fromCode: the currency that you want to sell and convert from
|
|
8507
|
+
:param str toCode: the currency that you want to buy and convert into
|
|
8508
|
+
:param float amount: how much you want to trade in units of the from currency
|
|
8509
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
8510
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
|
8511
|
+
"""
|
|
8512
|
+
self.load_markets()
|
|
8513
|
+
request: dict = {
|
|
8514
|
+
'quoteTxId': id,
|
|
8515
|
+
}
|
|
8516
|
+
response = self.privatePostV5AssetExchangeConvertExecute(self.extend(request, params))
|
|
8517
|
+
#
|
|
8518
|
+
# {
|
|
8519
|
+
# "retCode": 0,
|
|
8520
|
+
# "retMsg": "ok",
|
|
8521
|
+
# "result": {
|
|
8522
|
+
# "exchangeStatus": "processing",
|
|
8523
|
+
# "quoteTxId": "1010020692439483803499737088"
|
|
8524
|
+
# },
|
|
8525
|
+
# "retExtInfo": {},
|
|
8526
|
+
# "time": 1727257904969
|
|
8527
|
+
# }
|
|
8528
|
+
#
|
|
8529
|
+
data = self.safe_dict(response, 'result', {})
|
|
8530
|
+
return self.parse_conversion(data)
|
|
8531
|
+
|
|
8532
|
+
def fetch_convert_trade(self, id: str, code: Str = None, params={}) -> Conversion:
|
|
8533
|
+
"""
|
|
8534
|
+
fetch the data for a conversion trade
|
|
8535
|
+
|
|
8536
|
+
https://bybit-exchange.github.io/docs/v5/asset/convert/get-convert-result
|
|
8537
|
+
|
|
8538
|
+
:param str id: the id of the trade that you want to fetch
|
|
8539
|
+
:param str [code]: the unified currency code of the conversion trade
|
|
8540
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
8541
|
+
:param str [params.accountType]: eb_convert_uta, eb_convert_spot, eb_convert_funding, eb_convert_inverse, or eb_convert_contract
|
|
8542
|
+
:returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
|
|
8543
|
+
"""
|
|
8544
|
+
self.load_markets()
|
|
8545
|
+
accountType = None
|
|
8546
|
+
enableUnifiedMargin, enableUnifiedAccount = self.is_unified_enabled()
|
|
8547
|
+
isUnifiedAccount = (enableUnifiedMargin or enableUnifiedAccount)
|
|
8548
|
+
accountTypeDefault = 'eb_convert_uta' if isUnifiedAccount else 'eb_convert_spot'
|
|
8549
|
+
accountType, params = self.handle_option_and_params(params, 'fetchConvertQuote', 'accountType', accountTypeDefault)
|
|
8550
|
+
request: dict = {
|
|
8551
|
+
'quoteTxId': id,
|
|
8552
|
+
'accountType': accountType,
|
|
8553
|
+
}
|
|
8554
|
+
response = self.privateGetV5AssetExchangeConvertResultQuery(self.extend(request, params))
|
|
8555
|
+
#
|
|
8556
|
+
# {
|
|
8557
|
+
# "retCode": 0,
|
|
8558
|
+
# "retMsg": "ok",
|
|
8559
|
+
# "result": {
|
|
8560
|
+
# "result": {
|
|
8561
|
+
# "accountType": "eb_convert_uta",
|
|
8562
|
+
# "exchangeTxId": "1010020692439483803499737088",
|
|
8563
|
+
# "userId": "100406395",
|
|
8564
|
+
# "fromCoin": "USDT",
|
|
8565
|
+
# "fromCoinType": "crypto",
|
|
8566
|
+
# "fromAmount": "10",
|
|
8567
|
+
# "toCoin": "BTC",
|
|
8568
|
+
# "toCoinType": "crypto",
|
|
8569
|
+
# "toAmount": "0.00015344889",
|
|
8570
|
+
# "exchangeStatus": "success",
|
|
8571
|
+
# "extInfo": {},
|
|
8572
|
+
# "convertRate": "0.000015344889",
|
|
8573
|
+
# "createdAt": "1727257904726"
|
|
8574
|
+
# }
|
|
8575
|
+
# },
|
|
8576
|
+
# "retExtInfo": {},
|
|
8577
|
+
# "time": 1727258257216
|
|
8578
|
+
# }
|
|
8579
|
+
#
|
|
8580
|
+
data = self.safe_dict(response, 'result', {})
|
|
8581
|
+
result = self.safe_dict(data, 'result', {})
|
|
8582
|
+
fromCurrencyId = self.safe_string(result, 'fromCoin')
|
|
8583
|
+
toCurrencyId = self.safe_string(result, 'toCoin')
|
|
8584
|
+
fromCurrency = None
|
|
8585
|
+
toCurrency = None
|
|
8586
|
+
if fromCurrencyId is not None:
|
|
8587
|
+
fromCurrency = self.currency(fromCurrencyId)
|
|
8588
|
+
if toCurrencyId is not None:
|
|
8589
|
+
toCurrency = self.currency(toCurrencyId)
|
|
8590
|
+
return self.parse_conversion(result, fromCurrency, toCurrency)
|
|
8591
|
+
|
|
8592
|
+
def fetch_convert_trade_history(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Conversion]:
|
|
8593
|
+
"""
|
|
8594
|
+
fetch the users history of conversion trades
|
|
8595
|
+
|
|
8596
|
+
https://bybit-exchange.github.io/docs/v5/asset/convert/get-convert-history
|
|
8597
|
+
|
|
8598
|
+
:param str [code]: the unified currency code
|
|
8599
|
+
:param int [since]: the earliest time in ms to fetch conversions for
|
|
8600
|
+
:param int [limit]: the maximum number of conversion structures to retrieve
|
|
8601
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
8602
|
+
:param str [params.accountType]: eb_convert_uta, eb_convert_spot, eb_convert_funding, eb_convert_inverse, or eb_convert_contract
|
|
8603
|
+
:returns dict[]: a list of `conversion structures <https://docs.ccxt.com/#/?id=conversion-structure>`
|
|
8604
|
+
"""
|
|
8605
|
+
self.load_markets()
|
|
8606
|
+
request: dict = {}
|
|
8607
|
+
if limit is not None:
|
|
8608
|
+
request['limit'] = limit
|
|
8609
|
+
response = self.privateGetV5AssetExchangeQueryConvertHistory(self.extend(request, params))
|
|
8610
|
+
#
|
|
8611
|
+
# {
|
|
8612
|
+
# "retCode": 0,
|
|
8613
|
+
# "retMsg": "ok",
|
|
8614
|
+
# "result": {
|
|
8615
|
+
# "list": [
|
|
8616
|
+
# {
|
|
8617
|
+
# "accountType": "eb_convert_uta",
|
|
8618
|
+
# "exchangeTxId": "1010020692439483803499737088",
|
|
8619
|
+
# "userId": "100406395",
|
|
8620
|
+
# "fromCoin": "USDT",
|
|
8621
|
+
# "fromCoinType": "crypto",
|
|
8622
|
+
# "fromAmount": "10",
|
|
8623
|
+
# "toCoin": "BTC",
|
|
8624
|
+
# "toCoinType": "crypto",
|
|
8625
|
+
# "toAmount": "0.00015344889",
|
|
8626
|
+
# "exchangeStatus": "success",
|
|
8627
|
+
# "extInfo": {},
|
|
8628
|
+
# "convertRate": "0.000015344889",
|
|
8629
|
+
# "createdAt": "1727257904726"
|
|
8630
|
+
# }
|
|
8631
|
+
# ]
|
|
8632
|
+
# },
|
|
8633
|
+
# "retExtInfo": {},
|
|
8634
|
+
# "time": 1727258761874
|
|
8635
|
+
# }
|
|
8636
|
+
#
|
|
8637
|
+
data = self.safe_dict(response, 'result', {})
|
|
8638
|
+
dataList = self.safe_list(data, 'list', [])
|
|
8639
|
+
return self.parse_conversions(dataList, code, 'fromCoin', 'toCoin', since, limit)
|
|
8640
|
+
|
|
8641
|
+
def parse_conversion(self, conversion: dict, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
|
|
8642
|
+
#
|
|
8643
|
+
# fetchConvertQuote
|
|
8644
|
+
#
|
|
8645
|
+
# {
|
|
8646
|
+
# "quoteTxId": "1010020692439481682687668224",
|
|
8647
|
+
# "exchangeRate": "0.000015330836780000",
|
|
8648
|
+
# "fromCoin": "USDT",
|
|
8649
|
+
# "fromCoinType": "crypto",
|
|
8650
|
+
# "toCoin": "BTC",
|
|
8651
|
+
# "toCoinType": "crypto",
|
|
8652
|
+
# "fromAmount": "10",
|
|
8653
|
+
# "toAmount": "0.000153308367800000",
|
|
8654
|
+
# "expiredTime": "1727257413353",
|
|
8655
|
+
# "requestId": ""
|
|
8656
|
+
# }
|
|
8657
|
+
#
|
|
8658
|
+
# createConvertTrade
|
|
8659
|
+
#
|
|
8660
|
+
# {
|
|
8661
|
+
# "exchangeStatus": "processing",
|
|
8662
|
+
# "quoteTxId": "1010020692439483803499737088"
|
|
8663
|
+
# }
|
|
8664
|
+
#
|
|
8665
|
+
# fetchConvertTrade, fetchConvertTradeHistory
|
|
8666
|
+
#
|
|
8667
|
+
# {
|
|
8668
|
+
# "accountType": "eb_convert_uta",
|
|
8669
|
+
# "exchangeTxId": "1010020692439483803499737088",
|
|
8670
|
+
# "userId": "100406395",
|
|
8671
|
+
# "fromCoin": "USDT",
|
|
8672
|
+
# "fromCoinType": "crypto",
|
|
8673
|
+
# "fromAmount": "10",
|
|
8674
|
+
# "toCoin": "BTC",
|
|
8675
|
+
# "toCoinType": "crypto",
|
|
8676
|
+
# "toAmount": "0.00015344889",
|
|
8677
|
+
# "exchangeStatus": "success",
|
|
8678
|
+
# "extInfo": {},
|
|
8679
|
+
# "convertRate": "0.000015344889",
|
|
8680
|
+
# "createdAt": "1727257904726"
|
|
8681
|
+
# }
|
|
8682
|
+
#
|
|
8683
|
+
timestamp = self.safe_integer_2(conversion, 'expiredTime', 'createdAt')
|
|
8684
|
+
fromCoin = self.safe_string(conversion, 'fromCoin')
|
|
8685
|
+
fromCode = self.safe_currency_code(fromCoin, fromCurrency)
|
|
8686
|
+
to = self.safe_string(conversion, 'toCoin')
|
|
8687
|
+
toCode = self.safe_currency_code(to, toCurrency)
|
|
8688
|
+
return {
|
|
8689
|
+
'info': conversion,
|
|
8690
|
+
'timestamp': timestamp,
|
|
8691
|
+
'datetime': self.iso8601(timestamp),
|
|
8692
|
+
'id': self.safe_string_2(conversion, 'quoteTxId', 'exchangeTxId'),
|
|
8693
|
+
'fromCurrency': fromCode,
|
|
8694
|
+
'fromAmount': self.safe_number(conversion, 'fromAmount'),
|
|
8695
|
+
'toCurrency': toCode,
|
|
8696
|
+
'toAmount': self.safe_number(conversion, 'toAmount'),
|
|
8697
|
+
'price': None,
|
|
8698
|
+
'fee': None,
|
|
8699
|
+
}
|
|
8700
|
+
|
|
8701
|
+
def fetch_long_short_ratio_history(self, symbol: Str = None, timeframe: Str = None, since: Int = None, limit: Int = None, params={}) -> List[LongShortRatio]:
|
|
8702
|
+
"""
|
|
8703
|
+
fetches the long short ratio history for a unified market symbol
|
|
8704
|
+
|
|
8705
|
+
https://bybit-exchange.github.io/docs/v5/market/long-short-ratio
|
|
8706
|
+
|
|
8707
|
+
:param str symbol: unified symbol of the market to fetch the long short ratio for
|
|
8708
|
+
:param str [timeframe]: the period for the ratio, default is 24 hours
|
|
8709
|
+
:param int [since]: the earliest time in ms to fetch ratios for
|
|
8710
|
+
:param int [limit]: the maximum number of long short ratio structures to retrieve
|
|
8711
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
|
8712
|
+
:returns dict[]: an array of `long short ratio structures <https://docs.ccxt.com/#/?id=long-short-ratio-structure>`
|
|
8713
|
+
"""
|
|
8714
|
+
self.load_markets()
|
|
8715
|
+
market = self.market(symbol)
|
|
8716
|
+
type = None
|
|
8717
|
+
type, params = self.get_bybit_type('fetchLongShortRatioHistory', market, params)
|
|
8718
|
+
if type == 'spot' or type == 'option':
|
|
8719
|
+
raise NotSupported(self.id + ' fetchLongShortRatioHistory() only support linear and inverse markets')
|
|
8720
|
+
if timeframe is None:
|
|
8721
|
+
timeframe = '1d'
|
|
8722
|
+
request: dict = {
|
|
8723
|
+
'symbol': market['id'],
|
|
8724
|
+
'period': timeframe,
|
|
8725
|
+
'category': type,
|
|
8726
|
+
}
|
|
8727
|
+
if limit is not None:
|
|
8728
|
+
request['limit'] = limit
|
|
8729
|
+
response = self.publicGetV5MarketAccountRatio(self.extend(request, params))
|
|
8730
|
+
#
|
|
8731
|
+
# {
|
|
8732
|
+
# "retCode": 0,
|
|
8733
|
+
# "retMsg": "OK",
|
|
8734
|
+
# "result": {
|
|
8735
|
+
# "list": [
|
|
8736
|
+
# {
|
|
8737
|
+
# "symbol": "BTCUSDT",
|
|
8738
|
+
# "buyRatio": "0.5707",
|
|
8739
|
+
# "sellRatio": "0.4293",
|
|
8740
|
+
# "timestamp": "1729123200000"
|
|
8741
|
+
# },
|
|
8742
|
+
# ]
|
|
8743
|
+
# },
|
|
8744
|
+
# "retExtInfo": {},
|
|
8745
|
+
# "time": 1729147842516
|
|
8746
|
+
# }
|
|
8747
|
+
#
|
|
8748
|
+
result = self.safe_dict(response, 'result', {})
|
|
8749
|
+
data = self.safe_list(result, 'list', [])
|
|
8750
|
+
return self.parse_long_short_ratio_history(data, market)
|
|
8751
|
+
|
|
8752
|
+
def parse_long_short_ratio(self, info: dict, market: Market = None) -> LongShortRatio:
|
|
8753
|
+
#
|
|
8754
|
+
# {
|
|
8755
|
+
# "symbol": "BTCUSDT",
|
|
8756
|
+
# "buyRatio": "0.5707",
|
|
8757
|
+
# "sellRatio": "0.4293",
|
|
8758
|
+
# "timestamp": "1729123200000"
|
|
8759
|
+
# }
|
|
8760
|
+
#
|
|
8761
|
+
marketId = self.safe_string(info, 'symbol')
|
|
8762
|
+
timestamp = self.safe_integer_omit_zero(info, 'timestamp')
|
|
8763
|
+
longString = self.safe_string(info, 'buyRatio')
|
|
8764
|
+
shortString = self.safe_string(info, 'sellRatio')
|
|
8765
|
+
return {
|
|
8766
|
+
'info': info,
|
|
8767
|
+
'symbol': self.safe_symbol(marketId, market, None, 'contract'),
|
|
8768
|
+
'timestamp': timestamp,
|
|
8769
|
+
'datetime': self.iso8601(timestamp),
|
|
8770
|
+
'timeframe': None,
|
|
8771
|
+
'longShortRatio': self.parse_to_numeric(Precise.string_div(longString, shortString)),
|
|
8772
|
+
}
|
|
8773
|
+
|
|
8031
8774
|
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
|
8032
8775
|
url = self.implode_hostname(self.urls['api'][api]) + '/' + path
|
|
8033
8776
|
if api == 'public':
|
|
@@ -8073,7 +8816,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
8073
8816
|
authFull = auth_base + body
|
|
8074
8817
|
else:
|
|
8075
8818
|
authFull = auth_base + queryEncoded
|
|
8076
|
-
url += '?' +
|
|
8819
|
+
url += '?' + queryEncoded
|
|
8077
8820
|
signature = None
|
|
8078
8821
|
if self.secret.find('PRIVATE KEY') > -1:
|
|
8079
8822
|
signature = self.rsa(authFull, self.secret, 'sha256')
|
|
@@ -8087,7 +8830,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
8087
8830
|
'timestamp': timestamp,
|
|
8088
8831
|
})
|
|
8089
8832
|
sortedQuery = self.keysort(query)
|
|
8090
|
-
auth = self.rawencode(sortedQuery)
|
|
8833
|
+
auth = self.rawencode(sortedQuery, True)
|
|
8091
8834
|
signature = None
|
|
8092
8835
|
if self.secret.find('PRIVATE KEY') > -1:
|
|
8093
8836
|
signature = self.rsa(auth, self.secret, 'sha256')
|
|
@@ -8109,7 +8852,7 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
8109
8852
|
'Content-Type': 'application/json',
|
|
8110
8853
|
}
|
|
8111
8854
|
else:
|
|
8112
|
-
url += '?' + self.rawencode(sortedQuery)
|
|
8855
|
+
url += '?' + self.rawencode(sortedQuery, True)
|
|
8113
8856
|
url += '&sign=' + signature
|
|
8114
8857
|
if method == 'POST':
|
|
8115
8858
|
brokerId = self.safe_string(self.options, 'brokerId')
|
|
@@ -8152,6 +8895,8 @@ class bybit(Exchange, ImplicitAPI):
|
|
|
8152
8895
|
feedback = self.id + ' private api uses /user/v3/private/query-api to check if you have a unified account. The API key of user id must own one of permissions: "Account Transfer", "Subaccount Transfer", "Withdrawal" ' + body
|
|
8153
8896
|
else:
|
|
8154
8897
|
feedback = self.id + ' ' + body
|
|
8898
|
+
if body.find('Withdraw address chain or destination tag are not equal') > -1:
|
|
8899
|
+
feedback = feedback + '; You might also need to ensure the address is whitelisted'
|
|
8155
8900
|
self.throw_broadly_matched_exception(self.exceptions['broad'], body, feedback)
|
|
8156
8901
|
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
|
|
8157
8902
|
raise ExchangeError(feedback) # unknown message
|