ccxt 4.2.35__py2.py3-none-any.whl → 4.2.37__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ccxt/__init__.py +1 -1
- ccxt/abstract/bitfinex2.py +122 -122
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +347 -107
- ccxt/async_support/bitfinex.py +21 -0
- ccxt/async_support/bitfinex2.py +122 -122
- ccxt/async_support/bitget.py +23 -32
- ccxt/async_support/bithumb.py +14 -0
- ccxt/async_support/bitmex.py +22 -3
- ccxt/async_support/bybit.py +11 -4
- ccxt/async_support/woo.py +60 -35
- ccxt/base/exchange.py +1 -1
- ccxt/binance.py +347 -107
- ccxt/bitfinex.py +21 -0
- ccxt/bitfinex2.py +122 -122
- ccxt/bitget.py +23 -32
- ccxt/bithumb.py +14 -0
- ccxt/bitmex.py +22 -3
- ccxt/bybit.py +11 -4
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +2 -2
- ccxt/pro/gemini.py +165 -3
- ccxt/test/test_async.py +8 -6
- ccxt/test/test_sync.py +8 -6
- ccxt/woo.py +60 -35
- {ccxt-4.2.35.dist-info → ccxt-4.2.37.dist-info}/METADATA +6 -6
- {ccxt-4.2.35.dist-info → ccxt-4.2.37.dist-info}/RECORD +30 -30
- {ccxt-4.2.35.dist-info → ccxt-4.2.37.dist-info}/WHEEL +0 -0
- {ccxt-4.2.35.dist-info → ccxt-4.2.37.dist-info}/top_level.txt +0 -0
ccxt/binance.py
CHANGED
@@ -4545,7 +4545,7 @@ class binance(Exchange, ImplicitAPI):
|
|
4545
4545
|
if price is None:
|
4546
4546
|
raise InvalidOrder(self.id + ' editOrder() requires a price argument for a ' + type + ' order')
|
4547
4547
|
request['price'] = self.price_to_precision(symbol, price)
|
4548
|
-
if timeInForceIsRequired:
|
4548
|
+
if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None):
|
4549
4549
|
request['timeInForce'] = self.options['defaultTimeInForce'] # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
|
4550
4550
|
if stopPriceIsRequired:
|
4551
4551
|
if stopPrice is None:
|
@@ -4832,19 +4832,155 @@ class binance(Exchange, ImplicitAPI):
|
|
4832
4832
|
# "lastTrade": {"id":"69","time":"1676084430567","price":"24.9","qty":"1.00"},
|
4833
4833
|
# "mmp": False
|
4834
4834
|
# }
|
4835
|
-
#
|
4835
|
+
#
|
4836
4836
|
# cancelOrders/createOrders
|
4837
|
-
#
|
4838
|
-
#
|
4839
|
-
#
|
4837
|
+
#
|
4838
|
+
# {
|
4839
|
+
# "code": -4005,
|
4840
|
+
# "msg": "Quantity greater than max quantity."
|
4841
|
+
# }
|
4842
|
+
#
|
4843
|
+
# createOrder, fetchOpenOrders: portfolio margin linear swap and future
|
4844
|
+
#
|
4845
|
+
# {
|
4846
|
+
# "symbol": "BTCUSDT",
|
4847
|
+
# "side": "BUY",
|
4848
|
+
# "executedQty": "0.000",
|
4849
|
+
# "orderId": 258649539704,
|
4850
|
+
# "goodTillDate": 0,
|
4851
|
+
# "avgPrice": "0",
|
4852
|
+
# "origQty": "0.010",
|
4853
|
+
# "clientOrderId": "x-xcKtGhcu02573c6f15e544e990057b",
|
4854
|
+
# "positionSide": "BOTH",
|
4855
|
+
# "cumQty": "0.000",
|
4856
|
+
# "updateTime": 1707110415436,
|
4857
|
+
# "type": "LIMIT",
|
4858
|
+
# "reduceOnly": False,
|
4859
|
+
# "price": "35000.00",
|
4860
|
+
# "cumQuote": "0.00000",
|
4861
|
+
# "selfTradePreventionMode": "NONE",
|
4862
|
+
# "timeInForce": "GTC",
|
4863
|
+
# "status": "NEW"
|
4864
|
+
# }
|
4865
|
+
#
|
4866
|
+
# createOrder, fetchOpenOrders: portfolio margin inverse swap and future
|
4867
|
+
#
|
4868
|
+
# {
|
4869
|
+
# "symbol": "ETHUSD_PERP",
|
4870
|
+
# "side": "BUY",
|
4871
|
+
# "cumBase": "0",
|
4872
|
+
# "executedQty": "0",
|
4873
|
+
# "orderId": 71275227732,
|
4874
|
+
# "avgPrice": "0.00",
|
4875
|
+
# "origQty": "1",
|
4876
|
+
# "clientOrderId": "x-xcKtGhcuca5af3acfb5044198c5398",
|
4877
|
+
# "positionSide": "BOTH",
|
4878
|
+
# "cumQty": "0",
|
4879
|
+
# "updateTime": 1707110994334,
|
4880
|
+
# "type": "LIMIT",
|
4881
|
+
# "pair": "ETHUSD",
|
4882
|
+
# "reduceOnly": False,
|
4883
|
+
# "price": "2000",
|
4884
|
+
# "timeInForce": "GTC",
|
4885
|
+
# "status": "NEW"
|
4886
|
+
# }
|
4887
|
+
#
|
4888
|
+
# createOrder, fetchOpenOrders: portfolio margin linear swap and future conditional
|
4889
|
+
#
|
4890
|
+
# {
|
4891
|
+
# "newClientStrategyId": "x-xcKtGhcu27f109953d6e4dc0974006",
|
4892
|
+
# "strategyId": 3645916,
|
4893
|
+
# "strategyStatus": "NEW",
|
4894
|
+
# "strategyType": "STOP",
|
4895
|
+
# "origQty": "0.010",
|
4896
|
+
# "price": "35000.00",
|
4897
|
+
# "reduceOnly": False,
|
4898
|
+
# "side": "BUY",
|
4899
|
+
# "positionSide": "BOTH",
|
4900
|
+
# "stopPrice": "45000.00",
|
4901
|
+
# "symbol": "BTCUSDT",
|
4902
|
+
# "timeInForce": "GTC",
|
4903
|
+
# "bookTime": 1707112625879,
|
4904
|
+
# "updateTime": 1707112625879,
|
4905
|
+
# "workingType": "CONTRACT_PRICE",
|
4906
|
+
# "priceProtect": False,
|
4907
|
+
# "goodTillDate": 0,
|
4908
|
+
# "selfTradePreventionMode": "NONE"
|
4909
|
+
# }
|
4910
|
+
#
|
4911
|
+
# createOrder, fetchOpenOrders: portfolio margin inverse swap and future conditional
|
4912
|
+
#
|
4913
|
+
# {
|
4914
|
+
# "newClientStrategyId": "x-xcKtGhcuc6b86f053bb34933850739",
|
4915
|
+
# "strategyId": 1423462,
|
4916
|
+
# "strategyStatus": "NEW",
|
4917
|
+
# "strategyType": "STOP",
|
4918
|
+
# "origQty": "1",
|
4919
|
+
# "price": "2000",
|
4920
|
+
# "reduceOnly": False,
|
4921
|
+
# "side": "BUY",
|
4922
|
+
# "positionSide": "BOTH",
|
4923
|
+
# "stopPrice": "3000",
|
4924
|
+
# "symbol": "ETHUSD_PERP",
|
4925
|
+
# "timeInForce": "GTC",
|
4926
|
+
# "bookTime": 1707113098840,
|
4927
|
+
# "updateTime": 1707113098840,
|
4928
|
+
# "workingType": "CONTRACT_PRICE",
|
4929
|
+
# "priceProtect": False
|
4930
|
+
# }
|
4931
|
+
#
|
4932
|
+
# createOrder, cancelAllOrders: portfolio margin spot margin
|
4933
|
+
#
|
4934
|
+
# {
|
4935
|
+
# "clientOrderId": "x-R4BD3S82e9ef29d8346440f0b28b86",
|
4936
|
+
# "cummulativeQuoteQty": "0.00000000",
|
4937
|
+
# "executedQty": "0.00000000",
|
4938
|
+
# "fills": [],
|
4939
|
+
# "orderId": 24684460474,
|
4940
|
+
# "origQty": "0.00100000",
|
4941
|
+
# "price": "35000.00000000",
|
4942
|
+
# "selfTradePreventionMode": "EXPIRE_MAKER",
|
4943
|
+
# "side": "BUY",
|
4944
|
+
# "status": "NEW",
|
4945
|
+
# "symbol": "BTCUSDT",
|
4946
|
+
# "timeInForce": "GTC",
|
4947
|
+
# "transactTime": 1707113538870,
|
4948
|
+
# "type": "LIMIT"
|
4949
|
+
# }
|
4950
|
+
#
|
4951
|
+
# fetchOpenOrders: portfolio margin spot margin
|
4952
|
+
#
|
4953
|
+
# {
|
4954
|
+
# "symbol": "BTCUSDT",
|
4955
|
+
# "orderId": 24700763749,
|
4956
|
+
# "clientOrderId": "x-R4BD3S826f724c2a4af6425f98c7b6",
|
4957
|
+
# "price": "35000.00000000",
|
4958
|
+
# "origQty": "0.00100000",
|
4959
|
+
# "executedQty": "0.00000000",
|
4960
|
+
# "cummulativeQuoteQty": "0.00000000",
|
4961
|
+
# "status": "NEW",
|
4962
|
+
# "timeInForce": "GTC",
|
4963
|
+
# "type": "LIMIT",
|
4964
|
+
# "side": "BUY",
|
4965
|
+
# "stopPrice": "0.00000000",
|
4966
|
+
# "icebergQty": "0.00000000",
|
4967
|
+
# "time": 1707199187679,
|
4968
|
+
# "updateTime": 1707199187679,
|
4969
|
+
# "isWorking": True,
|
4970
|
+
# "accountId": 200180970,
|
4971
|
+
# "selfTradePreventionMode": "EXPIRE_MAKER",
|
4972
|
+
# "preventedMatchId": null,
|
4973
|
+
# "preventedQuantity": null
|
4974
|
+
# }
|
4840
4975
|
#
|
4841
4976
|
code = self.safe_string(order, 'code')
|
4842
4977
|
if code is not None:
|
4843
4978
|
# cancelOrders/createOrders might have a partial success
|
4844
4979
|
return self.safe_order({'info': order, 'status': 'rejected'}, market)
|
4845
|
-
status = self.parse_order_status(self.
|
4980
|
+
status = self.parse_order_status(self.safe_string_2(order, 'status', 'strategyStatus'))
|
4846
4981
|
marketId = self.safe_string(order, 'symbol')
|
4847
|
-
|
4982
|
+
isContract = ('positionSide' in order) or ('cumQuote' in order)
|
4983
|
+
marketType = 'contract' if isContract else 'spot'
|
4848
4984
|
symbol = self.safe_symbol(marketId, market, None, marketType)
|
4849
4985
|
filled = self.safe_string(order, 'executedQty', '0')
|
4850
4986
|
timestamp = self.safe_integer_n(order, ['time', 'createTime', 'workingTime', 'transactTime', 'updateTime']) # order of the keys matters here
|
@@ -4865,11 +5001,9 @@ class binance(Exchange, ImplicitAPI):
|
|
4865
5001
|
# Note self is not the actual cost, since Binance futures uses leverage to calculate margins.
|
4866
5002
|
cost = self.safe_string_2(order, 'cummulativeQuoteQty', 'cumQuote')
|
4867
5003
|
cost = self.safe_string(order, 'cumBase', cost)
|
4868
|
-
id = self.safe_string(order, 'orderId')
|
4869
5004
|
type = self.safe_string_lower(order, 'type')
|
4870
5005
|
side = self.safe_string_lower(order, 'side')
|
4871
5006
|
fills = self.safe_value(order, 'fills', [])
|
4872
|
-
clientOrderId = self.safe_string(order, 'clientOrderId')
|
4873
5007
|
timeInForce = self.safe_string(order, 'timeInForce')
|
4874
5008
|
if timeInForce == 'GTX':
|
4875
5009
|
# GTX means "Good Till Crossing" and is an equivalent way of saying Post Only
|
@@ -4889,8 +5023,8 @@ class binance(Exchange, ImplicitAPI):
|
|
4889
5023
|
}
|
4890
5024
|
return self.safe_order({
|
4891
5025
|
'info': order,
|
4892
|
-
'id':
|
4893
|
-
'clientOrderId': clientOrderId,
|
5026
|
+
'id': self.safe_string_2(order, 'orderId', 'strategyId'),
|
5027
|
+
'clientOrderId': self.safe_string_2(order, 'clientOrderId', 'newClientStrategyId'),
|
4894
5028
|
'timestamp': timestamp,
|
4895
5029
|
'datetime': self.iso8601(timestamp),
|
4896
5030
|
'lastTradeTimestamp': lastTradeTimestamp,
|
@@ -4995,58 +5129,96 @@ class binance(Exchange, ImplicitAPI):
|
|
4995
5129
|
:see: https://binance-docs.github.io/apidocs/voptions/en/#new-order-trade
|
4996
5130
|
:see: https://binance-docs.github.io/apidocs/spot/en/#new-order-using-sor-trade
|
4997
5131
|
:see: https://binance-docs.github.io/apidocs/spot/en/#test-new-order-using-sor-trade
|
5132
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#new-um-order-trade
|
5133
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#new-cm-order-trade
|
5134
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#new-margin-order-trade
|
5135
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#new-um-conditional-order-trade
|
5136
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#new-cm-conditional-order-trade
|
4998
5137
|
:param str symbol: unified symbol of the market to create an order in
|
4999
5138
|
:param str type: 'market' or 'limit' or 'STOP_LOSS' or 'STOP_LOSS_LIMIT' or 'TAKE_PROFIT' or 'TAKE_PROFIT_LIMIT' or 'STOP'
|
5000
5139
|
:param str side: 'buy' or 'sell'
|
5001
|
-
:param float amount: how much of
|
5002
|
-
:param float [price]: the price
|
5140
|
+
:param float amount: how much of you want to trade in units of the base currency
|
5141
|
+
:param float [price]: the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
5003
5142
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5143
|
+
:param str [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.
|
5004
5144
|
:param str [params.marginMode]: 'cross' or 'isolated', for spot margin trading
|
5005
5145
|
:param boolean [params.sor]: *spot only* whether to use SOR(Smart Order Routing) or not, default is False
|
5006
5146
|
:param boolean [params.test]: *spot only* whether to use the test endpoint or not, default is False
|
5007
5147
|
:param float [params.trailingPercent]: the percent to trail away from the current market price
|
5008
5148
|
:param float [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
|
5149
|
+
:param float [params.triggerPrice]: the price that a trigger order is triggered at
|
5150
|
+
:param float [params.stopLossPrice]: the price that a stop loss order is triggered at
|
5151
|
+
:param float [params.takeProfitPrice]: the price that a take profit order is triggered at
|
5152
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to create an order in a portfolio margin account
|
5009
5153
|
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
5010
5154
|
"""
|
5011
5155
|
self.load_markets()
|
5012
5156
|
market = self.market(symbol)
|
5013
5157
|
marketType = self.safe_string(params, 'type', market['type'])
|
5014
|
-
marginMode
|
5015
|
-
|
5016
|
-
|
5158
|
+
marginMode = None
|
5159
|
+
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
5160
|
+
isPortfolioMargin = None
|
5161
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'createOrder', 'papi', 'portfolioMargin', False)
|
5162
|
+
triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
|
5163
|
+
stopLossPrice = self.safe_string(params, 'stopLossPrice')
|
5164
|
+
takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
|
5165
|
+
trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRate')
|
5166
|
+
isTrailingPercentOrder = trailingPercent is not None
|
5167
|
+
isStopLoss = stopLossPrice is not None
|
5168
|
+
isTakeProfit = takeProfitPrice is not None
|
5169
|
+
isConditional = (triggerPrice is not None) or isTrailingPercentOrder or isStopLoss or isTakeProfit
|
5170
|
+
sor = self.safe_bool_2(params, 'sor', 'SOR', False)
|
5171
|
+
test = self.safe_bool(params, 'test', False)
|
5172
|
+
params = self.omit(params, ['sor', 'SOR', 'test'])
|
5173
|
+
if isPortfolioMargin:
|
5174
|
+
params['portfolioMargin'] = isPortfolioMargin
|
5017
5175
|
request = self.create_order_request(symbol, type, side, amount, price, params)
|
5018
|
-
|
5019
|
-
if
|
5020
|
-
|
5176
|
+
response = None
|
5177
|
+
if market['option']:
|
5178
|
+
response = self.eapiPrivatePostOrder(request)
|
5179
|
+
elif sor:
|
5180
|
+
if test:
|
5181
|
+
response = self.privatePostSorOrderTest(request)
|
5182
|
+
else:
|
5183
|
+
response = self.privatePostSorOrder(request)
|
5021
5184
|
elif market['linear']:
|
5022
|
-
|
5185
|
+
if isPortfolioMargin:
|
5186
|
+
if isConditional:
|
5187
|
+
response = self.papiPostUmConditionalOrder(request)
|
5188
|
+
else:
|
5189
|
+
response = self.papiPostUmOrder(request)
|
5190
|
+
else:
|
5191
|
+
response = self.fapiPrivatePostOrder(request)
|
5023
5192
|
elif market['inverse']:
|
5024
|
-
|
5193
|
+
if isPortfolioMargin:
|
5194
|
+
if isConditional:
|
5195
|
+
response = self.papiPostCmConditionalOrder(request)
|
5196
|
+
else:
|
5197
|
+
response = self.papiPostCmOrder(request)
|
5198
|
+
else:
|
5199
|
+
response = self.dapiPrivatePostOrder(request)
|
5025
5200
|
elif marketType == 'margin' or marginMode is not None:
|
5026
|
-
|
5027
|
-
|
5028
|
-
|
5029
|
-
|
5030
|
-
|
5031
|
-
test = self.safe_bool(query, 'test', False)
|
5201
|
+
if isPortfolioMargin:
|
5202
|
+
response = self.papiPostMarginOrder(request)
|
5203
|
+
else:
|
5204
|
+
response = self.sapiPostMarginOrder(request)
|
5205
|
+
else:
|
5032
5206
|
if test:
|
5033
|
-
|
5034
|
-
|
5207
|
+
response = self.privatePostOrderTest(request)
|
5208
|
+
else:
|
5209
|
+
response = self.privatePostOrder(request)
|
5035
5210
|
return self.parse_order(response, market)
|
5036
5211
|
|
5037
5212
|
def create_order_request(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: float = None, params={}):
|
5038
5213
|
"""
|
5039
5214
|
* @ignore
|
5040
|
-
helper function to build request
|
5215
|
+
helper function to build the request
|
5041
5216
|
:param str symbol: unified symbol of the market to create an order in
|
5042
|
-
:param str type: 'market' or 'limit'
|
5217
|
+
:param str type: 'market' or 'limit'
|
5043
5218
|
:param str side: 'buy' or 'sell'
|
5044
|
-
:param float amount: how much
|
5045
|
-
:param float
|
5046
|
-
:param dict params: extra parameters specific to the exchange API endpoint
|
5047
|
-
:param str|None params['marginMode']: 'cross' or 'isolated', for spot margin trading
|
5048
|
-
:param float [params.trailingPercent]: the percent to trail away from the current market price
|
5049
|
-
:param float [params.trailingTriggerPrice]: the price to trigger a trailing order, default uses the price argument
|
5219
|
+
:param float amount: how much you want to trade in units of the base currency
|
5220
|
+
:param float [price]: the price that the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
5221
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5050
5222
|
:returns dict: request to be sent to the exchange
|
5051
5223
|
"""
|
5052
5224
|
market = self.market(symbol)
|
@@ -5055,31 +5227,35 @@ class binance(Exchange, ImplicitAPI):
|
|
5055
5227
|
initialUppercaseType = type.upper()
|
5056
5228
|
isMarketOrder = initialUppercaseType == 'MARKET'
|
5057
5229
|
isLimitOrder = initialUppercaseType == 'LIMIT'
|
5058
|
-
|
5059
|
-
|
5060
|
-
|
5061
|
-
|
5062
|
-
|
5230
|
+
request = {
|
5231
|
+
'symbol': market['id'],
|
5232
|
+
'side': side.upper(),
|
5233
|
+
}
|
5234
|
+
isPortfolioMargin = None
|
5235
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'createOrder', 'papi', 'portfolioMargin', False)
|
5236
|
+
marginMode = None
|
5237
|
+
marginMode, params = self.handle_margin_mode_and_params('createOrder', params)
|
5238
|
+
if (marketType == 'margin') or (marginMode is not None) or market['option']:
|
5239
|
+
# for swap and future reduceOnly is a string that cant be sent with close position set to True or in hedge mode
|
5240
|
+
reduceOnly = self.safe_bool(params, 'reduceOnly', False)
|
5241
|
+
params = self.omit(params, 'reduceOnly')
|
5242
|
+
if market['option']:
|
5243
|
+
request['reduceOnly'] = reduceOnly
|
5244
|
+
else:
|
5245
|
+
if reduceOnly:
|
5246
|
+
request['sideEffectType'] = 'AUTO_REPAY'
|
5247
|
+
triggerPrice = self.safe_string_2(params, 'triggerPrice', 'stopPrice')
|
5248
|
+
stopLossPrice = self.safe_string(params, 'stopLossPrice', triggerPrice) # fallback to stopLoss
|
5249
|
+
takeProfitPrice = self.safe_string(params, 'takeProfitPrice')
|
5250
|
+
trailingDelta = self.safe_string(params, 'trailingDelta')
|
5063
5251
|
trailingTriggerPrice = self.safe_string_2(params, 'trailingTriggerPrice', 'activationPrice', self.number_to_string(price))
|
5064
5252
|
trailingPercent = self.safe_string_2(params, 'trailingPercent', 'callbackRate')
|
5065
5253
|
isTrailingPercentOrder = trailingPercent is not None
|
5066
5254
|
isStopLoss = stopLossPrice is not None or trailingDelta is not None
|
5067
5255
|
isTakeProfit = takeProfitPrice is not None
|
5068
|
-
|
5069
|
-
|
5070
|
-
|
5071
|
-
'symbol': market['id'],
|
5072
|
-
'side': side.upper(),
|
5073
|
-
}
|
5074
|
-
if market['spot'] or marketType == 'margin':
|
5075
|
-
# only supported for spot/margin api(all margin markets are spot markets)
|
5076
|
-
if postOnly:
|
5077
|
-
type = 'LIMIT_MAKER'
|
5078
|
-
if marketType == 'margin' or marginMode is not None:
|
5079
|
-
reduceOnly = self.safe_value(params, 'reduceOnly')
|
5080
|
-
if reduceOnly:
|
5081
|
-
request['sideEffectType'] = 'AUTO_REPAY'
|
5082
|
-
params = self.omit(params, 'reduceOnly')
|
5256
|
+
isTriggerOrder = triggerPrice is not None
|
5257
|
+
isConditional = isTriggerOrder or isTrailingPercentOrder or isStopLoss or isTakeProfit
|
5258
|
+
isPortfolioMarginConditional = (isPortfolioMargin and isConditional)
|
5083
5259
|
uppercaseType = type.upper()
|
5084
5260
|
stopPrice = None
|
5085
5261
|
if isTrailingPercentOrder:
|
@@ -5101,31 +5277,41 @@ class binance(Exchange, ImplicitAPI):
|
|
5101
5277
|
uppercaseType = 'TAKE_PROFIT_MARKET' if market['contract'] else 'TAKE_PROFIT'
|
5102
5278
|
elif isLimitOrder:
|
5103
5279
|
uppercaseType = 'TAKE_PROFIT' if market['contract'] else 'TAKE_PROFIT_LIMIT'
|
5104
|
-
if marginMode == 'isolated':
|
5105
|
-
request['isIsolated'] = True
|
5106
|
-
if clientOrderId is None:
|
5107
|
-
broker = self.safe_value(self.options, 'broker', {})
|
5108
|
-
defaultId = 'x-xcKtGhcu' if (market['contract']) else 'x-R4BD3S82'
|
5109
|
-
brokerId = self.safe_string(broker, marketType, defaultId)
|
5110
|
-
request['newClientOrderId'] = brokerId + self.uuid22()
|
5111
|
-
else:
|
5112
|
-
request['newClientOrderId'] = clientOrderId
|
5113
5280
|
if (marketType == 'spot') or (marketType == 'margin'):
|
5114
|
-
request['newOrderRespType'] = self.
|
5281
|
+
request['newOrderRespType'] = self.safe_string(self.options['newOrderRespType'], type, 'RESULT') # 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
|
5115
5282
|
else:
|
5116
5283
|
# swap, futures and options
|
5117
|
-
|
5284
|
+
if not isPortfolioMargin:
|
5285
|
+
request['newOrderRespType'] = 'RESULT' # "ACK", "RESULT", default "ACK"
|
5118
5286
|
if market['option']:
|
5119
5287
|
if type == 'market':
|
5120
5288
|
raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
|
5121
5289
|
else:
|
5122
|
-
validOrderTypes = self.
|
5290
|
+
validOrderTypes = self.safe_list(market['info'], 'orderTypes')
|
5123
5291
|
if not self.in_array(uppercaseType, validOrderTypes):
|
5124
5292
|
if initialUppercaseType != uppercaseType:
|
5125
5293
|
raise InvalidOrder(self.id + ' stopPrice parameter is not allowed for ' + symbol + ' ' + type + ' orders')
|
5126
5294
|
else:
|
5127
5295
|
raise InvalidOrder(self.id + ' ' + type + ' is not a valid order type for the ' + symbol + ' market')
|
5128
|
-
|
5296
|
+
clientOrderIdRequest = 'newClientStrategyId' if isPortfolioMarginConditional else 'newClientOrderId'
|
5297
|
+
if clientOrderId is None:
|
5298
|
+
broker = self.safe_dict(self.options, 'broker', {})
|
5299
|
+
defaultId = 'x-xcKtGhcu' if (market['contract']) else 'x-R4BD3S82'
|
5300
|
+
brokerId = self.safe_string(broker, marketType, defaultId)
|
5301
|
+
request[clientOrderIdRequest] = brokerId + self.uuid22()
|
5302
|
+
else:
|
5303
|
+
request[clientOrderIdRequest] = clientOrderId
|
5304
|
+
postOnly = None
|
5305
|
+
if not isPortfolioMargin:
|
5306
|
+
postOnly = self.is_post_only(isMarketOrder, initialUppercaseType == 'LIMIT_MAKER', params)
|
5307
|
+
if market['spot'] or marketType == 'margin':
|
5308
|
+
# only supported for spot/margin api(all margin markets are spot markets)
|
5309
|
+
if postOnly:
|
5310
|
+
uppercaseType = 'LIMIT_MAKER'
|
5311
|
+
if marginMode == 'isolated':
|
5312
|
+
request['isIsolated'] = True
|
5313
|
+
typeRequest = 'strategyType' if isPortfolioMarginConditional else 'type'
|
5314
|
+
request[typeRequest] = uppercaseType
|
5129
5315
|
# additional required fields depending on the order type
|
5130
5316
|
timeInForceIsRequired = False
|
5131
5317
|
priceIsRequired = False
|
@@ -5153,9 +5339,9 @@ class binance(Exchange, ImplicitAPI):
|
|
5153
5339
|
#
|
5154
5340
|
if uppercaseType == 'MARKET':
|
5155
5341
|
if market['spot']:
|
5156
|
-
quoteOrderQty = self.
|
5342
|
+
quoteOrderQty = self.safe_bool(self.options, 'quoteOrderQty', True)
|
5157
5343
|
if quoteOrderQty:
|
5158
|
-
quoteOrderQtyNew = self.
|
5344
|
+
quoteOrderQtyNew = self.safe_string_2(params, 'quoteOrderQty', 'cost')
|
5159
5345
|
precision = market['precision']['price']
|
5160
5346
|
if quoteOrderQtyNew is not None:
|
5161
5347
|
request['quoteOrderQty'] = self.decimal_to_precision(quoteOrderQtyNew, TRUNCATE, precision, self.precisionMode)
|
@@ -5192,7 +5378,7 @@ class binance(Exchange, ImplicitAPI):
|
|
5192
5378
|
stopPriceIsRequired = True
|
5193
5379
|
priceIsRequired = True
|
5194
5380
|
elif (uppercaseType == 'STOP_MARKET') or (uppercaseType == 'TAKE_PROFIT_MARKET'):
|
5195
|
-
closePosition = self.
|
5381
|
+
closePosition = self.safe_bool(params, 'closePosition')
|
5196
5382
|
if closePosition is None:
|
5197
5383
|
quantityIsRequired = True
|
5198
5384
|
stopPriceIsRequired = True
|
@@ -5201,15 +5387,15 @@ class binance(Exchange, ImplicitAPI):
|
|
5201
5387
|
if trailingPercent is None:
|
5202
5388
|
raise InvalidOrder(self.id + ' createOrder() requires a trailingPercent param for a ' + type + ' order')
|
5203
5389
|
if quantityIsRequired:
|
5204
|
-
|
5390
|
+
# portfolio margin has a different amount precision
|
5391
|
+
if isPortfolioMargin:
|
5392
|
+
request['quantity'] = self.parse_to_numeric(amount)
|
5393
|
+
else:
|
5394
|
+
request['quantity'] = self.amount_to_precision(symbol, amount)
|
5205
5395
|
if priceIsRequired:
|
5206
5396
|
if price is None:
|
5207
5397
|
raise InvalidOrder(self.id + ' createOrder() requires a price argument for a ' + type + ' order')
|
5208
5398
|
request['price'] = self.price_to_precision(symbol, price)
|
5209
|
-
if timeInForceIsRequired:
|
5210
|
-
request['timeInForce'] = self.options['defaultTimeInForce'] # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
|
5211
|
-
if market['contract'] and postOnly:
|
5212
|
-
request['timeInForce'] = 'GTX'
|
5213
5399
|
if stopPriceIsRequired:
|
5214
5400
|
if market['contract']:
|
5215
5401
|
if stopPrice is None:
|
@@ -5220,10 +5406,14 @@ class binance(Exchange, ImplicitAPI):
|
|
5220
5406
|
raise InvalidOrder(self.id + ' createOrder() requires a stopPrice or trailingDelta param for a ' + type + ' order')
|
5221
5407
|
if stopPrice is not None:
|
5222
5408
|
request['stopPrice'] = self.price_to_precision(symbol, stopPrice)
|
5409
|
+
if timeInForceIsRequired and (self.safe_string(params, 'timeInForce') is None):
|
5410
|
+
request['timeInForce'] = self.options['defaultTimeInForce'] # 'GTC' = Good To Cancel(default), 'IOC' = Immediate Or Cancel
|
5411
|
+
if not isPortfolioMargin and market['contract'] and postOnly:
|
5412
|
+
request['timeInForce'] = 'GTX'
|
5223
5413
|
# remove timeInForce from params because PO is only used by self.is_post_onlyand it's not a valid value for Binance
|
5224
5414
|
if self.safe_string(params, 'timeInForce') == 'PO':
|
5225
|
-
params = self.omit(params,
|
5226
|
-
requestParams = self.omit(params, ['
|
5415
|
+
params = self.omit(params, 'timeInForce')
|
5416
|
+
requestParams = self.omit(params, ['type', 'newClientOrderId', 'clientOrderId', 'postOnly', 'stopLossPrice', 'takeProfitPrice', 'stopPrice', 'triggerPrice', 'trailingTriggerPrice', 'trailingPercent', 'quoteOrderQty', 'cost', 'test'])
|
5227
5417
|
return self.extend(request, requestParams)
|
5228
5418
|
|
5229
5419
|
def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost, params={}):
|
@@ -5452,21 +5642,28 @@ class binance(Exchange, ImplicitAPI):
|
|
5452
5642
|
|
5453
5643
|
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
5454
5644
|
"""
|
5645
|
+
fetch all unfilled currently open orders
|
5455
5646
|
:see: https://binance-docs.github.io/apidocs/spot/en/#cancel-an-existing-order-and-send-a-new-order-trade
|
5456
5647
|
:see: https://binance-docs.github.io/apidocs/futures/en/#current-all-open-orders-user_data
|
5457
5648
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#current-all-open-orders-user_data
|
5458
5649
|
:see: https://binance-docs.github.io/apidocs/voptions/en/#query-current-open-option-orders-user_data
|
5459
|
-
fetch all unfilled currently open orders
|
5460
5650
|
:see: https://binance-docs.github.io/apidocs/spot/en/#current-open-orders-user_data
|
5461
5651
|
:see: https://binance-docs.github.io/apidocs/futures/en/#current-all-open-orders-user_data
|
5462
5652
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#current-all-open-orders-user_data
|
5463
5653
|
:see: https://binance-docs.github.io/apidocs/voptions/en/#query-current-open-option-orders-user_data
|
5464
5654
|
:see: https://binance-docs.github.io/apidocs/spot/en/#query-margin-account-39-s-open-orders-user_data
|
5655
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-all-current-um-open-orders-user_data
|
5656
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-all-current-cm-open-orders-user_data
|
5657
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-all-current-um-open-conditional-orders-user_data
|
5658
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-all-current-cm-open-conditional-orders-user_data
|
5659
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#query-current-margin-open-order-user_data
|
5465
5660
|
:param str symbol: unified market symbol
|
5466
5661
|
:param int [since]: the earliest time in ms to fetch open orders for
|
5467
5662
|
:param int [limit]: the maximum number of open orders structures to retrieve
|
5468
5663
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5469
5664
|
:param str [params.marginMode]: 'cross' or 'isolated', for spot margin trading
|
5665
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to fetch open orders in the portfolio margin account
|
5666
|
+
:param boolean [params.stop]: set to True if you would like to fetch portfolio margin account conditional orders
|
5470
5667
|
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
5471
5668
|
"""
|
5472
5669
|
self.load_markets()
|
@@ -5474,14 +5671,16 @@ class binance(Exchange, ImplicitAPI):
|
|
5474
5671
|
type = None
|
5475
5672
|
request = {}
|
5476
5673
|
marginMode = None
|
5477
|
-
|
5478
|
-
|
5674
|
+
marginMode, params = self.handle_margin_mode_and_params('fetchOpenOrders', params)
|
5675
|
+
isPortfolioMargin = None
|
5676
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'fetchOpenOrders', 'papi', 'portfolioMargin', False)
|
5677
|
+
isConditional = self.safe_bool_2(params, 'stop', 'conditional')
|
5479
5678
|
if symbol is not None:
|
5480
5679
|
market = self.market(symbol)
|
5481
5680
|
request['symbol'] = market['id']
|
5482
5681
|
defaultType = self.safe_string_2(self.options, 'fetchOpenOrders', 'defaultType', 'spot')
|
5483
5682
|
marketType = market['type'] if ('type' in market) else defaultType
|
5484
|
-
type = self.safe_string(
|
5683
|
+
type = self.safe_string(params, 'type', marketType)
|
5485
5684
|
elif self.options['warnOnFetchOpenOrdersWithoutSymbol']:
|
5486
5685
|
symbols = self.symbols
|
5487
5686
|
numSymbols = len(symbols)
|
@@ -5489,29 +5688,44 @@ class binance(Exchange, ImplicitAPI):
|
|
5489
5688
|
raise ExchangeError(self.id + ' fetchOpenOrders() WARNING: fetching open orders without specifying a symbol is rate-limited to one call per ' + str(fetchOpenOrdersRateLimit) + ' seconds. Do not call self method frequently to avoid ban. Set ' + self.id + '.options["warnOnFetchOpenOrdersWithoutSymbol"] = False to suppress self warning message.')
|
5490
5689
|
else:
|
5491
5690
|
defaultType = self.safe_string_2(self.options, 'fetchOpenOrders', 'defaultType', 'spot')
|
5492
|
-
type = self.safe_string(
|
5691
|
+
type = self.safe_string(params, 'type', defaultType)
|
5493
5692
|
subType = None
|
5494
|
-
subType,
|
5495
|
-
|
5693
|
+
subType, params = self.handle_sub_type_and_params('fetchOpenOrders', market, params)
|
5694
|
+
params = self.omit(params, ['type', 'stop', 'conditional'])
|
5496
5695
|
response = None
|
5497
5696
|
if type == 'option':
|
5498
5697
|
if since is not None:
|
5499
5698
|
request['startTime'] = since
|
5500
5699
|
if limit is not None:
|
5501
5700
|
request['limit'] = limit
|
5502
|
-
response = self.eapiPrivateGetOpenOrders(self.extend(request,
|
5701
|
+
response = self.eapiPrivateGetOpenOrders(self.extend(request, params))
|
5503
5702
|
elif self.is_linear(type, subType):
|
5504
|
-
|
5703
|
+
if isPortfolioMargin:
|
5704
|
+
if isConditional:
|
5705
|
+
response = self.papiGetUmConditionalOpenOrders(self.extend(request, params))
|
5706
|
+
else:
|
5707
|
+
response = self.papiGetUmOpenOrders(self.extend(request, params))
|
5708
|
+
else:
|
5709
|
+
response = self.fapiPrivateGetOpenOrders(self.extend(request, params))
|
5505
5710
|
elif self.is_inverse(type, subType):
|
5506
|
-
|
5711
|
+
if isPortfolioMargin:
|
5712
|
+
if isConditional:
|
5713
|
+
response = self.papiGetCmConditionalOpenOrders(self.extend(request, params))
|
5714
|
+
else:
|
5715
|
+
response = self.papiGetCmOpenOrders(self.extend(request, params))
|
5716
|
+
else:
|
5717
|
+
response = self.dapiPrivateGetOpenOrders(self.extend(request, params))
|
5507
5718
|
elif type == 'margin' or marginMode is not None:
|
5508
|
-
if
|
5509
|
-
|
5510
|
-
|
5511
|
-
|
5512
|
-
|
5719
|
+
if isPortfolioMargin:
|
5720
|
+
response = self.papiGetMarginOpenOrders(self.extend(request, params))
|
5721
|
+
else:
|
5722
|
+
if marginMode == 'isolated':
|
5723
|
+
request['isIsolated'] = True
|
5724
|
+
if symbol is None:
|
5725
|
+
raise ArgumentsRequired(self.id + ' fetchOpenOrders() requires a symbol argument for isolated markets')
|
5726
|
+
response = self.sapiGetMarginOpenOrders(self.extend(request, params))
|
5513
5727
|
else:
|
5514
|
-
response = self.privateGetOpenOrders(self.extend(request,
|
5728
|
+
response = self.privateGetOpenOrders(self.extend(request, params))
|
5515
5729
|
return self.parse_orders(response, market, since, limit)
|
5516
5730
|
|
5517
5731
|
def fetch_closed_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
@@ -5607,40 +5821,66 @@ class binance(Exchange, ImplicitAPI):
|
|
5607
5821
|
|
5608
5822
|
def cancel_all_orders(self, symbol: Str = None, params={}):
|
5609
5823
|
"""
|
5824
|
+
cancel all open orders in a market
|
5610
5825
|
:see: https://binance-docs.github.io/apidocs/spot/en/#cancel-all-open-orders-on-a-symbol-trade
|
5611
5826
|
:see: https://binance-docs.github.io/apidocs/futures/en/#cancel-all-open-orders-trade
|
5612
5827
|
:see: https://binance-docs.github.io/apidocs/delivery/en/#cancel-all-open-orders-trade
|
5613
5828
|
:see: https://binance-docs.github.io/apidocs/voptions/en/#cancel-all-option-orders-on-specific-symbol-trade
|
5614
5829
|
:see: https://binance-docs.github.io/apidocs/spot/en/#margin-account-cancel-order-trade
|
5615
|
-
cancel
|
5830
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#cancel-all-um-open-orders-trade
|
5831
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#cancel-all-cm-open-orders-trade
|
5832
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#cancel-all-um-open-conditional-orders-trade
|
5833
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#cancel-all-cm-open-conditional-orders-trade
|
5834
|
+
:see: https://binance-docs.github.io/apidocs/pm/en/#cancel-margin-account-all-open-orders-on-a-symbol-trade
|
5616
5835
|
:param str symbol: unified market symbol of the market to cancel orders in
|
5617
5836
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
5618
5837
|
:param str [params.marginMode]: 'cross' or 'isolated', for spot margin trading
|
5838
|
+
:param boolean [params.portfolioMargin]: set to True if you would like to cancel orders in a portfolio margin account
|
5839
|
+
:param boolean [params.stop]: set to True if you would like to cancel portfolio margin account conditional orders
|
5619
5840
|
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
5620
5841
|
"""
|
5621
5842
|
if symbol is None:
|
5622
|
-
raise ArgumentsRequired(self.id + '
|
5843
|
+
raise ArgumentsRequired(self.id + ' cancelAllOrders() requires a symbol argument')
|
5623
5844
|
self.load_markets()
|
5624
5845
|
market = self.market(symbol)
|
5625
5846
|
request = {
|
5626
5847
|
'symbol': market['id'],
|
5627
5848
|
}
|
5849
|
+
isPortfolioMargin = None
|
5850
|
+
isPortfolioMargin, params = self.handle_option_and_params_2(params, 'cancelAllOrders', 'papi', 'portfolioMargin', False)
|
5851
|
+
isConditional = self.safe_bool_2(params, 'stop', 'conditional')
|
5628
5852
|
type = self.safe_string(params, 'type', market['type'])
|
5629
|
-
params = self.omit(params, ['type'])
|
5630
|
-
marginMode
|
5853
|
+
params = self.omit(params, ['type', 'stop', 'conditional'])
|
5854
|
+
marginMode = None
|
5855
|
+
marginMode, params = self.handle_margin_mode_and_params('cancelAllOrders', params)
|
5631
5856
|
response = None
|
5632
5857
|
if market['option']:
|
5633
|
-
response = self.eapiPrivateDeleteAllOpenOrders(self.extend(request,
|
5858
|
+
response = self.eapiPrivateDeleteAllOpenOrders(self.extend(request, params))
|
5634
5859
|
elif market['linear']:
|
5635
|
-
|
5860
|
+
if isPortfolioMargin:
|
5861
|
+
if isConditional:
|
5862
|
+
response = self.papiDeleteUmConditionalAllOpenOrders(self.extend(request, params))
|
5863
|
+
else:
|
5864
|
+
response = self.papiDeleteUmAllOpenOrders(self.extend(request, params))
|
5865
|
+
else:
|
5866
|
+
response = self.fapiPrivateDeleteAllOpenOrders(self.extend(request, params))
|
5636
5867
|
elif market['inverse']:
|
5637
|
-
|
5868
|
+
if isPortfolioMargin:
|
5869
|
+
if isConditional:
|
5870
|
+
response = self.papiDeleteCmConditionalAllOpenOrders(self.extend(request, params))
|
5871
|
+
else:
|
5872
|
+
response = self.papiDeleteCmAllOpenOrders(self.extend(request, params))
|
5873
|
+
else:
|
5874
|
+
response = self.dapiPrivateDeleteAllOpenOrders(self.extend(request, params))
|
5638
5875
|
elif (type == 'margin') or (marginMode is not None):
|
5639
|
-
if
|
5640
|
-
|
5641
|
-
|
5876
|
+
if isPortfolioMargin:
|
5877
|
+
response = self.papiDeleteMarginAllOpenOrders(self.extend(request, params))
|
5878
|
+
else:
|
5879
|
+
if marginMode == 'isolated':
|
5880
|
+
request['isIsolated'] = True
|
5881
|
+
response = self.sapiDeleteMarginOpenOrders(self.extend(request, params))
|
5642
5882
|
else:
|
5643
|
-
response = self.privateDeleteOpenOrders(self.extend(request,
|
5883
|
+
response = self.privateDeleteOpenOrders(self.extend(request, params))
|
5644
5884
|
if isinstance(response, list):
|
5645
5885
|
return self.parse_orders(response, market)
|
5646
5886
|
else:
|