ccxt 4.2.35 → 4.2.36

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
@@ -176,7 +176,7 @@ var woo$1 = require('./src/pro/woo.js');
176
176
 
177
177
  //-----------------------------------------------------------------------------
178
178
  // this is updated by vss.js when building
179
- const version = '4.2.35';
179
+ const version = '4.2.36';
180
180
  Exchange["default"].ccxtVersion = version;
181
181
  const exchanges = {
182
182
  'ace': ace,
@@ -1069,9 +1069,9 @@ class Exchange {
1069
1069
  }
1070
1070
  handleMessage(client, message) { } // stub to override
1071
1071
  // ping (client) {} // stub to override
1072
- // ping (client) {
1073
- // return undefined;
1074
- // }
1072
+ ping(client) {
1073
+ return undefined;
1074
+ }
1075
1075
  client(url) {
1076
1076
  this.clients = this.clients || {};
1077
1077
  if (!this.clients[url]) {
@@ -144,9 +144,12 @@ class Client {
144
144
  this.onError(new errors.RequestTimeout('Connection to ' + this.url + ' timed out due to a ping-pong keepalive missing on time'));
145
145
  }
146
146
  else {
147
+ let message;
147
148
  if (this.ping) {
148
- this.send(this.ping(this))
149
- .catch((error) => {
149
+ message = this.ping(this);
150
+ }
151
+ if (message) {
152
+ this.send(message).catch((error) => {
150
153
  this.onError(error);
151
154
  });
152
155
  }
@@ -4735,7 +4735,7 @@ class binance extends binance$1 {
4735
4735
  }
4736
4736
  request['price'] = this.priceToPrecision(symbol, price);
4737
4737
  }
4738
- if (timeInForceIsRequired) {
4738
+ if (timeInForceIsRequired && (this.safeString(params, 'timeInForce') === undefined)) {
4739
4739
  request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
4740
4740
  }
4741
4741
  if (stopPriceIsRequired) {
@@ -5040,18 +5040,128 @@ class binance extends binance$1 {
5040
5040
  // "lastTrade": {"id":"69","time":"1676084430567","price":"24.9","qty":"1.00"},
5041
5041
  // "mmp": false
5042
5042
  // }
5043
- // {
5043
+ //
5044
5044
  // cancelOrders/createOrders
5045
- // "code": -4005,
5046
- // "msg": "Quantity greater than max quantity."
5047
- // },
5045
+ //
5046
+ // {
5047
+ // "code": -4005,
5048
+ // "msg": "Quantity greater than max quantity."
5049
+ // }
5050
+ //
5051
+ // createOrder: portfolio margin linear swap and future
5052
+ //
5053
+ // {
5054
+ // "symbol": "BTCUSDT",
5055
+ // "side": "BUY",
5056
+ // "executedQty": "0.000",
5057
+ // "orderId": 258649539704,
5058
+ // "goodTillDate": 0,
5059
+ // "avgPrice": "0",
5060
+ // "origQty": "0.010",
5061
+ // "clientOrderId": "x-xcKtGhcu02573c6f15e544e990057b",
5062
+ // "positionSide": "BOTH",
5063
+ // "cumQty": "0.000",
5064
+ // "updateTime": 1707110415436,
5065
+ // "type": "LIMIT",
5066
+ // "reduceOnly": false,
5067
+ // "price": "35000.00",
5068
+ // "cumQuote": "0.00000",
5069
+ // "selfTradePreventionMode": "NONE",
5070
+ // "timeInForce": "GTC",
5071
+ // "status": "NEW"
5072
+ // }
5073
+ //
5074
+ // createOrder: portfolio margin inverse swap and future
5075
+ //
5076
+ // {
5077
+ // "symbol": "ETHUSD_PERP",
5078
+ // "side": "BUY",
5079
+ // "cumBase": "0",
5080
+ // "executedQty": "0",
5081
+ // "orderId": 71275227732,
5082
+ // "avgPrice": "0.00",
5083
+ // "origQty": "1",
5084
+ // "clientOrderId": "x-xcKtGhcuca5af3acfb5044198c5398",
5085
+ // "positionSide": "BOTH",
5086
+ // "cumQty": "0",
5087
+ // "updateTime": 1707110994334,
5088
+ // "type": "LIMIT",
5089
+ // "pair": "ETHUSD",
5090
+ // "reduceOnly": false,
5091
+ // "price": "2000",
5092
+ // "timeInForce": "GTC",
5093
+ // "status": "NEW"
5094
+ // }
5095
+ //
5096
+ // createOrder: portfolio margin linear swap and future conditional
5097
+ //
5098
+ // {
5099
+ // "newClientStrategyId": "x-xcKtGhcu27f109953d6e4dc0974006",
5100
+ // "strategyId": 3645916,
5101
+ // "strategyStatus": "NEW",
5102
+ // "strategyType": "STOP",
5103
+ // "origQty": "0.010",
5104
+ // "price": "35000.00",
5105
+ // "reduceOnly": false,
5106
+ // "side": "BUY",
5107
+ // "positionSide": "BOTH",
5108
+ // "stopPrice": "45000.00",
5109
+ // "symbol": "BTCUSDT",
5110
+ // "timeInForce": "GTC",
5111
+ // "bookTime": 1707112625879,
5112
+ // "updateTime": 1707112625879,
5113
+ // "workingType": "CONTRACT_PRICE",
5114
+ // "priceProtect": false,
5115
+ // "goodTillDate": 0,
5116
+ // "selfTradePreventionMode": "NONE"
5117
+ // }
5118
+ //
5119
+ // createOrder: portfolio margin inverse swap and future conditional
5120
+ //
5121
+ // {
5122
+ // "newClientStrategyId": "x-xcKtGhcuc6b86f053bb34933850739",
5123
+ // "strategyId": 1423462,
5124
+ // "strategyStatus": "NEW",
5125
+ // "strategyType": "STOP",
5126
+ // "origQty": "1",
5127
+ // "price": "2000",
5128
+ // "reduceOnly": false,
5129
+ // "side": "BUY",
5130
+ // "positionSide": "BOTH",
5131
+ // "stopPrice": "3000",
5132
+ // "symbol": "ETHUSD_PERP",
5133
+ // "timeInForce": "GTC",
5134
+ // "bookTime": 1707113098840,
5135
+ // "updateTime": 1707113098840,
5136
+ // "workingType": "CONTRACT_PRICE",
5137
+ // "priceProtect": false
5138
+ // }
5139
+ //
5140
+ // createOrder: portfolio margin spot margin
5141
+ //
5142
+ // {
5143
+ // "clientOrderId": "x-R4BD3S82e9ef29d8346440f0b28b86",
5144
+ // "cummulativeQuoteQty": "0.00000000",
5145
+ // "executedQty": "0.00000000",
5146
+ // "fills": [],
5147
+ // "orderId": 24684460474,
5148
+ // "origQty": "0.00100000",
5149
+ // "price": "35000.00000000",
5150
+ // "selfTradePreventionMode": "EXPIRE_MAKER",
5151
+ // "side": "BUY",
5152
+ // "status": "NEW",
5153
+ // "symbol": "BTCUSDT",
5154
+ // "timeInForce": "GTC",
5155
+ // "transactTime": 1707113538870,
5156
+ // "type": "LIMIT"
5157
+ // }
5048
5158
  //
5049
5159
  const code = this.safeString(order, 'code');
5050
5160
  if (code !== undefined) {
5051
5161
  // cancelOrders/createOrders might have a partial success
5052
5162
  return this.safeOrder({ 'info': order, 'status': 'rejected' }, market);
5053
5163
  }
5054
- const status = this.parseOrderStatus(this.safeString(order, 'status'));
5164
+ const status = this.parseOrderStatus(this.safeString2(order, 'status', 'strategyStatus'));
5055
5165
  const marketId = this.safeString(order, 'symbol');
5056
5166
  const marketType = ('closePosition' in order) ? 'contract' : 'spot';
5057
5167
  const symbol = this.safeSymbol(marketId, market, undefined, marketType);
@@ -5078,11 +5188,9 @@ class binance extends binance$1 {
5078
5188
  // Note this is not the actual cost, since Binance futures uses leverage to calculate margins.
5079
5189
  let cost = this.safeString2(order, 'cummulativeQuoteQty', 'cumQuote');
5080
5190
  cost = this.safeString(order, 'cumBase', cost);
5081
- const id = this.safeString(order, 'orderId');
5082
5191
  let type = this.safeStringLower(order, 'type');
5083
5192
  const side = this.safeStringLower(order, 'side');
5084
5193
  const fills = this.safeValue(order, 'fills', []);
5085
- const clientOrderId = this.safeString(order, 'clientOrderId');
5086
5194
  let timeInForce = this.safeString(order, 'timeInForce');
5087
5195
  if (timeInForce === 'GTX') {
5088
5196
  // GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
@@ -5105,8 +5213,8 @@ class binance extends binance$1 {
5105
5213
  }
5106
5214
  return this.safeOrder({
5107
5215
  'info': order,
5108
- 'id': id,
5109
- 'clientOrderId': clientOrderId,
5216
+ 'id': this.safeString2(order, 'orderId', 'strategyId'),
5217
+ 'clientOrderId': this.safeString2(order, 'clientOrderId', 'newClientStrategyId'),
5110
5218
  'timestamp': timestamp,
5111
5219
  'datetime': this.iso8601(timestamp),
5112
5220
  'lastTradeTimestamp': lastTradeTimestamp,
@@ -5220,50 +5328,105 @@ class binance extends binance$1 {
5220
5328
  * @see https://binance-docs.github.io/apidocs/voptions/en/#new-order-trade
5221
5329
  * @see https://binance-docs.github.io/apidocs/spot/en/#new-order-using-sor-trade
5222
5330
  * @see https://binance-docs.github.io/apidocs/spot/en/#test-new-order-using-sor-trade
5331
+ * @see https://binance-docs.github.io/apidocs/pm/en/#new-um-order-trade
5332
+ * @see https://binance-docs.github.io/apidocs/pm/en/#new-cm-order-trade
5333
+ * @see https://binance-docs.github.io/apidocs/pm/en/#new-margin-order-trade
5334
+ * @see https://binance-docs.github.io/apidocs/pm/en/#new-um-conditional-order-trade
5335
+ * @see https://binance-docs.github.io/apidocs/pm/en/#new-cm-conditional-order-trade
5223
5336
  * @param {string} symbol unified symbol of the market to create an order in
5224
5337
  * @param {string} type 'market' or 'limit' or 'STOP_LOSS' or 'STOP_LOSS_LIMIT' or 'TAKE_PROFIT' or 'TAKE_PROFIT_LIMIT' or 'STOP'
5225
5338
  * @param {string} side 'buy' or 'sell'
5226
- * @param {float} amount how much of currency you want to trade in units of base currency
5227
- * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
5339
+ * @param {float} amount how much of you want to trade in units of the base currency
5340
+ * @param {float} [price] the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
5228
5341
  * @param {object} [params] extra parameters specific to the exchange API endpoint
5342
+ * @param {string} [params.reduceOnly] for swap and future reduceOnly is a string 'true' or 'false' that cant be sent with close position set to true or in hedge mode. For spot margin and option reduceOnly is a boolean.
5229
5343
  * @param {string} [params.marginMode] 'cross' or 'isolated', for spot margin trading
5230
5344
  * @param {boolean} [params.sor] *spot only* whether to use SOR (Smart Order Routing) or not, default is false
5231
5345
  * @param {boolean} [params.test] *spot only* whether to use the test endpoint or not, default is false
5232
5346
  * @param {float} [params.trailingPercent] the percent to trail away from the current market price
5233
5347
  * @param {float} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
5348
+ * @param {float} [params.triggerPrice] the price that a trigger order is triggered at
5349
+ * @param {float} [params.stopLossPrice] the price that a stop loss order is triggered at
5350
+ * @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at
5351
+ * @param {boolean} [params.portfolioMargin] set to true if you would like to create an order in a portfolio margin account
5234
5352
  * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
5235
5353
  */
5236
5354
  await this.loadMarkets();
5237
5355
  const market = this.market(symbol);
5238
5356
  const marketType = this.safeString(params, 'type', market['type']);
5239
- const [marginMode, query] = this.handleMarginModeAndParams('createOrder', params);
5240
- const sor = this.safeValue2(params, 'sor', 'SOR', false);
5241
- params = this.omit(params, 'sor', 'SOR');
5357
+ let marginMode = undefined;
5358
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
5359
+ let isPortfolioMargin = undefined;
5360
+ [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'createOrder', 'papi', 'portfolioMargin', false);
5361
+ const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
5362
+ const stopLossPrice = this.safeString(params, 'stopLossPrice');
5363
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
5364
+ const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
5365
+ const isTrailingPercentOrder = trailingPercent !== undefined;
5366
+ const isStopLoss = stopLossPrice !== undefined;
5367
+ const isTakeProfit = takeProfitPrice !== undefined;
5368
+ const isConditional = (triggerPrice !== undefined) || isTrailingPercentOrder || isStopLoss || isTakeProfit;
5369
+ const sor = this.safeBool2(params, 'sor', 'SOR', false);
5370
+ const test = this.safeBool(params, 'test', false);
5371
+ params = this.omit(params, ['sor', 'SOR', 'test']);
5372
+ if (isPortfolioMargin) {
5373
+ params['portfolioMargin'] = isPortfolioMargin;
5374
+ }
5242
5375
  const request = this.createOrderRequest(symbol, type, side, amount, price, params);
5243
- let method = 'privatePostOrder';
5244
- if (sor) {
5245
- method = 'privatePostSorOrder';
5376
+ let response = undefined;
5377
+ if (market['option']) {
5378
+ response = await this.eapiPrivatePostOrder(request);
5379
+ }
5380
+ else if (sor) {
5381
+ if (test) {
5382
+ response = await this.privatePostSorOrderTest(request);
5383
+ }
5384
+ else {
5385
+ response = await this.privatePostSorOrder(request);
5386
+ }
5246
5387
  }
5247
5388
  else if (market['linear']) {
5248
- method = 'fapiPrivatePostOrder';
5389
+ if (isPortfolioMargin) {
5390
+ if (isConditional) {
5391
+ response = await this.papiPostUmConditionalOrder(request);
5392
+ }
5393
+ else {
5394
+ response = await this.papiPostUmOrder(request);
5395
+ }
5396
+ }
5397
+ else {
5398
+ response = await this.fapiPrivatePostOrder(request);
5399
+ }
5249
5400
  }
5250
5401
  else if (market['inverse']) {
5251
- method = 'dapiPrivatePostOrder';
5402
+ if (isPortfolioMargin) {
5403
+ if (isConditional) {
5404
+ response = await this.papiPostCmConditionalOrder(request);
5405
+ }
5406
+ else {
5407
+ response = await this.papiPostCmOrder(request);
5408
+ }
5409
+ }
5410
+ else {
5411
+ response = await this.dapiPrivatePostOrder(request);
5412
+ }
5252
5413
  }
5253
5414
  else if (marketType === 'margin' || marginMode !== undefined) {
5254
- method = 'sapiPostMarginOrder';
5255
- }
5256
- if (market['option']) {
5257
- method = 'eapiPrivatePostOrder';
5415
+ if (isPortfolioMargin) {
5416
+ response = await this.papiPostMarginOrder(request);
5417
+ }
5418
+ else {
5419
+ response = await this.sapiPostMarginOrder(request);
5420
+ }
5258
5421
  }
5259
- // support for testing orders
5260
- if (market['spot'] || marketType === 'margin') {
5261
- const test = this.safeBool(query, 'test', false);
5422
+ else {
5262
5423
  if (test) {
5263
- method += 'Test';
5424
+ response = await this.privatePostOrderTest(request);
5425
+ }
5426
+ else {
5427
+ response = await this.privatePostOrder(request);
5264
5428
  }
5265
5429
  }
5266
- const response = await this[method](request);
5267
5430
  return this.parseOrder(response, market);
5268
5431
  }
5269
5432
  createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
@@ -5271,16 +5434,13 @@ class binance extends binance$1 {
5271
5434
  * @method
5272
5435
  * @ignore
5273
5436
  * @name binance#createOrderRequest
5274
- * @description helper function to build request
5437
+ * @description helper function to build the request
5275
5438
  * @param {string} symbol unified symbol of the market to create an order in
5276
- * @param {string} type 'market' or 'limit' or 'STOP_LOSS' or 'STOP_LOSS_LIMIT' or 'TAKE_PROFIT' or 'TAKE_PROFIT_LIMIT' or 'STOP'
5439
+ * @param {string} type 'market' or 'limit'
5277
5440
  * @param {string} side 'buy' or 'sell'
5278
- * @param {float} amount how much of currency you want to trade in units of base currency
5279
- * @param {float|undefined} price the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
5280
- * @param {object} params extra parameters specific to the exchange API endpoint
5281
- * @param {string|undefined} params.marginMode 'cross' or 'isolated', for spot margin trading
5282
- * @param {float} [params.trailingPercent] the percent to trail away from the current market price
5283
- * @param {float} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
5441
+ * @param {float} amount how much you want to trade in units of the base currency
5442
+ * @param {float} [price] the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
5443
+ * @param {object} [params] extra parameters specific to the exchange API endpoint
5284
5444
  * @returns {object} request to be sent to the exchange
5285
5445
  */
5286
5446
  const market = this.market(symbol);
@@ -5289,35 +5449,54 @@ class binance extends binance$1 {
5289
5449
  const initialUppercaseType = type.toUpperCase();
5290
5450
  const isMarketOrder = initialUppercaseType === 'MARKET';
5291
5451
  const isLimitOrder = initialUppercaseType === 'LIMIT';
5292
- const postOnly = this.isPostOnly(isMarketOrder, initialUppercaseType === 'LIMIT_MAKER', params);
5293
- const triggerPrice = this.safeValue2(params, 'triggerPrice', 'stopPrice');
5294
- const stopLossPrice = this.safeValue(params, 'stopLossPrice', triggerPrice); // fallback to stopLoss
5295
- const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
5296
- const trailingDelta = this.safeValue(params, 'trailingDelta');
5297
- const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice', this.numberToString(price));
5298
- const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
5299
- const isTrailingPercentOrder = trailingPercent !== undefined;
5300
- const isStopLoss = stopLossPrice !== undefined || trailingDelta !== undefined;
5301
- const isTakeProfit = takeProfitPrice !== undefined;
5302
- params = this.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent']);
5303
- const [marginMode, query] = this.handleMarginModeAndParams('createOrder', params);
5304
5452
  const request = {
5305
5453
  'symbol': market['id'],
5306
5454
  'side': side.toUpperCase(),
5307
5455
  };
5308
- if (market['spot'] || marketType === 'margin') {
5309
- // only supported for spot/margin api (all margin markets are spot markets)
5310
- if (postOnly) {
5311
- type = 'LIMIT_MAKER';
5456
+ let isPortfolioMargin = undefined;
5457
+ [isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'createOrder', 'papi', 'portfolioMargin', false);
5458
+ let marginMode = undefined;
5459
+ [marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
5460
+ if ((marketType === 'margin') || (marginMode !== undefined) || market['option']) {
5461
+ // for swap and future reduceOnly is a string that cant be sent with close position set to true or in hedge mode
5462
+ const reduceOnly = this.safeBool(params, 'reduceOnly', false);
5463
+ params = this.omit(params, 'reduceOnly');
5464
+ if (market['option']) {
5465
+ request['reduceOnly'] = reduceOnly;
5466
+ }
5467
+ else {
5468
+ if (reduceOnly) {
5469
+ request['sideEffectType'] = 'AUTO_REPAY';
5470
+ }
5312
5471
  }
5313
5472
  }
5314
- if (marketType === 'margin' || marginMode !== undefined) {
5315
- const reduceOnly = this.safeValue(params, 'reduceOnly');
5316
- if (reduceOnly) {
5317
- request['sideEffectType'] = 'AUTO_REPAY';
5318
- params = this.omit(params, 'reduceOnly');
5473
+ if (!isPortfolioMargin) {
5474
+ const postOnly = this.isPostOnly(isMarketOrder, initialUppercaseType === 'LIMIT_MAKER', params);
5475
+ if (market['spot'] || marketType === 'margin') {
5476
+ // only supported for spot/margin api (all margin markets are spot markets)
5477
+ if (postOnly) {
5478
+ type = 'LIMIT_MAKER';
5479
+ }
5480
+ if (marginMode === 'isolated') {
5481
+ request['isIsolated'] = true;
5482
+ }
5483
+ }
5484
+ if (market['contract'] && postOnly) {
5485
+ request['timeInForce'] = 'GTX';
5319
5486
  }
5320
5487
  }
5488
+ const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
5489
+ const stopLossPrice = this.safeString(params, 'stopLossPrice', triggerPrice); // fallback to stopLoss
5490
+ const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
5491
+ const trailingDelta = this.safeString(params, 'trailingDelta');
5492
+ const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice', this.numberToString(price));
5493
+ const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
5494
+ const isTrailingPercentOrder = trailingPercent !== undefined;
5495
+ const isStopLoss = stopLossPrice !== undefined || trailingDelta !== undefined;
5496
+ const isTakeProfit = takeProfitPrice !== undefined;
5497
+ const isTriggerOrder = triggerPrice !== undefined;
5498
+ const isConditional = isTriggerOrder || isTrailingPercentOrder || isStopLoss || isTakeProfit;
5499
+ const isPortfolioMarginConditional = (isPortfolioMargin && isConditional);
5321
5500
  let uppercaseType = type.toUpperCase();
5322
5501
  let stopPrice = undefined;
5323
5502
  if (isTrailingPercentOrder) {
@@ -5347,24 +5526,14 @@ class binance extends binance$1 {
5347
5526
  uppercaseType = market['contract'] ? 'TAKE_PROFIT' : 'TAKE_PROFIT_LIMIT';
5348
5527
  }
5349
5528
  }
5350
- if (marginMode === 'isolated') {
5351
- request['isIsolated'] = true;
5352
- }
5353
- if (clientOrderId === undefined) {
5354
- const broker = this.safeValue(this.options, 'broker', {});
5355
- const defaultId = (market['contract']) ? 'x-xcKtGhcu' : 'x-R4BD3S82';
5356
- const brokerId = this.safeString(broker, marketType, defaultId);
5357
- request['newClientOrderId'] = brokerId + this.uuid22();
5358
- }
5359
- else {
5360
- request['newClientOrderId'] = clientOrderId;
5361
- }
5362
5529
  if ((marketType === 'spot') || (marketType === 'margin')) {
5363
- request['newOrderRespType'] = this.safeValue(this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
5530
+ request['newOrderRespType'] = this.safeString(this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
5364
5531
  }
5365
5532
  else {
5366
5533
  // swap, futures and options
5367
- request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK"
5534
+ if (!isPortfolioMargin) {
5535
+ request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK"
5536
+ }
5368
5537
  }
5369
5538
  if (market['option']) {
5370
5539
  if (type === 'market') {
@@ -5372,7 +5541,7 @@ class binance extends binance$1 {
5372
5541
  }
5373
5542
  }
5374
5543
  else {
5375
- const validOrderTypes = this.safeValue(market['info'], 'orderTypes');
5544
+ const validOrderTypes = this.safeList(market['info'], 'orderTypes');
5376
5545
  if (!this.inArray(uppercaseType, validOrderTypes)) {
5377
5546
  if (initialUppercaseType !== uppercaseType) {
5378
5547
  throw new errors.InvalidOrder(this.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders');
@@ -5382,7 +5551,18 @@ class binance extends binance$1 {
5382
5551
  }
5383
5552
  }
5384
5553
  }
5385
- request['type'] = uppercaseType;
5554
+ const clientOrderIdRequest = isPortfolioMarginConditional ? 'newClientStrategyId' : 'newClientOrderId';
5555
+ if (clientOrderId === undefined) {
5556
+ const broker = this.safeDict(this.options, 'broker', {});
5557
+ const defaultId = (market['contract']) ? 'x-xcKtGhcu' : 'x-R4BD3S82';
5558
+ const brokerId = this.safeString(broker, marketType, defaultId);
5559
+ request[clientOrderIdRequest] = brokerId + this.uuid22();
5560
+ }
5561
+ else {
5562
+ request[clientOrderIdRequest] = clientOrderId;
5563
+ }
5564
+ const typeRequest = isPortfolioMarginConditional ? 'strategyType' : 'type';
5565
+ request[typeRequest] = uppercaseType;
5386
5566
  // additional required fields depending on the order type
5387
5567
  let timeInForceIsRequired = false;
5388
5568
  let priceIsRequired = false;
@@ -5410,9 +5590,9 @@ class binance extends binance$1 {
5410
5590
  //
5411
5591
  if (uppercaseType === 'MARKET') {
5412
5592
  if (market['spot']) {
5413
- const quoteOrderQty = this.safeValue(this.options, 'quoteOrderQty', true);
5593
+ const quoteOrderQty = this.safeBool(this.options, 'quoteOrderQty', true);
5414
5594
  if (quoteOrderQty) {
5415
- const quoteOrderQtyNew = this.safeValue2(query, 'quoteOrderQty', 'cost');
5595
+ const quoteOrderQtyNew = this.safeString2(params, 'quoteOrderQty', 'cost');
5416
5596
  const precision = market['precision']['price'];
5417
5597
  if (quoteOrderQtyNew !== undefined) {
5418
5598
  request['quoteOrderQty'] = this.decimalToPrecision(quoteOrderQtyNew, number.TRUNCATE, precision, this.precisionMode);
@@ -5463,7 +5643,7 @@ class binance extends binance$1 {
5463
5643
  priceIsRequired = true;
5464
5644
  }
5465
5645
  else if ((uppercaseType === 'STOP_MARKET') || (uppercaseType === 'TAKE_PROFIT_MARKET')) {
5466
- const closePosition = this.safeValue(query, 'closePosition');
5646
+ const closePosition = this.safeBool(params, 'closePosition');
5467
5647
  if (closePosition === undefined) {
5468
5648
  quantityIsRequired = true;
5469
5649
  }
@@ -5476,7 +5656,13 @@ class binance extends binance$1 {
5476
5656
  }
5477
5657
  }
5478
5658
  if (quantityIsRequired) {
5479
- request['quantity'] = this.amountToPrecision(symbol, amount);
5659
+ // portfolio margin has a different amount precision
5660
+ if (isPortfolioMargin) {
5661
+ request['quantity'] = this.parseToNumeric(amount);
5662
+ }
5663
+ else {
5664
+ request['quantity'] = this.amountToPrecision(symbol, amount);
5665
+ }
5480
5666
  }
5481
5667
  if (priceIsRequired) {
5482
5668
  if (price === undefined) {
@@ -5487,9 +5673,6 @@ class binance extends binance$1 {
5487
5673
  if (timeInForceIsRequired) {
5488
5674
  request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
5489
5675
  }
5490
- if (market['contract'] && postOnly) {
5491
- request['timeInForce'] = 'GTX';
5492
- }
5493
5676
  if (stopPriceIsRequired) {
5494
5677
  if (market['contract']) {
5495
5678
  if (stopPrice === undefined) {
@@ -5506,11 +5689,26 @@ class binance extends binance$1 {
5506
5689
  request['stopPrice'] = this.priceToPrecision(symbol, stopPrice);
5507
5690
  }
5508
5691
  }
5692
+ if (!isPortfolioMargin) {
5693
+ const postOnly = this.isPostOnly(isMarketOrder, initialUppercaseType === 'LIMIT_MAKER', params);
5694
+ if (market['spot'] || marketType === 'margin') {
5695
+ // only supported for spot/margin api (all margin markets are spot markets)
5696
+ if (postOnly) {
5697
+ type = 'LIMIT_MAKER';
5698
+ }
5699
+ if (marginMode === 'isolated') {
5700
+ request['isIsolated'] = true;
5701
+ }
5702
+ }
5703
+ if (market['contract'] && postOnly) {
5704
+ request['timeInForce'] = 'GTX';
5705
+ }
5706
+ }
5509
5707
  // remove timeInForce from params because PO is only used by this.isPostOnly and it's not a valid value for Binance
5510
5708
  if (this.safeString(params, 'timeInForce') === 'PO') {
5511
- params = this.omit(params, ['timeInForce']);
5709
+ params = this.omit(params, 'timeInForce');
5512
5710
  }
5513
- const requestParams = this.omit(params, ['quoteOrderQty', 'cost', 'stopPrice', 'test', 'type', 'newClientOrderId', 'clientOrderId', 'postOnly']);
5711
+ const requestParams = this.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent', 'quoteOrderQty', 'cost', 'test']);
5514
5712
  return this.extend(request, requestParams);
5515
5713
  }
5516
5714
  async createMarketOrderWithCost(symbol, side, cost, params = {}) {