ccxt 4.2.34 → 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/README.md +3 -3
- package/dist/ccxt.browser.js +520 -182
- package/dist/ccxt.browser.min.js +3 -3
- package/dist/cjs/ccxt.js +1 -1
- package/dist/cjs/src/base/Exchange.js +10 -2
- package/dist/cjs/src/base/ws/Client.js +5 -2
- package/dist/cjs/src/binance.js +335 -94
- package/dist/cjs/src/bitfinex.js +21 -0
- package/dist/cjs/src/bitfinex2.js +12 -1
- package/dist/cjs/src/bitget.js +28 -39
- package/dist/cjs/src/bithumb.js +14 -0
- package/dist/cjs/src/krakenfutures.js +25 -3
- package/dist/cjs/src/pro/binance.js +5 -5
- package/dist/cjs/src/woo.js +64 -35
- package/js/ccxt.d.ts +1 -1
- package/js/ccxt.js +1 -1
- package/js/src/base/Exchange.js +10 -2
- package/js/src/base/ws/Client.js +5 -2
- package/js/src/binance.js +335 -94
- package/js/src/bitfinex.js +21 -0
- package/js/src/bitfinex2.js +12 -1
- package/js/src/bitget.js +28 -39
- package/js/src/bithumb.js +14 -0
- package/js/src/krakenfutures.js +25 -3
- package/js/src/pro/binance.js +5 -5
- package/js/src/woo.js +64 -35
- package/package.json +1 -1
package/js/src/binance.js
CHANGED
|
@@ -3146,9 +3146,24 @@ export default class binance extends Exchange {
|
|
|
3146
3146
|
let timestamp = undefined;
|
|
3147
3147
|
const isolated = marginMode === 'isolated';
|
|
3148
3148
|
const cross = (type === 'margin') || (marginMode === 'cross');
|
|
3149
|
-
if (
|
|
3149
|
+
if (type === 'papi') {
|
|
3150
|
+
for (let i = 0; i < response.length; i++) {
|
|
3151
|
+
const entry = response[i];
|
|
3152
|
+
const account = this.account();
|
|
3153
|
+
const currencyId = this.safeString(entry, 'asset');
|
|
3154
|
+
const code = this.safeCurrencyCode(currencyId);
|
|
3155
|
+
const borrowed = this.safeString(entry, 'crossMarginBorrowed');
|
|
3156
|
+
const interest = this.safeString(entry, 'crossMarginInterest');
|
|
3157
|
+
account['free'] = this.safeString(entry, 'crossMarginFree');
|
|
3158
|
+
account['used'] = this.safeString(entry, 'crossMarginLocked');
|
|
3159
|
+
account['total'] = this.safeString(entry, 'crossMarginAsset');
|
|
3160
|
+
account['debt'] = Precise.stringAdd(borrowed, interest);
|
|
3161
|
+
result[code] = account;
|
|
3162
|
+
}
|
|
3163
|
+
}
|
|
3164
|
+
else if (!isolated && ((type === 'spot') || cross)) {
|
|
3150
3165
|
timestamp = this.safeInteger(response, 'updateTime');
|
|
3151
|
-
const balances = this.
|
|
3166
|
+
const balances = this.safeList2(response, 'balances', 'userAssets', []);
|
|
3152
3167
|
for (let i = 0; i < balances.length; i++) {
|
|
3153
3168
|
const balance = balances[i];
|
|
3154
3169
|
const currencyId = this.safeString(balance, 'asset');
|
|
@@ -3165,13 +3180,13 @@ export default class binance extends Exchange {
|
|
|
3165
3180
|
}
|
|
3166
3181
|
}
|
|
3167
3182
|
else if (isolated) {
|
|
3168
|
-
const assets = this.
|
|
3183
|
+
const assets = this.safeList(response, 'assets');
|
|
3169
3184
|
for (let i = 0; i < assets.length; i++) {
|
|
3170
3185
|
const asset = assets[i];
|
|
3171
|
-
const marketId = this.
|
|
3186
|
+
const marketId = this.safeString(asset, 'symbol');
|
|
3172
3187
|
const symbol = this.safeSymbol(marketId, undefined, undefined, 'spot');
|
|
3173
|
-
const base = this.
|
|
3174
|
-
const quote = this.
|
|
3188
|
+
const base = this.safeDict(asset, 'baseAsset', {});
|
|
3189
|
+
const quote = this.safeDict(asset, 'quoteAsset', {});
|
|
3175
3190
|
const baseCode = this.safeCurrencyCode(this.safeString(base, 'asset'));
|
|
3176
3191
|
const quoteCode = this.safeCurrencyCode(this.safeString(quote, 'asset'));
|
|
3177
3192
|
const subResult = {};
|
|
@@ -3181,7 +3196,7 @@ export default class binance extends Exchange {
|
|
|
3181
3196
|
}
|
|
3182
3197
|
}
|
|
3183
3198
|
else if (type === 'savings') {
|
|
3184
|
-
const positionAmountVos = this.
|
|
3199
|
+
const positionAmountVos = this.safeList(response, 'positionAmountVos', []);
|
|
3185
3200
|
for (let i = 0; i < positionAmountVos.length; i++) {
|
|
3186
3201
|
const entry = positionAmountVos[i];
|
|
3187
3202
|
const currencyId = this.safeString(entry, 'asset');
|
|
@@ -3210,7 +3225,7 @@ export default class binance extends Exchange {
|
|
|
3210
3225
|
else {
|
|
3211
3226
|
let balances = response;
|
|
3212
3227
|
if (!Array.isArray(response)) {
|
|
3213
|
-
balances = this.
|
|
3228
|
+
balances = this.safeList(response, 'assets', []);
|
|
3214
3229
|
}
|
|
3215
3230
|
for (let i = 0; i < balances.length; i++) {
|
|
3216
3231
|
const balance = balances[i];
|
|
@@ -3240,10 +3255,12 @@ export default class binance extends Exchange {
|
|
|
3240
3255
|
* @see https://binance-docs.github.io/apidocs/futures/en/#account-information-v2-user_data // swap
|
|
3241
3256
|
* @see https://binance-docs.github.io/apidocs/delivery/en/#account-information-user_data // future
|
|
3242
3257
|
* @see https://binance-docs.github.io/apidocs/voptions/en/#option-account-information-trade // option
|
|
3258
|
+
* @see https://binance-docs.github.io/apidocs/pm/en/#account-balance-user_data // portfolio margin
|
|
3243
3259
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
3244
|
-
* @param {string} [params.type] 'future', 'delivery', 'savings', 'funding', or 'spot'
|
|
3260
|
+
* @param {string} [params.type] 'future', 'delivery', 'savings', 'funding', or 'spot' or 'papi'
|
|
3245
3261
|
* @param {string} [params.marginMode] 'cross' or 'isolated', for margin trading, uses this.options.defaultMarginMode if not passed, defaults to undefined/None/null
|
|
3246
3262
|
* @param {string[]|undefined} [params.symbols] unified market symbols, only used in isolated margin mode
|
|
3263
|
+
* @param {boolean} [params.portfolioMargin] set to true if you would like to fetch the balance for a portfolio margin account
|
|
3247
3264
|
* @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure}
|
|
3248
3265
|
*/
|
|
3249
3266
|
await this.loadMarkets();
|
|
@@ -3251,13 +3268,19 @@ export default class binance extends Exchange {
|
|
|
3251
3268
|
let type = this.safeString(params, 'type', defaultType);
|
|
3252
3269
|
let subType = undefined;
|
|
3253
3270
|
[subType, params] = this.handleSubTypeAndParams('fetchBalance', undefined, params);
|
|
3271
|
+
let isPortfolioMargin = undefined;
|
|
3272
|
+
[isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'fetchBalance', 'papi', 'portfolioMargin', false);
|
|
3254
3273
|
let marginMode = undefined;
|
|
3255
3274
|
let query = undefined;
|
|
3256
3275
|
[marginMode, query] = this.handleMarginModeAndParams('fetchBalance', params);
|
|
3257
3276
|
query = this.omit(query, 'type');
|
|
3258
3277
|
let response = undefined;
|
|
3259
3278
|
const request = {};
|
|
3260
|
-
if (
|
|
3279
|
+
if (isPortfolioMargin || (type === 'papi')) {
|
|
3280
|
+
type = 'papi';
|
|
3281
|
+
response = await this.papiGetBalance(this.extend(request, query));
|
|
3282
|
+
}
|
|
3283
|
+
else if (this.isLinear(type, subType)) {
|
|
3261
3284
|
type = 'linear';
|
|
3262
3285
|
response = await this.fapiPrivateV2GetAccount(this.extend(request, query));
|
|
3263
3286
|
}
|
|
@@ -3266,7 +3289,7 @@ export default class binance extends Exchange {
|
|
|
3266
3289
|
response = await this.dapiPrivateGetAccount(this.extend(request, query));
|
|
3267
3290
|
}
|
|
3268
3291
|
else if (marginMode === 'isolated') {
|
|
3269
|
-
const paramSymbols = this.
|
|
3292
|
+
const paramSymbols = this.safeList(params, 'symbols');
|
|
3270
3293
|
query = this.omit(query, 'symbols');
|
|
3271
3294
|
if (paramSymbols !== undefined) {
|
|
3272
3295
|
let symbols = '';
|
|
@@ -3482,6 +3505,26 @@ export default class binance extends Exchange {
|
|
|
3482
3505
|
// }
|
|
3483
3506
|
// ]
|
|
3484
3507
|
//
|
|
3508
|
+
// portfolio margin
|
|
3509
|
+
//
|
|
3510
|
+
// [
|
|
3511
|
+
// {
|
|
3512
|
+
// "asset": "USDT",
|
|
3513
|
+
// "totalWalletBalance": "66.9923261",
|
|
3514
|
+
// "crossMarginAsset": "35.9697141",
|
|
3515
|
+
// "crossMarginBorrowed": "0.0",
|
|
3516
|
+
// "crossMarginFree": "35.9697141",
|
|
3517
|
+
// "crossMarginInterest": "0.0",
|
|
3518
|
+
// "crossMarginLocked": "0.0",
|
|
3519
|
+
// "umWalletBalance": "31.022612",
|
|
3520
|
+
// "umUnrealizedPNL": "0.0",
|
|
3521
|
+
// "cmWalletBalance": "0.0",
|
|
3522
|
+
// "cmUnrealizedPNL": "0.0",
|
|
3523
|
+
// "updateTime": 0,
|
|
3524
|
+
// "negativeBalance": "0.0"
|
|
3525
|
+
// },
|
|
3526
|
+
// ]
|
|
3527
|
+
//
|
|
3485
3528
|
return this.parseBalanceCustom(response, type, marginMode);
|
|
3486
3529
|
}
|
|
3487
3530
|
async fetchOrderBook(symbol, limit = undefined, params = {}) {
|
|
@@ -4695,7 +4738,7 @@ export default class binance extends Exchange {
|
|
|
4695
4738
|
}
|
|
4696
4739
|
request['price'] = this.priceToPrecision(symbol, price);
|
|
4697
4740
|
}
|
|
4698
|
-
if (timeInForceIsRequired) {
|
|
4741
|
+
if (timeInForceIsRequired && (this.safeString(params, 'timeInForce') === undefined)) {
|
|
4699
4742
|
request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
|
|
4700
4743
|
}
|
|
4701
4744
|
if (stopPriceIsRequired) {
|
|
@@ -5000,18 +5043,128 @@ export default class binance extends Exchange {
|
|
|
5000
5043
|
// "lastTrade": {"id":"69","time":"1676084430567","price":"24.9","qty":"1.00"},
|
|
5001
5044
|
// "mmp": false
|
|
5002
5045
|
// }
|
|
5003
|
-
//
|
|
5046
|
+
//
|
|
5004
5047
|
// cancelOrders/createOrders
|
|
5005
|
-
//
|
|
5006
|
-
//
|
|
5007
|
-
//
|
|
5048
|
+
//
|
|
5049
|
+
// {
|
|
5050
|
+
// "code": -4005,
|
|
5051
|
+
// "msg": "Quantity greater than max quantity."
|
|
5052
|
+
// }
|
|
5053
|
+
//
|
|
5054
|
+
// createOrder: portfolio margin linear swap and future
|
|
5055
|
+
//
|
|
5056
|
+
// {
|
|
5057
|
+
// "symbol": "BTCUSDT",
|
|
5058
|
+
// "side": "BUY",
|
|
5059
|
+
// "executedQty": "0.000",
|
|
5060
|
+
// "orderId": 258649539704,
|
|
5061
|
+
// "goodTillDate": 0,
|
|
5062
|
+
// "avgPrice": "0",
|
|
5063
|
+
// "origQty": "0.010",
|
|
5064
|
+
// "clientOrderId": "x-xcKtGhcu02573c6f15e544e990057b",
|
|
5065
|
+
// "positionSide": "BOTH",
|
|
5066
|
+
// "cumQty": "0.000",
|
|
5067
|
+
// "updateTime": 1707110415436,
|
|
5068
|
+
// "type": "LIMIT",
|
|
5069
|
+
// "reduceOnly": false,
|
|
5070
|
+
// "price": "35000.00",
|
|
5071
|
+
// "cumQuote": "0.00000",
|
|
5072
|
+
// "selfTradePreventionMode": "NONE",
|
|
5073
|
+
// "timeInForce": "GTC",
|
|
5074
|
+
// "status": "NEW"
|
|
5075
|
+
// }
|
|
5076
|
+
//
|
|
5077
|
+
// createOrder: portfolio margin inverse swap and future
|
|
5078
|
+
//
|
|
5079
|
+
// {
|
|
5080
|
+
// "symbol": "ETHUSD_PERP",
|
|
5081
|
+
// "side": "BUY",
|
|
5082
|
+
// "cumBase": "0",
|
|
5083
|
+
// "executedQty": "0",
|
|
5084
|
+
// "orderId": 71275227732,
|
|
5085
|
+
// "avgPrice": "0.00",
|
|
5086
|
+
// "origQty": "1",
|
|
5087
|
+
// "clientOrderId": "x-xcKtGhcuca5af3acfb5044198c5398",
|
|
5088
|
+
// "positionSide": "BOTH",
|
|
5089
|
+
// "cumQty": "0",
|
|
5090
|
+
// "updateTime": 1707110994334,
|
|
5091
|
+
// "type": "LIMIT",
|
|
5092
|
+
// "pair": "ETHUSD",
|
|
5093
|
+
// "reduceOnly": false,
|
|
5094
|
+
// "price": "2000",
|
|
5095
|
+
// "timeInForce": "GTC",
|
|
5096
|
+
// "status": "NEW"
|
|
5097
|
+
// }
|
|
5098
|
+
//
|
|
5099
|
+
// createOrder: portfolio margin linear swap and future conditional
|
|
5100
|
+
//
|
|
5101
|
+
// {
|
|
5102
|
+
// "newClientStrategyId": "x-xcKtGhcu27f109953d6e4dc0974006",
|
|
5103
|
+
// "strategyId": 3645916,
|
|
5104
|
+
// "strategyStatus": "NEW",
|
|
5105
|
+
// "strategyType": "STOP",
|
|
5106
|
+
// "origQty": "0.010",
|
|
5107
|
+
// "price": "35000.00",
|
|
5108
|
+
// "reduceOnly": false,
|
|
5109
|
+
// "side": "BUY",
|
|
5110
|
+
// "positionSide": "BOTH",
|
|
5111
|
+
// "stopPrice": "45000.00",
|
|
5112
|
+
// "symbol": "BTCUSDT",
|
|
5113
|
+
// "timeInForce": "GTC",
|
|
5114
|
+
// "bookTime": 1707112625879,
|
|
5115
|
+
// "updateTime": 1707112625879,
|
|
5116
|
+
// "workingType": "CONTRACT_PRICE",
|
|
5117
|
+
// "priceProtect": false,
|
|
5118
|
+
// "goodTillDate": 0,
|
|
5119
|
+
// "selfTradePreventionMode": "NONE"
|
|
5120
|
+
// }
|
|
5121
|
+
//
|
|
5122
|
+
// createOrder: portfolio margin inverse swap and future conditional
|
|
5123
|
+
//
|
|
5124
|
+
// {
|
|
5125
|
+
// "newClientStrategyId": "x-xcKtGhcuc6b86f053bb34933850739",
|
|
5126
|
+
// "strategyId": 1423462,
|
|
5127
|
+
// "strategyStatus": "NEW",
|
|
5128
|
+
// "strategyType": "STOP",
|
|
5129
|
+
// "origQty": "1",
|
|
5130
|
+
// "price": "2000",
|
|
5131
|
+
// "reduceOnly": false,
|
|
5132
|
+
// "side": "BUY",
|
|
5133
|
+
// "positionSide": "BOTH",
|
|
5134
|
+
// "stopPrice": "3000",
|
|
5135
|
+
// "symbol": "ETHUSD_PERP",
|
|
5136
|
+
// "timeInForce": "GTC",
|
|
5137
|
+
// "bookTime": 1707113098840,
|
|
5138
|
+
// "updateTime": 1707113098840,
|
|
5139
|
+
// "workingType": "CONTRACT_PRICE",
|
|
5140
|
+
// "priceProtect": false
|
|
5141
|
+
// }
|
|
5142
|
+
//
|
|
5143
|
+
// createOrder: portfolio margin spot margin
|
|
5144
|
+
//
|
|
5145
|
+
// {
|
|
5146
|
+
// "clientOrderId": "x-R4BD3S82e9ef29d8346440f0b28b86",
|
|
5147
|
+
// "cummulativeQuoteQty": "0.00000000",
|
|
5148
|
+
// "executedQty": "0.00000000",
|
|
5149
|
+
// "fills": [],
|
|
5150
|
+
// "orderId": 24684460474,
|
|
5151
|
+
// "origQty": "0.00100000",
|
|
5152
|
+
// "price": "35000.00000000",
|
|
5153
|
+
// "selfTradePreventionMode": "EXPIRE_MAKER",
|
|
5154
|
+
// "side": "BUY",
|
|
5155
|
+
// "status": "NEW",
|
|
5156
|
+
// "symbol": "BTCUSDT",
|
|
5157
|
+
// "timeInForce": "GTC",
|
|
5158
|
+
// "transactTime": 1707113538870,
|
|
5159
|
+
// "type": "LIMIT"
|
|
5160
|
+
// }
|
|
5008
5161
|
//
|
|
5009
5162
|
const code = this.safeString(order, 'code');
|
|
5010
5163
|
if (code !== undefined) {
|
|
5011
5164
|
// cancelOrders/createOrders might have a partial success
|
|
5012
5165
|
return this.safeOrder({ 'info': order, 'status': 'rejected' }, market);
|
|
5013
5166
|
}
|
|
5014
|
-
const status = this.parseOrderStatus(this.
|
|
5167
|
+
const status = this.parseOrderStatus(this.safeString2(order, 'status', 'strategyStatus'));
|
|
5015
5168
|
const marketId = this.safeString(order, 'symbol');
|
|
5016
5169
|
const marketType = ('closePosition' in order) ? 'contract' : 'spot';
|
|
5017
5170
|
const symbol = this.safeSymbol(marketId, market, undefined, marketType);
|
|
@@ -5038,11 +5191,9 @@ export default class binance extends Exchange {
|
|
|
5038
5191
|
// Note this is not the actual cost, since Binance futures uses leverage to calculate margins.
|
|
5039
5192
|
let cost = this.safeString2(order, 'cummulativeQuoteQty', 'cumQuote');
|
|
5040
5193
|
cost = this.safeString(order, 'cumBase', cost);
|
|
5041
|
-
const id = this.safeString(order, 'orderId');
|
|
5042
5194
|
let type = this.safeStringLower(order, 'type');
|
|
5043
5195
|
const side = this.safeStringLower(order, 'side');
|
|
5044
5196
|
const fills = this.safeValue(order, 'fills', []);
|
|
5045
|
-
const clientOrderId = this.safeString(order, 'clientOrderId');
|
|
5046
5197
|
let timeInForce = this.safeString(order, 'timeInForce');
|
|
5047
5198
|
if (timeInForce === 'GTX') {
|
|
5048
5199
|
// GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
|
|
@@ -5065,8 +5216,8 @@ export default class binance extends Exchange {
|
|
|
5065
5216
|
}
|
|
5066
5217
|
return this.safeOrder({
|
|
5067
5218
|
'info': order,
|
|
5068
|
-
'id':
|
|
5069
|
-
'clientOrderId': clientOrderId,
|
|
5219
|
+
'id': this.safeString2(order, 'orderId', 'strategyId'),
|
|
5220
|
+
'clientOrderId': this.safeString2(order, 'clientOrderId', 'newClientStrategyId'),
|
|
5070
5221
|
'timestamp': timestamp,
|
|
5071
5222
|
'datetime': this.iso8601(timestamp),
|
|
5072
5223
|
'lastTradeTimestamp': lastTradeTimestamp,
|
|
@@ -5180,50 +5331,105 @@ export default class binance extends Exchange {
|
|
|
5180
5331
|
* @see https://binance-docs.github.io/apidocs/voptions/en/#new-order-trade
|
|
5181
5332
|
* @see https://binance-docs.github.io/apidocs/spot/en/#new-order-using-sor-trade
|
|
5182
5333
|
* @see https://binance-docs.github.io/apidocs/spot/en/#test-new-order-using-sor-trade
|
|
5334
|
+
* @see https://binance-docs.github.io/apidocs/pm/en/#new-um-order-trade
|
|
5335
|
+
* @see https://binance-docs.github.io/apidocs/pm/en/#new-cm-order-trade
|
|
5336
|
+
* @see https://binance-docs.github.io/apidocs/pm/en/#new-margin-order-trade
|
|
5337
|
+
* @see https://binance-docs.github.io/apidocs/pm/en/#new-um-conditional-order-trade
|
|
5338
|
+
* @see https://binance-docs.github.io/apidocs/pm/en/#new-cm-conditional-order-trade
|
|
5183
5339
|
* @param {string} symbol unified symbol of the market to create an order in
|
|
5184
5340
|
* @param {string} type 'market' or 'limit' or 'STOP_LOSS' or 'STOP_LOSS_LIMIT' or 'TAKE_PROFIT' or 'TAKE_PROFIT_LIMIT' or 'STOP'
|
|
5185
5341
|
* @param {string} side 'buy' or 'sell'
|
|
5186
|
-
* @param {float} amount how much of
|
|
5187
|
-
* @param {float} [price] the price
|
|
5342
|
+
* @param {float} amount how much of you want to trade in units of the base currency
|
|
5343
|
+
* @param {float} [price] the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
5188
5344
|
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
5345
|
+
* @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.
|
|
5189
5346
|
* @param {string} [params.marginMode] 'cross' or 'isolated', for spot margin trading
|
|
5190
5347
|
* @param {boolean} [params.sor] *spot only* whether to use SOR (Smart Order Routing) or not, default is false
|
|
5191
5348
|
* @param {boolean} [params.test] *spot only* whether to use the test endpoint or not, default is false
|
|
5192
5349
|
* @param {float} [params.trailingPercent] the percent to trail away from the current market price
|
|
5193
5350
|
* @param {float} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
|
|
5351
|
+
* @param {float} [params.triggerPrice] the price that a trigger order is triggered at
|
|
5352
|
+
* @param {float} [params.stopLossPrice] the price that a stop loss order is triggered at
|
|
5353
|
+
* @param {float} [params.takeProfitPrice] the price that a take profit order is triggered at
|
|
5354
|
+
* @param {boolean} [params.portfolioMargin] set to true if you would like to create an order in a portfolio margin account
|
|
5194
5355
|
* @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure}
|
|
5195
5356
|
*/
|
|
5196
5357
|
await this.loadMarkets();
|
|
5197
5358
|
const market = this.market(symbol);
|
|
5198
5359
|
const marketType = this.safeString(params, 'type', market['type']);
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
|
|
5360
|
+
let marginMode = undefined;
|
|
5361
|
+
[marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
|
|
5362
|
+
let isPortfolioMargin = undefined;
|
|
5363
|
+
[isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'createOrder', 'papi', 'portfolioMargin', false);
|
|
5364
|
+
const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
|
|
5365
|
+
const stopLossPrice = this.safeString(params, 'stopLossPrice');
|
|
5366
|
+
const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
|
|
5367
|
+
const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
|
|
5368
|
+
const isTrailingPercentOrder = trailingPercent !== undefined;
|
|
5369
|
+
const isStopLoss = stopLossPrice !== undefined;
|
|
5370
|
+
const isTakeProfit = takeProfitPrice !== undefined;
|
|
5371
|
+
const isConditional = (triggerPrice !== undefined) || isTrailingPercentOrder || isStopLoss || isTakeProfit;
|
|
5372
|
+
const sor = this.safeBool2(params, 'sor', 'SOR', false);
|
|
5373
|
+
const test = this.safeBool(params, 'test', false);
|
|
5374
|
+
params = this.omit(params, ['sor', 'SOR', 'test']);
|
|
5375
|
+
if (isPortfolioMargin) {
|
|
5376
|
+
params['portfolioMargin'] = isPortfolioMargin;
|
|
5377
|
+
}
|
|
5202
5378
|
const request = this.createOrderRequest(symbol, type, side, amount, price, params);
|
|
5203
|
-
let
|
|
5204
|
-
if (
|
|
5205
|
-
|
|
5379
|
+
let response = undefined;
|
|
5380
|
+
if (market['option']) {
|
|
5381
|
+
response = await this.eapiPrivatePostOrder(request);
|
|
5382
|
+
}
|
|
5383
|
+
else if (sor) {
|
|
5384
|
+
if (test) {
|
|
5385
|
+
response = await this.privatePostSorOrderTest(request);
|
|
5386
|
+
}
|
|
5387
|
+
else {
|
|
5388
|
+
response = await this.privatePostSorOrder(request);
|
|
5389
|
+
}
|
|
5206
5390
|
}
|
|
5207
5391
|
else if (market['linear']) {
|
|
5208
|
-
|
|
5392
|
+
if (isPortfolioMargin) {
|
|
5393
|
+
if (isConditional) {
|
|
5394
|
+
response = await this.papiPostUmConditionalOrder(request);
|
|
5395
|
+
}
|
|
5396
|
+
else {
|
|
5397
|
+
response = await this.papiPostUmOrder(request);
|
|
5398
|
+
}
|
|
5399
|
+
}
|
|
5400
|
+
else {
|
|
5401
|
+
response = await this.fapiPrivatePostOrder(request);
|
|
5402
|
+
}
|
|
5209
5403
|
}
|
|
5210
5404
|
else if (market['inverse']) {
|
|
5211
|
-
|
|
5405
|
+
if (isPortfolioMargin) {
|
|
5406
|
+
if (isConditional) {
|
|
5407
|
+
response = await this.papiPostCmConditionalOrder(request);
|
|
5408
|
+
}
|
|
5409
|
+
else {
|
|
5410
|
+
response = await this.papiPostCmOrder(request);
|
|
5411
|
+
}
|
|
5412
|
+
}
|
|
5413
|
+
else {
|
|
5414
|
+
response = await this.dapiPrivatePostOrder(request);
|
|
5415
|
+
}
|
|
5212
5416
|
}
|
|
5213
5417
|
else if (marketType === 'margin' || marginMode !== undefined) {
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5418
|
+
if (isPortfolioMargin) {
|
|
5419
|
+
response = await this.papiPostMarginOrder(request);
|
|
5420
|
+
}
|
|
5421
|
+
else {
|
|
5422
|
+
response = await this.sapiPostMarginOrder(request);
|
|
5423
|
+
}
|
|
5218
5424
|
}
|
|
5219
|
-
|
|
5220
|
-
if (market['spot'] || marketType === 'margin') {
|
|
5221
|
-
const test = this.safeBool(query, 'test', false);
|
|
5425
|
+
else {
|
|
5222
5426
|
if (test) {
|
|
5223
|
-
|
|
5427
|
+
response = await this.privatePostOrderTest(request);
|
|
5428
|
+
}
|
|
5429
|
+
else {
|
|
5430
|
+
response = await this.privatePostOrder(request);
|
|
5224
5431
|
}
|
|
5225
5432
|
}
|
|
5226
|
-
const response = await this[method](request);
|
|
5227
5433
|
return this.parseOrder(response, market);
|
|
5228
5434
|
}
|
|
5229
5435
|
createOrderRequest(symbol, type, side, amount, price = undefined, params = {}) {
|
|
@@ -5231,16 +5437,13 @@ export default class binance extends Exchange {
|
|
|
5231
5437
|
* @method
|
|
5232
5438
|
* @ignore
|
|
5233
5439
|
* @name binance#createOrderRequest
|
|
5234
|
-
* @description helper function to build request
|
|
5440
|
+
* @description helper function to build the request
|
|
5235
5441
|
* @param {string} symbol unified symbol of the market to create an order in
|
|
5236
|
-
* @param {string} type 'market' or 'limit'
|
|
5442
|
+
* @param {string} type 'market' or 'limit'
|
|
5237
5443
|
* @param {string} side 'buy' or 'sell'
|
|
5238
|
-
* @param {float} amount how much
|
|
5239
|
-
* @param {float
|
|
5240
|
-
* @param {object} params extra parameters specific to the exchange API endpoint
|
|
5241
|
-
* @param {string|undefined} params.marginMode 'cross' or 'isolated', for spot margin trading
|
|
5242
|
-
* @param {float} [params.trailingPercent] the percent to trail away from the current market price
|
|
5243
|
-
* @param {float} [params.trailingTriggerPrice] the price to trigger a trailing order, default uses the price argument
|
|
5444
|
+
* @param {float} amount how much you want to trade in units of the base currency
|
|
5445
|
+
* @param {float} [price] the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
|
5446
|
+
* @param {object} [params] extra parameters specific to the exchange API endpoint
|
|
5244
5447
|
* @returns {object} request to be sent to the exchange
|
|
5245
5448
|
*/
|
|
5246
5449
|
const market = this.market(symbol);
|
|
@@ -5249,35 +5452,54 @@ export default class binance extends Exchange {
|
|
|
5249
5452
|
const initialUppercaseType = type.toUpperCase();
|
|
5250
5453
|
const isMarketOrder = initialUppercaseType === 'MARKET';
|
|
5251
5454
|
const isLimitOrder = initialUppercaseType === 'LIMIT';
|
|
5252
|
-
const postOnly = this.isPostOnly(isMarketOrder, initialUppercaseType === 'LIMIT_MAKER', params);
|
|
5253
|
-
const triggerPrice = this.safeValue2(params, 'triggerPrice', 'stopPrice');
|
|
5254
|
-
const stopLossPrice = this.safeValue(params, 'stopLossPrice', triggerPrice); // fallback to stopLoss
|
|
5255
|
-
const takeProfitPrice = this.safeValue(params, 'takeProfitPrice');
|
|
5256
|
-
const trailingDelta = this.safeValue(params, 'trailingDelta');
|
|
5257
|
-
const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice', this.numberToString(price));
|
|
5258
|
-
const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
|
|
5259
|
-
const isTrailingPercentOrder = trailingPercent !== undefined;
|
|
5260
|
-
const isStopLoss = stopLossPrice !== undefined || trailingDelta !== undefined;
|
|
5261
|
-
const isTakeProfit = takeProfitPrice !== undefined;
|
|
5262
|
-
params = this.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent']);
|
|
5263
|
-
const [marginMode, query] = this.handleMarginModeAndParams('createOrder', params);
|
|
5264
5455
|
const request = {
|
|
5265
5456
|
'symbol': market['id'],
|
|
5266
5457
|
'side': side.toUpperCase(),
|
|
5267
5458
|
};
|
|
5268
|
-
|
|
5269
|
-
|
|
5270
|
-
|
|
5271
|
-
|
|
5459
|
+
let isPortfolioMargin = undefined;
|
|
5460
|
+
[isPortfolioMargin, params] = this.handleOptionAndParams2(params, 'createOrder', 'papi', 'portfolioMargin', false);
|
|
5461
|
+
let marginMode = undefined;
|
|
5462
|
+
[marginMode, params] = this.handleMarginModeAndParams('createOrder', params);
|
|
5463
|
+
if ((marketType === 'margin') || (marginMode !== undefined) || market['option']) {
|
|
5464
|
+
// for swap and future reduceOnly is a string that cant be sent with close position set to true or in hedge mode
|
|
5465
|
+
const reduceOnly = this.safeBool(params, 'reduceOnly', false);
|
|
5466
|
+
params = this.omit(params, 'reduceOnly');
|
|
5467
|
+
if (market['option']) {
|
|
5468
|
+
request['reduceOnly'] = reduceOnly;
|
|
5469
|
+
}
|
|
5470
|
+
else {
|
|
5471
|
+
if (reduceOnly) {
|
|
5472
|
+
request['sideEffectType'] = 'AUTO_REPAY';
|
|
5473
|
+
}
|
|
5272
5474
|
}
|
|
5273
5475
|
}
|
|
5274
|
-
if (
|
|
5275
|
-
const
|
|
5276
|
-
if (
|
|
5277
|
-
|
|
5278
|
-
|
|
5476
|
+
if (!isPortfolioMargin) {
|
|
5477
|
+
const postOnly = this.isPostOnly(isMarketOrder, initialUppercaseType === 'LIMIT_MAKER', params);
|
|
5478
|
+
if (market['spot'] || marketType === 'margin') {
|
|
5479
|
+
// only supported for spot/margin api (all margin markets are spot markets)
|
|
5480
|
+
if (postOnly) {
|
|
5481
|
+
type = 'LIMIT_MAKER';
|
|
5482
|
+
}
|
|
5483
|
+
if (marginMode === 'isolated') {
|
|
5484
|
+
request['isIsolated'] = true;
|
|
5485
|
+
}
|
|
5486
|
+
}
|
|
5487
|
+
if (market['contract'] && postOnly) {
|
|
5488
|
+
request['timeInForce'] = 'GTX';
|
|
5279
5489
|
}
|
|
5280
5490
|
}
|
|
5491
|
+
const triggerPrice = this.safeString2(params, 'triggerPrice', 'stopPrice');
|
|
5492
|
+
const stopLossPrice = this.safeString(params, 'stopLossPrice', triggerPrice); // fallback to stopLoss
|
|
5493
|
+
const takeProfitPrice = this.safeString(params, 'takeProfitPrice');
|
|
5494
|
+
const trailingDelta = this.safeString(params, 'trailingDelta');
|
|
5495
|
+
const trailingTriggerPrice = this.safeString2(params, 'trailingTriggerPrice', 'activationPrice', this.numberToString(price));
|
|
5496
|
+
const trailingPercent = this.safeString2(params, 'trailingPercent', 'callbackRate');
|
|
5497
|
+
const isTrailingPercentOrder = trailingPercent !== undefined;
|
|
5498
|
+
const isStopLoss = stopLossPrice !== undefined || trailingDelta !== undefined;
|
|
5499
|
+
const isTakeProfit = takeProfitPrice !== undefined;
|
|
5500
|
+
const isTriggerOrder = triggerPrice !== undefined;
|
|
5501
|
+
const isConditional = isTriggerOrder || isTrailingPercentOrder || isStopLoss || isTakeProfit;
|
|
5502
|
+
const isPortfolioMarginConditional = (isPortfolioMargin && isConditional);
|
|
5281
5503
|
let uppercaseType = type.toUpperCase();
|
|
5282
5504
|
let stopPrice = undefined;
|
|
5283
5505
|
if (isTrailingPercentOrder) {
|
|
@@ -5307,24 +5529,14 @@ export default class binance extends Exchange {
|
|
|
5307
5529
|
uppercaseType = market['contract'] ? 'TAKE_PROFIT' : 'TAKE_PROFIT_LIMIT';
|
|
5308
5530
|
}
|
|
5309
5531
|
}
|
|
5310
|
-
if (marginMode === 'isolated') {
|
|
5311
|
-
request['isIsolated'] = true;
|
|
5312
|
-
}
|
|
5313
|
-
if (clientOrderId === undefined) {
|
|
5314
|
-
const broker = this.safeValue(this.options, 'broker', {});
|
|
5315
|
-
const defaultId = (market['contract']) ? 'x-xcKtGhcu' : 'x-R4BD3S82';
|
|
5316
|
-
const brokerId = this.safeString(broker, marketType, defaultId);
|
|
5317
|
-
request['newClientOrderId'] = brokerId + this.uuid22();
|
|
5318
|
-
}
|
|
5319
|
-
else {
|
|
5320
|
-
request['newClientOrderId'] = clientOrderId;
|
|
5321
|
-
}
|
|
5322
5532
|
if ((marketType === 'spot') || (marketType === 'margin')) {
|
|
5323
|
-
request['newOrderRespType'] = this.
|
|
5533
|
+
request['newOrderRespType'] = this.safeString(this.options['newOrderRespType'], type, 'RESULT'); // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
|
|
5324
5534
|
}
|
|
5325
5535
|
else {
|
|
5326
5536
|
// swap, futures and options
|
|
5327
|
-
|
|
5537
|
+
if (!isPortfolioMargin) {
|
|
5538
|
+
request['newOrderRespType'] = 'RESULT'; // "ACK", "RESULT", default "ACK"
|
|
5539
|
+
}
|
|
5328
5540
|
}
|
|
5329
5541
|
if (market['option']) {
|
|
5330
5542
|
if (type === 'market') {
|
|
@@ -5332,7 +5544,7 @@ export default class binance extends Exchange {
|
|
|
5332
5544
|
}
|
|
5333
5545
|
}
|
|
5334
5546
|
else {
|
|
5335
|
-
const validOrderTypes = this.
|
|
5547
|
+
const validOrderTypes = this.safeList(market['info'], 'orderTypes');
|
|
5336
5548
|
if (!this.inArray(uppercaseType, validOrderTypes)) {
|
|
5337
5549
|
if (initialUppercaseType !== uppercaseType) {
|
|
5338
5550
|
throw new InvalidOrder(this.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders');
|
|
@@ -5342,7 +5554,18 @@ export default class binance extends Exchange {
|
|
|
5342
5554
|
}
|
|
5343
5555
|
}
|
|
5344
5556
|
}
|
|
5345
|
-
|
|
5557
|
+
const clientOrderIdRequest = isPortfolioMarginConditional ? 'newClientStrategyId' : 'newClientOrderId';
|
|
5558
|
+
if (clientOrderId === undefined) {
|
|
5559
|
+
const broker = this.safeDict(this.options, 'broker', {});
|
|
5560
|
+
const defaultId = (market['contract']) ? 'x-xcKtGhcu' : 'x-R4BD3S82';
|
|
5561
|
+
const brokerId = this.safeString(broker, marketType, defaultId);
|
|
5562
|
+
request[clientOrderIdRequest] = brokerId + this.uuid22();
|
|
5563
|
+
}
|
|
5564
|
+
else {
|
|
5565
|
+
request[clientOrderIdRequest] = clientOrderId;
|
|
5566
|
+
}
|
|
5567
|
+
const typeRequest = isPortfolioMarginConditional ? 'strategyType' : 'type';
|
|
5568
|
+
request[typeRequest] = uppercaseType;
|
|
5346
5569
|
// additional required fields depending on the order type
|
|
5347
5570
|
let timeInForceIsRequired = false;
|
|
5348
5571
|
let priceIsRequired = false;
|
|
@@ -5370,9 +5593,9 @@ export default class binance extends Exchange {
|
|
|
5370
5593
|
//
|
|
5371
5594
|
if (uppercaseType === 'MARKET') {
|
|
5372
5595
|
if (market['spot']) {
|
|
5373
|
-
const quoteOrderQty = this.
|
|
5596
|
+
const quoteOrderQty = this.safeBool(this.options, 'quoteOrderQty', true);
|
|
5374
5597
|
if (quoteOrderQty) {
|
|
5375
|
-
const quoteOrderQtyNew = this.
|
|
5598
|
+
const quoteOrderQtyNew = this.safeString2(params, 'quoteOrderQty', 'cost');
|
|
5376
5599
|
const precision = market['precision']['price'];
|
|
5377
5600
|
if (quoteOrderQtyNew !== undefined) {
|
|
5378
5601
|
request['quoteOrderQty'] = this.decimalToPrecision(quoteOrderQtyNew, TRUNCATE, precision, this.precisionMode);
|
|
@@ -5423,7 +5646,7 @@ export default class binance extends Exchange {
|
|
|
5423
5646
|
priceIsRequired = true;
|
|
5424
5647
|
}
|
|
5425
5648
|
else if ((uppercaseType === 'STOP_MARKET') || (uppercaseType === 'TAKE_PROFIT_MARKET')) {
|
|
5426
|
-
const closePosition = this.
|
|
5649
|
+
const closePosition = this.safeBool(params, 'closePosition');
|
|
5427
5650
|
if (closePosition === undefined) {
|
|
5428
5651
|
quantityIsRequired = true;
|
|
5429
5652
|
}
|
|
@@ -5436,7 +5659,13 @@ export default class binance extends Exchange {
|
|
|
5436
5659
|
}
|
|
5437
5660
|
}
|
|
5438
5661
|
if (quantityIsRequired) {
|
|
5439
|
-
|
|
5662
|
+
// portfolio margin has a different amount precision
|
|
5663
|
+
if (isPortfolioMargin) {
|
|
5664
|
+
request['quantity'] = this.parseToNumeric(amount);
|
|
5665
|
+
}
|
|
5666
|
+
else {
|
|
5667
|
+
request['quantity'] = this.amountToPrecision(symbol, amount);
|
|
5668
|
+
}
|
|
5440
5669
|
}
|
|
5441
5670
|
if (priceIsRequired) {
|
|
5442
5671
|
if (price === undefined) {
|
|
@@ -5447,9 +5676,6 @@ export default class binance extends Exchange {
|
|
|
5447
5676
|
if (timeInForceIsRequired) {
|
|
5448
5677
|
request['timeInForce'] = this.options['defaultTimeInForce']; // 'GTC' = Good To Cancel (default), 'IOC' = Immediate Or Cancel
|
|
5449
5678
|
}
|
|
5450
|
-
if (market['contract'] && postOnly) {
|
|
5451
|
-
request['timeInForce'] = 'GTX';
|
|
5452
|
-
}
|
|
5453
5679
|
if (stopPriceIsRequired) {
|
|
5454
5680
|
if (market['contract']) {
|
|
5455
5681
|
if (stopPrice === undefined) {
|
|
@@ -5466,11 +5692,26 @@ export default class binance extends Exchange {
|
|
|
5466
5692
|
request['stopPrice'] = this.priceToPrecision(symbol, stopPrice);
|
|
5467
5693
|
}
|
|
5468
5694
|
}
|
|
5695
|
+
if (!isPortfolioMargin) {
|
|
5696
|
+
const postOnly = this.isPostOnly(isMarketOrder, initialUppercaseType === 'LIMIT_MAKER', params);
|
|
5697
|
+
if (market['spot'] || marketType === 'margin') {
|
|
5698
|
+
// only supported for spot/margin api (all margin markets are spot markets)
|
|
5699
|
+
if (postOnly) {
|
|
5700
|
+
type = 'LIMIT_MAKER';
|
|
5701
|
+
}
|
|
5702
|
+
if (marginMode === 'isolated') {
|
|
5703
|
+
request['isIsolated'] = true;
|
|
5704
|
+
}
|
|
5705
|
+
}
|
|
5706
|
+
if (market['contract'] && postOnly) {
|
|
5707
|
+
request['timeInForce'] = 'GTX';
|
|
5708
|
+
}
|
|
5709
|
+
}
|
|
5469
5710
|
// remove timeInForce from params because PO is only used by this.isPostOnly and it's not a valid value for Binance
|
|
5470
5711
|
if (this.safeString(params, 'timeInForce') === 'PO') {
|
|
5471
|
-
params = this.omit(params,
|
|
5712
|
+
params = this.omit(params, 'timeInForce');
|
|
5472
5713
|
}
|
|
5473
|
-
const requestParams = this.omit(params, ['
|
|
5714
|
+
const requestParams = this.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent', 'quoteOrderQty', 'cost', 'test']);
|
|
5474
5715
|
return this.extend(request, requestParams);
|
|
5475
5716
|
}
|
|
5476
5717
|
async createMarketOrderWithCost(symbol, side, cost, params = {}) {
|