ccxt 4.2.4 → 4.2.6

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.
package/dist/cjs/ccxt.js CHANGED
@@ -169,7 +169,7 @@ var woo$1 = require('./src/pro/woo.js');
169
169
 
170
170
  //-----------------------------------------------------------------------------
171
171
  // this is updated by vss.js when building
172
- const version = '4.2.4';
172
+ const version = '4.2.6';
173
173
  Exchange["default"].ccxtVersion = version;
174
174
  const exchanges = {
175
175
  'ace': ace,
@@ -349,10 +349,16 @@ class alpaca extends alpaca$1 {
349
349
  //
350
350
  const marketId = this.safeString(asset, 'symbol');
351
351
  const parts = marketId.split('/');
352
+ const assetClass = this.safeString(asset, 'class');
352
353
  const baseId = this.safeString(parts, 0);
353
354
  const quoteId = this.safeString(parts, 1);
354
355
  const base = this.safeCurrencyCode(baseId);
355
- const quote = this.safeCurrencyCode(quoteId);
356
+ let quote = this.safeCurrencyCode(quoteId);
357
+ // Us equity markets do not include quote in symbol.
358
+ // We can safely coerce us_equity quote to USD
359
+ if (quote === undefined && assetClass === 'us_equity') {
360
+ quote = 'USD';
361
+ }
356
362
  const symbol = base + '/' + quote;
357
363
  const status = this.safeString(asset, 'status');
358
364
  const active = (status === 'active');
@@ -1231,10 +1231,15 @@ class Exchange {
1231
1231
  const closedClients = [];
1232
1232
  for (let i = 0; i < clients.length; i++) {
1233
1233
  const client = clients[i];
1234
- delete this.clients[client.url];
1234
+ client.error = new errors.ExchangeClosedByUser(this.id + ' closedByUser');
1235
1235
  closedClients.push(client.close());
1236
1236
  }
1237
- return Promise.all(closedClients);
1237
+ await Promise.all(closedClients);
1238
+ for (let i = 0; i < clients.length; i++) {
1239
+ const client = clients[i];
1240
+ delete this.clients[client.url];
1241
+ }
1242
+ return;
1238
1243
  }
1239
1244
  async loadOrderBook(client, messageHash, symbol, limit = undefined, params = {}) {
1240
1245
  if (!(symbol in this.orderbooks)) {
@@ -46,6 +46,12 @@ class ExchangeError extends Error {
46
46
  this.name = 'ExchangeError';
47
47
  }
48
48
  }
49
+ class ExchangeClosedByUser extends Error {
50
+ constructor(message) {
51
+ super(message);
52
+ this.name = 'ExchangeClosedByUser';
53
+ }
54
+ }
49
55
  class AuthenticationError extends ExchangeError {
50
56
  constructor(message) {
51
57
  super(message);
@@ -252,7 +258,7 @@ class RequestTimeout extends NetworkError {
252
258
  // // Derived class hierarchy
253
259
  // errorHierarchy
254
260
  // )
255
- const errors = { BaseError, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
261
+ const errors = { BaseError, ExchangeClosedByUser, ExchangeError, PermissionDenied, AccountNotEnabled, AccountSuspended, ArgumentsRequired, BadRequest, BadSymbol, MarginModeAlreadySet, BadResponse, NullResponse, InsufficientFunds, InvalidAddress, InvalidOrder, OrderNotFound, OrderNotCached, CancelPending, OrderImmediatelyFillable, OrderNotFillable, DuplicateOrderId, NotSupported, NetworkError, DDoSProtection, RateLimitExceeded, ExchangeNotAvailable, OnMaintenance, InvalidNonce, RequestTimeout, AuthenticationError, AddressPending, ContractUnavailable, NoChange, OperationRejected, OperationFailed, ProxyError };
256
262
 
257
263
  exports.AccountNotEnabled = AccountNotEnabled;
258
264
  exports.AccountSuspended = AccountSuspended;
@@ -267,6 +273,7 @@ exports.CancelPending = CancelPending;
267
273
  exports.ContractUnavailable = ContractUnavailable;
268
274
  exports.DDoSProtection = DDoSProtection;
269
275
  exports.DuplicateOrderId = DuplicateOrderId;
276
+ exports.ExchangeClosedByUser = ExchangeClosedByUser;
270
277
  exports.ExchangeError = ExchangeError;
271
278
  exports.ExchangeNotAvailable = ExchangeNotAvailable;
272
279
  exports.InsufficientFunds = InsufficientFunds;
@@ -209,6 +209,9 @@ class Client {
209
209
  // todo: exception types for server-side disconnects
210
210
  this.reset(new errors.NetworkError('connection closed by remote server, closing code ' + String(event.code)));
211
211
  }
212
+ if (this.error instanceof errors.ExchangeClosedByUser) {
213
+ this.reset(this.error);
214
+ }
212
215
  if (this.disconnected !== undefined) {
213
216
  this.disconnected.resolve(true);
214
217
  }
@@ -229,6 +232,7 @@ class Client {
229
232
  const future = Future.Future();
230
233
  if (platform.isNode) {
231
234
  /* eslint-disable no-inner-declarations */
235
+ /* eslint-disable jsdoc/require-jsdoc */
232
236
  function onSendComplete(error) {
233
237
  if (error) {
234
238
  future.reject(error);
@@ -1331,18 +1331,11 @@ class bingx extends bingx$1 {
1331
1331
  const close = this.safeString(ticker, 'lastPrice');
1332
1332
  const quoteVolume = this.safeString(ticker, 'quoteVolume');
1333
1333
  const baseVolume = this.safeString(ticker, 'volume');
1334
- let percentage = undefined;
1335
- let change = undefined;
1336
- if (market['swap']) {
1337
- // right now only swap uses the 24h change, spot will be added soon
1338
- percentage = this.safeString(ticker, 'priceChangePercent');
1339
- change = this.safeString(ticker, 'priceChange');
1340
- }
1341
- // let percentage = this.safeString (ticker, 'priceChangePercent');
1342
- // if (percentage !== undefined) {
1343
- // percentage = percentage.replace ('%', '');
1344
- // } similarly to change, it's not ccxt's percentage because it does priceChange/open, and priceChange is high-low
1345
- // const change = this.safeString (ticker, 'priceChange'); // this is not ccxt's change because it does high-low instead of last-open
1334
+ let percentage = this.safeString(ticker, 'priceChangePercent');
1335
+ if (percentage !== undefined) {
1336
+ percentage = percentage.replace('%', '');
1337
+ }
1338
+ const change = this.safeString(ticker, 'priceChange');
1346
1339
  const ts = this.safeInteger(ticker, 'closeTime');
1347
1340
  const datetime = this.iso8601(ts);
1348
1341
  const bid = this.safeString(ticker, 'bidPrice');
@@ -1671,6 +1664,11 @@ class bingx extends bingx$1 {
1671
1664
  };
1672
1665
  const isMarketOrder = type === 'MARKET';
1673
1666
  const isSpot = marketType === 'spot';
1667
+ const exchangeClientOrderId = isSpot ? 'newClientOrderId' : 'clientOrderID';
1668
+ const clientOrderId = this.safeString2(params, exchangeClientOrderId, 'clientOrderId');
1669
+ if (clientOrderId !== undefined) {
1670
+ request[exchangeClientOrderId] = clientOrderId;
1671
+ }
1674
1672
  const timeInForce = this.safeStringUpper(params, 'timeInForce');
1675
1673
  if (timeInForce === 'IOC') {
1676
1674
  request['timeInForce'] = 'IOC';
@@ -1815,7 +1813,7 @@ class bingx extends bingx$1 {
1815
1813
  }
1816
1814
  request['positionSide'] = positionSide;
1817
1815
  request['quantity'] = this.parseToNumeric(this.amountToPrecision(symbol, amount));
1818
- params = this.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'takeProfit', 'stopLoss']);
1816
+ params = this.omit(params, ['reduceOnly', 'triggerPrice', 'stopLossPrice', 'takeProfitPrice', 'trailingAmount', 'trailingPercent', 'takeProfit', 'stopLoss', 'clientOrderId']);
1819
1817
  }
1820
1818
  return this.extend(request, params);
1821
1819
  }
@@ -1832,6 +1830,7 @@ class bingx extends bingx$1 {
1832
1830
  * @param {float} amount how much you want to trade in units of the base currency
1833
1831
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1834
1832
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1833
+ * @param {string} [params.clientOrderId] a unique id for the order
1835
1834
  * @param {bool} [params.postOnly] true to place a post only order
1836
1835
  * @param {string} [params.timeInForce] spot supports 'PO' and 'IOC', swap supports 'PO', 'GTC', 'IOC' and 'FOK'
1837
1836
  * @param {bool} [params.reduceOnly] *swap only* true or false whether the order is reduce only
@@ -1896,7 +1895,7 @@ class bingx extends bingx$1 {
1896
1895
  // }
1897
1896
  //
1898
1897
  if (typeof response === 'string') {
1899
- response = JSON.parse(response);
1898
+ response = this.parseJson(response);
1900
1899
  }
1901
1900
  const data = this.safeValue(response, 'data', {});
1902
1901
  const order = this.safeValue(data, 'order', data);
@@ -2157,7 +2156,7 @@ class bingx extends bingx$1 {
2157
2156
  'currency': feeCurrencyCode,
2158
2157
  'cost': Precise["default"].stringAbs(feeCost),
2159
2158
  };
2160
- const clientOrderId = this.safeString2(order, 'clientOrderId', 'c');
2159
+ const clientOrderId = this.safeStringN(order, ['clientOrderID', 'origClientOrderId', 'c']);
2161
2160
  let stopLoss = this.safeValue(order, 'stopLoss');
2162
2161
  let stopLossPrice = undefined;
2163
2162
  if (stopLoss !== undefined) {
@@ -2166,7 +2165,7 @@ class bingx extends bingx$1 {
2166
2165
  if ((stopLoss !== undefined) && (typeof stopLoss !== 'number')) {
2167
2166
  // stopLoss: '{"stopPrice":50,"workingType":"MARK_PRICE","type":"STOP_MARKET","quantity":1}',
2168
2167
  if (typeof stopLoss === 'string') {
2169
- stopLoss = JSON.parse(stopLoss);
2168
+ stopLoss = this.parseJson(stopLoss);
2170
2169
  }
2171
2170
  stopLossPrice = this.safeNumber(stopLoss, 'stopPrice');
2172
2171
  }
@@ -2178,7 +2177,7 @@ class bingx extends bingx$1 {
2178
2177
  if ((takeProfit !== undefined) && (typeof takeProfit !== 'number')) {
2179
2178
  // takeProfit: '{"stopPrice":150,"workingType":"MARK_PRICE","type":"TAKE_PROFIT_MARKET","quantity":1}',
2180
2179
  if (typeof takeProfit === 'string') {
2181
- takeProfit = JSON.parse(takeProfit);
2180
+ takeProfit = this.parseJson(takeProfit);
2182
2181
  }
2183
2182
  takeProfitPrice = this.safeNumber(takeProfit, 'stopPrice');
2184
2183
  }
@@ -2232,6 +2231,7 @@ class bingx extends bingx$1 {
2232
2231
  * @param {string} id order id
2233
2232
  * @param {string} symbol unified symbol of the market the order was made in
2234
2233
  * @param {object} [params] extra parameters specific to the exchange API endpoint
2234
+ * @param {string} [params.clientOrderId] a unique id for the order
2235
2235
  * @returns {object} An [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
2236
2236
  */
2237
2237
  if (symbol === undefined) {
@@ -2241,8 +2241,15 @@ class bingx extends bingx$1 {
2241
2241
  const market = this.market(symbol);
2242
2242
  const request = {
2243
2243
  'symbol': market['id'],
2244
- 'orderId': id,
2245
2244
  };
2245
+ const clientOrderId = this.safeString2(params, 'clientOrderId', 'clientOrderID');
2246
+ params = this.omit(params, ['clientOrderId']);
2247
+ if (clientOrderId !== undefined) {
2248
+ request['clientOrderID'] = clientOrderId;
2249
+ }
2250
+ else {
2251
+ request['orderId'] = id;
2252
+ }
2246
2253
  let response = undefined;
2247
2254
  const [marketType, query] = this.handleMarketTypeAndParams('cancelOrder', market, params);
2248
2255
  if (marketType === 'spot') {
@@ -2418,7 +2425,7 @@ class bingx extends bingx$1 {
2418
2425
  }
2419
2426
  let response = undefined;
2420
2427
  if (market['spot']) {
2421
- const spotReqKey = areClientOrderIds ? 'clientOrderIds' : 'orderIds';
2428
+ const spotReqKey = areClientOrderIds ? 'clientOrderIDs' : 'orderIds';
2422
2429
  request[spotReqKey] = parsedIds.join(',');
2423
2430
  response = await this.spotV1PrivatePostTradeCancelOrders(this.extend(request, params));
2424
2431
  }
@@ -1827,14 +1827,15 @@ class bitmex extends bitmex$1 {
1827
1827
  * @param {object} [params] extra parameters specific to the exchange API endpoint
1828
1828
  * @param {object} [params.triggerPrice] the price at which a trigger order is triggered at
1829
1829
  * @param {object} [params.triggerDirection] the direction whenever the trigger happens with relation to price - 'above' or 'below'
1830
+ * @param {float} [params.trailingAmount] the quote amount to trail away from the current market price
1830
1831
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1831
1832
  */
1832
1833
  await this.loadMarkets();
1833
1834
  const market = this.market(symbol);
1834
- const orderType = this.capitalize(type);
1835
+ let orderType = this.capitalize(type);
1835
1836
  const reduceOnly = this.safeValue(params, 'reduceOnly');
1836
1837
  if (reduceOnly !== undefined) {
1837
- if ((market['type'] !== 'swap') && (market['type'] !== 'future')) {
1838
+ if ((!market['swap']) && (!market['future'])) {
1838
1839
  throw new errors.InvalidOrder(this.id + ' createOrder() does not support reduceOnly for ' + market['type'] + ' orders, reduceOnly orders are supported for swap and future markets only');
1839
1840
  }
1840
1841
  }
@@ -1847,44 +1848,54 @@ class bitmex extends bitmex$1 {
1847
1848
  'ordType': orderType,
1848
1849
  'text': brokerId,
1849
1850
  };
1850
- const customTriggerType = (orderType === 'Stop') || (orderType === 'StopLimit') || (orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched');
1851
1851
  // support for unified trigger format
1852
1852
  const triggerPrice = this.safeNumberN(params, ['triggerPrice', 'stopPx', 'stopPrice']);
1853
- if ((triggerPrice !== undefined) && !customTriggerType) {
1854
- request['stopPx'] = parseFloat(this.priceToPrecision(symbol, triggerPrice));
1853
+ let trailingAmount = this.safeString2(params, 'trailingAmount', 'pegOffsetValue');
1854
+ const isTriggerOrder = triggerPrice !== undefined;
1855
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1856
+ if (isTriggerOrder || isTrailingAmountOrder) {
1855
1857
  const triggerDirection = this.safeString(params, 'triggerDirection');
1856
- params = this.omit(params, ['triggerPrice', 'stopPrice', 'stopPx', 'triggerDirection']);
1857
1858
  const triggerAbove = (triggerDirection === 'above');
1858
- this.checkRequiredArgument('createOrder', triggerDirection, 'triggerDirection', ['above', 'below']);
1859
- this.checkRequiredArgument('createOrder', side, 'side', ['buy', 'sell']);
1859
+ if ((type === 'limit') || (type === 'market')) {
1860
+ this.checkRequiredArgument('createOrder', triggerDirection, 'triggerDirection', ['above', 'below']);
1861
+ }
1860
1862
  if (type === 'limit') {
1861
- request['price'] = parseFloat(this.priceToPrecision(symbol, price));
1862
1863
  if (side === 'buy') {
1863
- request['ordType'] = triggerAbove ? 'StopLimit' : 'LimitIfTouched';
1864
+ orderType = triggerAbove ? 'StopLimit' : 'LimitIfTouched';
1864
1865
  }
1865
1866
  else {
1866
- request['ordType'] = triggerAbove ? 'LimitIfTouched' : 'StopLimit';
1867
+ orderType = triggerAbove ? 'LimitIfTouched' : 'StopLimit';
1867
1868
  }
1868
1869
  }
1869
1870
  else if (type === 'market') {
1870
1871
  if (side === 'buy') {
1871
- request['ordType'] = triggerAbove ? 'Stop' : 'MarketIfTouched';
1872
+ orderType = triggerAbove ? 'Stop' : 'MarketIfTouched';
1872
1873
  }
1873
1874
  else {
1874
- request['ordType'] = triggerAbove ? 'MarketIfTouched' : 'Stop';
1875
+ orderType = triggerAbove ? 'MarketIfTouched' : 'Stop';
1875
1876
  }
1876
1877
  }
1877
- }
1878
- else if (customTriggerType) {
1879
- if (triggerPrice === undefined) {
1880
- // if exchange specific trigger types were provided
1881
- throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a triggerPrice (stopPx|stopPrice) parameter for the ' + orderType + ' order type');
1878
+ if (isTrailingAmountOrder) {
1879
+ const isStopSellOrder = (side === 'sell') && ((orderType === 'Stop') || (orderType === 'StopLimit'));
1880
+ const isBuyIfTouchedOrder = (side === 'buy') && ((orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched'));
1881
+ if (isStopSellOrder || isBuyIfTouchedOrder) {
1882
+ trailingAmount = '-' + trailingAmount;
1883
+ }
1884
+ request['pegOffsetValue'] = this.parseToNumeric(trailingAmount);
1885
+ request['pegPriceType'] = 'TrailingStopPeg';
1886
+ }
1887
+ else {
1888
+ if (triggerPrice === undefined) {
1889
+ // if exchange specific trigger types were provided
1890
+ throw new errors.ArgumentsRequired(this.id + ' createOrder() requires a triggerPrice (stopPx|stopPrice) parameter for the ' + orderType + ' order type');
1891
+ }
1892
+ request['stopPx'] = this.parseToNumeric(this.priceToPrecision(symbol, triggerPrice));
1882
1893
  }
1883
- params = this.omit(params, ['triggerPrice', 'stopPrice', 'stopPx']);
1884
- request['stopPx'] = parseFloat(this.priceToPrecision(symbol, triggerPrice));
1894
+ request['ordType'] = orderType;
1895
+ params = this.omit(params, ['triggerPrice', 'stopPrice', 'stopPx', 'triggerDirection', 'trailingAmount']);
1885
1896
  }
1886
1897
  if ((orderType === 'Limit') || (orderType === 'StopLimit') || (orderType === 'LimitIfTouched')) {
1887
- request['price'] = parseFloat(this.priceToPrecision(symbol, price));
1898
+ request['price'] = this.parseToNumeric(this.priceToPrecision(symbol, price));
1888
1899
  }
1889
1900
  const clientOrderId = this.safeString2(params, 'clOrdID', 'clientOrderId');
1890
1901
  if (clientOrderId !== undefined) {
@@ -1897,6 +1908,39 @@ class bitmex extends bitmex$1 {
1897
1908
  async editOrder(id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
1898
1909
  await this.loadMarkets();
1899
1910
  const request = {};
1911
+ let trailingAmount = this.safeString2(params, 'trailingAmount', 'pegOffsetValue');
1912
+ const isTrailingAmountOrder = trailingAmount !== undefined;
1913
+ if (isTrailingAmountOrder) {
1914
+ const triggerDirection = this.safeString(params, 'triggerDirection');
1915
+ const triggerAbove = (triggerDirection === 'above');
1916
+ if ((type === 'limit') || (type === 'market')) {
1917
+ this.checkRequiredArgument('createOrder', triggerDirection, 'triggerDirection', ['above', 'below']);
1918
+ }
1919
+ let orderType = undefined;
1920
+ if (type === 'limit') {
1921
+ if (side === 'buy') {
1922
+ orderType = triggerAbove ? 'StopLimit' : 'LimitIfTouched';
1923
+ }
1924
+ else {
1925
+ orderType = triggerAbove ? 'LimitIfTouched' : 'StopLimit';
1926
+ }
1927
+ }
1928
+ else if (type === 'market') {
1929
+ if (side === 'buy') {
1930
+ orderType = triggerAbove ? 'Stop' : 'MarketIfTouched';
1931
+ }
1932
+ else {
1933
+ orderType = triggerAbove ? 'MarketIfTouched' : 'Stop';
1934
+ }
1935
+ }
1936
+ const isStopSellOrder = (side === 'sell') && ((orderType === 'Stop') || (orderType === 'StopLimit'));
1937
+ const isBuyIfTouchedOrder = (side === 'buy') && ((orderType === 'MarketIfTouched') || (orderType === 'LimitIfTouched'));
1938
+ if (isStopSellOrder || isBuyIfTouchedOrder) {
1939
+ trailingAmount = '-' + trailingAmount;
1940
+ }
1941
+ request['pegOffsetValue'] = this.parseToNumeric(trailingAmount);
1942
+ params = this.omit(params, ['triggerDirection', 'trailingAmount']);
1943
+ }
1900
1944
  const origClOrdID = this.safeString2(params, 'origClOrdID', 'clientOrderId');
1901
1945
  if (origClOrdID !== undefined) {
1902
1946
  request['origClOrdID'] = origClOrdID;
@@ -280,6 +280,7 @@ class bybit extends bybit$1 {
280
280
  'v5/position/list': 5,
281
281
  'v5/execution/list': 5,
282
282
  'v5/position/closed-pnl': 5,
283
+ 'v5/position/move-history': 5,
283
284
  // pre-upgrade
284
285
  'v5/pre-upgrade/order/history': 5,
285
286
  'v5/pre-upgrade/execution/list': 5,
@@ -444,6 +445,7 @@ class bybit extends bybit$1 {
444
445
  'v5/position/trading-stop': 5,
445
446
  'v5/position/set-auto-add-margin': 5,
446
447
  'v5/position/add-margin': 5,
448
+ 'v5/position/move-positions': 5,
447
449
  'v5/position/confirm-pending-mmr': 5,
448
450
  // account
449
451
  'v5/account/upgrade-to-uta': 5,
@@ -327,14 +327,14 @@ class delta extends delta$1 {
327
327
  const markets = this.markets_by_id[symbol];
328
328
  return markets[0];
329
329
  }
330
- else if ((symbol.indexOf('-C') > -1) || (symbol.indexOf('-P') > -1) || (symbol.indexOf('C')) || (symbol.indexOf('P'))) {
330
+ else if ((symbol.endsWith('-C')) || (symbol.endsWith('-P')) || (symbol.startsWith('C-')) || (symbol.startsWith('P-'))) {
331
331
  return this.createExpiredOptionMarket(symbol);
332
332
  }
333
333
  }
334
334
  throw new errors.BadSymbol(this.id + ' does not have market symbol ' + symbol);
335
335
  }
336
336
  safeMarket(marketId = undefined, market = undefined, delimiter = undefined, marketType = undefined) {
337
- const isOption = (marketId !== undefined) && ((marketId.indexOf('-C') > -1) || (marketId.indexOf('-P') > -1) || (marketId.indexOf('C')) || (marketId.indexOf('P')));
337
+ const isOption = (marketId !== undefined) && ((marketId.endsWith('-C')) || (marketId.endsWith('-P')) || (marketId.startsWith('C-')) || (marketId.startsWith('P-')));
338
338
  if (isOption && !(marketId in this.markets_by_id)) {
339
339
  // handle expired option contracts
340
340
  return this.createExpiredOptionMarket(marketId);