ccxt 4.4.45__py2.py3-none-any.whl → 4.4.47__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 (118) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/binance.py +1 -0
  3. ccxt/abstract/binancecoinm.py +1 -0
  4. ccxt/abstract/binanceus.py +1 -0
  5. ccxt/abstract/binanceusdm.py +1 -0
  6. ccxt/abstract/bybit.py +1 -0
  7. ccxt/ace.py +58 -0
  8. ccxt/alpaca.py +80 -0
  9. ccxt/ascendex.py +110 -3
  10. ccxt/async_support/__init__.py +1 -1
  11. ccxt/async_support/ace.py +58 -0
  12. ccxt/async_support/alpaca.py +80 -0
  13. ccxt/async_support/ascendex.py +110 -3
  14. ccxt/async_support/base/exchange.py +1 -1
  15. ccxt/async_support/bigone.py +113 -4
  16. ccxt/async_support/binance.py +4 -5
  17. ccxt/async_support/binanceus.py +10 -0
  18. ccxt/async_support/bingx.py +1 -2
  19. ccxt/async_support/bit2c.py +56 -0
  20. ccxt/async_support/bitbank.py +58 -0
  21. ccxt/async_support/bitbns.py +60 -0
  22. ccxt/async_support/bitfinex.py +2 -3
  23. ccxt/async_support/bitfinex1.py +8 -0
  24. ccxt/async_support/bitflyer.py +71 -0
  25. ccxt/async_support/bitget.py +103 -40
  26. ccxt/async_support/bithumb.py +54 -0
  27. ccxt/async_support/bitmex.py +1 -2
  28. ccxt/async_support/bitopro.py +74 -0
  29. ccxt/async_support/bitrue.py +97 -17
  30. ccxt/async_support/bitso.py +59 -0
  31. ccxt/async_support/bitteam.py +73 -0
  32. ccxt/async_support/bitvavo.py +70 -2
  33. ccxt/async_support/bl3p.py +42 -0
  34. ccxt/async_support/blockchaincom.py +66 -2
  35. ccxt/async_support/blofin.py +87 -1
  36. ccxt/async_support/btcalpha.py +73 -0
  37. ccxt/async_support/btcbox.py +58 -0
  38. ccxt/async_support/btcmarkets.py +73 -0
  39. ccxt/async_support/btcturk.py +61 -0
  40. ccxt/async_support/bybit.py +87 -39
  41. ccxt/async_support/cex.py +57 -0
  42. ccxt/async_support/coinbase.py +1 -1
  43. ccxt/async_support/coinbaseexchange.py +76 -0
  44. ccxt/async_support/coinex.py +1 -2
  45. ccxt/async_support/delta.py +10 -6
  46. ccxt/async_support/gate.py +3 -4
  47. ccxt/async_support/hashkey.py +1 -2
  48. ccxt/async_support/hollaex.py +1 -1
  49. ccxt/async_support/htx.py +2 -4
  50. ccxt/async_support/hyperliquid.py +6 -7
  51. ccxt/async_support/krakenfutures.py +2 -0
  52. ccxt/async_support/lbank.py +1 -2
  53. ccxt/async_support/mexc.py +1 -0
  54. ccxt/async_support/okx.py +13 -9
  55. ccxt/async_support/onetrading.py +18 -3
  56. ccxt/async_support/oxfun.py +1 -2
  57. ccxt/async_support/whitebit.py +2 -2
  58. ccxt/async_support/woo.py +1 -2
  59. ccxt/async_support/woofipro.py +1 -2
  60. ccxt/base/errors.py +6 -0
  61. ccxt/base/exchange.py +16 -14
  62. ccxt/bigone.py +113 -4
  63. ccxt/binance.py +4 -5
  64. ccxt/binanceus.py +10 -0
  65. ccxt/bingx.py +1 -2
  66. ccxt/bit2c.py +56 -0
  67. ccxt/bitbank.py +58 -0
  68. ccxt/bitbns.py +60 -0
  69. ccxt/bitfinex.py +2 -3
  70. ccxt/bitfinex1.py +8 -0
  71. ccxt/bitflyer.py +71 -0
  72. ccxt/bitget.py +103 -40
  73. ccxt/bithumb.py +54 -0
  74. ccxt/bitmex.py +1 -2
  75. ccxt/bitopro.py +74 -0
  76. ccxt/bitrue.py +97 -17
  77. ccxt/bitso.py +59 -0
  78. ccxt/bitteam.py +73 -0
  79. ccxt/bitvavo.py +70 -2
  80. ccxt/bl3p.py +42 -0
  81. ccxt/blockchaincom.py +66 -2
  82. ccxt/blofin.py +87 -1
  83. ccxt/btcalpha.py +73 -0
  84. ccxt/btcbox.py +58 -0
  85. ccxt/btcmarkets.py +73 -0
  86. ccxt/btcturk.py +61 -0
  87. ccxt/bybit.py +87 -39
  88. ccxt/cex.py +57 -0
  89. ccxt/coinbase.py +1 -1
  90. ccxt/coinbaseexchange.py +76 -0
  91. ccxt/coinex.py +1 -2
  92. ccxt/delta.py +10 -6
  93. ccxt/gate.py +3 -4
  94. ccxt/hashkey.py +1 -2
  95. ccxt/hollaex.py +1 -1
  96. ccxt/htx.py +2 -4
  97. ccxt/hyperliquid.py +6 -7
  98. ccxt/krakenfutures.py +2 -0
  99. ccxt/lbank.py +1 -2
  100. ccxt/mexc.py +1 -0
  101. ccxt/okx.py +13 -9
  102. ccxt/onetrading.py +18 -3
  103. ccxt/oxfun.py +1 -2
  104. ccxt/pro/__init__.py +1 -1
  105. ccxt/pro/bingx.py +3 -5
  106. ccxt/pro/bitget.py +2 -4
  107. ccxt/pro/coinex.py +1 -1
  108. ccxt/pro/xt.py +1 -1
  109. ccxt/test/tests_async.py +2 -0
  110. ccxt/test/tests_sync.py +2 -0
  111. ccxt/whitebit.py +2 -2
  112. ccxt/woo.py +1 -2
  113. ccxt/woofipro.py +1 -2
  114. {ccxt-4.4.45.dist-info → ccxt-4.4.47.dist-info}/METADATA +4 -5
  115. {ccxt-4.4.45.dist-info → ccxt-4.4.47.dist-info}/RECORD +118 -118
  116. {ccxt-4.4.45.dist-info → ccxt-4.4.47.dist-info}/LICENSE.txt +0 -0
  117. {ccxt-4.4.45.dist-info → ccxt-4.4.47.dist-info}/WHEEL +0 -0
  118. {ccxt-4.4.45.dist-info → ccxt-4.4.47.dist-info}/top_level.txt +0 -0
ccxt/__init__.py CHANGED
@@ -22,7 +22,7 @@
22
22
 
23
23
  # ----------------------------------------------------------------------------
24
24
 
25
- __version__ = '4.4.45'
25
+ __version__ = '4.4.47'
26
26
 
27
27
  # ----------------------------------------------------------------------------
28
28
 
ccxt/abstract/binance.py CHANGED
@@ -727,6 +727,7 @@ class ImplicitAPI:
727
727
  papi_get_um_symbolconfig = papiGetUmSymbolConfig = Entry('um/symbolConfig', 'papi', 'GET', {'cost': 1})
728
728
  papi_get_cm_accountconfig = papiGetCmAccountConfig = Entry('cm/accountConfig', 'papi', 'GET', {'cost': 1})
729
729
  papi_get_cm_symbolconfig = papiGetCmSymbolConfig = Entry('cm/symbolConfig', 'papi', 'GET', {'cost': 1})
730
+ papi_get_ratelimit_order = papiGetRateLimitOrder = Entry('rateLimit/order', 'papi', 'GET', {'cost': 1})
730
731
  papi_post_um_order = papiPostUmOrder = Entry('um/order', 'papi', 'POST', {'cost': 1})
731
732
  papi_post_um_conditional_order = papiPostUmConditionalOrder = Entry('um/conditional/order', 'papi', 'POST', {'cost': 1})
732
733
  papi_post_cm_order = papiPostCmOrder = Entry('cm/order', 'papi', 'POST', {'cost': 1})
@@ -727,6 +727,7 @@ class ImplicitAPI:
727
727
  papi_get_um_symbolconfig = papiGetUmSymbolConfig = Entry('um/symbolConfig', 'papi', 'GET', {'cost': 1})
728
728
  papi_get_cm_accountconfig = papiGetCmAccountConfig = Entry('cm/accountConfig', 'papi', 'GET', {'cost': 1})
729
729
  papi_get_cm_symbolconfig = papiGetCmSymbolConfig = Entry('cm/symbolConfig', 'papi', 'GET', {'cost': 1})
730
+ papi_get_ratelimit_order = papiGetRateLimitOrder = Entry('rateLimit/order', 'papi', 'GET', {'cost': 1})
730
731
  papi_post_um_order = papiPostUmOrder = Entry('um/order', 'papi', 'POST', {'cost': 1})
731
732
  papi_post_um_conditional_order = papiPostUmConditionalOrder = Entry('um/conditional/order', 'papi', 'POST', {'cost': 1})
732
733
  papi_post_cm_order = papiPostCmOrder = Entry('cm/order', 'papi', 'POST', {'cost': 1})
@@ -779,6 +779,7 @@ class ImplicitAPI:
779
779
  papi_get_um_symbolconfig = papiGetUmSymbolConfig = Entry('um/symbolConfig', 'papi', 'GET', {'cost': 1})
780
780
  papi_get_cm_accountconfig = papiGetCmAccountConfig = Entry('cm/accountConfig', 'papi', 'GET', {'cost': 1})
781
781
  papi_get_cm_symbolconfig = papiGetCmSymbolConfig = Entry('cm/symbolConfig', 'papi', 'GET', {'cost': 1})
782
+ papi_get_ratelimit_order = papiGetRateLimitOrder = Entry('rateLimit/order', 'papi', 'GET', {'cost': 1})
782
783
  papi_post_um_order = papiPostUmOrder = Entry('um/order', 'papi', 'POST', {'cost': 1})
783
784
  papi_post_um_conditional_order = papiPostUmConditionalOrder = Entry('um/conditional/order', 'papi', 'POST', {'cost': 1})
784
785
  papi_post_cm_order = papiPostCmOrder = Entry('cm/order', 'papi', 'POST', {'cost': 1})
@@ -727,6 +727,7 @@ class ImplicitAPI:
727
727
  papi_get_um_symbolconfig = papiGetUmSymbolConfig = Entry('um/symbolConfig', 'papi', 'GET', {'cost': 1})
728
728
  papi_get_cm_accountconfig = papiGetCmAccountConfig = Entry('cm/accountConfig', 'papi', 'GET', {'cost': 1})
729
729
  papi_get_cm_symbolconfig = papiGetCmSymbolConfig = Entry('cm/symbolConfig', 'papi', 'GET', {'cost': 1})
730
+ papi_get_ratelimit_order = papiGetRateLimitOrder = Entry('rateLimit/order', 'papi', 'GET', {'cost': 1})
730
731
  papi_post_um_order = papiPostUmOrder = Entry('um/order', 'papi', 'POST', {'cost': 1})
731
732
  papi_post_um_conditional_order = papiPostUmConditionalOrder = Entry('um/conditional/order', 'papi', 'POST', {'cost': 1})
732
733
  papi_post_cm_order = papiPostCmOrder = Entry('cm/order', 'papi', 'POST', {'cost': 1})
ccxt/abstract/bybit.py CHANGED
@@ -134,6 +134,7 @@ class ImplicitAPI:
134
134
  private_get_v5_account_contract_transaction_log = privateGetV5AccountContractTransactionLog = Entry('v5/account/contract-transaction-log', 'private', 'GET', {'cost': 1})
135
135
  private_get_v5_account_smp_group = privateGetV5AccountSmpGroup = Entry('v5/account/smp-group', 'private', 'GET', {'cost': 1})
136
136
  private_get_v5_account_mmp_state = privateGetV5AccountMmpState = Entry('v5/account/mmp-state', 'private', 'GET', {'cost': 5})
137
+ private_get_v5_account_withdrawal = privateGetV5AccountWithdrawal = Entry('v5/account/withdrawal', 'private', 'GET', {'cost': 5})
137
138
  private_get_v5_asset_exchange_query_coin_list = privateGetV5AssetExchangeQueryCoinList = Entry('v5/asset/exchange/query-coin-list', 'private', 'GET', {'cost': 0.5})
138
139
  private_get_v5_asset_exchange_convert_result_query = privateGetV5AssetExchangeConvertResultQuery = Entry('v5/asset/exchange/convert-result-query', 'private', 'GET', {'cost': 0.5})
139
140
  private_get_v5_asset_exchange_query_convert_history = privateGetV5AssetExchangeQueryConvertHistory = Entry('v5/asset/exchange/query-convert-history', 'private', 'GET', {'cost': 0.5})
ccxt/ace.py CHANGED
@@ -154,6 +154,64 @@ class ace(Exchange, ImplicitAPI):
154
154
  'options': {
155
155
  'brokerId': 'ccxt',
156
156
  },
157
+ 'features': {
158
+ 'spot': {
159
+ 'sandbox': False,
160
+ 'createOrder': {
161
+ 'marginMode': False,
162
+ 'triggerPrice': False,
163
+ 'triggerPriceType': None,
164
+ 'triggerDirection': False,
165
+ 'stopLossPrice': False,
166
+ 'takeProfitPrice': False,
167
+ 'attachedStopLossTakeProfit': None, # not supported
168
+ 'timeInForce': {
169
+ 'IOC': False,
170
+ 'FOK': False,
171
+ 'PO': False,
172
+ 'GTD': False,
173
+ },
174
+ 'hedged': False,
175
+ 'leverage': False,
176
+ 'marketBuyRequiresPrice': False,
177
+ 'marketBuyByCost': False,
178
+ 'selfTradePrevention': False,
179
+ 'trailing': False,
180
+ 'iceberg': False,
181
+ },
182
+ 'createOrders': None,
183
+ 'fetchMyTrades': {
184
+ 'marginMode': False,
185
+ 'limit': 500,
186
+ 'daysBack': None,
187
+ 'untilDays': None,
188
+ },
189
+ 'fetchOrder': {
190
+ 'marginMode': False,
191
+ 'trigger': False,
192
+ 'trailing': False,
193
+ },
194
+ 'fetchOpenOrders': {
195
+ 'marginMode': False,
196
+ 'limit': None,
197
+ 'trigger': False,
198
+ 'trailing': False,
199
+ },
200
+ 'fetchOrders': None,
201
+ 'fetchClosedOrders': None,
202
+ 'fetchOHLCV': {
203
+ 'limit': 2000,
204
+ },
205
+ },
206
+ 'swap': {
207
+ 'linear': None,
208
+ 'inverse': None,
209
+ },
210
+ 'future': {
211
+ 'linear': None,
212
+ 'inverse': None,
213
+ },
214
+ },
157
215
  'precisionMode': TICK_SIZE,
158
216
  'exceptions': {
159
217
  'exact': {
ccxt/alpaca.py CHANGED
@@ -274,6 +274,86 @@ class alpaca(Exchange, ImplicitAPI):
274
274
  'defaultTimeInForce': 'gtc', # fok, gtc, ioc
275
275
  'clientOrderId': 'ccxt_{id}',
276
276
  },
277
+ 'features': {
278
+ 'spot': {
279
+ 'sandbox': True,
280
+ 'createOrder': {
281
+ 'marginMode': False,
282
+ 'triggerPrice': True,
283
+ 'triggerPriceType': None,
284
+ 'triggerDirection': False,
285
+ 'stopLossPrice': False, # todo
286
+ 'takeProfitPrice': False, # todo
287
+ 'attachedStopLossTakeProfit': {
288
+ 'triggerPriceType': {
289
+ 'last': True,
290
+ 'mark': True,
291
+ 'index': True,
292
+ },
293
+ 'price': True,
294
+ },
295
+ 'timeInForce': {
296
+ 'IOC': True,
297
+ 'FOK': True,
298
+ 'PO': True,
299
+ 'GTD': False,
300
+ },
301
+ 'hedged': False,
302
+ 'trailing': True, # todo: implementation
303
+ 'leverage': False,
304
+ 'marketBuyRequiresPrice': False,
305
+ 'marketBuyByCost': False,
306
+ 'selfTradePrevention': False,
307
+ 'iceberg': False,
308
+ },
309
+ 'createOrders': None,
310
+ 'fetchMyTrades': {
311
+ 'marginMode': False,
312
+ 'limit': 100,
313
+ 'daysBack': 100000,
314
+ 'untilDays': 100000,
315
+ },
316
+ 'fetchOrder': {
317
+ 'marginMode': False,
318
+ 'trigger': False,
319
+ 'trailing': False,
320
+ },
321
+ 'fetchOpenOrders': {
322
+ 'marginMode': False,
323
+ 'limit': 500,
324
+ 'trigger': False,
325
+ 'trailing': False,
326
+ },
327
+ 'fetchOrders': {
328
+ 'marginMode': False,
329
+ 'limit': 500,
330
+ 'daysBack': 100000,
331
+ 'untilDays': 100000,
332
+ 'trigger': False,
333
+ 'trailing': False,
334
+ },
335
+ 'fetchClosedOrders': {
336
+ 'marginMode': False,
337
+ 'limit': 500,
338
+ 'daysBack': 100000,
339
+ 'daysBackCanceled': None,
340
+ 'untilDays': 100000,
341
+ 'trigger': False,
342
+ 'trailing': False,
343
+ },
344
+ 'fetchOHLCV': {
345
+ 'limit': 1000,
346
+ },
347
+ },
348
+ 'swap': {
349
+ 'linear': None,
350
+ 'inverse': None,
351
+ },
352
+ 'future': {
353
+ 'linear': None,
354
+ 'inverse': None,
355
+ },
356
+ },
277
357
  'exceptions': {
278
358
  'exact': {
279
359
  'forbidden.': PermissionDenied, # {"message": "forbidden."}
ccxt/ascendex.py CHANGED
@@ -306,6 +306,100 @@ class ascendex(Exchange, ImplicitAPI):
306
306
  'AKT': 'Akash',
307
307
  },
308
308
  },
309
+ 'features': {
310
+ 'default': {
311
+ 'sandbox': True,
312
+ 'createOrder': {
313
+ 'marginMode': True,
314
+ 'triggerPrice': True,
315
+ 'triggerPriceType': None,
316
+ 'triggerDirection': False,
317
+ 'stopLossPrice': False, # todo with triggerprice
318
+ 'takeProfitPrice': False, # todo with triggerprice
319
+ 'attachedStopLossTakeProfit': None,
320
+ 'timeInForce': {
321
+ 'IOC': True,
322
+ 'FOK': True,
323
+ 'PO': True,
324
+ 'GTD': False,
325
+ },
326
+ 'hedged': False,
327
+ 'trailing': False,
328
+ 'leverage': False,
329
+ 'marketBuyRequiresPrice': False,
330
+ 'marketBuyByCost': False,
331
+ 'selfTradePrevention': False,
332
+ 'iceberg': False,
333
+ },
334
+ 'createOrders': {
335
+ 'max': 10,
336
+ },
337
+ 'fetchMyTrades': None,
338
+ 'fetchOrder': {
339
+ 'marginMode': False,
340
+ 'trigger': False,
341
+ 'trailing': False,
342
+ 'marketType': True,
343
+ },
344
+ 'fetchOpenOrders': {
345
+ 'marginMode': False,
346
+ 'limit': None,
347
+ 'trigger': False,
348
+ 'trailing': False,
349
+ 'marketType': True,
350
+ },
351
+ 'fetchOrders': None,
352
+ 'fetchClosedOrders': None,
353
+ 'fetchOHLCV': {
354
+ 'limit': 500,
355
+ },
356
+ },
357
+ 'spot': {
358
+ 'extends': 'default',
359
+ 'fetchClosedOrders': {
360
+ 'marginMode': False,
361
+ 'limit': 1000,
362
+ 'daysBack': 100000,
363
+ 'daysBackCanceled': 1,
364
+ 'untilDays': 100000,
365
+ 'trigger': False,
366
+ 'trailing': False,
367
+ },
368
+ },
369
+ 'forDerivatives': {
370
+ 'extends': 'default',
371
+ 'createOrder': {
372
+ # todo: implementation
373
+ 'attachedStopLossTakeProfit': {
374
+ 'triggerPriceType': {
375
+ 'last': True,
376
+ 'mark': False,
377
+ 'index': False,
378
+ },
379
+ 'price': False,
380
+ },
381
+ },
382
+ 'fetchClosedOrders': {
383
+ 'marginMode': False,
384
+ 'limit': 1000,
385
+ 'daysBack': None,
386
+ 'daysBackCanceled': None,
387
+ 'untilDays': None,
388
+ 'trigger': False,
389
+ 'trailing': False,
390
+ },
391
+ },
392
+ 'swap': {
393
+ 'linear': {
394
+ 'extends': 'forDerivatives',
395
+ },
396
+ 'inverse': None,
397
+ },
398
+ 'future': {
399
+ 'linear': None,
400
+ 'inverse': None,
401
+ },
402
+ },
309
403
  'exceptions': {
310
404
  'exact': {
311
405
  # not documented
@@ -1092,6 +1186,7 @@ class ascendex(Exchange, ImplicitAPI):
1092
1186
  :param int [since]: timestamp in ms of the earliest candle to fetch
1093
1187
  :param int [limit]: the maximum amount of candles to fetch
1094
1188
  :param dict [params]: extra parameters specific to the exchange API endpoint
1189
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
1095
1190
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1096
1191
  """
1097
1192
  self.load_markets()
@@ -1105,15 +1200,28 @@ class ascendex(Exchange, ImplicitAPI):
1105
1200
  duration = self.parse_timeframe(timeframe)
1106
1201
  options = self.safe_dict(self.options, 'fetchOHLCV', {})
1107
1202
  defaultLimit = self.safe_integer(options, 'limit', 500)
1203
+ until = self.safe_integer(params, 'until')
1108
1204
  if since is not None:
1109
1205
  request['from'] = since
1110
1206
  if limit is None:
1111
1207
  limit = defaultLimit
1112
1208
  else:
1113
1209
  limit = min(limit, defaultLimit)
1114
- request['to'] = self.sum(since, limit * duration * 1000, 1)
1210
+ toWithLimit = self.sum(since, limit * duration * 1000, 1)
1211
+ if until is not None:
1212
+ request['to'] = min(toWithLimit, until + 1)
1213
+ else:
1214
+ request['to'] = toWithLimit
1215
+ elif until is not None:
1216
+ request['to'] = until + 1
1217
+ if limit is None:
1218
+ limit = defaultLimit
1219
+ else:
1220
+ limit = min(limit, defaultLimit)
1221
+ request['from'] = until - (limit * duration * 1000)
1115
1222
  elif limit is not None:
1116
1223
  request['n'] = limit # max 500
1224
+ params = self.omit(params, 'until')
1117
1225
  response = self.v1PublicGetBarhist(self.extend(request, params))
1118
1226
  #
1119
1227
  # {
@@ -2714,8 +2822,7 @@ class ascendex(Exchange, ImplicitAPI):
2714
2822
  #
2715
2823
  data = self.safe_dict(response, 'data', {})
2716
2824
  contracts = self.safe_list(data, 'contracts', [])
2717
- result = self.parse_funding_rates(contracts)
2718
- return self.filter_by_array(result, 'symbol', symbols)
2825
+ return self.parse_funding_rates(contracts, symbols)
2719
2826
 
2720
2827
  def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
2721
2828
  self.load_markets()
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.45'
7
+ __version__ = '4.4.47'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
ccxt/async_support/ace.py CHANGED
@@ -154,6 +154,64 @@ class ace(Exchange, ImplicitAPI):
154
154
  'options': {
155
155
  'brokerId': 'ccxt',
156
156
  },
157
+ 'features': {
158
+ 'spot': {
159
+ 'sandbox': False,
160
+ 'createOrder': {
161
+ 'marginMode': False,
162
+ 'triggerPrice': False,
163
+ 'triggerPriceType': None,
164
+ 'triggerDirection': False,
165
+ 'stopLossPrice': False,
166
+ 'takeProfitPrice': False,
167
+ 'attachedStopLossTakeProfit': None, # not supported
168
+ 'timeInForce': {
169
+ 'IOC': False,
170
+ 'FOK': False,
171
+ 'PO': False,
172
+ 'GTD': False,
173
+ },
174
+ 'hedged': False,
175
+ 'leverage': False,
176
+ 'marketBuyRequiresPrice': False,
177
+ 'marketBuyByCost': False,
178
+ 'selfTradePrevention': False,
179
+ 'trailing': False,
180
+ 'iceberg': False,
181
+ },
182
+ 'createOrders': None,
183
+ 'fetchMyTrades': {
184
+ 'marginMode': False,
185
+ 'limit': 500,
186
+ 'daysBack': None,
187
+ 'untilDays': None,
188
+ },
189
+ 'fetchOrder': {
190
+ 'marginMode': False,
191
+ 'trigger': False,
192
+ 'trailing': False,
193
+ },
194
+ 'fetchOpenOrders': {
195
+ 'marginMode': False,
196
+ 'limit': None,
197
+ 'trigger': False,
198
+ 'trailing': False,
199
+ },
200
+ 'fetchOrders': None,
201
+ 'fetchClosedOrders': None,
202
+ 'fetchOHLCV': {
203
+ 'limit': 2000,
204
+ },
205
+ },
206
+ 'swap': {
207
+ 'linear': None,
208
+ 'inverse': None,
209
+ },
210
+ 'future': {
211
+ 'linear': None,
212
+ 'inverse': None,
213
+ },
214
+ },
157
215
  'precisionMode': TICK_SIZE,
158
216
  'exceptions': {
159
217
  'exact': {
@@ -274,6 +274,86 @@ class alpaca(Exchange, ImplicitAPI):
274
274
  'defaultTimeInForce': 'gtc', # fok, gtc, ioc
275
275
  'clientOrderId': 'ccxt_{id}',
276
276
  },
277
+ 'features': {
278
+ 'spot': {
279
+ 'sandbox': True,
280
+ 'createOrder': {
281
+ 'marginMode': False,
282
+ 'triggerPrice': True,
283
+ 'triggerPriceType': None,
284
+ 'triggerDirection': False,
285
+ 'stopLossPrice': False, # todo
286
+ 'takeProfitPrice': False, # todo
287
+ 'attachedStopLossTakeProfit': {
288
+ 'triggerPriceType': {
289
+ 'last': True,
290
+ 'mark': True,
291
+ 'index': True,
292
+ },
293
+ 'price': True,
294
+ },
295
+ 'timeInForce': {
296
+ 'IOC': True,
297
+ 'FOK': True,
298
+ 'PO': True,
299
+ 'GTD': False,
300
+ },
301
+ 'hedged': False,
302
+ 'trailing': True, # todo: implementation
303
+ 'leverage': False,
304
+ 'marketBuyRequiresPrice': False,
305
+ 'marketBuyByCost': False,
306
+ 'selfTradePrevention': False,
307
+ 'iceberg': False,
308
+ },
309
+ 'createOrders': None,
310
+ 'fetchMyTrades': {
311
+ 'marginMode': False,
312
+ 'limit': 100,
313
+ 'daysBack': 100000,
314
+ 'untilDays': 100000,
315
+ },
316
+ 'fetchOrder': {
317
+ 'marginMode': False,
318
+ 'trigger': False,
319
+ 'trailing': False,
320
+ },
321
+ 'fetchOpenOrders': {
322
+ 'marginMode': False,
323
+ 'limit': 500,
324
+ 'trigger': False,
325
+ 'trailing': False,
326
+ },
327
+ 'fetchOrders': {
328
+ 'marginMode': False,
329
+ 'limit': 500,
330
+ 'daysBack': 100000,
331
+ 'untilDays': 100000,
332
+ 'trigger': False,
333
+ 'trailing': False,
334
+ },
335
+ 'fetchClosedOrders': {
336
+ 'marginMode': False,
337
+ 'limit': 500,
338
+ 'daysBack': 100000,
339
+ 'daysBackCanceled': None,
340
+ 'untilDays': 100000,
341
+ 'trigger': False,
342
+ 'trailing': False,
343
+ },
344
+ 'fetchOHLCV': {
345
+ 'limit': 1000,
346
+ },
347
+ },
348
+ 'swap': {
349
+ 'linear': None,
350
+ 'inverse': None,
351
+ },
352
+ 'future': {
353
+ 'linear': None,
354
+ 'inverse': None,
355
+ },
356
+ },
277
357
  'exceptions': {
278
358
  'exact': {
279
359
  'forbidden.': PermissionDenied, # {"message": "forbidden."}
@@ -307,6 +307,100 @@ class ascendex(Exchange, ImplicitAPI):
307
307
  'AKT': 'Akash',
308
308
  },
309
309
  },
310
+ 'features': {
311
+ 'default': {
312
+ 'sandbox': True,
313
+ 'createOrder': {
314
+ 'marginMode': True,
315
+ 'triggerPrice': True,
316
+ 'triggerPriceType': None,
317
+ 'triggerDirection': False,
318
+ 'stopLossPrice': False, # todo with triggerprice
319
+ 'takeProfitPrice': False, # todo with triggerprice
320
+ 'attachedStopLossTakeProfit': None,
321
+ 'timeInForce': {
322
+ 'IOC': True,
323
+ 'FOK': True,
324
+ 'PO': True,
325
+ 'GTD': False,
326
+ },
327
+ 'hedged': False,
328
+ 'trailing': False,
329
+ 'leverage': False,
330
+ 'marketBuyRequiresPrice': False,
331
+ 'marketBuyByCost': False,
332
+ 'selfTradePrevention': False,
333
+ 'iceberg': False,
334
+ },
335
+ 'createOrders': {
336
+ 'max': 10,
337
+ },
338
+ 'fetchMyTrades': None,
339
+ 'fetchOrder': {
340
+ 'marginMode': False,
341
+ 'trigger': False,
342
+ 'trailing': False,
343
+ 'marketType': True,
344
+ },
345
+ 'fetchOpenOrders': {
346
+ 'marginMode': False,
347
+ 'limit': None,
348
+ 'trigger': False,
349
+ 'trailing': False,
350
+ 'marketType': True,
351
+ },
352
+ 'fetchOrders': None,
353
+ 'fetchClosedOrders': None,
354
+ 'fetchOHLCV': {
355
+ 'limit': 500,
356
+ },
357
+ },
358
+ 'spot': {
359
+ 'extends': 'default',
360
+ 'fetchClosedOrders': {
361
+ 'marginMode': False,
362
+ 'limit': 1000,
363
+ 'daysBack': 100000,
364
+ 'daysBackCanceled': 1,
365
+ 'untilDays': 100000,
366
+ 'trigger': False,
367
+ 'trailing': False,
368
+ },
369
+ },
370
+ 'forDerivatives': {
371
+ 'extends': 'default',
372
+ 'createOrder': {
373
+ # todo: implementation
374
+ 'attachedStopLossTakeProfit': {
375
+ 'triggerPriceType': {
376
+ 'last': True,
377
+ 'mark': False,
378
+ 'index': False,
379
+ },
380
+ 'price': False,
381
+ },
382
+ },
383
+ 'fetchClosedOrders': {
384
+ 'marginMode': False,
385
+ 'limit': 1000,
386
+ 'daysBack': None,
387
+ 'daysBackCanceled': None,
388
+ 'untilDays': None,
389
+ 'trigger': False,
390
+ 'trailing': False,
391
+ },
392
+ },
393
+ 'swap': {
394
+ 'linear': {
395
+ 'extends': 'forDerivatives',
396
+ },
397
+ 'inverse': None,
398
+ },
399
+ 'future': {
400
+ 'linear': None,
401
+ 'inverse': None,
402
+ },
403
+ },
310
404
  'exceptions': {
311
405
  'exact': {
312
406
  # not documented
@@ -1093,6 +1187,7 @@ class ascendex(Exchange, ImplicitAPI):
1093
1187
  :param int [since]: timestamp in ms of the earliest candle to fetch
1094
1188
  :param int [limit]: the maximum amount of candles to fetch
1095
1189
  :param dict [params]: extra parameters specific to the exchange API endpoint
1190
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
1096
1191
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
1097
1192
  """
1098
1193
  await self.load_markets()
@@ -1106,15 +1201,28 @@ class ascendex(Exchange, ImplicitAPI):
1106
1201
  duration = self.parse_timeframe(timeframe)
1107
1202
  options = self.safe_dict(self.options, 'fetchOHLCV', {})
1108
1203
  defaultLimit = self.safe_integer(options, 'limit', 500)
1204
+ until = self.safe_integer(params, 'until')
1109
1205
  if since is not None:
1110
1206
  request['from'] = since
1111
1207
  if limit is None:
1112
1208
  limit = defaultLimit
1113
1209
  else:
1114
1210
  limit = min(limit, defaultLimit)
1115
- request['to'] = self.sum(since, limit * duration * 1000, 1)
1211
+ toWithLimit = self.sum(since, limit * duration * 1000, 1)
1212
+ if until is not None:
1213
+ request['to'] = min(toWithLimit, until + 1)
1214
+ else:
1215
+ request['to'] = toWithLimit
1216
+ elif until is not None:
1217
+ request['to'] = until + 1
1218
+ if limit is None:
1219
+ limit = defaultLimit
1220
+ else:
1221
+ limit = min(limit, defaultLimit)
1222
+ request['from'] = until - (limit * duration * 1000)
1116
1223
  elif limit is not None:
1117
1224
  request['n'] = limit # max 500
1225
+ params = self.omit(params, 'until')
1118
1226
  response = await self.v1PublicGetBarhist(self.extend(request, params))
1119
1227
  #
1120
1228
  # {
@@ -2715,8 +2823,7 @@ class ascendex(Exchange, ImplicitAPI):
2715
2823
  #
2716
2824
  data = self.safe_dict(response, 'data', {})
2717
2825
  contracts = self.safe_list(data, 'contracts', [])
2718
- result = self.parse_funding_rates(contracts)
2719
- return self.filter_by_array(result, 'symbol', symbols)
2826
+ return self.parse_funding_rates(contracts, symbols)
2720
2827
 
2721
2828
  async def modify_margin_helper(self, symbol: str, amount, type, params={}) -> MarginModification:
2722
2829
  await self.load_markets()