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