trading works!

This commit is contained in:
Dobromir Popov
2025-07-15 01:10:37 +03:00
parent 24230f7f79
commit 439611cf88
5 changed files with 309 additions and 16 deletions

View File

@ -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