ccxt 4.3.18__py2.py3-none-any.whl → 4.3.19__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.
Files changed (193) hide show
  1. ccxt/__init__.py +3 -1
  2. ccxt/abstract/bybit.py +1 -0
  3. ccxt/abstract/okx.py +1 -0
  4. ccxt/abstract/woofipro.py +119 -0
  5. ccxt/ace.py +1 -1
  6. ccxt/ascendex.py +7 -8
  7. ccxt/async_support/__init__.py +3 -1
  8. ccxt/async_support/ace.py +1 -1
  9. ccxt/async_support/ascendex.py +7 -8
  10. ccxt/async_support/base/exchange.py +23 -2
  11. ccxt/async_support/bigone.py +4 -4
  12. ccxt/async_support/binance.py +9 -9
  13. ccxt/async_support/bingx.py +4 -4
  14. ccxt/async_support/bit2c.py +1 -1
  15. ccxt/async_support/bitbank.py +1 -1
  16. ccxt/async_support/bitbns.py +1 -1
  17. ccxt/async_support/bitfinex.py +28 -4
  18. ccxt/async_support/bitfinex2.py +62 -54
  19. ccxt/async_support/bitflyer.py +1 -1
  20. ccxt/async_support/bitget.py +8 -11
  21. ccxt/async_support/bithumb.py +1 -1
  22. ccxt/async_support/bitmart.py +8 -8
  23. ccxt/async_support/bitmex.py +2 -2
  24. ccxt/async_support/bitopro.py +1 -1
  25. ccxt/async_support/bitrue.py +3 -3
  26. ccxt/async_support/bitso.py +1 -1
  27. ccxt/async_support/bitstamp.py +3 -5
  28. ccxt/async_support/bitteam.py +1 -1
  29. ccxt/async_support/bitvavo.py +1 -1
  30. ccxt/async_support/bl3p.py +1 -1
  31. ccxt/async_support/blockchaincom.py +1 -1
  32. ccxt/async_support/blofin.py +3 -3
  33. ccxt/async_support/btcalpha.py +1 -1
  34. ccxt/async_support/btcbox.py +1 -1
  35. ccxt/async_support/btcmarkets.py +1 -1
  36. ccxt/async_support/btcturk.py +1 -1
  37. ccxt/async_support/bybit.py +9 -8
  38. ccxt/async_support/cex.py +1 -1
  39. ccxt/async_support/coinbase.py +2 -2
  40. ccxt/async_support/coinbasepro.py +1 -1
  41. ccxt/async_support/coincheck.py +1 -1
  42. ccxt/async_support/coinex.py +320 -520
  43. ccxt/async_support/coinlist.py +6 -7
  44. ccxt/async_support/coinmate.py +1 -1
  45. ccxt/async_support/coinmetro.py +1 -1
  46. ccxt/async_support/coinone.py +1 -1
  47. ccxt/async_support/coinsph.py +1 -1
  48. ccxt/async_support/coinspot.py +1 -1
  49. ccxt/async_support/cryptocom.py +1 -1
  50. ccxt/async_support/currencycom.py +2 -2
  51. ccxt/async_support/delta.py +4 -4
  52. ccxt/async_support/deribit.py +8 -8
  53. ccxt/async_support/digifinex.py +5 -5
  54. ccxt/async_support/exmo.py +1 -1
  55. ccxt/async_support/gate.py +5 -5
  56. ccxt/async_support/gemini.py +1 -1
  57. ccxt/async_support/hitbtc.py +3 -3
  58. ccxt/async_support/hollaex.py +4 -4
  59. ccxt/async_support/htx.py +2 -2
  60. ccxt/async_support/huobijp.py +1 -1
  61. ccxt/async_support/idex.py +1 -1
  62. ccxt/async_support/independentreserve.py +1 -1
  63. ccxt/async_support/indodax.py +2 -2
  64. ccxt/async_support/kraken.py +2 -2
  65. ccxt/async_support/krakenfutures.py +3 -3
  66. ccxt/async_support/kucoin.py +3 -3
  67. ccxt/async_support/kucoinfutures.py +3 -3
  68. ccxt/async_support/kuna.py +1 -1
  69. ccxt/async_support/latoken.py +6 -6
  70. ccxt/async_support/lbank.py +1 -1
  71. ccxt/async_support/luno.py +1 -1
  72. ccxt/async_support/lykke.py +1 -1
  73. ccxt/async_support/mercado.py +1 -1
  74. ccxt/async_support/mexc.py +7 -7
  75. ccxt/async_support/ndax.py +1 -1
  76. ccxt/async_support/novadax.py +3 -4
  77. ccxt/async_support/okcoin.py +3 -3
  78. ccxt/async_support/okx.py +27 -10
  79. ccxt/async_support/onetrading.py +1 -1
  80. ccxt/async_support/paymium.py +3 -3
  81. ccxt/async_support/phemex.py +5 -5
  82. ccxt/async_support/poloniex.py +3 -4
  83. ccxt/async_support/poloniexfutures.py +1 -1
  84. ccxt/async_support/probit.py +1 -1
  85. ccxt/async_support/timex.py +1 -1
  86. ccxt/async_support/tokocrypto.py +1 -1
  87. ccxt/async_support/upbit.py +1 -1
  88. ccxt/async_support/wavesexchange.py +3 -3
  89. ccxt/async_support/wazirx.py +1 -1
  90. ccxt/async_support/whitebit.py +2 -2
  91. ccxt/async_support/woo.py +25 -10
  92. ccxt/async_support/woofipro.py +2524 -0
  93. ccxt/async_support/yobit.py +1 -1
  94. ccxt/async_support/zaif.py +1 -1
  95. ccxt/async_support/zonda.py +3 -3
  96. ccxt/base/exchange.py +62 -16
  97. ccxt/base/types.py +20 -0
  98. ccxt/bigone.py +4 -4
  99. ccxt/binance.py +9 -9
  100. ccxt/bingx.py +4 -4
  101. ccxt/bit2c.py +1 -1
  102. ccxt/bitbank.py +1 -1
  103. ccxt/bitbns.py +1 -1
  104. ccxt/bitfinex.py +28 -4
  105. ccxt/bitfinex2.py +62 -54
  106. ccxt/bitflyer.py +1 -1
  107. ccxt/bitget.py +8 -11
  108. ccxt/bithumb.py +1 -1
  109. ccxt/bitmart.py +8 -8
  110. ccxt/bitmex.py +2 -2
  111. ccxt/bitopro.py +1 -1
  112. ccxt/bitrue.py +3 -3
  113. ccxt/bitso.py +1 -1
  114. ccxt/bitstamp.py +3 -5
  115. ccxt/bitteam.py +1 -1
  116. ccxt/bitvavo.py +1 -1
  117. ccxt/bl3p.py +1 -1
  118. ccxt/blockchaincom.py +1 -1
  119. ccxt/blofin.py +3 -3
  120. ccxt/btcalpha.py +1 -1
  121. ccxt/btcbox.py +1 -1
  122. ccxt/btcmarkets.py +1 -1
  123. ccxt/btcturk.py +1 -1
  124. ccxt/bybit.py +9 -8
  125. ccxt/cex.py +1 -1
  126. ccxt/coinbase.py +2 -2
  127. ccxt/coinbasepro.py +1 -1
  128. ccxt/coincheck.py +1 -1
  129. ccxt/coinex.py +320 -520
  130. ccxt/coinlist.py +6 -7
  131. ccxt/coinmate.py +1 -1
  132. ccxt/coinmetro.py +1 -1
  133. ccxt/coinone.py +1 -1
  134. ccxt/coinsph.py +1 -1
  135. ccxt/coinspot.py +1 -1
  136. ccxt/cryptocom.py +1 -1
  137. ccxt/currencycom.py +2 -2
  138. ccxt/delta.py +4 -4
  139. ccxt/deribit.py +8 -8
  140. ccxt/digifinex.py +5 -5
  141. ccxt/exmo.py +1 -1
  142. ccxt/gate.py +5 -5
  143. ccxt/gemini.py +1 -1
  144. ccxt/hitbtc.py +3 -3
  145. ccxt/hollaex.py +4 -4
  146. ccxt/htx.py +2 -2
  147. ccxt/huobijp.py +1 -1
  148. ccxt/idex.py +1 -1
  149. ccxt/independentreserve.py +1 -1
  150. ccxt/indodax.py +2 -2
  151. ccxt/kraken.py +2 -2
  152. ccxt/krakenfutures.py +3 -3
  153. ccxt/kucoin.py +3 -3
  154. ccxt/kucoinfutures.py +3 -3
  155. ccxt/kuna.py +1 -1
  156. ccxt/latoken.py +6 -6
  157. ccxt/lbank.py +1 -1
  158. ccxt/luno.py +1 -1
  159. ccxt/lykke.py +1 -1
  160. ccxt/mercado.py +1 -1
  161. ccxt/mexc.py +7 -7
  162. ccxt/ndax.py +1 -1
  163. ccxt/novadax.py +3 -4
  164. ccxt/okcoin.py +3 -3
  165. ccxt/okx.py +27 -10
  166. ccxt/onetrading.py +1 -1
  167. ccxt/paymium.py +3 -3
  168. ccxt/phemex.py +5 -5
  169. ccxt/poloniex.py +3 -4
  170. ccxt/poloniexfutures.py +1 -1
  171. ccxt/pro/__init__.py +3 -1
  172. ccxt/pro/bitget.py +127 -190
  173. ccxt/pro/coinbaseinternational.py +11 -4
  174. ccxt/pro/okx.py +79 -1
  175. ccxt/pro/woofipro.py +1183 -0
  176. ccxt/probit.py +1 -1
  177. ccxt/test/test_async.py +31 -1
  178. ccxt/test/test_sync.py +31 -1
  179. ccxt/timex.py +1 -1
  180. ccxt/tokocrypto.py +1 -1
  181. ccxt/upbit.py +1 -1
  182. ccxt/wavesexchange.py +3 -3
  183. ccxt/wazirx.py +1 -1
  184. ccxt/whitebit.py +2 -2
  185. ccxt/woo.py +25 -10
  186. ccxt/woofipro.py +2524 -0
  187. ccxt/yobit.py +1 -1
  188. ccxt/zaif.py +1 -1
  189. ccxt/zonda.py +3 -3
  190. {ccxt-4.3.18.dist-info → ccxt-4.3.19.dist-info}/METADATA +8 -6
  191. {ccxt-4.3.18.dist-info → ccxt-4.3.19.dist-info}/RECORD +193 -189
  192. {ccxt-4.3.18.dist-info → ccxt-4.3.19.dist-info}/WHEEL +0 -0
  193. {ccxt-4.3.18.dist-info → ccxt-4.3.19.dist-info}/top_level.txt +0 -0
ccxt/pro/bitget.py CHANGED
@@ -13,7 +13,6 @@ from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
14
14
  from ccxt.base.errors import ArgumentsRequired
15
15
  from ccxt.base.errors import BadRequest
16
- from ccxt.base.errors import NotSupported
17
16
  from ccxt.base.errors import RateLimitExceeded
18
17
  from ccxt.base.errors import InvalidNonce
19
18
  from ccxt.base.precise import Precise
@@ -924,9 +923,9 @@ class bitget(ccxt.async_support.bitget):
924
923
  await self.load_markets()
925
924
  market = None
926
925
  marketId = None
927
- isStop = self.safe_bool(params, 'stop', False)
928
- params = self.omit(params, 'stop')
929
- messageHash = 'triggerOrder' if (isStop) else 'order'
926
+ isTrigger = None
927
+ isTrigger, params = self.is_trigger_order(params)
928
+ messageHash = 'triggerOrder' if (isTrigger) else 'order'
930
929
  subscriptionHash = 'order:trades'
931
930
  if symbol is not None:
932
931
  market = self.market(symbol)
@@ -937,16 +936,14 @@ class bitget(ccxt.async_support.bitget):
937
936
  type, params = self.handle_market_type_and_params('watchOrders', market, params)
938
937
  if (type == 'spot') and (symbol is None):
939
938
  raise ArgumentsRequired(self.id + ' watchOrders requires a symbol argument for ' + type + ' markets.')
940
- if isStop and type == 'spot':
941
- raise NotSupported(self.id + ' watchOrders does not support stop orders for ' + type + ' markets.')
942
939
  instType = None
943
940
  instType, params = self.get_inst_type(market, params)
944
941
  if type == 'spot':
945
942
  subscriptionHash = subscriptionHash + ':' + symbol
946
- if isStop:
943
+ if isTrigger:
947
944
  subscriptionHash = subscriptionHash + ':stop' # we don't want to re-use the same subscription hash for stop orders
948
945
  instId = marketId if (type == 'spot') else 'default' # different from other streams here the 'rest' id is required for spot markets, contract markets require default here
949
- channel = 'orders-algo' if isStop else 'orders'
946
+ channel = 'orders-algo' if isTrigger else 'orders'
950
947
  marginMode = None
951
948
  marginMode, params = self.handle_margin_mode_and_params('watchOrders', params)
952
949
  if marginMode is not None:
@@ -973,25 +970,7 @@ class bitget(ccxt.async_support.bitget):
973
970
  # "action": "snapshot",
974
971
  # "arg": {"instType": "SPOT", "channel": "orders", "instId": "BTCUSDT"},
975
972
  # "data": [
976
- # {
977
- # "instId": "BTCUSDT",
978
- # "orderId": "1116512721422422017",
979
- # "clientOid": "798d1425-d31d-4ada-a51b-ec701e00a1d9",
980
- # "price": "35000.00",
981
- # "size": "7.0000",
982
- # "newSize": "500.0000",
983
- # "notional": "7.000000",
984
- # "orderType": "limit",
985
- # "force": "gtc",
986
- # "side": "buy",
987
- # "accBaseVolume": "0.0000",
988
- # "priceAvg": "0.00",
989
- # "status": "live",
990
- # "cTime": "1701923297267",
991
- # "uTime": "1701923297267",
992
- # "feeDetail": [],
993
- # "enterPointSource": "WEB"
994
- # }
973
+ # # see all examples in parseWsOrder
995
974
  # ],
996
975
  # "ts": 1701923297285
997
976
  # }
@@ -1002,98 +981,18 @@ class bitget(ccxt.async_support.bitget):
1002
981
  # "action": "snapshot",
1003
982
  # "arg": {"instType": "USDT-FUTURES", "channel": "orders", "instId": "default"},
1004
983
  # "data": [
1005
- # {
1006
- # "accBaseVolume": "0",
1007
- # "cTime": "1701920553759",
1008
- # "clientOid": "1116501214318198793",
1009
- # "enterPointSource": "WEB",
1010
- # "feeDetail": [{
1011
- # "feeCoin": "USDT",
1012
- # "fee": "-0.162003"
1013
- # }],
1014
- # "force": "gtc",
1015
- # "instId": "BTCUSDT",
1016
- # "leverage": "20",
1017
- # "marginCoin": "USDT",
1018
- # "marginMode": "isolated",
1019
- # "notionalUsd": "105",
1020
- # "orderId": "1116501214293032964",
1021
- # "orderType": "limit",
1022
- # "posMode": "hedge_mode",
1023
- # "posSide": "long",
1024
- # "price": "35000",
1025
- # "reduceOnly": "no",
1026
- # "side": "buy",
1027
- # "size": "0.003",
1028
- # "status": "canceled",
1029
- # "tradeSide": "open",
1030
- # "uTime": "1701920595866"
1031
- # }
984
+ # # see all examples in parseWsOrder
1032
985
  # ],
1033
986
  # "ts": 1701920595879
1034
987
  # }
1035
988
  #
1036
- # trigger
1037
- #
1038
- # {
1039
- # "action": "snapshot",
1040
- # "arg": {
1041
- # "instType": "USDT-FUTURES",
1042
- # "channel": "orders-algo",
1043
- # "instId": "default"
1044
- # },
1045
- # "data": [
1046
- # {
1047
- # "instId": "BTCUSDT",
1048
- # "orderId": "1116508960750899201",
1049
- # "clientOid": "1116508960750899200",
1050
- # "triggerPrice": "35000.000000000",
1051
- # "triggerType": "mark_price",
1052
- # "triggerTime": "1701922464373",
1053
- # "planType": "pl",
1054
- # "price": "35000.000000000",
1055
- # "size": "0.001000000",
1056
- # "actualSize": "0.000000000",
1057
- # "orderType": "limit",
1058
- # "side": "buy",
1059
- # "tradeSide": "open",
1060
- # "posSide": "long",
1061
- # "marginCoin": "USDT",
1062
- # "status": "cancelled",
1063
- # "posMode": "hedge_mode",
1064
- # "enterPointSource": "api",
1065
- # "stopSurplusTriggerType": "fill_price",
1066
- # "stopLossTriggerType": "fill_price",
1067
- # "cTime": "1701922400653",
1068
- # "uTime": "1701922464373"
1069
- # }
1070
- # ],
1071
- # "ts": 1701922464417
1072
- # }
1073
- #
1074
989
  # isolated and cross margin
1075
990
  #
1076
991
  # {
1077
992
  # "action": "snapshot",
1078
993
  # "arg": {"instType": "MARGIN", "channel": "orders-crossed", "instId": "BTCUSDT"},
1079
994
  # "data": [
1080
- # {
1081
- # "enterPointSource": "web",
1082
- # "force": "gtc",
1083
- # "orderType": "limit",
1084
- # "price": "35000.000000000",
1085
- # "quoteSize": "10.500000000",
1086
- # "side": "buy",
1087
- # "status": "live",
1088
- # "baseSize": "0.000300000",
1089
- # "cTime": "1701923982427",
1090
- # "clientOid": "4902047879864dc980c4840e9906db4e",
1091
- # "fillPrice": "0.000000000",
1092
- # "baseVolume": "0.000000000",
1093
- # "fillTotalAmount": "0.000000000",
1094
- # "loanType": "auto-loan-and-repay",
1095
- # "orderId": "1116515595178356737"
1096
- # }
995
+ # # see examples in parseWsOrder
1097
996
  # ],
1098
997
  # "ts": 1701923982497
1099
998
  # }
@@ -1113,8 +1012,9 @@ class bitget(ccxt.async_support.bitget):
1113
1012
  limit = self.safe_integer(self.options, 'ordersLimit', 1000)
1114
1013
  self.orders = ArrayCacheBySymbolById(limit)
1115
1014
  self.triggerOrders = ArrayCacheBySymbolById(limit)
1116
- stored = self.triggerOrders if (channel == 'ordersAlgo') else self.orders
1117
- messageHash = 'triggerOrder' if (channel == 'ordersAlgo') else 'order'
1015
+ isTrigger = (channel == 'orders-algo') or (channel == 'ordersAlgo')
1016
+ stored = self.triggerOrders if isTrigger else self.orders
1017
+ messageHash = 'triggerOrder' if isTrigger else 'order'
1118
1018
  marketSymbols = {}
1119
1019
  for i in range(0, len(data)):
1120
1020
  order = data[i]
@@ -1135,81 +1035,90 @@ class bitget(ccxt.async_support.bitget):
1135
1035
  #
1136
1036
  # spot
1137
1037
  #
1138
- # {
1139
- # "instId": "BTCUSDT",
1140
- # "orderId": "1116512721422422017",
1141
- # "clientOid": "798d1425-d31d-4ada-a51b-ec701e00a1d9",
1142
- # "price": "35000.00",
1143
- # "size": "7.0000",
1144
- # "newSize": "500.0000",
1145
- # "notional": "7.000000",
1146
- # "orderType": "limit",
1147
- # "force": "gtc",
1148
- # "side": "buy",
1149
- # "accBaseVolume": "0.0000",
1150
- # "priceAvg": "0.00",
1151
- # "status": "live",
1152
- # "cTime": "1701923297267",
1153
- # "uTime": "1701923297267",
1154
- # "feeDetail": [],
1155
- # "enterPointSource": "WEB"
1156
- # }
1038
+ # {
1039
+ # instId: 'EOSUSDT',
1040
+ # orderId: '1171779081105780739',
1041
+ # price: '0.81075', # limit price, field not present for market orders
1042
+ # clientOid: 'a2330139-1d04-4d78-98be-07de3cfd1055',
1043
+ # notional: '5.675250', # self is not cost! but notional
1044
+ # newSize: '7.0000', # self is not cost! quanity(for limit order or market sell) or cost(for market buy order)
1045
+ # size: '5.6752', # self is not cost, neither quanity, but notional! self field for "spot" can be ignored at all
1046
+ # # Note: for limit order(even filled) we don't have cost value in response, only in market order
1047
+ # orderType: 'limit', # limit, market
1048
+ # force: 'gtc',
1049
+ # side: 'buy',
1050
+ # accBaseVolume: '0.0000', # in case of 'filled', self would be set(for limit orders, self is the only indicator of the amount filled)
1051
+ # priceAvg: '0.00000', # in case of 'filled', self would be set
1052
+ # status: 'live', # live, filled, partially_filled
1053
+ # cTime: '1715099824215',
1054
+ # uTime: '1715099824215',
1055
+ # feeDetail: [],
1056
+ # enterPointSource: 'API'
1057
+ # #### trigger order has these additional fields: ####
1058
+ # "triggerPrice": "35100",
1059
+ # "price": "35100", # self is same price
1060
+ # "executePrice": "35123", # self is limit price
1061
+ # "triggerType": "fill_price",
1062
+ # "planType": "amount",
1063
+ # #### in case order had fill: ####
1064
+ # fillPrice: '35123',
1065
+ # tradeId: '1171775539946528779',
1066
+ # baseVolume: '7', # field present in market order
1067
+ # fillTime: '1715098979937',
1068
+ # fillFee: '-0.0069987',
1069
+ # fillFeeCoin: 'BTC',
1070
+ # tradeScope: 'T',
1071
+ # }
1157
1072
  #
1158
1073
  # contract
1159
1074
  #
1160
1075
  # {
1161
- # "accBaseVolume": "0",
1162
- # "cTime": "1701920553759",
1163
- # "clientOid": "1116501214318198793",
1164
- # "enterPointSource": "WEB",
1165
- # "feeDetail": [{
1076
+ # accBaseVolume: '0', # total amount filled during lifetime for order
1077
+ # cTime: '1715065875539',
1078
+ # clientOid: '1171636690041344003',
1079
+ # enterPointSource: 'API',
1080
+ # feeDetail: [{
1166
1081
  # "feeCoin": "USDT",
1167
1082
  # "fee": "-0.162003"
1168
1083
  # }],
1169
- # "force": "gtc",
1170
- # "instId": "BTCUSDT",
1171
- # "leverage": "20",
1172
- # "marginCoin": "USDT",
1173
- # "marginMode": "isolated",
1174
- # "notionalUsd": "105",
1175
- # "orderId": "1116501214293032964",
1176
- # "orderType": "limit",
1177
- # "posMode": "hedge_mode",
1178
- # "posSide": "long",
1179
- # "price": "35000",
1180
- # "reduceOnly": "no",
1181
- # "side": "buy",
1182
- # "size": "0.003",
1183
- # "status": "canceled",
1184
- # "tradeSide": "open",
1185
- # "uTime": "1701920595866"
1186
- # }
1187
- #
1188
- # trigger
1189
- #
1190
- # {
1191
- # "instId": "BTCUSDT",
1192
- # "orderId": "1116508960750899201",
1193
- # "clientOid": "1116508960750899200",
1194
- # "triggerPrice": "35000.000000000",
1084
+ # force: 'gtc',
1085
+ # instId: 'SEOSSUSDT',
1086
+ # leverage: '10',
1087
+ # marginCoin: 'USDT',
1088
+ # marginMode: 'crossed',
1089
+ # notionalUsd: '10.4468',
1090
+ # orderId: '1171636690028761089',
1091
+ # orderType: 'market',
1092
+ # posMode: 'hedge_mode', # one_way_mode, hedge_mode
1093
+ # posSide: 'short', # short, long, net
1094
+ # price: '0', # zero for market order
1095
+ # reduceOnly: 'no',
1096
+ # side: 'sell',
1097
+ # size: '13', # self is contracts amount
1098
+ # status: 'live', # live, filled, cancelled
1099
+ # tradeSide: 'open',
1100
+ # uTime: '1715065875539'
1101
+ # #### when filled order is incoming, these additional fields are present too: ###
1102
+ # baseVolume: '9', # amount filled for the incoming update/trade
1103
+ # accBaseVolume: '13', # i.e. 9 has been filled from 13 amount(self value is same as 'size')
1104
+ # fillFee: '-0.0062712',
1105
+ # fillFeeCoin: 'SUSDT',
1106
+ # fillNotionalUsd: '10.452',
1107
+ # fillPrice: '0.804',
1108
+ # fillTime: '1715065875605',
1109
+ # pnl: '0',
1110
+ # priceAvg: '0.804',
1111
+ # tradeId: '1171636690314407937',
1112
+ # tradeScope: 'T',
1113
+ # #### trigger order has these additional fields:
1114
+ # "triggerPrice": "0.800000000",
1115
+ # "price": "0.800000000", # <-- self is same price, actual limit-price is not present in initial response
1195
1116
  # "triggerType": "mark_price",
1196
- # "triggerTime": "1701922464373",
1117
+ # "triggerTime": "1715082796679",
1197
1118
  # "planType": "pl",
1198
- # "price": "35000.000000000",
1199
- # "size": "0.001000000",
1200
1119
  # "actualSize": "0.000000000",
1201
- # "orderType": "limit",
1202
- # "side": "buy",
1203
- # "tradeSide": "open",
1204
- # "posSide": "long",
1205
- # "marginCoin": "USDT",
1206
- # "status": "cancelled",
1207
- # "posMode": "hedge_mode",
1208
- # "enterPointSource": "api",
1209
1120
  # "stopSurplusTriggerType": "fill_price",
1210
1121
  # "stopLossTriggerType": "fill_price",
1211
- # "cTime": "1701922400653",
1212
- # "uTime": "1701922464373"
1213
1122
  # }
1214
1123
  #
1215
1124
  # isolated and cross margin
@@ -1217,6 +1126,7 @@ class bitget(ccxt.async_support.bitget):
1217
1126
  # {
1218
1127
  # "enterPointSource": "web",
1219
1128
  # "force": "gtc",
1129
+ # "feeDetail": [],
1220
1130
  # "orderType": "limit",
1221
1131
  # "price": "35000.000000000",
1222
1132
  # "quoteSize": "10.500000000",
@@ -1232,6 +1142,8 @@ class bitget(ccxt.async_support.bitget):
1232
1142
  # "orderId": "1116515595178356737"
1233
1143
  # }
1234
1144
  #
1145
+ isSpot = not ('posMode' in order)
1146
+ isMargin = ('loanType' in order)
1235
1147
  marketId = self.safe_string(order, 'instId')
1236
1148
  market = self.safe_market(marketId, market)
1237
1149
  timestamp = self.safe_integer(order, 'cTime')
@@ -1248,22 +1160,45 @@ class bitget(ccxt.async_support.bitget):
1248
1160
  'currency': self.safe_currency_code(feeCurrency),
1249
1161
  }
1250
1162
  triggerPrice = self.safe_number(order, 'triggerPrice')
1251
- price = self.safe_string(order, 'price')
1163
+ isTriggerOrder = (triggerPrice is not None)
1164
+ price = None
1165
+ if not isTriggerOrder:
1166
+ price = self.safe_number(order, 'price')
1167
+ elif isSpot and isTriggerOrder:
1168
+ # for spot trigger order, limit price is self
1169
+ price = self.safe_number(order, 'executePrice')
1252
1170
  avgPrice = self.omit_zero(self.safe_string_2(order, 'priceAvg', 'fillPrice'))
1253
- cost = self.safe_string_n(order, ['notional', 'notionalUsd', 'quoteSize'])
1254
1171
  side = self.safe_string(order, 'side')
1255
1172
  type = self.safe_string(order, 'orderType')
1256
- if side == 'buy' and market['spot'] and (type == 'market'):
1257
- cost = self.safe_string(order, 'newSize', cost)
1258
- filled = self.safe_string_2(order, 'accBaseVolume', 'baseVolume')
1259
- # if market['spot'] and (rawStatus != 'live'):
1260
- # filled = Precise.string_div(cost, avgPrice)
1261
- # }
1262
- amount = self.safe_string(order, 'baseVolume')
1263
- if not market['spot'] or not (side == 'buy' and type == 'market'):
1264
- amount = self.safe_string(order, 'newSize', amount)
1265
- if market['swap'] and (amount is None):
1266
- amount = self.safe_string(order, 'size')
1173
+ accBaseVolume = self.omit_zero(self.safe_string(order, 'accBaseVolume'))
1174
+ newSizeValue = self.omit_zero(self.safe_string(order, 'newSize'))
1175
+ isMarketOrder = (type == 'market')
1176
+ isBuy = (side == 'buy')
1177
+ totalAmount = None
1178
+ filledAmount = None
1179
+ cost = None
1180
+ if isSpot:
1181
+ if isMargin:
1182
+ filledAmount = self.omit_zero(self.safe_string(order, 'fillTotalAmount'))
1183
+ totalAmount = self.omit_zero(self.safe_string(order, 'baseSize')) # for margin trading
1184
+ cost = self.safe_string(order, 'quoteSize')
1185
+ else:
1186
+ filledAmount = self.omit_zero(self.safe_string_2(order, 'accBaseVolume', 'baseVolume'))
1187
+ if isMarketOrder:
1188
+ if isBuy:
1189
+ totalAmount = accBaseVolume
1190
+ cost = newSizeValue
1191
+ else:
1192
+ totalAmount = newSizeValue
1193
+ # we don't have cost for market-sell order
1194
+ else:
1195
+ totalAmount = self.safe_string(order, 'newSize')
1196
+ # we don't have cost for limit order
1197
+ else:
1198
+ # baseVolume should not be used for "amount" for contracts !
1199
+ filledAmount = self.safe_string(order, 'baseVolume')
1200
+ totalAmount = self.safe_string(order, 'size')
1201
+ cost = self.safe_string(order, 'fillNotionalUsd')
1267
1202
  return self.safe_order({
1268
1203
  'info': order,
1269
1204
  'symbol': symbol,
@@ -1277,12 +1212,11 @@ class bitget(ccxt.async_support.bitget):
1277
1212
  'postOnly': None,
1278
1213
  'side': side,
1279
1214
  'price': price,
1280
- 'stopPrice': triggerPrice,
1281
1215
  'triggerPrice': triggerPrice,
1282
- 'amount': amount,
1216
+ 'amount': totalAmount,
1283
1217
  'cost': cost,
1284
1218
  'average': avgPrice,
1285
- 'filled': filled,
1219
+ 'filled': filledAmount,
1286
1220
  'remaining': None,
1287
1221
  'status': self.parse_ws_order_status(rawStatus),
1288
1222
  'fee': feeObject,
@@ -1680,6 +1614,9 @@ class bitget(ccxt.async_support.bitget):
1680
1614
  'fill': self.handle_my_trades,
1681
1615
  'orders': self.handle_order,
1682
1616
  'ordersAlgo': self.handle_order,
1617
+ 'orders-algo': self.handle_order,
1618
+ 'orders-crossed': self.handle_order,
1619
+ 'orders-isolated': self.handle_order,
1683
1620
  'account': self.handle_balance,
1684
1621
  'positions': self.handle_positions,
1685
1622
  'account-isolated': self.handle_balance,
@@ -6,7 +6,7 @@
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache
8
8
  import hashlib
9
- from ccxt.base.types import Int, Market, OrderBook, Strings, Ticker, Trade
9
+ from ccxt.base.types import Int, Market, OrderBook, Strings, Ticker, FundingRate, FundingRates, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
@@ -148,7 +148,7 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
148
148
  }
149
149
  return await self.watch_multiple(url, messageHashes, self.extend(subscribe, params), messageHashes)
150
150
 
151
- async def watch_funding_rate(self, symbol: str, params={}) -> {}:
151
+ async def watch_funding_rate(self, symbol: str, params={}) -> FundingRate:
152
152
  """
153
153
  watch the current funding rate
154
154
  :see: https://docs.cloud.coinbase.com/intx/docs/websocket-channels#funding-channel
@@ -158,7 +158,7 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
158
158
  """
159
159
  return await self.subscribe('RISK', [symbol], params)
160
160
 
161
- async def watch_funding_rates(self, symbols: List[str], params={}) -> {}:
161
+ async def watch_funding_rates(self, symbols: List[str], params={}) -> FundingRates:
162
162
  """
163
163
  watch the funding rate for multiple markets
164
164
  :see: https://docs.cloud.coinbase.com/intx/docs/websocket-channels#funding-channel
@@ -166,7 +166,13 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
166
166
  :param dict [params]: extra parameters specific to the exchange API endpoint
167
167
  :returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
168
168
  """
169
- return await self.subscribe_multiple('RISK', symbols, params)
169
+ fundingRate = await self.subscribe_multiple('RISK', symbols, params)
170
+ symbol = self.safe_string(fundingRate, 'symbol')
171
+ if self.newUpdates:
172
+ result = {}
173
+ result[symbol] = fundingRate
174
+ return result
175
+ return self.filter_by_array(self.fundingRates, 'symbol', symbols)
170
176
 
171
177
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
172
178
  """
@@ -566,6 +572,7 @@ class coinbaseinternational(ccxt.async_support.coinbaseinternational):
566
572
  #
567
573
  channel = self.safe_string(message, 'channel')
568
574
  fundingRate = self.parse_funding_rate(message)
575
+ self.fundingRates[fundingRate['symbol']] = fundingRate
569
576
  client.resolve(fundingRate, channel + '::' + fundingRate['symbol'])
570
577
 
571
578
  def handle_error_message(self, client: Client, message):
ccxt/pro/okx.py CHANGED
@@ -6,7 +6,7 @@
6
6
  import ccxt.async_support
7
7
  from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
9
+ from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade
10
10
  from ccxt.async_support.base.ws.client import Client
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
@@ -34,6 +34,8 @@ class okx(ccxt.async_support.okx):
34
34
  'watchOrders': True,
35
35
  'watchMyTrades': True,
36
36
  'watchPositions': True,
37
+ 'watchFundingRate': True,
38
+ 'watchFundingRates': True,
37
39
  'createOrderWs': True,
38
40
  'editOrderWs': True,
39
41
  'cancelOrderWs': True,
@@ -241,6 +243,81 @@ class okx(ccxt.async_support.okx):
241
243
  stored.append(trade)
242
244
  client.resolve(stored, messageHash)
243
245
 
246
+ async def watch_funding_rate(self, symbol: str, params={}) -> FundingRate:
247
+ """
248
+ watch the current funding rate
249
+ :see: https://www.okx.com/docs-v5/en/#public-data-websocket-funding-rate-channel
250
+ :param str symbol: unified market symbol
251
+ :param dict [params]: extra parameters specific to the exchange API endpoint
252
+ :returns dict: a `funding rate structure <https://docs.ccxt.com/#/?id=funding-rate-structure>`
253
+ """
254
+ symbol = self.symbol(symbol)
255
+ fr = await self.watch_funding_rates([symbol], params)
256
+ return fr[symbol]
257
+
258
+ async def watch_funding_rates(self, symbols: List[str], params={}) -> FundingRates:
259
+ """
260
+ watch the funding rate for multiple markets
261
+ :see: https://www.okx.com/docs-v5/en/#public-data-websocket-funding-rate-channel
262
+ :param str[] symbols: list of unified market symbols
263
+ :param dict [params]: extra parameters specific to the exchange API endpoint
264
+ :returns dict: a dictionary of `funding rates structures <https://docs.ccxt.com/#/?id=funding-rates-structure>`, indexe by market symbols
265
+ """
266
+ await self.load_markets()
267
+ symbols = self.market_symbols(symbols)
268
+ channel = 'funding-rate'
269
+ topics = []
270
+ messageHashes = []
271
+ for i in range(0, len(symbols)):
272
+ symbol = symbols[i]
273
+ messageHashes.append(channel + ':' + symbol)
274
+ marketId = self.market_id(symbol)
275
+ topic = {
276
+ 'channel': channel,
277
+ 'instId': marketId,
278
+ }
279
+ topics.append(topic)
280
+ request = {
281
+ 'op': 'subscribe',
282
+ 'args': topics,
283
+ }
284
+ url = self.get_url(channel, 'public')
285
+ fundingRate = await self.watch_multiple(url, messageHashes, request, messageHashes)
286
+ if self.newUpdates:
287
+ symbol = self.safe_string(fundingRate, 'symbol')
288
+ result = {}
289
+ result[symbol] = fundingRate
290
+ return result
291
+ return self.filter_by_array(self.fundingRates, 'symbol', symbols)
292
+
293
+ def handle_funding_rate(self, client: Client, message):
294
+ #
295
+ # "data":[
296
+ # {
297
+ # "fundingRate":"0.0001875391284828",
298
+ # "fundingTime":"1700726400000",
299
+ # "instId":"BTC-USD-SWAP",
300
+ # "instType":"SWAP",
301
+ # "method": "next_period",
302
+ # "maxFundingRate":"0.00375",
303
+ # "minFundingRate":"-0.00375",
304
+ # "nextFundingRate":"0.0002608059239328",
305
+ # "nextFundingTime":"1700755200000",
306
+ # "premium": "0.0001233824646391",
307
+ # "settFundingRate":"0.0001699799259033",
308
+ # "settState":"settled",
309
+ # "ts":"1700724675402"
310
+ # }
311
+ # ]
312
+ #
313
+ data = self.safe_list(message, 'data', [])
314
+ for i in range(0, len(data)):
315
+ rawfr = data[i]
316
+ fundingRate = self.parse_funding_rate(rawfr)
317
+ symbol = fundingRate['symbol']
318
+ self.fundingRates[symbol] = fundingRate
319
+ client.resolve(fundingRate, 'funding-rate' + ':' + fundingRate['symbol'])
320
+
244
321
  async def watch_ticker(self, symbol: str, params={}) -> Ticker:
245
322
  """
246
323
  :see: https://www.okx.com/docs-v5/en/#order-book-trading-market-data-ws-tickers-channel
@@ -1519,6 +1596,7 @@ class okx(ccxt.async_support.okx):
1519
1596
  'block-tickers': self.handle_ticker,
1520
1597
  'trades': self.handle_trades,
1521
1598
  'account': self.handle_balance,
1599
+ 'funding-rate': self.handle_funding_rate,
1522
1600
  # 'margin_account': self.handle_balance,
1523
1601
  'orders': self.handle_orders,
1524
1602
  'orders-algo': self.handle_orders,