ccxt 4.4.11 → 4.4.13

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 (70) hide show
  1. package/README.md +3 -4
  2. package/dist/ccxt.browser.min.js +4 -4
  3. package/dist/cjs/ccxt.js +1 -1
  4. package/dist/cjs/src/base/Exchange.js +6 -0
  5. package/dist/cjs/src/bigone.js +2 -0
  6. package/dist/cjs/src/binance.js +61 -3
  7. package/dist/cjs/src/bingx.js +96 -6
  8. package/dist/cjs/src/bitget.js +2 -0
  9. package/dist/cjs/src/bitmex.js +1 -0
  10. package/dist/cjs/src/bybit.js +4 -1
  11. package/dist/cjs/src/coinbaseinternational.js +2 -0
  12. package/dist/cjs/src/coinex.js +2 -0
  13. package/dist/cjs/src/delta.js +2 -0
  14. package/dist/cjs/src/deribit.js +2 -0
  15. package/dist/cjs/src/digifinex.js +2 -0
  16. package/dist/cjs/src/gate.js +2 -0
  17. package/dist/cjs/src/htx.js +8 -2
  18. package/dist/cjs/src/kraken.js +4 -4
  19. package/dist/cjs/src/krakenfutures.js +2 -0
  20. package/dist/cjs/src/kucoinfutures.js +2 -0
  21. package/dist/cjs/src/mexc.js +19 -4
  22. package/dist/cjs/src/okx.js +56 -23
  23. package/dist/cjs/src/oxfun.js +1 -0
  24. package/dist/cjs/src/paradex.js +1 -0
  25. package/dist/cjs/src/phemex.js +13 -4
  26. package/dist/cjs/src/poloniex.js +1 -0
  27. package/dist/cjs/src/pro/binance.js +80 -5
  28. package/dist/cjs/src/pro/bitfinex.js +8 -8
  29. package/dist/cjs/src/pro/krakenfutures.js +2 -0
  30. package/dist/cjs/src/pro/phemex.js +2 -0
  31. package/dist/cjs/src/pro/woo.js +73 -0
  32. package/examples/README.md +4 -0
  33. package/js/ccxt.d.ts +1 -1
  34. package/js/ccxt.js +1 -1
  35. package/js/src/base/Exchange.d.ts +2 -0
  36. package/js/src/base/Exchange.js +6 -0
  37. package/js/src/base/types.d.ts +18 -16
  38. package/js/src/bigone.js +2 -0
  39. package/js/src/binance.d.ts +1 -0
  40. package/js/src/binance.js +61 -3
  41. package/js/src/bingx.d.ts +1 -0
  42. package/js/src/bingx.js +96 -6
  43. package/js/src/bitget.js +2 -0
  44. package/js/src/bitmex.js +1 -0
  45. package/js/src/bybit.js +4 -1
  46. package/js/src/coinbaseinternational.js +2 -0
  47. package/js/src/coinex.js +2 -0
  48. package/js/src/delta.js +2 -0
  49. package/js/src/deribit.js +2 -0
  50. package/js/src/digifinex.js +2 -0
  51. package/js/src/gate.js +2 -0
  52. package/js/src/htx.js +8 -2
  53. package/js/src/kraken.js +4 -4
  54. package/js/src/krakenfutures.js +2 -0
  55. package/js/src/kucoinfutures.js +2 -0
  56. package/js/src/mexc.js +19 -4
  57. package/js/src/okx.d.ts +1 -0
  58. package/js/src/okx.js +56 -23
  59. package/js/src/oxfun.js +1 -0
  60. package/js/src/paradex.js +1 -0
  61. package/js/src/phemex.js +13 -4
  62. package/js/src/poloniex.js +1 -0
  63. package/js/src/pro/binance.d.ts +5 -0
  64. package/js/src/pro/binance.js +80 -5
  65. package/js/src/pro/bitfinex.js +8 -8
  66. package/js/src/pro/krakenfutures.js +2 -0
  67. package/js/src/pro/phemex.js +2 -0
  68. package/js/src/pro/woo.d.ts +3 -0
  69. package/js/src/pro/woo.js +73 -0
  70. package/package.json +2 -2
@@ -95,6 +95,7 @@ class okx extends okx$1 {
95
95
  'fetchMarketLeverageTiers': true,
96
96
  'fetchMarkets': true,
97
97
  'fetchMarkOHLCV': true,
98
+ 'fetchMarkPrices': true,
98
99
  'fetchMySettlementHistory': false,
99
100
  'fetchMyTrades': true,
100
101
  'fetchOHLCV': true,
@@ -1801,6 +1802,13 @@ class okx extends okx$1 {
1801
1802
  return this.parseOrderBook(first, symbol, timestamp);
1802
1803
  }
1803
1804
  parseTicker(ticker, market = undefined) {
1805
+ //
1806
+ // {
1807
+ // "instType":"SWAP",
1808
+ // "instId":"BTC-USDT-SWAP",
1809
+ // "markPx":"200",
1810
+ // "ts":"1597026383085"
1811
+ // }
1804
1812
  //
1805
1813
  // {
1806
1814
  // "instType": "SPOT",
@@ -1852,6 +1860,7 @@ class okx extends okx$1 {
1852
1860
  'average': undefined,
1853
1861
  'baseVolume': baseVolume,
1854
1862
  'quoteVolume': quoteVolume,
1863
+ 'markPrice': this.safeString(ticker, 'markPx'),
1855
1864
  'info': ticker,
1856
1865
  }, market);
1857
1866
  }
@@ -1959,6 +1968,38 @@ class okx extends okx$1 {
1959
1968
  const tickers = this.safeList(response, 'data', []);
1960
1969
  return this.parseTickers(tickers, symbols);
1961
1970
  }
1971
+ async fetchMarkPrices(symbols = undefined, params = {}) {
1972
+ /**
1973
+ * @method
1974
+ * @name okx#fetchMarkPrices
1975
+ * @description fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1976
+ * @see https://www.okx.com/docs-v5/en/#public-data-rest-api-get-mark-price
1977
+ * @param {string[]} [symbols] unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1978
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1979
+ * @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1980
+ */
1981
+ await this.loadMarkets();
1982
+ symbols = this.marketSymbols(symbols);
1983
+ const market = this.getMarketFromSymbols(symbols);
1984
+ let marketType = undefined;
1985
+ [marketType, params] = this.handleMarketTypeAndParams('fetchTickers', market, params, 'swap');
1986
+ const request = {
1987
+ 'instType': this.convertToInstrumentType(marketType),
1988
+ };
1989
+ if (marketType === 'option') {
1990
+ const defaultUnderlying = this.safeString(this.options, 'defaultUnderlying', 'BTC-USD');
1991
+ const currencyId = this.safeString2(params, 'uly', 'marketId', defaultUnderlying);
1992
+ if (currencyId === undefined) {
1993
+ throw new errors.ArgumentsRequired(this.id + ' fetchTickers() requires an underlying uly or marketId parameter for options markets');
1994
+ }
1995
+ else {
1996
+ request['uly'] = currencyId;
1997
+ }
1998
+ }
1999
+ const response = await this.publicGetPublicMarkPrice(this.extend(request, params));
2000
+ const tickers = this.safeList(response, 'data', []);
2001
+ return this.parseTickers(tickers, symbols);
2002
+ }
1962
2003
  parseTrade(trade, market = undefined) {
1963
2004
  //
1964
2005
  // public fetchTrades
@@ -2937,7 +2978,7 @@ class okx extends okx$1 {
2937
2978
  * @param {string} [params.positionSide] if position mode is one-way: set to 'net', if position mode is hedge-mode: set to 'long' or 'short'
2938
2979
  * @param {string} [params.trailingPercent] the percent to trail away from the current market price
2939
2980
  * @param {string} [params.tpOrdKind] 'condition' or 'limit', the default is 'condition'
2940
- * @param {string} [params.hedged] true/false, to automatically set exchange-specific params needed when trading in hedge mode
2981
+ * @param {bool} [params.hedged] *swap and future only* true for hedged mode, false for one way mode
2941
2982
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2942
2983
  */
2943
2984
  await this.loadMarkets();
@@ -4825,38 +4866,30 @@ class okx extends okx$1 {
4825
4866
  * @see https://www.okx.com/docs-v5/en/#funding-account-rest-api-get-deposit-address
4826
4867
  * @param {string} code unified currency code
4827
4868
  * @param {object} [params] extra parameters specific to the exchange API endpoint
4869
+ * @param {string} [params.network] the network name for the deposit address
4828
4870
  * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure}
4829
4871
  */
4872
+ await this.loadMarkets();
4830
4873
  const rawNetwork = this.safeStringUpper(params, 'network');
4831
- const networks = this.safeValue(this.options, 'networks', {});
4832
- const network = this.safeString(networks, rawNetwork, rawNetwork);
4833
4874
  params = this.omit(params, 'network');
4875
+ code = this.safeCurrencyCode(code);
4876
+ const network = this.networkIdToCode(rawNetwork, code);
4834
4877
  const response = await this.fetchDepositAddressesByNetwork(code, params);
4835
- let result = undefined;
4836
- if (network === undefined) {
4837
- result = this.safeValue(response, code);
4878
+ if (network !== undefined) {
4879
+ const result = this.safeDict(response, network);
4838
4880
  if (result === undefined) {
4839
- const alias = this.safeString(networks, code, code);
4840
- result = this.safeValue(response, alias);
4841
- if (result === undefined) {
4842
- const defaultNetwork = this.safeString(this.options, 'defaultNetwork', 'ERC20');
4843
- result = this.safeValue(response, defaultNetwork);
4844
- if (result === undefined) {
4845
- const values = Object.values(response);
4846
- result = this.safeValue(values, 0);
4847
- if (result === undefined) {
4848
- throw new errors.InvalidAddress(this.id + ' fetchDepositAddress() cannot find deposit address for ' + code);
4849
- }
4850
- }
4851
- }
4881
+ throw new errors.InvalidAddress(this.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code);
4852
4882
  }
4853
4883
  return result;
4854
4884
  }
4855
- result = this.safeValue(response, network);
4856
- if (result === undefined) {
4857
- throw new errors.InvalidAddress(this.id + ' fetchDepositAddress() cannot find ' + network + ' deposit address for ' + code);
4885
+ const codeNetwork = this.networkIdToCode(code, code);
4886
+ if (codeNetwork in response) {
4887
+ return response[codeNetwork];
4858
4888
  }
4859
- return result;
4889
+ // if the network is not specified, return the first address
4890
+ const keys = Object.keys(response);
4891
+ const first = this.safeString(keys, 0);
4892
+ return this.safeDict(response, first);
4860
4893
  }
4861
4894
  async withdraw(code, amount, address, tag = undefined, params = {}) {
4862
4895
  /**
@@ -859,6 +859,7 @@ class oxfun extends oxfun$1 {
859
859
  'average': undefined,
860
860
  'baseVolume': this.safeString(ticker, 'currencyVolume24h'),
861
861
  'quoteVolume': undefined,
862
+ 'markPrice': this.safeString(ticker, 'markPrice'),
862
863
  'info': ticker,
863
864
  }, market);
864
865
  }
@@ -669,6 +669,7 @@ class paradex extends paradex$1 {
669
669
  'average': undefined,
670
670
  'baseVolume': undefined,
671
671
  'quoteVolume': this.safeString(ticker, 'volume_24h'),
672
+ 'markPrice': this.safeString(ticker, 'mark_price'),
672
673
  'info': ticker,
673
674
  }, market);
674
675
  }
@@ -2495,6 +2495,8 @@ class phemex extends phemex$1 {
2495
2495
  * @param {float} [params.takeProfit.triggerPrice] take profit trigger price
2496
2496
  * @param {object} [params.stopLoss] *swap only* *stopLoss object in params* containing the triggerPrice at which the attached stop loss order will be triggered (perpetual swap markets only)
2497
2497
  * @param {float} [params.stopLoss.triggerPrice] stop loss trigger price
2498
+ * @param {string} [params.posSide] *swap only* "Merged" for one way mode, "Long" for buy side of hedged mode, "Short" for sell side of hedged mode
2499
+ * @param {bool} [params.hedged] *swap only* true for hedged mode, false for one way mode, default is false
2498
2500
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2499
2501
  */
2500
2502
  await this.loadMarkets();
@@ -2596,15 +2598,22 @@ class phemex extends phemex$1 {
2596
2598
  }
2597
2599
  }
2598
2600
  else if (market['swap']) {
2601
+ const hedged = this.safeBool(params, 'hedged', false);
2602
+ params = this.omit(params, 'hedged');
2599
2603
  let posSide = this.safeStringLower(params, 'posSide');
2600
2604
  if (posSide === undefined) {
2601
- posSide = 'Merged';
2605
+ if (hedged) {
2606
+ if (reduceOnly) {
2607
+ side = (side === 'buy') ? 'sell' : 'buy';
2608
+ }
2609
+ posSide = (side === 'buy') ? 'Long' : 'Short';
2610
+ }
2611
+ else {
2612
+ posSide = 'Merged';
2613
+ }
2602
2614
  }
2603
2615
  posSide = this.capitalize(posSide);
2604
2616
  request['posSide'] = posSide;
2605
- if (reduceOnly !== undefined) {
2606
- request['reduceOnly'] = reduceOnly;
2607
- }
2608
2617
  if (market['settle'] === 'USDT') {
2609
2618
  request['orderQtyRq'] = amount;
2610
2619
  }
@@ -627,6 +627,7 @@ class poloniex extends poloniex$1 {
627
627
  'average': undefined,
628
628
  'baseVolume': this.safeString(ticker, 'quantity'),
629
629
  'quoteVolume': this.safeString(ticker, 'amount'),
630
+ 'markPrice': this.safeString(ticker, 'markPrice'),
630
631
  'info': ticker,
631
632
  }, market);
632
633
  }
@@ -36,6 +36,8 @@ class binance extends binance$1 {
36
36
  'watchPositions': true,
37
37
  'watchTicker': true,
38
38
  'watchTickers': true,
39
+ 'watchMarkPrices': true,
40
+ 'watchMarkPrice': true,
39
41
  'watchTrades': true,
40
42
  'watchTradesForSymbols': true,
41
43
  'createOrderWs': true,
@@ -152,6 +154,7 @@ class binance extends binance$1 {
152
154
  'tickerChannelsMap': {
153
155
  '24hrTicker': 'ticker',
154
156
  '24hrMiniTicker': 'miniTicker',
157
+ 'markPriceUpdate': 'markPrice',
155
158
  // rolling window tickers
156
159
  '1hTicker': 'ticker_1h',
157
160
  '4hTicker': 'ticker_4h',
@@ -1767,6 +1770,44 @@ class binance extends binance$1 {
1767
1770
  const tickers = await this.watchTickers([symbol], this.extend(params, { 'callerMethodName': 'watchTicker' }));
1768
1771
  return tickers[symbol];
1769
1772
  }
1773
+ async watchMarkPrice(symbol, params = {}) {
1774
+ /**
1775
+ * @method
1776
+ * @name binance#watchMarkPrice
1777
+ * @see https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream
1778
+ * @description watches a mark price for a specific market
1779
+ * @param {string} symbol unified symbol of the market to fetch the ticker for
1780
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1781
+ * @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
1782
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1783
+ */
1784
+ await this.loadMarkets();
1785
+ symbol = this.symbol(symbol);
1786
+ const tickers = await this.watchMarkPrices([symbol], this.extend(params, { 'callerMethodName': 'watchMarkPrice' }));
1787
+ return tickers[symbol];
1788
+ }
1789
+ async watchMarkPrices(symbols = undefined, params = {}) {
1790
+ /**
1791
+ * @method
1792
+ * @name binance#watchMarkPrices
1793
+ * @see https://developers.binance.com/docs/derivatives/usds-margined-futures/websocket-market-streams/Mark-Price-Stream-for-All-market
1794
+ * @description watches the mark price for all markets
1795
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
1796
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
1797
+ * @param {boolean} [params.use1sFreq] *default is true* if set to true, the mark price will be updated every second, otherwise every 3 seconds
1798
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
1799
+ */
1800
+ let channelName = undefined;
1801
+ // for now watchmarkPrice uses the same messageHash as watchTicker
1802
+ // so it's impossible to watch both at the same time
1803
+ // refactor this to use different messageHashes
1804
+ [channelName, params] = this.handleOptionAndParams(params, 'watchMarkPrices', 'name', 'markPrice');
1805
+ const newTickers = await this.watchMultiTickerHelper('watchMarkPrices', channelName, symbols, params);
1806
+ if (this.newUpdates) {
1807
+ return newTickers;
1808
+ }
1809
+ return this.filterByArray(this.tickers, 'symbol', symbols);
1810
+ }
1770
1811
  async watchTickers(symbols = undefined, params = {}) {
1771
1812
  /**
1772
1813
  * @method
@@ -1922,13 +1963,17 @@ class binance extends binance$1 {
1922
1963
  async watchMultiTickerHelper(methodName, channelName, symbols = undefined, params = {}) {
1923
1964
  await this.loadMarkets();
1924
1965
  symbols = this.marketSymbols(symbols, undefined, true, false, true);
1966
+ const isBidAsk = (channelName === 'bookTicker');
1967
+ const isMarkPrice = (channelName === 'markPrice');
1968
+ const use1sFreq = this.safeBool(params, 'use1sFreq', true);
1925
1969
  let firstMarket = undefined;
1926
1970
  let marketType = undefined;
1927
1971
  const symbolsDefined = (symbols !== undefined);
1928
1972
  if (symbolsDefined) {
1929
1973
  firstMarket = this.market(symbols[0]);
1930
1974
  }
1931
- [marketType, params] = this.handleMarketTypeAndParams(methodName, firstMarket, params);
1975
+ const defaultMarket = (isMarkPrice) ? 'swap' : 'spot';
1976
+ [marketType, params] = this.handleMarketTypeAndParams(methodName, firstMarket, params, defaultMarket);
1932
1977
  let subType = undefined;
1933
1978
  [subType, params] = this.handleSubTypeAndParams(methodName, firstMarket, params);
1934
1979
  let rawMarketType = undefined;
@@ -1944,14 +1989,17 @@ class binance extends binance$1 {
1944
1989
  else {
1945
1990
  throw new errors.NotSupported(this.id + ' ' + methodName + '() does not support options markets');
1946
1991
  }
1947
- const isBidAsk = (channelName === 'bookTicker');
1948
1992
  const subscriptionArgs = [];
1949
1993
  const messageHashes = [];
1994
+ let suffix = '';
1995
+ if (isMarkPrice) {
1996
+ suffix = (use1sFreq) ? '@1s' : '';
1997
+ }
1950
1998
  if (symbolsDefined) {
1951
1999
  for (let i = 0; i < symbols.length; i++) {
1952
2000
  const symbol = symbols[i];
1953
2001
  const market = this.market(symbol);
1954
- subscriptionArgs.push(market['lowercaseId'] + '@' + channelName);
2002
+ subscriptionArgs.push(market['lowercaseId'] + '@' + channelName + suffix);
1955
2003
  messageHashes.push(this.getMessageHash(channelName, market['symbol'], isBidAsk));
1956
2004
  }
1957
2005
  }
@@ -1962,6 +2010,9 @@ class binance extends binance$1 {
1962
2010
  }
1963
2011
  subscriptionArgs.push('!' + channelName);
1964
2012
  }
2013
+ else if (isMarkPrice) {
2014
+ subscriptionArgs.push('!' + channelName + '@arr' + suffix);
2015
+ }
1965
2016
  else {
1966
2017
  subscriptionArgs.push('!' + channelName + '@arr');
1967
2018
  }
@@ -1994,6 +2045,17 @@ class binance extends binance$1 {
1994
2045
  }
1995
2046
  }
1996
2047
  parseWsTicker(message, marketType) {
2048
+ // markPrice
2049
+ // {
2050
+ // "e": "markPriceUpdate", // Event type
2051
+ // "E": 1562305380000, // Event time
2052
+ // "s": "BTCUSDT", // Symbol
2053
+ // "p": "11794.15000000", // Mark price
2054
+ // "i": "11784.62659091", // Index price
2055
+ // "P": "11784.25641265", // Estimated Settle Price, only useful in the last hour before the settlement starts
2056
+ // "r": "0.00038167", // Funding rate
2057
+ // "T": 1562306400000 // Next funding time
2058
+ // }
1997
2059
  //
1998
2060
  // ticker
1999
2061
  // {
@@ -2051,10 +2113,23 @@ class binance extends binance$1 {
2051
2113
  // "time":1589437530011,
2052
2114
  // }
2053
2115
  //
2116
+ const marketId = this.safeString2(message, 's', 'symbol');
2117
+ const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
2054
2118
  let event = this.safeString(message, 'e', 'bookTicker');
2055
2119
  if (event === '24hrTicker') {
2056
2120
  event = 'ticker';
2057
2121
  }
2122
+ if (event === 'markPriceUpdate') {
2123
+ // handle this separately because some fields clash with the ticker fields
2124
+ return this.safeTicker({
2125
+ 'symbol': symbol,
2126
+ 'timestamp': this.safeInteger(message, 'E'),
2127
+ 'datetime': this.iso8601(this.safeInteger(message, 'E')),
2128
+ 'info': message,
2129
+ 'markPrice': this.safeString(message, 'p'),
2130
+ 'indexPrice': this.safeString(message, 'i'),
2131
+ });
2132
+ }
2058
2133
  let timestamp = undefined;
2059
2134
  if (event === 'bookTicker') {
2060
2135
  // take the event timestamp, if available, for spot tickers it is not
@@ -2064,8 +2139,6 @@ class binance extends binance$1 {
2064
2139
  // take the timestamp of the closing price for candlestick streams
2065
2140
  timestamp = this.safeIntegerN(message, ['C', 'E', 'time']);
2066
2141
  }
2067
- const marketId = this.safeString2(message, 's', 'symbol');
2068
- const symbol = this.safeSymbol(marketId, undefined, undefined, marketType);
2069
2142
  const market = this.safeMarket(marketId, undefined, undefined, marketType);
2070
2143
  const last = this.safeString2(message, 'c', 'price');
2071
2144
  return this.safeTicker({
@@ -4234,6 +4307,8 @@ class binance extends binance$1 {
4234
4307
  '1dTicker': this.handleTickers,
4235
4308
  '24hrTicker': this.handleTickers,
4236
4309
  '24hrMiniTicker': this.handleTickers,
4310
+ 'markPriceUpdate': this.handleTickers,
4311
+ 'markPriceUpdate@arr': this.handleTickers,
4237
4312
  'bookTicker': this.handleBidsAsks,
4238
4313
  'outboundAccountPosition': this.handleBalance,
4239
4314
  'balanceUpdate': this.handleBalance,
@@ -221,15 +221,15 @@ class bitfinex extends bitfinex$1 {
221
221
  if ((last !== undefined) && (change !== undefined)) {
222
222
  open = Precise["default"].stringSub(last, change);
223
223
  }
224
- const result = {
224
+ const result = this.safeTicker({
225
225
  'symbol': symbol,
226
226
  'timestamp': undefined,
227
227
  'datetime': undefined,
228
- 'high': this.safeFloat(message, 9),
229
- 'low': this.safeFloat(message, 10),
230
- 'bid': this.safeFloat(message, 1),
228
+ 'high': this.safeString(message, 9),
229
+ 'low': this.safeString(message, 10),
230
+ 'bid': this.safeString(message, 1),
231
231
  'bidVolume': undefined,
232
- 'ask': this.safeFloat(message, 3),
232
+ 'ask': this.safeString(message, 3),
233
233
  'askVolume': undefined,
234
234
  'vwap': undefined,
235
235
  'open': this.parseNumber(open),
@@ -237,12 +237,12 @@ class bitfinex extends bitfinex$1 {
237
237
  'last': this.parseNumber(last),
238
238
  'previousClose': undefined,
239
239
  'change': this.parseNumber(change),
240
- 'percentage': this.safeFloat(message, 6),
240
+ 'percentage': this.safeString(message, 6),
241
241
  'average': undefined,
242
- 'baseVolume': this.safeFloat(message, 8),
242
+ 'baseVolume': this.safeString(message, 8),
243
243
  'quoteVolume': undefined,
244
244
  'info': message,
245
- };
245
+ });
246
246
  this.tickers[symbol] = result;
247
247
  client.resolve(result, messageHash);
248
248
  }
@@ -1062,6 +1062,8 @@ class krakenfutures extends krakenfutures$1 {
1062
1062
  'average': undefined,
1063
1063
  'baseVolume': this.safeString(ticker, 'volume'),
1064
1064
  'quoteVolume': this.safeString(ticker, 'volumeQuote'),
1065
+ 'markPrice': this.safeString(ticker, 'markPrice'),
1066
+ 'indexPrice': this.safeString(ticker, 'index'),
1065
1067
  });
1066
1068
  }
1067
1069
  handleOrderBookSnapshot(client, message) {
@@ -131,6 +131,8 @@ class phemex extends phemex$1 {
131
131
  'average': average,
132
132
  'baseVolume': baseVolume,
133
133
  'quoteVolume': quoteVolume,
134
+ 'markPrice': this.parseNumber(this.fromEp(this.safeString(ticker, 'markPrice'), market)),
135
+ 'indexPrice': this.parseNumber(this.fromEp(this.safeString(ticker, 'indexPrice'), market)),
134
136
  'info': ticker,
135
137
  };
136
138
  return result;
@@ -20,6 +20,7 @@ class woo extends woo$1 {
20
20
  'watchOrders': true,
21
21
  'watchTicker': true,
22
22
  'watchTickers': true,
23
+ 'watchBidsAsks': true,
23
24
  'watchTrades': true,
24
25
  'watchTradesForSymbols': false,
25
26
  'watchPositions': true,
@@ -401,6 +402,77 @@ class woo extends woo$1 {
401
402
  }
402
403
  client.resolve(result, topic);
403
404
  }
405
+ async watchBidsAsks(symbols = undefined, params = {}) {
406
+ /**
407
+ * @method
408
+ * @name woo#watchBidsAsks
409
+ * @see https://docs.woox.io/#bbos
410
+ * @description watches best bid & ask for symbols
411
+ * @param {string[]} symbols unified symbol of the market to fetch the ticker for
412
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
413
+ * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
414
+ */
415
+ await this.loadMarkets();
416
+ symbols = this.marketSymbols(symbols, undefined, false);
417
+ const name = 'bbos';
418
+ const topic = name;
419
+ const request = {
420
+ 'event': 'subscribe',
421
+ 'topic': topic,
422
+ };
423
+ const message = this.extend(request, params);
424
+ const tickers = await this.watchPublic(topic, message);
425
+ if (this.newUpdates) {
426
+ return tickers;
427
+ }
428
+ return this.filterByArray(this.bidsasks, 'symbol', symbols);
429
+ }
430
+ handleBidAsk(client, message) {
431
+ //
432
+ // {
433
+ // "topic": "bbos",
434
+ // "ts": 1618822376000,
435
+ // "data": [
436
+ // {
437
+ // "symbol": "SPOT_FIL_USDT",
438
+ // "ask": 159.0318,
439
+ // "askSize": 370.43,
440
+ // "bid": 158.9158,
441
+ // "bidSize": 16
442
+ // }
443
+ // ]
444
+ // }
445
+ //
446
+ const topic = this.safeString(message, 'topic');
447
+ const data = this.safeList(message, 'data', []);
448
+ const timestamp = this.safeInteger(message, 'ts');
449
+ const result = {};
450
+ for (let i = 0; i < data.length; i++) {
451
+ const ticker = this.safeDict(data, i);
452
+ ticker['ts'] = timestamp;
453
+ const parsedTicker = this.parseWsBidAsk(ticker);
454
+ const symbol = parsedTicker['symbol'];
455
+ this.bidsasks[symbol] = parsedTicker;
456
+ result[symbol] = parsedTicker;
457
+ }
458
+ client.resolve(result, topic);
459
+ }
460
+ parseWsBidAsk(ticker, market = undefined) {
461
+ const marketId = this.safeString(ticker, 'symbol');
462
+ market = this.safeMarket(marketId, market);
463
+ const symbol = this.safeString(market, 'symbol');
464
+ const timestamp = this.safeInteger(ticker, 'ts');
465
+ return this.safeTicker({
466
+ 'symbol': symbol,
467
+ 'timestamp': timestamp,
468
+ 'datetime': this.iso8601(timestamp),
469
+ 'ask': this.safeString(ticker, 'ask'),
470
+ 'askVolume': this.safeString(ticker, 'askSize'),
471
+ 'bid': this.safeString(ticker, 'bid'),
472
+ 'bidVolume': this.safeString(ticker, 'bidSize'),
473
+ 'info': ticker,
474
+ }, market);
475
+ }
404
476
  async watchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
405
477
  /**
406
478
  * @method
@@ -1181,6 +1253,7 @@ class woo extends woo$1 {
1181
1253
  'trade': this.handleTrade,
1182
1254
  'balance': this.handleBalance,
1183
1255
  'position': this.handlePositions,
1256
+ 'bbos': this.handleBidAsk,
1184
1257
  };
1185
1258
  const event = this.safeString(message, 'event');
1186
1259
  let method = this.safeValue(methods, event);
@@ -145,6 +145,8 @@ python path/to/example.py # substitute for actual filename here
145
145
 
146
146
  [How to make your own trading bot](https://codeburst.io/how-to-make-your-own-trading-bot-83b5c6e35036) – A tutorial on algortrading in Python.
147
147
 
148
+ [Comprehensive Cryptocurrency Trading Utility with ccxt: Real-time and Historical Data Analysis](https://medium.com/@deepml1818/comprehensive-cryptocurrency-trading-utility-with-ccxt-real-time-and-historical-data-analysis-6b9cbba57375) – A tutorial on technical analysis with CCXT.
149
+
148
150
  [Writing crypto trading bot in Python with Telegram and ccxt](https://medium.com/@maxAvdyushkin/writing-crypto-trading-bot-in-python-with-telegram-and-ccxt-80632a00c637) – A tutorial on programming a Telegram bot in Python with CCXT
149
151
 
150
152
  [Data science is eating the world — Here’s how you can start exploring it](https://medium.com/covee-network/data-science-is-eating-the-world-heres-how-you-can-start-exploring-it-37501414af15) – An article on collecting and analyzing financial big data.
@@ -197,6 +199,8 @@ python path/to/example.py # substitute for actual filename here
197
199
 
198
200
  [CryptoCurrency eXchange Trading library - CCXT](https://barbotine.medium.com/crypto-currency-exchange-trading-library-ccxt-34ed66ebede8) – An overview of CCXT.
199
201
 
202
+ [Simplifying Trading Automation with CCXT](https://j4nt4ncrypto.medium.com/simplifying-trading-automation-with-ccxt-creating-orders-and-fetching-positions-on-kucoin-futures-d42c329577de) – Creating Orders and Fetching Positions on Kucoin Futures.
203
+
200
204
  [https://python.plainenglish.io/cryptocurrency-trading-with-python-5f655d06a4bd](Cryptocurrency Trading with Python) – How to trade cryptocurrencies with CCXT in Python.
201
205
 
202
206
  [비트코인 해외 거래소 API - 바이낸스 CCXT설치](https://www.youtube.com/watch?v=7dMGbjwZwlU) – Using CCXT to trade with Binance API, a video overview of CCXT in Korean.
package/js/ccxt.d.ts CHANGED
@@ -4,7 +4,7 @@ import * as functions from './src/base/functions.js';
4
4
  import * as errors from './src/base/errors.js';
5
5
  import type { Int, int, Str, Strings, Num, Bool, IndexType, OrderSide, OrderType, MarketType, SubType, Dict, NullableDict, List, NullableList, Fee, OHLCV, OHLCVC, implicitReturnType, Market, Currency, Dictionary, MinMax, FeeInterface, TradingFeeInterface, MarketInterface, Trade, Order, OrderBook, Ticker, Transaction, Tickers, CurrencyInterface, Balance, BalanceAccount, Account, PartialBalances, Balances, DepositAddress, WithdrawalResponse, DepositAddressResponse, FundingRate, FundingRates, Position, BorrowInterest, LeverageTier, LedgerEntry, DepositWithdrawFeeNetwork, DepositWithdrawFee, TransferEntry, CrossBorrowRate, IsolatedBorrowRate, FundingRateHistory, OpenInterest, Liquidation, OrderRequest, CancellationRequest, FundingHistory, MarketMarginModes, MarginMode, Greeks, Conversion, Option, LastPrice, Leverage, MarginModification, Leverages, LastPrices, Currencies, TradingFees, MarginModes, OptionChain, IsolatedBorrowRates, CrossBorrowRates, LeverageTiers } from './src/base/types.js';
6
6
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError } from './src/base/errors.js';
7
- declare const version = "4.4.10";
7
+ declare const version = "4.4.12";
8
8
  import ace from './src/ace.js';
9
9
  import alpaca from './src/alpaca.js';
10
10
  import ascendex from './src/ascendex.js';
package/js/ccxt.js CHANGED
@@ -38,7 +38,7 @@ import * as errors from './src/base/errors.js';
38
38
  import { BaseError, ExchangeError, AuthenticationError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, OperationRejected, NoChange, MarginModeAlreadySet, MarketClosed, ManualInteractionNeeded, InsufficientFunds, InvalidAddress, AddressPending, InvalidOrder, OrderNotFound, OrderNotCached, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, ContractUnavailable, NotSupported, InvalidProxySettings, ExchangeClosedByUser, OperationFailed, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, ChecksumError, RequestTimeout, BadResponse, NullResponse, CancelPending, UnsubscribeError } from './src/base/errors.js';
39
39
  //-----------------------------------------------------------------------------
40
40
  // this is updated by vss.js when building
41
- const version = '4.4.11';
41
+ const version = '4.4.13';
42
42
  Exchange.ccxtVersion = version;
43
43
  //-----------------------------------------------------------------------------
44
44
  import ace from './src/ace.js';
@@ -555,6 +555,7 @@ export default class Exchange {
555
555
  fetchTicker: boolean;
556
556
  fetchTickerWs: any;
557
557
  fetchTickers: any;
558
+ fetchMarkPrices: any;
558
559
  fetchTickersWs: any;
559
560
  fetchTime: any;
560
561
  fetchTrades: boolean;
@@ -967,6 +968,7 @@ export default class Exchange {
967
968
  fetchTickerWs(symbol: string, params?: {}): Promise<Ticker>;
968
969
  watchTicker(symbol: string, params?: {}): Promise<Ticker>;
969
970
  fetchTickers(symbols?: Strings, params?: {}): Promise<Tickers>;
971
+ fetchMarkPrices(symbols?: Strings, params?: {}): Promise<Tickers>;
970
972
  fetchTickersWs(symbols?: Strings, params?: {}): Promise<Tickers>;
971
973
  fetchOrderBooks(symbols?: Strings, limit?: Int, params?: {}): Promise<Dictionary<OrderBook>>;
972
974
  watchBidsAsks(symbols?: Strings, params?: {}): Promise<Tickers>;
@@ -1443,6 +1443,7 @@ export default class Exchange {
1443
1443
  'fetchTicker': true,
1444
1444
  'fetchTickerWs': undefined,
1445
1445
  'fetchTickers': undefined,
1446
+ 'fetchMarkPrices': undefined,
1446
1447
  'fetchTickersWs': undefined,
1447
1448
  'fetchTime': undefined,
1448
1449
  'fetchTrades': true,
@@ -3197,6 +3198,8 @@ export default class Exchange {
3197
3198
  'baseVolume': this.parseNumber(baseVolume),
3198
3199
  'quoteVolume': this.parseNumber(quoteVolume),
3199
3200
  'previousClose': this.safeNumber(ticker, 'previousClose'),
3201
+ 'indexPrice': this.safeNumber(ticker, 'indexPrice'),
3202
+ 'markPrice': this.safeNumber(ticker, 'markPrice'),
3200
3203
  });
3201
3204
  }
3202
3205
  async fetchBorrowRate(code, amount, params = {}) {
@@ -4421,6 +4424,9 @@ export default class Exchange {
4421
4424
  async fetchTickers(symbols = undefined, params = {}) {
4422
4425
  throw new NotSupported(this.id + ' fetchTickers() is not supported yet');
4423
4426
  }
4427
+ async fetchMarkPrices(symbols = undefined, params = {}) {
4428
+ throw new NotSupported(this.id + ' fetchMarkPrices() is not supported yet');
4429
+ }
4424
4430
  async fetchTickersWs(symbols = undefined, params = {}) {
4425
4431
  throw new NotSupported(this.id + ' fetchTickers() is not supported yet');
4426
4432
  }
@@ -144,22 +144,24 @@ export interface Ticker {
144
144
  info: any;
145
145
  timestamp: Int;
146
146
  datetime: Str;
147
- high: Int;
148
- low: Int;
149
- bid: Int;
150
- bidVolume: Int;
151
- ask: Int;
152
- askVolume: Int;
153
- vwap: Int;
154
- open: Int;
155
- close: Int;
156
- last: Int;
157
- previousClose: Int;
158
- change: Int;
159
- percentage: Int;
160
- average: Int;
161
- quoteVolume: Int;
162
- baseVolume: Int;
147
+ high: Num;
148
+ low: Num;
149
+ bid: Num;
150
+ bidVolume: Num;
151
+ ask: Num;
152
+ askVolume: Num;
153
+ vwap: Num;
154
+ open: Num;
155
+ close: Num;
156
+ last: Num;
157
+ previousClose: Num;
158
+ change: Num;
159
+ percentage: Num;
160
+ average: Num;
161
+ quoteVolume: Num;
162
+ baseVolume: Num;
163
+ indexPrice: Num;
164
+ markPrice: Num;
163
165
  }
164
166
  export interface Transaction {
165
167
  info: any;