trading works!
This commit is contained in:
@ -139,6 +139,13 @@ class TradingExecutor:
|
||||
self.lock = RLock()
|
||||
self.lock_timeout = 10.0 # 10 second timeout for order execution
|
||||
|
||||
# Open order management
|
||||
self.max_open_orders = 2 # Maximum number of open orders allowed
|
||||
self.open_orders_count = 0 # Current count of open orders
|
||||
|
||||
# Trading symbols
|
||||
self.symbols = self.config.get('symbols', ['ETH/USDT', 'BTC/USDT'])
|
||||
|
||||
# Connect to exchange
|
||||
if self.trading_enabled:
|
||||
logger.info("TRADING EXECUTOR: Attempting to connect to exchange...")
|
||||
@ -324,6 +331,109 @@ class TradingExecutor:
|
||||
self.lock.release()
|
||||
logger.debug(f"LOCK RELEASED: {action} for {symbol}")
|
||||
|
||||
def _get_open_orders_count(self) -> int:
|
||||
"""Get current count of open orders across all symbols"""
|
||||
try:
|
||||
if self.simulation_mode:
|
||||
return 0
|
||||
|
||||
total_open_orders = 0
|
||||
for symbol in self.symbols:
|
||||
open_orders = self.exchange.get_open_orders(symbol)
|
||||
total_open_orders += len(open_orders)
|
||||
|
||||
return total_open_orders
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting open orders count: {e}")
|
||||
return 0
|
||||
|
||||
def _can_place_new_order(self) -> bool:
|
||||
"""Check if we can place a new order based on open order limit"""
|
||||
current_count = self._get_open_orders_count()
|
||||
can_place = current_count < self.max_open_orders
|
||||
|
||||
if not can_place:
|
||||
logger.warning(f"Cannot place new order: {current_count}/{self.max_open_orders} open orders")
|
||||
|
||||
return can_place
|
||||
|
||||
def sync_open_orders(self) -> Dict[str, Any]:
|
||||
"""Synchronize open orders with exchange and update internal state
|
||||
|
||||
Returns:
|
||||
dict: Sync result with status and order details
|
||||
"""
|
||||
try:
|
||||
if self.simulation_mode:
|
||||
return {
|
||||
'status': 'success',
|
||||
'message': 'Simulation mode - no real orders to sync',
|
||||
'orders': [],
|
||||
'count': 0
|
||||
}
|
||||
|
||||
sync_result = {
|
||||
'status': 'started',
|
||||
'orders': [],
|
||||
'count': 0,
|
||||
'errors': []
|
||||
}
|
||||
|
||||
total_orders = 0
|
||||
all_orders = []
|
||||
|
||||
# Sync orders for each symbol
|
||||
for symbol in self.symbols:
|
||||
try:
|
||||
open_orders = self.exchange.get_open_orders(symbol)
|
||||
if open_orders:
|
||||
symbol_orders = []
|
||||
for order in open_orders:
|
||||
order_info = {
|
||||
'symbol': symbol,
|
||||
'order_id': order.get('orderId'),
|
||||
'side': order.get('side'),
|
||||
'type': order.get('type'),
|
||||
'quantity': float(order.get('origQty', 0)),
|
||||
'price': float(order.get('price', 0)),
|
||||
'status': order.get('status'),
|
||||
'time': order.get('time')
|
||||
}
|
||||
symbol_orders.append(order_info)
|
||||
all_orders.append(order_info)
|
||||
|
||||
total_orders += len(symbol_orders)
|
||||
logger.info(f"Synced {len(symbol_orders)} open orders for {symbol}")
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error syncing orders for {symbol}: {e}"
|
||||
logger.error(error_msg)
|
||||
sync_result['errors'].append(error_msg)
|
||||
|
||||
# Update internal state
|
||||
self.open_orders_count = total_orders
|
||||
|
||||
sync_result.update({
|
||||
'status': 'success',
|
||||
'orders': all_orders,
|
||||
'count': total_orders,
|
||||
'message': f"Synced {total_orders} open orders across {len(self.symbols)} symbols"
|
||||
})
|
||||
|
||||
logger.info(f"Open order sync completed: {total_orders} orders")
|
||||
return sync_result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in open order sync: {e}")
|
||||
return {
|
||||
'status': 'error',
|
||||
'message': str(e),
|
||||
'orders': [],
|
||||
'count': 0,
|
||||
'errors': [str(e)]
|
||||
}
|
||||
|
||||
def _cancel_open_orders(self, symbol: str) -> int:
|
||||
"""Cancel all open orders for a symbol and return count of cancelled orders"""
|
||||
try:
|
||||
@ -395,6 +505,11 @@ class TradingExecutor:
|
||||
logger.warning(f"Maximum concurrent positions reached: {len(self.positions)}")
|
||||
return False
|
||||
|
||||
# Check open order limit
|
||||
if not self._can_place_new_order():
|
||||
logger.warning(f"Maximum open orders reached: {self._get_open_orders_count()}/{self.max_open_orders}")
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def _execute_buy(self, symbol: str, confidence: float, current_price: float) -> bool:
|
||||
@ -848,13 +963,11 @@ class TradingExecutor:
|
||||
)
|
||||
|
||||
if order:
|
||||
# Calculate simulated fees in simulation mode
|
||||
taker_fee_rate = self.mexc_config.get('trading_fees', {}).get('taker_fee', 0.0006)
|
||||
simulated_fees = position.quantity * current_price * taker_fee_rate
|
||||
# Calculate fees using real API data when available
|
||||
fees = self._calculate_real_trading_fees(order, symbol, position.quantity, current_price)
|
||||
|
||||
# Calculate P&L, fees, and hold time
|
||||
pnl = position.calculate_pnl(current_price)
|
||||
fees = simulated_fees
|
||||
exit_time = datetime.now()
|
||||
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
|
||||
|
||||
@ -989,13 +1102,11 @@ class TradingExecutor:
|
||||
)
|
||||
|
||||
if order:
|
||||
# Calculate simulated fees in simulation mode
|
||||
taker_fee_rate = self.mexc_config.get('trading_fees', {}).get('taker_fee', 0.0006)
|
||||
simulated_fees = position.quantity * current_price * taker_fee_rate
|
||||
# Calculate fees using real API data when available
|
||||
fees = self._calculate_real_trading_fees(order, symbol, position.quantity, current_price)
|
||||
|
||||
# Calculate P&L, fees, and hold time
|
||||
pnl = position.calculate_pnl(current_price)
|
||||
fees = simulated_fees
|
||||
exit_time = datetime.now()
|
||||
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
|
||||
|
||||
@ -1213,6 +1324,38 @@ class TradingExecutor:
|
||||
logger.error(f"Error getting account balance: {e}")
|
||||
return {}
|
||||
|
||||
def _calculate_real_trading_fees(self, order_result: Dict[str, Any], symbol: str,
|
||||
quantity: float, price: float) -> float:
|
||||
"""Calculate trading fees using real API data when available
|
||||
|
||||
Args:
|
||||
order_result: Order result from exchange API
|
||||
symbol: Trading symbol
|
||||
quantity: Order quantity
|
||||
price: Execution price
|
||||
|
||||
Returns:
|
||||
float: Trading fee amount in quote currency
|
||||
"""
|
||||
try:
|
||||
# Try to get actual fee from API response first
|
||||
if order_result and 'fills' in order_result:
|
||||
total_commission = 0.0
|
||||
for fill in order_result['fills']:
|
||||
commission = float(fill.get('commission', 0))
|
||||
total_commission += commission
|
||||
|
||||
if total_commission > 0:
|
||||
logger.info(f"Using real API fee: {total_commission}")
|
||||
return total_commission
|
||||
|
||||
# Fall back to config-based calculation
|
||||
return self._calculate_trading_fee(order_result, symbol, quantity, price)
|
||||
|
||||
except Exception as e:
|
||||
logger.warning(f"Error calculating real fees: {e}, falling back to config-based")
|
||||
return self._calculate_trading_fee(order_result, symbol, quantity, price)
|
||||
|
||||
def _calculate_trading_fee(self, order_result: Dict[str, Any], symbol: str,
|
||||
quantity: float, price: float) -> float:
|
||||
"""Calculate trading fee based on order execution details with enhanced MEXC API support
|
||||
|
Reference in New Issue
Block a user