Fix Binance API error -2015 when fetching positions on spot exchanges
- Check if exchange supports fetchPositions before calling it - Handle PermissionDenied (error -2015) gracefully with debug log instead of error - Handle NotSupported exception for exchanges that don't support positions - Use ccxt standard field names (contracts, entryPrice) with fallbacks - Skip positions with zero size - Add documentation noting this is a futures/derivatives feature Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
3644c219d4
commit
dd8467468c
|
|
@ -512,28 +512,59 @@ class Exchange:
|
|||
|
||||
def get_active_trades(self) -> List[Dict[str, Union[str, float]]]:
|
||||
"""
|
||||
Returns a list of active trades.
|
||||
Returns a list of active trades/positions.
|
||||
|
||||
Note: This method uses fetch_positions() which is only available on futures/derivatives
|
||||
exchanges. For spot exchanges, this will return an empty list since spot trading
|
||||
doesn't have the concept of "positions" - only balances.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Union[str, float]]]: A list of active trades with symbol, side, quantity, and price.
|
||||
"""
|
||||
if self.api_key and self.api_key_secret:
|
||||
try:
|
||||
positions = self.client.fetch_positions()
|
||||
formatted_trades = []
|
||||
for position in positions:
|
||||
active_trade = {
|
||||
'symbol': position['symbol'],
|
||||
'side': 'buy' if float(position['quantity']) > 0 else 'sell',
|
||||
'quantity': abs(float(position['quantity'])),
|
||||
'price': float(position['entry_price'])
|
||||
}
|
||||
formatted_trades.append(active_trade)
|
||||
return formatted_trades
|
||||
except ccxt.BaseError as e:
|
||||
logger.error(f"Error fetching active trades: {str(e)}")
|
||||
return []
|
||||
else:
|
||||
if not self.api_key or not self.api_key_secret:
|
||||
return []
|
||||
|
||||
# Check if the exchange supports fetching positions (futures/derivatives feature)
|
||||
if not self.client.has.get('fetchPositions'):
|
||||
logger.debug(f"Exchange {self.exchange_id} does not support fetchPositions (spot exchange)")
|
||||
return []
|
||||
|
||||
try:
|
||||
positions = self.client.fetch_positions()
|
||||
formatted_trades = []
|
||||
for position in positions:
|
||||
# Get position size - ccxt uses 'contracts' or 'contractSize', fallback to legacy 'quantity'
|
||||
quantity = position.get('contracts') or position.get('contractSize') or position.get('quantity', 0)
|
||||
if quantity is None:
|
||||
quantity = 0
|
||||
quantity = float(quantity)
|
||||
|
||||
# Skip positions with zero size
|
||||
if quantity == 0:
|
||||
continue
|
||||
|
||||
# Get entry price - ccxt uses 'entryPrice', fallback to legacy 'entry_price'
|
||||
entry_price = position.get('entryPrice') or position.get('entry_price', 0)
|
||||
if entry_price is None:
|
||||
entry_price = 0
|
||||
|
||||
active_trade = {
|
||||
'symbol': position['symbol'],
|
||||
'side': position.get('side') or ('buy' if quantity > 0 else 'sell'),
|
||||
'quantity': abs(quantity),
|
||||
'price': float(entry_price)
|
||||
}
|
||||
formatted_trades.append(active_trade)
|
||||
return formatted_trades
|
||||
except ccxt.PermissionDenied as e:
|
||||
# Error -2015: API key doesn't have permission for this endpoint
|
||||
logger.debug(f"API key lacks permission for fetchPositions on {self.exchange_id}: {e}")
|
||||
return []
|
||||
except ccxt.NotSupported as e:
|
||||
logger.debug(f"fetchPositions not supported on {self.exchange_id}: {e}")
|
||||
return []
|
||||
except ccxt.BaseError as e:
|
||||
logger.error(f"Error fetching active trades from {self.exchange_id}: {str(e)}")
|
||||
return []
|
||||
|
||||
def get_open_orders(self) -> List[Dict[str, Union[str, float]]]:
|
||||
|
|
|
|||
Loading…
Reference in New Issue