ccxt 4.4.82__py2.py3-none-any.whl → 4.4.86__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 (121) hide show
  1. ccxt/__init__.py +3 -9
  2. ccxt/abstract/blofin.py +8 -0
  3. ccxt/abstract/btcbox.py +1 -0
  4. ccxt/abstract/myokx.py +2 -0
  5. ccxt/abstract/okx.py +2 -0
  6. ccxt/apex.py +2 -1
  7. ccxt/ascendex.py +187 -151
  8. ccxt/async_support/__init__.py +3 -9
  9. ccxt/async_support/apex.py +2 -1
  10. ccxt/async_support/ascendex.py +187 -151
  11. ccxt/async_support/base/exchange.py +51 -24
  12. ccxt/async_support/base/ws/cache.py +6 -1
  13. ccxt/async_support/bequant.py +1 -1
  14. ccxt/async_support/bitget.py +5 -6
  15. ccxt/async_support/bitmart.py +1 -1
  16. ccxt/async_support/bitrue.py +14 -32
  17. ccxt/async_support/bitso.py +33 -0
  18. ccxt/async_support/bitstamp.py +33 -0
  19. ccxt/async_support/{huobijp.py → bittrade.py} +11 -11
  20. ccxt/async_support/blofin.py +145 -14
  21. ccxt/async_support/btcbox.py +25 -5
  22. ccxt/async_support/bybit.py +16 -37
  23. ccxt/async_support/cex.py +2 -4
  24. ccxt/async_support/coinbase.py +58 -47
  25. ccxt/async_support/coinbaseexchange.py +141 -32
  26. ccxt/async_support/coincatch.py +14 -67
  27. ccxt/async_support/coinex.py +28 -29
  28. ccxt/async_support/coinlist.py +17 -16
  29. ccxt/async_support/coinmetro.py +20 -11
  30. ccxt/async_support/coinone.py +8 -10
  31. ccxt/async_support/coinsph.py +124 -2
  32. ccxt/async_support/cryptocom.py +109 -2
  33. ccxt/async_support/cryptomus.py +42 -80
  34. ccxt/async_support/delta.py +75 -36
  35. ccxt/async_support/deribit.py +4 -5
  36. ccxt/async_support/derive.py +46 -10
  37. ccxt/async_support/ellipx.py +175 -77
  38. ccxt/async_support/gate.py +1 -1
  39. ccxt/async_support/gemini.py +3 -4
  40. ccxt/async_support/hitbtc.py +56 -65
  41. ccxt/async_support/hollaex.py +106 -49
  42. ccxt/async_support/htx.py +20 -43
  43. ccxt/async_support/hyperliquid.py +6 -6
  44. ccxt/async_support/kraken.py +27 -23
  45. ccxt/async_support/kucoinfutures.py +5 -0
  46. ccxt/async_support/lbank.py +1 -1
  47. ccxt/async_support/mexc.py +2 -2
  48. ccxt/async_support/ndax.py +25 -24
  49. ccxt/async_support/okcoin.py +12 -29
  50. ccxt/async_support/okx.py +9 -0
  51. ccxt/async_support/onetrading.py +10 -7
  52. ccxt/async_support/oxfun.py +40 -110
  53. ccxt/async_support/paradex.py +123 -4
  54. ccxt/base/exchange.py +21 -2
  55. ccxt/base/types.py +3 -0
  56. ccxt/bequant.py +1 -1
  57. ccxt/bitget.py +5 -6
  58. ccxt/bitmart.py +1 -1
  59. ccxt/bitrue.py +14 -32
  60. ccxt/bitso.py +33 -0
  61. ccxt/bitstamp.py +33 -0
  62. ccxt/{huobijp.py → bittrade.py} +11 -11
  63. ccxt/blofin.py +145 -14
  64. ccxt/btcbox.py +24 -5
  65. ccxt/bybit.py +16 -37
  66. ccxt/cex.py +2 -4
  67. ccxt/coinbase.py +58 -47
  68. ccxt/coinbaseexchange.py +141 -32
  69. ccxt/coincatch.py +14 -67
  70. ccxt/coinex.py +28 -29
  71. ccxt/coinlist.py +17 -16
  72. ccxt/coinmetro.py +20 -11
  73. ccxt/coinone.py +8 -10
  74. ccxt/coinsph.py +124 -2
  75. ccxt/cryptocom.py +109 -2
  76. ccxt/cryptomus.py +42 -80
  77. ccxt/delta.py +75 -36
  78. ccxt/deribit.py +4 -5
  79. ccxt/derive.py +46 -10
  80. ccxt/ellipx.py +175 -77
  81. ccxt/gate.py +1 -1
  82. ccxt/gemini.py +3 -4
  83. ccxt/hitbtc.py +56 -65
  84. ccxt/hollaex.py +106 -49
  85. ccxt/htx.py +20 -43
  86. ccxt/hyperliquid.py +6 -6
  87. ccxt/kraken.py +27 -23
  88. ccxt/kucoinfutures.py +5 -0
  89. ccxt/lbank.py +1 -1
  90. ccxt/mexc.py +2 -2
  91. ccxt/ndax.py +25 -24
  92. ccxt/okcoin.py +12 -29
  93. ccxt/okx.py +9 -0
  94. ccxt/onetrading.py +10 -7
  95. ccxt/oxfun.py +40 -110
  96. ccxt/paradex.py +123 -4
  97. ccxt/pro/__init__.py +109 -5
  98. ccxt/pro/binance.py +32 -33
  99. ccxt/pro/bithumb.py +5 -3
  100. ccxt/pro/{huobijp.py → bittrade.py} +3 -3
  101. ccxt/pro/kraken.py +249 -79
  102. ccxt/pro/luno.py +6 -5
  103. ccxt/pro/mexc.py +254 -7
  104. ccxt/pro/poloniex.py +6 -2
  105. {ccxt-4.4.82.dist-info → ccxt-4.4.86.dist-info}/METADATA +8 -11
  106. {ccxt-4.4.82.dist-info → ccxt-4.4.86.dist-info}/RECORD +110 -121
  107. ccxt/abstract/bl3p.py +0 -19
  108. ccxt/abstract/idex.py +0 -26
  109. ccxt/abstract/kuna.py +0 -182
  110. ccxt/async_support/base/ws/fast_client.py +0 -97
  111. ccxt/async_support/bl3p.py +0 -543
  112. ccxt/async_support/idex.py +0 -1889
  113. ccxt/async_support/kuna.py +0 -1935
  114. ccxt/bl3p.py +0 -543
  115. ccxt/idex.py +0 -1889
  116. ccxt/kuna.py +0 -1935
  117. ccxt/pro/idex.py +0 -687
  118. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  119. {ccxt-4.4.82.dist-info → ccxt-4.4.86.dist-info}/LICENSE.txt +0 -0
  120. {ccxt-4.4.82.dist-info → ccxt-4.4.86.dist-info}/WHEEL +0 -0
  121. {ccxt-4.4.82.dist-info → ccxt-4.4.86.dist-info}/top_level.txt +0 -0
ccxt/bitrue.py CHANGED
@@ -782,66 +782,48 @@ class bitrue(Exchange, ImplicitAPI):
782
782
  id = self.safe_string(currency, 'coin')
783
783
  name = self.safe_string(currency, 'coinFulName')
784
784
  code = self.safe_currency_code(id)
785
- deposit = None
786
- withdraw = None
787
- minWithdrawString = None
788
- maxWithdrawString = None
789
- minWithdrawFeeString = None
790
785
  networkDetails = self.safe_list(currency, 'chainDetail', [])
791
786
  networks: dict = {}
792
787
  for j in range(0, len(networkDetails)):
793
788
  entry = networkDetails[j]
794
789
  networkId = self.safe_string(entry, 'chain')
795
790
  network = self.network_id_to_code(networkId, code)
796
- enableDeposit = self.safe_bool(entry, 'enableDeposit')
797
- deposit = enableDeposit if (enableDeposit) else deposit
798
- enableWithdraw = self.safe_bool(entry, 'enableWithdraw')
799
- withdraw = enableWithdraw if (enableWithdraw) else withdraw
800
- networkWithdrawFeeString = self.safe_string(entry, 'withdrawFee')
801
- if networkWithdrawFeeString is not None:
802
- minWithdrawFeeString = networkWithdrawFeeString if (minWithdrawFeeString is None) else Precise.string_min(networkWithdrawFeeString, minWithdrawFeeString)
803
- networkMinWithdrawString = self.safe_string(entry, 'minWithdraw')
804
- if networkMinWithdrawString is not None:
805
- minWithdrawString = networkMinWithdrawString if (minWithdrawString is None) else Precise.string_min(networkMinWithdrawString, minWithdrawString)
806
- networkMaxWithdrawString = self.safe_string(entry, 'maxWithdraw')
807
- if networkMaxWithdrawString is not None:
808
- maxWithdrawString = networkMaxWithdrawString if (maxWithdrawString is None) else Precise.string_max(networkMaxWithdrawString, maxWithdrawString)
809
791
  networks[network] = {
810
792
  'info': entry,
811
793
  'id': networkId,
812
794
  'network': network,
813
- 'deposit': enableDeposit,
814
- 'withdraw': enableWithdraw,
815
- 'active': enableDeposit and enableWithdraw,
816
- 'fee': self.parse_number(networkWithdrawFeeString),
795
+ 'deposit': self.safe_bool(entry, 'enableDeposit'),
796
+ 'withdraw': self.safe_bool(entry, 'enableWithdraw'),
797
+ 'active': None,
798
+ 'fee': self.safe_number(entry, 'withdrawFee'),
817
799
  'precision': None,
818
800
  'limits': {
819
801
  'withdraw': {
820
- 'min': self.parse_number(networkMinWithdrawString),
821
- 'max': self.parse_number(networkMaxWithdrawString),
802
+ 'min': self.safe_number(entry, 'minWithdraw'),
803
+ 'max': self.safe_number(entry, 'maxWithdraw'),
822
804
  },
823
805
  },
824
806
  }
825
- result[code] = {
807
+ result[code] = self.safe_currency_structure({
826
808
  'id': id,
827
809
  'name': name,
828
810
  'code': code,
829
811
  'precision': None,
830
812
  'info': currency,
831
- 'active': deposit and withdraw,
832
- 'deposit': deposit,
833
- 'withdraw': withdraw,
813
+ 'active': None,
814
+ 'deposit': None,
815
+ 'withdraw': None,
834
816
  'networks': networks,
835
- 'fee': self.parse_number(minWithdrawFeeString),
817
+ 'fee': None,
836
818
  'fees': None,
837
819
  'type': 'crypto',
838
820
  'limits': {
839
821
  'withdraw': {
840
- 'min': self.parse_number(minWithdrawString),
841
- 'max': self.parse_number(maxWithdrawString),
822
+ 'min': None,
823
+ 'max': None,
842
824
  },
843
825
  },
844
- }
826
+ })
845
827
  return result
846
828
 
847
829
  def fetch_markets(self, params={}) -> List[Market]:
ccxt/bitso.py CHANGED
@@ -36,6 +36,9 @@ class bitso(Exchange, ImplicitAPI):
36
36
  'future': False,
37
37
  'option': False,
38
38
  'addMargin': False,
39
+ 'borrowCrossMargin': False,
40
+ 'borrowIsolatedMargin': False,
41
+ 'borrowMargin': False,
39
42
  'cancelAllOrders': True,
40
43
  'cancelOrder': True,
41
44
  'cancelOrders': True,
@@ -43,11 +46,17 @@ class bitso(Exchange, ImplicitAPI):
43
46
  'closePosition': False,
44
47
  'createDepositAddress': False,
45
48
  'createOrder': True,
49
+ 'createOrderWithTakeProfitAndStopLoss': False,
50
+ 'createOrderWithTakeProfitAndStopLossWs': False,
46
51
  'createReduceOnlyOrder': False,
47
52
  'fetchAccounts': False,
48
53
  'fetchBalance': True,
54
+ 'fetchBorrowInterest': False,
55
+ 'fetchBorrowRate': False,
49
56
  'fetchBorrowRateHistories': False,
50
57
  'fetchBorrowRateHistory': False,
58
+ 'fetchBorrowRates': False,
59
+ 'fetchBorrowRatesPerSymbol': False,
51
60
  'fetchCrossBorrowRate': False,
52
61
  'fetchCrossBorrowRates': False,
53
62
  'fetchDeposit': True,
@@ -59,21 +68,40 @@ class bitso(Exchange, ImplicitAPI):
59
68
  'fetchDepositWithdrawFee': 'emulated',
60
69
  'fetchDepositWithdrawFees': True,
61
70
  'fetchFundingHistory': False,
71
+ 'fetchFundingInterval': False,
72
+ 'fetchFundingIntervals': False,
62
73
  'fetchFundingRate': False,
63
74
  'fetchFundingRateHistory': False,
64
75
  'fetchFundingRates': False,
76
+ 'fetchGreeks': False,
65
77
  'fetchIndexOHLCV': False,
66
78
  'fetchIsolatedBorrowRate': False,
67
79
  'fetchIsolatedBorrowRates': False,
80
+ 'fetchIsolatedPositions': False,
68
81
  'fetchLedger': True,
69
82
  'fetchLeverage': False,
83
+ 'fetchLeverages': False,
84
+ 'fetchLeverageTiers': False,
85
+ 'fetchLiquidations': False,
86
+ 'fetchLongShortRatio': False,
87
+ 'fetchLongShortRatioHistory': False,
88
+ 'fetchMarginAdjustmentHistory': False,
70
89
  'fetchMarginMode': False,
90
+ 'fetchMarginModes': False,
91
+ 'fetchMarketLeverageTiers': False,
71
92
  'fetchMarkets': True,
72
93
  'fetchMarkOHLCV': False,
94
+ 'fetchMarkPrices': False,
95
+ 'fetchMyLiquidations': False,
96
+ 'fetchMySettlementHistory': False,
73
97
  'fetchMyTrades': True,
74
98
  'fetchOHLCV': True,
99
+ 'fetchOpenInterest': False,
75
100
  'fetchOpenInterestHistory': False,
101
+ 'fetchOpenInterests': False,
76
102
  'fetchOpenOrders': True,
103
+ 'fetchOption': False,
104
+ 'fetchOptionChain': False,
77
105
  'fetchOrder': True,
78
106
  'fetchOrderBook': True,
79
107
  'fetchOrderTrades': True,
@@ -85,6 +113,7 @@ class bitso(Exchange, ImplicitAPI):
85
113
  'fetchPositionsHistory': False,
86
114
  'fetchPositionsRisk': False,
87
115
  'fetchPremiumIndexOHLCV': False,
116
+ 'fetchSettlementHistory': False,
88
117
  'fetchTicker': True,
89
118
  'fetchTickers': False,
90
119
  'fetchTime': False,
@@ -96,8 +125,12 @@ class bitso(Exchange, ImplicitAPI):
96
125
  'fetchTransactions': False,
97
126
  'fetchTransfer': False,
98
127
  'fetchTransfers': False,
128
+ 'fetchVolatilityHistory': False,
99
129
  'reduceMargin': False,
130
+ 'repayCrossMargin': False,
131
+ 'repayIsolatedMargin': False,
100
132
  'setLeverage': False,
133
+ 'setMargin': False,
101
134
  'setMarginMode': False,
102
135
  'setPositionMode': False,
103
136
  'transfer': False,
ccxt/bitstamp.py CHANGED
@@ -44,18 +44,27 @@ class bitstamp(Exchange, ImplicitAPI):
44
44
  'future': False,
45
45
  'option': False,
46
46
  'addMargin': False,
47
+ 'borrowCrossMargin': False,
48
+ 'borrowIsolatedMargin': False,
49
+ 'borrowMargin': False,
47
50
  'cancelAllOrders': True,
48
51
  'cancelOrder': True,
49
52
  'closeAllPositions': False,
50
53
  'closePosition': False,
51
54
  'createOrder': True,
55
+ 'createOrderWithTakeProfitAndStopLoss': False,
56
+ 'createOrderWithTakeProfitAndStopLossWs': False,
52
57
  'createReduceOnlyOrder': False,
53
58
  'createStopLimitOrder': False,
54
59
  'createStopMarketOrder': False,
55
60
  'createStopOrder': False,
56
61
  'fetchBalance': True,
62
+ 'fetchBorrowInterest': False,
63
+ 'fetchBorrowRate': False,
57
64
  'fetchBorrowRateHistories': False,
58
65
  'fetchBorrowRateHistory': False,
66
+ 'fetchBorrowRates': False,
67
+ 'fetchBorrowRatesPerSymbol': False,
59
68
  'fetchCrossBorrowRate': False,
60
69
  'fetchCrossBorrowRates': False,
61
70
  'fetchCurrencies': True,
@@ -66,21 +75,40 @@ class bitstamp(Exchange, ImplicitAPI):
66
75
  'fetchDepositWithdrawFee': 'emulated',
67
76
  'fetchDepositWithdrawFees': True,
68
77
  'fetchFundingHistory': False,
78
+ 'fetchFundingInterval': False,
79
+ 'fetchFundingIntervals': False,
69
80
  'fetchFundingRate': False,
70
81
  'fetchFundingRateHistory': False,
71
82
  'fetchFundingRates': False,
83
+ 'fetchGreeks': False,
72
84
  'fetchIndexOHLCV': False,
73
85
  'fetchIsolatedBorrowRate': False,
74
86
  'fetchIsolatedBorrowRates': False,
87
+ 'fetchIsolatedPositions': False,
75
88
  'fetchLedger': True,
76
89
  'fetchLeverage': False,
90
+ 'fetchLeverages': False,
91
+ 'fetchLeverageTiers': False,
92
+ 'fetchLiquidations': False,
93
+ 'fetchLongShortRatio': False,
94
+ 'fetchLongShortRatioHistory': False,
95
+ 'fetchMarginAdjustmentHistory': False,
77
96
  'fetchMarginMode': False,
97
+ 'fetchMarginModes': False,
98
+ 'fetchMarketLeverageTiers': False,
78
99
  'fetchMarkets': True,
79
100
  'fetchMarkOHLCV': False,
101
+ 'fetchMarkPrices': False,
102
+ 'fetchMyLiquidations': False,
103
+ 'fetchMySettlementHistory': False,
80
104
  'fetchMyTrades': True,
81
105
  'fetchOHLCV': True,
106
+ 'fetchOpenInterest': False,
82
107
  'fetchOpenInterestHistory': False,
108
+ 'fetchOpenInterests': False,
83
109
  'fetchOpenOrders': True,
110
+ 'fetchOption': False,
111
+ 'fetchOptionChain': False,
84
112
  'fetchOrder': True,
85
113
  'fetchOrderBook': True,
86
114
  'fetchPosition': False,
@@ -91,6 +119,7 @@ class bitstamp(Exchange, ImplicitAPI):
91
119
  'fetchPositionsHistory': False,
92
120
  'fetchPositionsRisk': False,
93
121
  'fetchPremiumIndexOHLCV': False,
122
+ 'fetchSettlementHistory': False,
94
123
  'fetchTicker': True,
95
124
  'fetchTickers': True,
96
125
  'fetchTrades': True,
@@ -98,9 +127,13 @@ class bitstamp(Exchange, ImplicitAPI):
98
127
  'fetchTradingFees': True,
99
128
  'fetchTransactionFees': True,
100
129
  'fetchTransactions': 'emulated',
130
+ 'fetchVolatilityHistory': False,
101
131
  'fetchWithdrawals': True,
102
132
  'reduceMargin': False,
133
+ 'repayCrossMargin': False,
134
+ 'repayIsolatedMargin': False,
103
135
  'setLeverage': False,
136
+ 'setMargin': False,
104
137
  'setMarginMode': False,
105
138
  'setPositionMode': False,
106
139
  'transfer': True,
@@ -4,7 +4,7 @@
4
4
  # https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
- from ccxt.abstract.huobijp import ImplicitAPI
7
+ from ccxt.abstract.bittrade import ImplicitAPI
8
8
  import hashlib
9
9
  from ccxt.base.types import Account, Any, Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
10
10
  from typing import List
@@ -27,12 +27,12 @@ from ccxt.base.decimal_to_precision import TICK_SIZE
27
27
  from ccxt.base.precise import Precise
28
28
 
29
29
 
30
- class huobijp(Exchange, ImplicitAPI):
30
+ class bittrade(Exchange, ImplicitAPI):
31
31
 
32
32
  def describe(self) -> Any:
33
- return self.deep_extend(super(huobijp, self).describe(), {
34
- 'id': 'huobijp',
35
- 'name': 'Huobi Japan',
33
+ return self.deep_extend(super(bittrade, self).describe(), {
34
+ 'id': 'bittrade',
35
+ 'name': 'BitTrade',
36
36
  'countries': ['JP'],
37
37
  'rateLimit': 100,
38
38
  'userAgent': self.userAgents['chrome39'],
@@ -108,10 +108,10 @@ class huobijp(Exchange, ImplicitAPI):
108
108
  'v2Public': 'https://{hostname}',
109
109
  'v2Private': 'https://{hostname}',
110
110
  },
111
- 'www': 'https://www.huobi.co.jp',
112
- 'referral': 'https://www.huobi.co.jp/register/?invite_code=znnq3',
113
- 'doc': 'https://api-doc.huobi.co.jp',
114
- 'fees': 'https://www.huobi.co.jp/support/fee',
111
+ 'www': 'https://www.bittrade.co.jp',
112
+ 'referral': 'https://www.bittrade.co.jp/register/?invite_code=znnq3',
113
+ 'doc': 'https://api-doc.bittrade.co.jp',
114
+ 'fees': 'https://www.bittrade.co.jp/ja-jp/support/fee',
115
115
  },
116
116
  'api': {
117
117
  'v2Public': {
@@ -1483,7 +1483,7 @@ class huobijp(Exchange, ImplicitAPI):
1483
1483
  """
1484
1484
  cancels an open order
1485
1485
  :param str id: order id
1486
- :param str symbol: not used by huobijp cancelOrder()
1486
+ :param str symbol: not used by bittrade cancelOrder()
1487
1487
  :param dict [params]: extra parameters specific to the exchange API endpoint
1488
1488
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1489
1489
  """
@@ -1503,7 +1503,7 @@ class huobijp(Exchange, ImplicitAPI):
1503
1503
  """
1504
1504
  cancel multiple orders
1505
1505
  :param str[] ids: order ids
1506
- :param str symbol: not used by huobijp cancelOrders()
1506
+ :param str symbol: not used by bittrade cancelOrders()
1507
1507
  :param dict [params]: extra parameters specific to the exchange API endpoint
1508
1508
  :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1509
1509
  """
ccxt/blofin.py CHANGED
@@ -57,6 +57,7 @@ class blofin(Exchange, ImplicitAPI):
57
57
  'createStopMarketOrder': False,
58
58
  'createStopOrder': False,
59
59
  'createTakeProfitOrder': True,
60
+ 'createTriggerOrder': True,
60
61
  'editOrder': False,
61
62
  'fetchAccounts': False,
62
63
  'fetchBalance': True,
@@ -110,6 +111,7 @@ class blofin(Exchange, ImplicitAPI):
110
111
  'fetchOrders': False,
111
112
  'fetchOrderTrades': True,
112
113
  'fetchPosition': True,
114
+ 'fetchPositionMode': True,
113
115
  'fetchPositions': True,
114
116
  'fetchPositionsForSymbol': False,
115
117
  'fetchPositionsRisk': False,
@@ -137,8 +139,8 @@ class blofin(Exchange, ImplicitAPI):
137
139
  'repayCrossMargin': False,
138
140
  'setLeverage': True,
139
141
  'setMargin': False,
140
- 'setMarginMode': False,
141
- 'setPositionMode': False,
142
+ 'setMarginMode': True,
143
+ 'setPositionMode': True,
142
144
  'signIn': False,
143
145
  'transfer': True,
144
146
  'withdraw': False,
@@ -201,10 +203,14 @@ class blofin(Exchange, ImplicitAPI):
201
203
  'account/positions': 1,
202
204
  'account/leverage-info': 1,
203
205
  'account/margin-mode': 1,
206
+ 'account/position-mode': 1,
204
207
  'account/batch-leverage-info': 1,
205
208
  'trade/orders-tpsl-pending': 1,
209
+ 'trade/orders-algo-pending': 1,
206
210
  'trade/orders-history': 1,
207
211
  'trade/orders-tpsl-history': 1,
212
+ 'trade/orders-algo-history': 1, # todo new
213
+ 'trade/order/price-range': 1,
208
214
  'user/query-apikey': 1,
209
215
  'affiliate/basic': 1,
210
216
  'copytrading/instruments': 1,
@@ -221,8 +227,12 @@ class blofin(Exchange, ImplicitAPI):
221
227
  'copytrading/trade/pending-tpsl-by-order': 1,
222
228
  },
223
229
  'post': {
230
+ 'account/set-margin-mode': 1,
231
+ 'account/set-position-mode': 1,
224
232
  'trade/order': 1,
233
+ 'trade/order-algo': 1,
225
234
  'trade/cancel-order': 1,
235
+ 'trade/cancel-algo': 1,
226
236
  'account/set-leverage': 1,
227
237
  'trade/batch-orders': 1,
228
238
  'trade/order-tpsl': 1,
@@ -1135,7 +1145,11 @@ class blofin(Exchange, ImplicitAPI):
1135
1145
  marginMode = None
1136
1146
  marginMode, params = self.handle_margin_mode_and_params('createOrder', params, 'cross')
1137
1147
  request['marginMode'] = marginMode
1148
+ triggerPrice = self.safe_string(params, 'triggerPrice')
1138
1149
  timeInForce = self.safe_string(params, 'timeInForce', 'GTC')
1150
+ isHedged = self.safe_bool(params, 'hedged', False)
1151
+ if isHedged:
1152
+ request['positionSide'] = 'long' if (side == 'buy') else 'short'
1139
1153
  isMarketOrder = type == 'market'
1140
1154
  params = self.omit(params, ['timeInForce'])
1141
1155
  ioc = (timeInForce == 'IOC') or (type == 'ioc')
@@ -1143,14 +1157,15 @@ class blofin(Exchange, ImplicitAPI):
1143
1157
  if isMarketOrder or marketIOC:
1144
1158
  request['orderType'] = 'market'
1145
1159
  else:
1146
- request['price'] = self.price_to_precision(symbol, price)
1160
+ key = 'orderPrice' if (triggerPrice is not None) else 'price'
1161
+ request[key] = self.price_to_precision(symbol, price)
1147
1162
  postOnly = False
1148
1163
  postOnly, params = self.handle_post_only(isMarketOrder, type == 'post_only', params)
1149
1164
  if postOnly:
1150
1165
  request['type'] = 'post_only'
1151
1166
  stopLoss = self.safe_dict(params, 'stopLoss')
1152
1167
  takeProfit = self.safe_dict(params, 'takeProfit')
1153
- params = self.omit(params, ['stopLoss', 'takeProfit'])
1168
+ params = self.omit(params, ['stopLoss', 'takeProfit', 'hedged'])
1154
1169
  isStopLoss = stopLoss is not None
1155
1170
  isTakeProfit = takeProfit is not None
1156
1171
  if isStopLoss or isTakeProfit:
@@ -1164,6 +1179,11 @@ class blofin(Exchange, ImplicitAPI):
1164
1179
  request['tpTriggerPrice'] = self.price_to_precision(symbol, tpTriggerPrice)
1165
1180
  tpPrice = self.safe_string(takeProfit, 'price', '-1')
1166
1181
  request['tpOrderPrice'] = self.price_to_precision(symbol, tpPrice)
1182
+ elif triggerPrice is not None:
1183
+ request['orderType'] = 'trigger'
1184
+ request['triggerPrice'] = self.price_to_precision(symbol, triggerPrice)
1185
+ if isMarketOrder:
1186
+ request['orderPrice'] = '-1'
1167
1187
  return self.extend(request, params)
1168
1188
 
1169
1189
  def parse_order_status(self, status: Str):
@@ -1213,7 +1233,7 @@ class blofin(Exchange, ImplicitAPI):
1213
1233
  # "instType": "SWAP", # only in WS
1214
1234
  # }
1215
1235
  #
1216
- id = self.safe_string_2(order, 'tpslId', 'orderId')
1236
+ id = self.safe_string_n(order, ['tpslId', 'orderId', 'algoId'])
1217
1237
  timestamp = self.safe_integer(order, 'createTime')
1218
1238
  lastUpdateTimestamp = self.safe_integer(order, 'updateTime')
1219
1239
  lastTradeTimestamp = self.safe_integer(order, 'fillTime')
@@ -1307,12 +1327,14 @@ class blofin(Exchange, ImplicitAPI):
1307
1327
  :param float amount: how much of currency you want to trade in units of base currency
1308
1328
  :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1309
1329
  :param dict [params]: extra parameters specific to the exchange API endpoint
1330
+ :param str [params.triggerPrice]: the trigger price for a trigger order
1310
1331
  :param bool [params.reduceOnly]: a mark to reduce the position size for margin, swap and future orders
1311
1332
  :param bool [params.postOnly]: True to place a post only order
1312
1333
  :param str [params.marginMode]: 'cross' or 'isolated', default is 'cross'
1313
1334
  :param float [params.stopLossPrice]: stop loss trigger price(will use privatePostTradeOrderTpsl)
1314
1335
  :param float [params.takeProfitPrice]: take profit trigger price(will use privatePostTradeOrderTpsl)
1315
1336
  :param str [params.positionSide]: *stopLossPrice/takeProfitPrice orders only* 'long' or 'short' or 'net' default is 'net'
1337
+ :param boolean [params.hedged]: if True, the positionSide will be set to long/short instead of net, default is False
1316
1338
  :param str [params.clientOrderId]: a unique id for the order
1317
1339
  :param dict [params.takeProfit]: *takeProfit object in params* containing the triggerPrice at which the attached take profit order will be triggered
1318
1340
  :param float [params.takeProfit.triggerPrice]: take profit trigger price
@@ -1330,14 +1352,25 @@ class blofin(Exchange, ImplicitAPI):
1330
1352
  method, params = self.handle_option_and_params(params, 'createOrder', 'method', 'privatePostTradeOrder')
1331
1353
  isStopLossPriceDefined = self.safe_string(params, 'stopLossPrice') is not None
1332
1354
  isTakeProfitPriceDefined = self.safe_string(params, 'takeProfitPrice') is not None
1355
+ isTriggerOrder = self.safe_string(params, 'triggerPrice') is not None
1333
1356
  isType2Order = (isStopLossPriceDefined or isTakeProfitPriceDefined)
1334
1357
  response = None
1358
+ reduceOnly = self.safe_bool(params, 'reduceOnly')
1359
+ if reduceOnly is not None:
1360
+ params['reduceOnly'] = 'true' if reduceOnly else 'false'
1335
1361
  if tpsl or (method == 'privatePostTradeOrderTpsl') or isType2Order:
1336
1362
  tpslRequest = self.create_tpsl_order_request(symbol, type, side, amount, price, params)
1337
1363
  response = self.privatePostTradeOrderTpsl(tpslRequest)
1364
+ elif isTriggerOrder or (method == 'privatePostTradeOrderAlgo'):
1365
+ triggerRequest = self.create_order_request(symbol, type, side, amount, price, params)
1366
+ response = self.privatePostTradeOrderAlgo(triggerRequest)
1338
1367
  else:
1339
1368
  request = self.create_order_request(symbol, type, side, amount, price, params)
1340
1369
  response = self.privatePostTradeOrder(request)
1370
+ if isTriggerOrder or (method == 'privatePostTradeOrderAlgo'):
1371
+ dataDict = self.safe_dict(response, 'data', {})
1372
+ triggerOrder = self.parse_order(dataDict, market)
1373
+ return triggerOrder
1341
1374
  data = self.safe_list(response, 'data', [])
1342
1375
  first = self.safe_dict(data, 0)
1343
1376
  order = self.parse_order(first, market)
@@ -1387,7 +1420,8 @@ class blofin(Exchange, ImplicitAPI):
1387
1420
  :param str id: order id
1388
1421
  :param str symbol: unified symbol of the market the order was made in
1389
1422
  :param dict [params]: extra parameters specific to the exchange API endpoint
1390
- :param boolean [params.trigger]: True if cancelling a trigger/conditional order/tp sl orders
1423
+ :param boolean [params.trigger]: True if cancelling a trigger/conditional
1424
+ :param boolean [params.tpsl]: True if cancelling a tpsl order
1391
1425
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1392
1426
  """
1393
1427
  if symbol is None:
@@ -1397,20 +1431,27 @@ class blofin(Exchange, ImplicitAPI):
1397
1431
  request: dict = {
1398
1432
  'instId': market['id'],
1399
1433
  }
1400
- isTrigger = self.safe_bool_n(params, ['stop', 'trigger', 'tpsl'], False)
1434
+ isTrigger = self.safe_bool_n(params, ['trigger'], False)
1435
+ isTpsl = self.safe_bool_2(params, 'tpsl', 'TPSL', False)
1401
1436
  clientOrderId = self.safe_string(params, 'clientOrderId')
1402
1437
  if clientOrderId is not None:
1403
1438
  request['clientOrderId'] = clientOrderId
1404
1439
  else:
1405
- if not isTrigger:
1440
+ if not isTrigger and not isTpsl:
1406
1441
  request['orderId'] = str(id)
1407
- else:
1442
+ elif isTpsl:
1408
1443
  request['tpslId'] = str(id)
1444
+ elif isTrigger:
1445
+ request['algoId'] = str(id)
1409
1446
  query = self.omit(params, ['orderId', 'clientOrderId', 'stop', 'trigger', 'tpsl'])
1410
- if isTrigger:
1447
+ if isTpsl:
1411
1448
  tpslResponse = self.cancel_orders([id], symbol, params)
1412
1449
  first = self.safe_dict(tpslResponse, 0)
1413
1450
  return first
1451
+ elif isTrigger:
1452
+ triggerResponse = self.privatePostTradeCancelAlgo(self.extend(request, query))
1453
+ triggerData = self.safe_dict(triggerResponse, 'data')
1454
+ return self.parse_order(triggerData, market)
1414
1455
  response = self.privatePostTradeCancelOrder(self.extend(request, query))
1415
1456
  data = self.safe_list(response, 'data', [])
1416
1457
  order = self.safe_dict(data, 0)
@@ -1449,6 +1490,7 @@ class blofin(Exchange, ImplicitAPI):
1449
1490
 
1450
1491
  https://blofin.com/docs#get-active-orders
1451
1492
  https://blofin.com/docs#get-active-tpsl-orders
1493
+ https://docs.blofin.com/index.html#get-active-algo-orders
1452
1494
 
1453
1495
  :param str symbol: unified market symbol
1454
1496
  :param int [since]: the earliest time in ms to fetch open orders for
@@ -1471,13 +1513,17 @@ class blofin(Exchange, ImplicitAPI):
1471
1513
  request['instId'] = market['id']
1472
1514
  if limit is not None:
1473
1515
  request['limit'] = limit # default 100, max 100
1474
- isTrigger = self.safe_bool_n(params, ['stop', 'trigger', 'tpsl', 'TPSL'], False)
1516
+ isTrigger = self.safe_bool_n(params, ['stop', 'trigger'], False)
1517
+ isTpSl = self.safe_bool_2(params, 'tpsl', 'TPSL', False)
1475
1518
  method: Str = None
1476
1519
  method, params = self.handle_option_and_params(params, 'fetchOpenOrders', 'method', 'privateGetTradeOrdersPending')
1477
1520
  query = self.omit(params, ['method', 'stop', 'trigger', 'tpsl', 'TPSL'])
1478
1521
  response = None
1479
- if isTrigger or (method == 'privateGetTradeOrdersTpslPending'):
1522
+ if isTpSl or (method == 'privateGetTradeOrdersTpslPending'):
1480
1523
  response = self.privateGetTradeOrdersTpslPending(self.extend(request, query))
1524
+ elif isTrigger or (method == 'privateGetTradeOrdersAlgoPending'):
1525
+ request['orderType'] = 'trigger'
1526
+ response = self.privateGetTradeOrdersAlgoPending(self.extend(request, query))
1481
1527
  else:
1482
1528
  response = self.privateGetTradeOrdersPending(self.extend(request, query))
1483
1529
  data = self.safe_list(response, 'data', [])
@@ -2118,6 +2164,7 @@ class blofin(Exchange, ImplicitAPI):
2118
2164
  :param str symbol: unified market symbol
2119
2165
  :param dict [params]: extra parameters specific to the exchange API endpoint
2120
2166
  :param str [params.marginMode]: 'cross' or 'isolated'
2167
+ :param str [params.positionSide]: 'long' or 'short' - required for hedged mode in isolated margin
2121
2168
  :returns dict: response from the exchange
2122
2169
  """
2123
2170
  if symbol is None:
@@ -2239,13 +2286,97 @@ class blofin(Exchange, ImplicitAPI):
2239
2286
  data = self.safe_dict(response, 'data', {})
2240
2287
  return self.parse_margin_mode(data, market)
2241
2288
 
2242
- def parse_margin_mode(self, marginMode: dict, market=None) -> MarginMode:
2289
+ def parse_margin_mode(self, marginMode: dict, market: Market = None) -> MarginMode:
2243
2290
  return {
2244
2291
  'info': marginMode,
2245
- 'symbol': market['symbol'],
2292
+ 'symbol': self.safe_string(market, 'symbol'),
2246
2293
  'marginMode': self.safe_string(marginMode, 'marginMode'),
2247
2294
  }
2248
2295
 
2296
+ def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
2297
+ """
2298
+ set margin mode to 'cross' or 'isolated'
2299
+
2300
+ https://docs.blofin.com/index.html#set-margin-mode
2301
+
2302
+ :param str marginMode: 'cross' or 'isolated'
2303
+ :param str [symbol]: unified market symbol(not used in blofin setMarginMode)
2304
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2305
+ :returns dict: response from the exchange
2306
+ """
2307
+ self.check_required_argument('setMarginMode', marginMode, 'marginMode', ['cross', 'isolated'])
2308
+ self.load_markets()
2309
+ market = None
2310
+ if symbol is not None:
2311
+ market = self.market(symbol)
2312
+ request: dict = {
2313
+ 'marginMode': marginMode,
2314
+ }
2315
+ response = self.privatePostAccountSetMarginMode(self.extend(request, params))
2316
+ #
2317
+ # {
2318
+ # "code": "0",
2319
+ # "msg": "success",
2320
+ # "data": {
2321
+ # "marginMode": "isolated"
2322
+ # }
2323
+ # }
2324
+ #
2325
+ data = self.safe_dict(response, 'data', {})
2326
+ return self.parse_margin_mode(data, market)
2327
+
2328
+ def fetch_position_mode(self, symbol: Str = None, params={}):
2329
+ """
2330
+ fetchs the position mode, hedged or one way
2331
+
2332
+ https://docs.blofin.com/index.html#get-position-mode
2333
+
2334
+ :param str [symbol]: unified symbol of the market to fetch the position mode for(not used in blofin fetchPositionMode)
2335
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2336
+ :returns dict: an object detailing whether the market is in hedged or one-way mode
2337
+ """
2338
+ response = self.privateGetAccountPositionMode(params)
2339
+ data = self.safe_dict(response, 'data', {})
2340
+ positionMode = self.safe_string(data, 'positionMode')
2341
+ #
2342
+ # {
2343
+ # "code": "0",
2344
+ # "msg": "success",
2345
+ # "data": {
2346
+ # "positionMode": "long_short_mode"
2347
+ # }
2348
+ # }
2349
+ #
2350
+ return {
2351
+ 'info': data,
2352
+ 'hedged': positionMode == 'long_short_mode',
2353
+ }
2354
+
2355
+ def set_position_mode(self, hedged: bool, symbol: Str = None, params={}):
2356
+ """
2357
+ set hedged to True or False for a market
2358
+
2359
+ https://docs.blofin.com/index.html#set-position-mode
2360
+
2361
+ :param bool hedged: set to True to use hedged mode, False for one-way mode
2362
+ :param str [symbol]: not used by blofin setPositionMode()
2363
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2364
+ :returns dict: response from the exchange
2365
+ """
2366
+ request: dict = {
2367
+ 'positionMode': 'long_short_mode' if hedged else 'net_mode',
2368
+ }
2369
+ #
2370
+ # {
2371
+ # "code": "0",
2372
+ # "msg": "success",
2373
+ # "data": {
2374
+ # "positionMode": "net_mode"
2375
+ # }
2376
+ # }
2377
+ #
2378
+ return self.privatePostAccountSetPositionMode(self.extend(request, params))
2379
+
2249
2380
  def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2250
2381
  if response is None:
2251
2382
  return None # fallback to default error handler