ccxt 4.4.68__py2.py3-none-any.whl → 4.4.69__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/paradex.py CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.paradex import ImplicitAPI
8
- from ccxt.base.types import Any, Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
8
+ from ccxt.base.types import Any, Balances, Currency, Int, Leverage, MarginMode, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
9
  from typing import List
10
10
  from ccxt.base.errors import ExchangeError
11
11
  from ccxt.base.errors import AuthenticationError
@@ -79,10 +79,10 @@ class paradex(Exchange, ImplicitAPI):
79
79
  'fetchIsolatedBorrowRate': False,
80
80
  'fetchIsolatedBorrowRates': False,
81
81
  'fetchLedger': False,
82
- 'fetchLeverage': False,
82
+ 'fetchLeverage': True,
83
83
  'fetchLeverageTiers': False,
84
84
  'fetchLiquidations': True,
85
- 'fetchMarginMode': None,
85
+ 'fetchMarginMode': True,
86
86
  'fetchMarketLeverageTiers': False,
87
87
  'fetchMarkets': True,
88
88
  'fetchMarkOHLCV': False,
@@ -116,8 +116,8 @@ class paradex(Exchange, ImplicitAPI):
116
116
  'repayCrossMargin': False,
117
117
  'repayIsolatedMargin': False,
118
118
  'sandbox': True,
119
- 'setLeverage': False,
120
- 'setMarginMode': False,
119
+ 'setLeverage': True,
120
+ 'setMarginMode': True,
121
121
  'setPositionMode': False,
122
122
  'transfer': False,
123
123
  'withdraw': False,
@@ -159,12 +159,23 @@ class paradex(Exchange, ImplicitAPI):
159
159
  'system/state': 1,
160
160
  'system/time': 1,
161
161
  'trades': 1,
162
+ 'vaults': 1,
163
+ 'vaults/balance': 1,
164
+ 'vaults/config': 1,
165
+ 'vaults/history': 1,
166
+ 'vaults/positions': 1,
167
+ 'vaults/summary': 1,
168
+ 'vaults/transfers': 1,
162
169
  },
163
170
  },
164
171
  'private': {
165
172
  'get': {
166
173
  'account': 1,
174
+ 'account/info': 1,
175
+ 'account/history': 1,
176
+ 'account/margin': 1,
167
177
  'account/profile': 1,
178
+ 'account/subaccounts': 1,
168
179
  'balance': 1,
169
180
  'fills': 1,
170
181
  'funding/payments': 1,
@@ -177,20 +188,34 @@ class paradex(Exchange, ImplicitAPI):
177
188
  'orders/by_client_id/{client_id}': 1,
178
189
  'orders/{order_id}': 1,
179
190
  'points_data/{market}/{program}': 1,
191
+ 'referrals/qr-code': 1,
180
192
  'referrals/summary': 1,
181
193
  'transfers': 1,
194
+ 'algo/orders': 1,
195
+ 'algo/orders-history': 1,
196
+ 'algo/orders/{algo_id}': 1,
197
+ 'vaults/account-summary': 1,
182
198
  },
183
199
  'post': {
200
+ 'account/margin/{market}': 1,
201
+ 'account/profile/max_slippage': 1,
184
202
  'account/profile/referral_code': 1,
185
203
  'account/profile/username': 1,
186
204
  'auth': 1,
187
205
  'onboarding': 1,
188
206
  'orders': 1,
207
+ 'orders/batch': 1,
208
+ 'algo/orders': 1,
209
+ 'vaults': 1,
210
+ },
211
+ 'put': {
212
+ 'orders/{order_id}': 1,
189
213
  },
190
214
  'delete': {
191
215
  'orders': 1,
192
216
  'orders/by_client_id/{client_id}': 1,
193
217
  'orders/{order_id}': 1,
218
+ 'algo/orders/{algo_id}': 1,
194
219
  },
195
220
  },
196
221
  },
@@ -2063,6 +2088,149 @@ class paradex(Exchange, ImplicitAPI):
2063
2088
  }
2064
2089
  return self.safe_string(statuses, status, status)
2065
2090
 
2091
+ def fetch_margin_mode(self, symbol: str, params={}) -> MarginMode:
2092
+ """
2093
+ fetches the margin mode of a specific symbol
2094
+
2095
+ https://docs.api.testnet.paradex.trade/#get-account-margin-configuration
2096
+
2097
+ :param str symbol: unified symbol of the market the order was made in
2098
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2099
+ :returns dict: a `margin mode structure <https://docs.ccxt.com/#/?id=margin-mode-structure>`
2100
+ """
2101
+ self.authenticate_rest()
2102
+ self.load_markets()
2103
+ market = self.market(symbol)
2104
+ request: dict = {
2105
+ 'market': market['id'],
2106
+ }
2107
+ response = self.privateGetAccountMargin(self.extend(request, params))
2108
+ #
2109
+ # {
2110
+ # "account": "0x6343248026a845b39a8a73fbe9c7ef0a841db31ed5c61ec1446aa9d25e54dbc",
2111
+ # "configs": [
2112
+ # {
2113
+ # "market": "SOL-USD-PERP",
2114
+ # "leverage": 50,
2115
+ # "margin_type": "CROSS"
2116
+ # }
2117
+ # ]
2118
+ # }
2119
+ #
2120
+ configs = self.safe_list(response, 'configs')
2121
+ return self.parse_margin_mode(self.safe_dict(configs, 0), market)
2122
+
2123
+ def parse_margin_mode(self, rawMarginMode: dict, market=None) -> MarginMode:
2124
+ marketId = self.safe_string(rawMarginMode, 'market')
2125
+ market = self.safe_market(marketId, market)
2126
+ marginMode = self.safe_string_lower(rawMarginMode, 'margin_type')
2127
+ return {
2128
+ 'info': rawMarginMode,
2129
+ 'symbol': market['symbol'],
2130
+ 'marginMode': marginMode,
2131
+ }
2132
+
2133
+ def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
2134
+ """
2135
+ set margin mode to 'cross' or 'isolated'
2136
+
2137
+ https://docs.api.testnet.paradex.trade/#set-margin-configuration
2138
+
2139
+ :param str marginMode: 'cross' or 'isolated'
2140
+ :param str symbol: unified market symbol
2141
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2142
+ :param float [params.leverage]: the rate of leverage
2143
+ :returns dict: response from the exchange
2144
+ """
2145
+ self.check_required_argument('setMarginMode', symbol, 'symbol')
2146
+ self.authenticate_rest()
2147
+ self.load_markets()
2148
+ market: Market = self.market(symbol)
2149
+ leverage: Str = None
2150
+ leverage, params = self.handle_option_and_params(params, 'setMarginMode', 'leverage', 1)
2151
+ request: dict = {
2152
+ 'market': market['id'],
2153
+ 'leverage': leverage,
2154
+ 'margin_type': self.encode_margin_mode(marginMode),
2155
+ }
2156
+ return self.privatePostAccountMarginMarket(self.extend(request, params))
2157
+
2158
+ def fetch_leverage(self, symbol: str, params={}) -> Leverage:
2159
+ """
2160
+ fetch the set leverage for a market
2161
+
2162
+ https://docs.api.testnet.paradex.trade/#get-account-margin-configuration
2163
+
2164
+ :param str symbol: unified market symbol
2165
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2166
+ :returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
2167
+ """
2168
+ self.authenticate_rest()
2169
+ self.load_markets()
2170
+ market = self.market(symbol)
2171
+ request: dict = {
2172
+ 'market': market['id'],
2173
+ }
2174
+ response = self.privateGetAccountMargin(self.extend(request, params))
2175
+ #
2176
+ # {
2177
+ # "account": "0x6343248026a845b39a8a73fbe9c7ef0a841db31ed5c61ec1446aa9d25e54dbc",
2178
+ # "configs": [
2179
+ # {
2180
+ # "market": "SOL-USD-PERP",
2181
+ # "leverage": 50,
2182
+ # "margin_type": "CROSS"
2183
+ # }
2184
+ # ]
2185
+ # }
2186
+ #
2187
+ configs = self.safe_list(response, 'configs')
2188
+ return self.parse_leverage(self.safe_dict(configs, 0), market)
2189
+
2190
+ def parse_leverage(self, leverage: dict, market: Market = None) -> Leverage:
2191
+ marketId = self.safe_string(leverage, 'market')
2192
+ market = self.safe_market(marketId, market)
2193
+ marginMode = self.safe_string_lower(leverage, 'margin_type')
2194
+ return {
2195
+ 'info': leverage,
2196
+ 'symbol': self.safe_symbol(marketId, market),
2197
+ 'marginMode': marginMode,
2198
+ 'longLeverage': self.safe_integer(leverage, 'leverage'),
2199
+ 'shortLeverage': self.safe_integer(leverage, 'leverage'),
2200
+ }
2201
+
2202
+ def encode_margin_mode(self, mode):
2203
+ modes = {
2204
+ 'cross': 'CROSS',
2205
+ 'isolated': 'ISOLATED',
2206
+ }
2207
+ return self.safe_string(modes, mode, mode)
2208
+
2209
+ def set_leverage(self, leverage: Int, symbol: Str = None, params={}):
2210
+ """
2211
+ set the level of leverage for a market
2212
+
2213
+ https://docs.api.testnet.paradex.trade/#set-margin-configuration
2214
+
2215
+ :param float leverage: the rate of leverage
2216
+ :param str [symbol]: unified market symbol(is mandatory for swap markets)
2217
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2218
+ :param str [params.marginMode]: 'cross' or 'isolated'
2219
+ :returns dict: response from the exchange
2220
+ """
2221
+ self.check_required_argument('setLeverage', symbol, 'symbol')
2222
+ self.authenticate_rest()
2223
+ self.load_markets()
2224
+ market: Market = self.market(symbol)
2225
+ marginMode: Str = None
2226
+ marginMode, params = self.handle_margin_mode_and_params('setLeverage', params, 'cross')
2227
+ request: dict = {
2228
+ 'market': market['id'],
2229
+ 'leverage': leverage,
2230
+ 'margin_type': self.encode_margin_mode(marginMode),
2231
+ }
2232
+ return self.privatePostAccountMarginMarket(self.extend(request, params))
2233
+
2066
2234
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
2067
2235
  url = self.implode_hostname(self.urls['api'][self.version]) + '/' + self.implode_params(path, params)
2068
2236
  query = self.omit(params, self.extract_params(path))
ccxt/phemex.py CHANGED
@@ -3580,14 +3580,14 @@ class phemex(Exchange, ImplicitAPI):
3580
3580
 
3581
3581
  :param str[] [symbols]: list of unified market symbols
3582
3582
  :param dict [params]: extra parameters specific to the exchange API endpoint
3583
- :param str [params.code]: the currency code to fetch positions for, USD, BTC or USDT, USD is the default
3583
+ :param str [params.code]: the currency code to fetch positions for, USD, BTC or USDT, USDT is the default
3584
3584
  :param str [params.method]: *USDT contracts only* 'privateGetGAccountsAccountPositions' or 'privateGetAccountsPositions' default is 'privateGetGAccountsAccountPositions'
3585
3585
  :returns dict[]: a list of `position structure <https://docs.ccxt.com/#/?id=position-structure>`
3586
3586
  """
3587
3587
  self.load_markets()
3588
3588
  symbols = self.market_symbols(symbols)
3589
3589
  subType = None
3590
- code = self.safe_string_2(params, 'currency', 'code', 'USD')
3590
+ code = self.safe_string_2(params, 'currency', 'code', 'USDT')
3591
3591
  params = self.omit(params, ['currency', 'code'])
3592
3592
  settle = None
3593
3593
  market = None
ccxt/pro/__init__.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # ----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.4.68'
7
+ __version__ = '4.4.69'
8
8
 
9
9
  # ----------------------------------------------------------------------------
10
10
 
ccxt/test/tests_async.py CHANGED
@@ -1180,6 +1180,28 @@ class testMainClass:
1180
1180
  assert client_order_id_swap.startswith(swap_id_string), 'binance - swap clientOrderId: ' + client_order_id_swap + ' does not start with swapId' + swap_id_string
1181
1181
  client_order_id_inverse = swap_inverse_order_request['newClientOrderId']
1182
1182
  assert client_order_id_inverse.startswith(swap_id_string), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + swap_id_string
1183
+ create_orders_request = None
1184
+ try:
1185
+ orders = [{
1186
+ 'symbol': 'BTC/USDT:USDT',
1187
+ 'type': 'limit',
1188
+ 'side': 'sell',
1189
+ 'amount': 1,
1190
+ 'price': 100000,
1191
+ }, {
1192
+ 'symbol': 'BTC/USDT:USDT',
1193
+ 'type': 'market',
1194
+ 'side': 'buy',
1195
+ 'amount': 1,
1196
+ }]
1197
+ await exchange.create_orders(orders)
1198
+ except Exception as e:
1199
+ create_orders_request = self.urlencoded_to_dict(exchange.last_request_body)
1200
+ batch_orders = create_orders_request['batchOrders']
1201
+ for i in range(0, len(batch_orders)):
1202
+ current = batch_orders[i]
1203
+ current_client_order_id = current['newClientOrderId']
1204
+ assert current_client_order_id.startswith(swap_id_string), 'binance createOrders - clientOrderId: ' + current_client_order_id + ' does not start with swapId' + swap_id_string
1183
1205
  if not is_sync():
1184
1206
  await close(exchange)
1185
1207
  return True
ccxt/test/tests_sync.py CHANGED
@@ -1177,6 +1177,28 @@ class testMainClass:
1177
1177
  assert client_order_id_swap.startswith(swap_id_string), 'binance - swap clientOrderId: ' + client_order_id_swap + ' does not start with swapId' + swap_id_string
1178
1178
  client_order_id_inverse = swap_inverse_order_request['newClientOrderId']
1179
1179
  assert client_order_id_inverse.startswith(swap_id_string), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + swap_id_string
1180
+ create_orders_request = None
1181
+ try:
1182
+ orders = [{
1183
+ 'symbol': 'BTC/USDT:USDT',
1184
+ 'type': 'limit',
1185
+ 'side': 'sell',
1186
+ 'amount': 1,
1187
+ 'price': 100000,
1188
+ }, {
1189
+ 'symbol': 'BTC/USDT:USDT',
1190
+ 'type': 'market',
1191
+ 'side': 'buy',
1192
+ 'amount': 1,
1193
+ }]
1194
+ exchange.create_orders(orders)
1195
+ except Exception as e:
1196
+ create_orders_request = self.urlencoded_to_dict(exchange.last_request_body)
1197
+ batch_orders = create_orders_request['batchOrders']
1198
+ for i in range(0, len(batch_orders)):
1199
+ current = batch_orders[i]
1200
+ current_client_order_id = current['newClientOrderId']
1201
+ assert current_client_order_id.startswith(swap_id_string), 'binance createOrders - clientOrderId: ' + current_client_order_id + ' does not start with swapId' + swap_id_string
1180
1202
  if not is_sync():
1181
1203
  close(exchange)
1182
1204
  return True
ccxt/tradeogre.py CHANGED
@@ -134,6 +134,7 @@ class tradeogre(Exchange, ImplicitAPI):
134
134
  'orders/{market}': 1,
135
135
  'ticker/{market}': 1,
136
136
  'history/{market}': 1,
137
+ 'chart/{interval}/{market}/{timestamp}': 1,
137
138
  'chart/{interval}/{market}': 1,
138
139
  },
139
140
  },
@@ -422,15 +423,15 @@ class tradeogre(Exchange, ImplicitAPI):
422
423
  'ask': self.safe_string(ticker, 'ask'),
423
424
  'askVolume': None,
424
425
  'vwap': None,
425
- 'open': self.safe_string(ticker, 'open'),
426
- 'close': None,
426
+ 'open': self.safe_string(ticker, 'initialprice'),
427
+ 'close': self.safe_string(ticker, 'price'),
427
428
  'last': None,
428
429
  'previousClose': None,
429
430
  'change': None,
430
431
  'percentage': None,
431
432
  'average': None,
432
- 'baseVolume': self.safe_string(ticker, 'volume'),
433
- 'quoteVolume': None,
433
+ 'baseVolume': None,
434
+ 'quoteVolume': self.safe_string(ticker, 'volume'),
434
435
  'info': ticker,
435
436
  }, market)
436
437
 
@@ -451,11 +452,14 @@ class tradeogre(Exchange, ImplicitAPI):
451
452
  'market': market['id'],
452
453
  'interval': self.safe_string(self.timeframes, timeframe, timeframe),
453
454
  }
455
+ response = None
454
456
  until = self.safe_integer(params, 'until')
455
457
  if until is not None:
456
458
  params = self.omit(params, 'until')
457
- request['timestamp'] = until
458
- response = self.publicGetChartIntervalMarket(self.extend(request, params))
459
+ request['timestamp'] = self.parse_to_int(until / 1000)
460
+ response = self.publicGetChartIntervalMarketTimestamp(self.extend(request, params))
461
+ else:
462
+ response = self.publicGetChartIntervalMarket(self.extend(request, params))
459
463
  #
460
464
  # [
461
465
  # [
@@ -484,9 +488,9 @@ class tradeogre(Exchange, ImplicitAPI):
484
488
  return [
485
489
  self.safe_timestamp(ohlcv, 0),
486
490
  self.safe_number(ohlcv, 1),
491
+ self.safe_number(ohlcv, 2),
487
492
  self.safe_number(ohlcv, 3),
488
493
  self.safe_number(ohlcv, 4),
489
- self.safe_number(ohlcv, 2),
490
494
  self.safe_number(ohlcv, 5),
491
495
  ]
492
496
 
ccxt/whitebit.py CHANGED
@@ -6,7 +6,7 @@
6
6
  from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.whitebit import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Any, Balances, BorrowInterest, Bool, Conversion, Currencies, Currency, DepositAddress, FundingHistory, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
9
+ from ccxt.base.types import Any, Balances, BorrowInterest, Bool, Conversion, Currencies, Currency, DepositAddress, FundingHistory, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade, TradingFees, Transaction, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import AuthenticationError
@@ -38,7 +38,7 @@ class whitebit(Exchange, ImplicitAPI):
38
38
  'CORS': None,
39
39
  'spot': True,
40
40
  'margin': True,
41
- 'swap': False,
41
+ 'swap': True,
42
42
  'future': False,
43
43
  'option': False,
44
44
  'cancelAllOrders': True,
@@ -88,7 +88,10 @@ class whitebit(Exchange, ImplicitAPI):
88
88
  'fetchOpenOrders': True,
89
89
  'fetchOrderBook': True,
90
90
  'fetchOrderTrades': True,
91
+ 'fetchPosition': True,
92
+ 'fetchPositionHistory': True,
91
93
  'fetchPositionMode': False,
94
+ 'fetchPositions': True,
92
95
  'fetchPremiumIndexOHLCV': False,
93
96
  'fetchStatus': True,
94
97
  'fetchTicker': True,
@@ -2859,6 +2862,211 @@ class whitebit(Exchange, ImplicitAPI):
2859
2862
  'fee': None,
2860
2863
  }
2861
2864
 
2865
+ def fetch_position_history(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Position]:
2866
+ """
2867
+ fetches historical positions
2868
+
2869
+ https://docs.whitebit.com/private/http-trade-v4/#positions-history
2870
+
2871
+ :param str symbol: unified contract symbol
2872
+ :param int [since]: the earliest time in ms to fetch positions for
2873
+ :param int [limit]: the maximum amount of records to fetch
2874
+ :param dict [params]: extra parameters specific to the exchange api endpoint
2875
+ :param int [params.positionId]: the id of the requested position
2876
+ :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
2877
+ """
2878
+ self.load_markets()
2879
+ market = self.market(symbol)
2880
+ request: dict = {
2881
+ 'market': market['id'],
2882
+ }
2883
+ if since is not None:
2884
+ request['startDate'] = since
2885
+ if limit is not None:
2886
+ request['limit'] = since
2887
+ request, params = self.handle_until_option('endDate', request, params)
2888
+ response = self.v4PrivatePostCollateralAccountPositionsHistory(self.extend(request, params))
2889
+ #
2890
+ # [
2891
+ # {
2892
+ # "positionId": 479975679,
2893
+ # "market": "BTC_PERP",
2894
+ # "openDate": 1741941025.309887,
2895
+ # "modifyDate": 1741941025.309887,
2896
+ # "amount": "0.001",
2897
+ # "basePrice": "82498.7",
2898
+ # "realizedFunding": "0",
2899
+ # "liquidationPrice": "0",
2900
+ # "liquidationState": null,
2901
+ # "orderDetail": {
2902
+ # "id": 1224727949521,
2903
+ # "tradeAmount": "0.001",
2904
+ # "price": "82498.7",
2905
+ # "tradeFee": "0.028874545",
2906
+ # "fundingFee": "0",
2907
+ # "realizedPnl": "-0.028874545"
2908
+ # }
2909
+ # }
2910
+ # ]
2911
+ #
2912
+ positions = self.parse_positions(response)
2913
+ return self.filter_by_symbol_since_limit(positions, symbol, since, limit)
2914
+
2915
+ def fetch_positions(self, symbols: Strings = None, params={}) -> List[Position]:
2916
+ """
2917
+ fetch all open positions
2918
+
2919
+ https://docs.whitebit.com/private/http-trade-v4/#open-positions
2920
+
2921
+ :param str[] [symbols]: list of unified market symbols
2922
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2923
+ :returns dict[]: a list of `position structures <https://docs.ccxt.com/#/?id=position-structure>`
2924
+ """
2925
+ self.load_markets()
2926
+ symbols = self.market_symbols(symbols)
2927
+ response = self.v4PrivatePostCollateralAccountPositionsOpen(params)
2928
+ #
2929
+ # [
2930
+ # {
2931
+ # "positionId": 479975679,
2932
+ # "market": "BTC_PERP",
2933
+ # "openDate": 1741941025.3098869,
2934
+ # "modifyDate": 1741941025.3098869,
2935
+ # "amount": "0.001",
2936
+ # "basePrice": "82498.7",
2937
+ # "liquidationPrice": "70177.2",
2938
+ # "pnl": "0",
2939
+ # "pnlPercent": "0.00",
2940
+ # "margin": "4.2",
2941
+ # "freeMargin": "9.9",
2942
+ # "funding": "0",
2943
+ # "unrealizedFunding": "0",
2944
+ # "liquidationState": null,
2945
+ # "tpsl": null
2946
+ # }
2947
+ # ]
2948
+ #
2949
+ return self.parse_positions(response, symbols)
2950
+
2951
+ def fetch_position(self, symbol: str, params={}) -> Position:
2952
+ """
2953
+ fetch data on a single open contract trade position
2954
+
2955
+ https://docs.whitebit.com/private/http-trade-v4/#open-positions
2956
+
2957
+ :param str symbol: unified market symbol of the market the position is held in
2958
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2959
+ :returns dict: a `position structure <https://docs.ccxt.com/#/?id=position-structure>`
2960
+ """
2961
+ self.load_markets()
2962
+ market = self.market(symbol)
2963
+ request: dict = {
2964
+ 'symbol': market['id'],
2965
+ }
2966
+ response = self.v4PrivatePostCollateralAccountPositionsOpen(self.extend(request, params))
2967
+ #
2968
+ # [
2969
+ # {
2970
+ # "positionId": 479975679,
2971
+ # "market": "BTC_PERP",
2972
+ # "openDate": 1741941025.3098869,
2973
+ # "modifyDate": 1741941025.3098869,
2974
+ # "amount": "0.001",
2975
+ # "basePrice": "82498.7",
2976
+ # "liquidationPrice": "70177.2",
2977
+ # "pnl": "0",
2978
+ # "pnlPercent": "0.00",
2979
+ # "margin": "4.2",
2980
+ # "freeMargin": "9.9",
2981
+ # "funding": "0",
2982
+ # "unrealizedFunding": "0",
2983
+ # "liquidationState": null,
2984
+ # "tpsl": null
2985
+ # }
2986
+ # ]
2987
+ #
2988
+ data = self.safe_dict(response, 0, {})
2989
+ return self.parse_position(data, market)
2990
+
2991
+ def parse_position(self, position: dict, market: Market = None) -> Position:
2992
+ #
2993
+ # fetchPosition, fetchPositions
2994
+ #
2995
+ # {
2996
+ # "positionId": 479975679,
2997
+ # "market": "BTC_PERP",
2998
+ # "openDate": 1741941025.3098869,
2999
+ # "modifyDate": 1741941025.3098869,
3000
+ # "amount": "0.001",
3001
+ # "basePrice": "82498.7",
3002
+ # "liquidationPrice": "70177.2",
3003
+ # "pnl": "0",
3004
+ # "pnlPercent": "0.00",
3005
+ # "margin": "4.2",
3006
+ # "freeMargin": "9.9",
3007
+ # "funding": "0",
3008
+ # "unrealizedFunding": "0",
3009
+ # "liquidationState": null,
3010
+ # "tpsl": null
3011
+ # }
3012
+ #
3013
+ # fetchPositionHistory
3014
+ #
3015
+ # {
3016
+ # "positionId": 479975679,
3017
+ # "market": "BTC_PERP",
3018
+ # "openDate": 1741941025.309887,
3019
+ # "modifyDate": 1741941025.309887,
3020
+ # "amount": "0.001",
3021
+ # "basePrice": "82498.7",
3022
+ # "realizedFunding": "0",
3023
+ # "liquidationPrice": "0",
3024
+ # "liquidationState": null,
3025
+ # "orderDetail": {
3026
+ # "id": 1224727949521,
3027
+ # "tradeAmount": "0.001",
3028
+ # "price": "82498.7",
3029
+ # "tradeFee": "0.028874545",
3030
+ # "fundingFee": "0",
3031
+ # "realizedPnl": "-0.028874545"
3032
+ # }
3033
+ # }
3034
+ #
3035
+ marketId = self.safe_string(position, 'market')
3036
+ timestamp = self.safe_timestamp(position, 'openDate')
3037
+ tpsl = self.safe_dict(position, 'tpsl', {})
3038
+ orderDetail = self.safe_dict(position, 'orderDetail', {})
3039
+ return self.safe_position({
3040
+ 'info': position,
3041
+ 'id': self.safe_string(position, 'positionId'),
3042
+ 'symbol': self.safe_symbol(marketId, market),
3043
+ 'notional': None,
3044
+ 'marginMode': None,
3045
+ 'liquidationPrice': self.safe_number(position, 'liquidationPrice'),
3046
+ 'entryPrice': self.safe_number(position, 'basePrice'),
3047
+ 'unrealizedPnl': self.safe_number(position, 'pnl'),
3048
+ 'realizedPnl': self.safe_number(orderDetail, 'realizedPnl'),
3049
+ 'percentage': self.safe_number(position, 'pnlPercent'),
3050
+ 'contracts': None,
3051
+ 'contractSize': None,
3052
+ 'markPrice': None,
3053
+ 'lastPrice': None,
3054
+ 'side': None,
3055
+ 'hedged': None,
3056
+ 'timestamp': timestamp,
3057
+ 'datetime': self.iso8601(timestamp),
3058
+ 'lastUpdateTimestamp': self.safe_timestamp(position, 'modifyDate'),
3059
+ 'maintenanceMargin': None,
3060
+ 'maintenanceMarginPercentage': None,
3061
+ 'collateral': self.safe_number(position, 'margin'),
3062
+ 'initialMargin': None,
3063
+ 'initialMarginPercentage': None,
3064
+ 'leverage': None,
3065
+ 'marginRatio': None,
3066
+ 'stopLossPrice': self.safe_number(tpsl, 'stopLoss'),
3067
+ 'takeProfitPrice': self.safe_number(tpsl, 'takeProfit'),
3068
+ })
3069
+
2862
3070
  def is_fiat(self, currency: str) -> bool:
2863
3071
  fiatCurrencies = self.safe_value(self.options, 'fiatCurrencies', [])
2864
3072
  return self.in_array(currency, fiatCurrencies)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ccxt
3
- Version: 4.4.68
3
+ Version: 4.4.69
4
4
  Summary: A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges
5
5
  Home-page: https://ccxt.com
6
6
  Author: Igor Kroitor
@@ -278,13 +278,13 @@ console.log(version, Object.keys(exchanges));
278
278
 
279
279
  All-in-one browser bundle (dependencies included), served from a CDN of your choice:
280
280
 
281
- * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.68/dist/ccxt.browser.min.js
282
- * unpkg: https://unpkg.com/ccxt@4.4.68/dist/ccxt.browser.min.js
281
+ * jsDelivr: https://cdn.jsdelivr.net/npm/ccxt@4.4.69/dist/ccxt.browser.min.js
282
+ * unpkg: https://unpkg.com/ccxt@4.4.69/dist/ccxt.browser.min.js
283
283
 
284
284
  CDNs are not updated in real-time and may have delays. Defaulting to the most recent version without specifying the version number is not recommended. Please, keep in mind that we are not responsible for the correct operation of those CDN servers.
285
285
 
286
286
  ```HTML
287
- <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.68/dist/ccxt.browser.min.js"></script>
287
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ccxt@4.4.69/dist/ccxt.browser.min.js"></script>
288
288
  ```
289
289
 
290
290
  Creates a global `ccxt` object: