UI and stability

This commit is contained in:
Dobromir Popov
2025-07-28 14:05:37 +03:00
parent 25b2d3840a
commit 44821b2a89
7 changed files with 934 additions and 135 deletions

View File

@ -1247,27 +1247,23 @@ class TradingExecutor:
taker_fee_rate = trading_fees.get('taker_fee', trading_fees.get('default_fee', 0.0006))
simulated_fees = position.quantity * current_price * taker_fee_rate
# Calculate P&L for short position and hold time
pnl = position.calculate_pnl(current_price)
exit_time = datetime.now()
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
# Get current leverage setting from dashboard or config
# Get current leverage setting
leverage = self.get_leverage()
# Calculate position size in USD
position_size_usd = position.quantity * position.entry_price
# Calculate gross PnL (before fees) with leverage
if position.side == 'SHORT':
gross_pnl = (position.entry_price - current_price) * position.quantity * leverage
else: # LONG
gross_pnl = (current_price - position.entry_price) * position.quantity * leverage
gross_pnl = (current_price - position.entry_price) * position.quantity * leverage
# Calculate net PnL (after fees)
net_pnl = gross_pnl - simulated_fees
# Create trade record with enhanced PnL calculations
# Calculate hold time
exit_time = datetime.now()
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
# Create trade record with corrected PnL calculations
trade_record = TradeRecord(
symbol=symbol,
side='SHORT',
@ -1287,16 +1283,16 @@ class TradingExecutor:
)
self.trade_history.append(trade_record)
self.trade_records.append(trade_record) # Add to trade records for success rate tracking
self.daily_loss += max(0, -pnl) # Add to daily loss if negative
self.trade_records.append(trade_record)
self.daily_loss += max(0, -net_pnl) # Use net_pnl instead of pnl
# Adjust profitability reward multiplier based on recent performance
self._adjust_profitability_reward_multiplier()
# Update consecutive losses
if pnl < -0.001: # A losing trade
# Update consecutive losses using net_pnl
if net_pnl < -0.001: # A losing trade
self.consecutive_losses += 1
elif pnl > 0.001: # A winning trade
elif net_pnl > 0.001: # A winning trade
self.consecutive_losses = 0
else: # Breakeven trade
self.consecutive_losses = 0
@ -1306,7 +1302,7 @@ class TradingExecutor:
self.last_trade_time[symbol] = datetime.now()
self.daily_trades += 1
logger.info(f"Position closed - P&L: ${pnl:.2f}")
logger.info(f"SHORT position closed - Gross P&L: ${gross_pnl:.2f}, Net P&L: ${net_pnl:.2f}, Fees: ${simulated_fees:.3f}")
return True
try:
@ -1342,27 +1338,23 @@ class TradingExecutor:
# 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)
exit_time = datetime.now()
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
# Get current leverage setting from dashboard or config
# Get current leverage setting
leverage = self.get_leverage()
# Calculate position size in USD
position_size_usd = position.quantity * position.entry_price
# Calculate gross PnL (before fees) with leverage
if position.side == 'SHORT':
gross_pnl = (position.entry_price - current_price) * position.quantity * leverage
else: # LONG
gross_pnl = (current_price - position.entry_price) * position.quantity * leverage
gross_pnl = (current_price - position.entry_price) * position.quantity * leverage
# Calculate net PnL (after fees)
net_pnl = gross_pnl - fees
# Create trade record with enhanced PnL calculations
# Calculate hold time
exit_time = datetime.now()
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
# Create trade record with corrected PnL calculations
trade_record = TradeRecord(
symbol=symbol,
side='SHORT',
@ -1382,16 +1374,16 @@ class TradingExecutor:
)
self.trade_history.append(trade_record)
self.trade_records.append(trade_record) # Add to trade records for success rate tracking
self.daily_loss += max(0, -(pnl - fees)) # Add to daily loss if negative
self.trade_records.append(trade_record)
self.daily_loss += max(0, -net_pnl) # Use net_pnl instead of pnl
# Adjust profitability reward multiplier based on recent performance
self._adjust_profitability_reward_multiplier()
# Update consecutive losses
if pnl < -0.001: # A losing trade
# Update consecutive losses using net_pnl
if net_pnl < -0.001: # A losing trade
self.consecutive_losses += 1
elif pnl > 0.001: # A winning trade
elif net_pnl > 0.001: # A winning trade
self.consecutive_losses = 0
else: # Breakeven trade
self.consecutive_losses = 0
@ -1402,7 +1394,7 @@ class TradingExecutor:
self.daily_trades += 1
logger.info(f"SHORT close order executed: {order}")
logger.info(f"SHORT position closed - P&L: ${pnl - fees:.2f}")
logger.info(f"SHORT position closed - Gross P&L: ${gross_pnl:.2f}, Net P&L: ${net_pnl:.2f}, Fees: ${fees:.3f}")
return True
else:
logger.error("Failed to place SHORT close order")
@ -1417,7 +1409,7 @@ class TradingExecutor:
if symbol not in self.positions:
logger.warning(f"No position to close in {symbol}")
return False
position = self.positions[symbol]
if position.side != 'LONG':
logger.warning(f"Position in {symbol} is not LONG, cannot close with SELL")
@ -1429,15 +1421,27 @@ class TradingExecutor:
if self.simulation_mode:
logger.info(f"SIMULATION MODE ({self.trading_mode.upper()}) - Long close logged but not executed")
# Calculate simulated fees in simulation mode
taker_fee_rate = self.mexc_config.get('trading_fees', {}).get('taker_fee', 0.0006)
trading_fees = self.exchange_config.get('trading_fees', {})
taker_fee_rate = trading_fees.get('taker_fee', trading_fees.get('default_fee', 0.0006))
simulated_fees = position.quantity * current_price * taker_fee_rate
# Calculate P&L for long position and hold time
pnl = position.calculate_pnl(current_price)
# Get current leverage setting
leverage = self.get_leverage()
# Calculate position size in USD
position_size_usd = position.quantity * position.entry_price
# Calculate gross PnL (before fees) with leverage
gross_pnl = (current_price - position.entry_price) * position.quantity * leverage
# Calculate net PnL (after fees)
net_pnl = gross_pnl - simulated_fees
# Calculate hold time
exit_time = datetime.now()
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
# Create trade record
# Create trade record with corrected PnL calculations
trade_record = TradeRecord(
symbol=symbol,
side='LONG',
@ -1446,23 +1450,27 @@ class TradingExecutor:
exit_price=current_price,
entry_time=position.entry_time,
exit_time=exit_time,
pnl=pnl,
pnl=net_pnl, # Store net PnL as the main PnL value
fees=simulated_fees,
confidence=confidence,
hold_time_seconds=hold_time_seconds
hold_time_seconds=hold_time_seconds,
leverage=leverage,
position_size_usd=position_size_usd,
gross_pnl=gross_pnl,
net_pnl=net_pnl
)
self.trade_history.append(trade_record)
self.trade_records.append(trade_record) # Add to trade records for success rate tracking
self.daily_loss += max(0, -pnl) # Add to daily loss if negative
self.trade_records.append(trade_record)
self.daily_loss += max(0, -net_pnl) # Use net_pnl instead of pnl
# Adjust profitability reward multiplier based on recent performance
self._adjust_profitability_reward_multiplier()
# Update consecutive losses
if pnl < -0.001: # A losing trade
# Update consecutive losses using net_pnl
if net_pnl < -0.001: # A losing trade
self.consecutive_losses += 1
elif pnl > 0.001: # A winning trade
elif net_pnl > 0.001: # A winning trade
self.consecutive_losses = 0
else: # Breakeven trade
self.consecutive_losses = 0
@ -1472,7 +1480,7 @@ class TradingExecutor:
self.last_trade_time[symbol] = datetime.now()
self.daily_trades += 1
logger.info(f"Position closed - P&L: ${pnl:.2f}")
logger.info(f"LONG position closed - Gross P&L: ${gross_pnl:.2f}, Net P&L: ${net_pnl:.2f}, Fees: ${simulated_fees:.3f}")
return True
try:
@ -1508,12 +1516,23 @@ class TradingExecutor:
# 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)
# Get current leverage setting
leverage = self.get_leverage()
# Calculate position size in USD
position_size_usd = position.quantity * position.entry_price
# Calculate gross PnL (before fees) with leverage
gross_pnl = (current_price - position.entry_price) * position.quantity * leverage
# Calculate net PnL (after fees)
net_pnl = gross_pnl - fees
# Calculate hold time
exit_time = datetime.now()
hold_time_seconds = (exit_time - position.entry_time).total_seconds()
# Create trade record
# Create trade record with corrected PnL calculations
trade_record = TradeRecord(
symbol=symbol,
side='LONG',
@ -1522,23 +1541,27 @@ class TradingExecutor:
exit_price=current_price,
entry_time=position.entry_time,
exit_time=exit_time,
pnl=pnl - fees,
pnl=net_pnl, # Store net PnL as the main PnL value
fees=fees,
confidence=confidence,
hold_time_seconds=hold_time_seconds
hold_time_seconds=hold_time_seconds,
leverage=leverage,
position_size_usd=position_size_usd,
gross_pnl=gross_pnl,
net_pnl=net_pnl
)
self.trade_history.append(trade_record)
self.trade_records.append(trade_record) # Add to trade records for success rate tracking
self.daily_loss += max(0, -(pnl - fees)) # Add to daily loss if negative
self.trade_records.append(trade_record)
self.daily_loss += max(0, -net_pnl) # Use net_pnl instead of pnl
# Adjust profitability reward multiplier based on recent performance
self._adjust_profitability_reward_multiplier()
# Update consecutive losses
if pnl < -0.001: # A losing trade
# Update consecutive losses using net_pnl
if net_pnl < -0.001: # A losing trade
self.consecutive_losses += 1
elif pnl > 0.001: # A winning trade
elif net_pnl > 0.001: # A winning trade
self.consecutive_losses = 0
else: # Breakeven trade
self.consecutive_losses = 0
@ -1549,7 +1572,7 @@ class TradingExecutor:
self.daily_trades += 1
logger.info(f"LONG close order executed: {order}")
logger.info(f"LONG position closed - P&L: ${pnl - fees:.2f}")
logger.info(f"LONG position closed - Gross P&L: ${gross_pnl:.2f}, Net P&L: ${net_pnl:.2f}, Fees: ${fees:.3f}")
return True
else:
logger.error("Failed to place LONG close order")
@ -2406,6 +2429,44 @@ class TradingExecutor:
else:
logger.info("TRADING EXECUTOR: Test mode disabled - normal safety checks active")
def set_trading_mode(self, mode: str) -> bool:
"""Set trading mode (simulation/live) and update all related settings
Args:
mode: Trading mode ('simulation' or 'live')
Returns:
bool: True if mode was set successfully
"""
try:
if mode not in ['simulation', 'live']:
logger.error(f"Invalid trading mode: {mode}. Must be 'simulation' or 'live'")
return False
# Store original mode if not already stored
if not hasattr(self, 'original_trading_mode'):
self.original_trading_mode = self.trading_mode
# Update trading mode
self.trading_mode = mode
self.simulation_mode = (mode == 'simulation')
# Update primary config if available
if hasattr(self, 'primary_config') and self.primary_config:
self.primary_config['trading_mode'] = mode
# Log the change
if mode == 'live':
logger.warning("TRADING EXECUTOR: MODE CHANGED TO LIVE - Real orders will be executed!")
else:
logger.info("TRADING EXECUTOR: MODE CHANGED TO SIMULATION - Orders are simulated")
return True
except Exception as e:
logger.error(f"Error setting trading mode to {mode}: {e}")
return False
def get_status(self) -> Dict[str, Any]:
"""Get trading executor status with safety feature information"""
try:
@ -2731,3 +2792,85 @@ class TradingExecutor:
import traceback
logger.error(f"CORRECTIVE: Full traceback: {traceback.format_exc()}")
return False
def recalculate_all_trade_records(self):
"""Recalculate all existing trade records with correct leverage and PnL"""
logger.info("Recalculating all trade records with correct leverage and PnL...")
updated_count = 0
for i, trade in enumerate(self.trade_history):
try:
# Get current leverage setting
leverage = self.get_leverage()
# Calculate position size in USD
position_size_usd = trade.entry_price * trade.quantity
# Calculate gross PnL (before fees) with leverage
if trade.side == 'LONG':
gross_pnl = (trade.exit_price - trade.entry_price) * trade.quantity * leverage
else: # SHORT
gross_pnl = (trade.entry_price - trade.exit_price) * trade.quantity * leverage
# Calculate fees (0.1% open + 0.1% close = 0.2% total)
entry_value = trade.entry_price * trade.quantity
exit_value = trade.exit_price * trade.quantity
fees = (entry_value + exit_value) * 0.001
# Calculate net PnL (after fees)
net_pnl = gross_pnl - fees
# Update trade record with corrected values
trade.leverage = leverage
trade.position_size_usd = position_size_usd
trade.gross_pnl = gross_pnl
trade.net_pnl = net_pnl
trade.pnl = net_pnl # Main PnL field
trade.fees = fees
updated_count += 1
except Exception as e:
logger.error(f"Error recalculating trade record {i}: {e}")
continue
logger.info(f"Updated {updated_count} trade records with correct leverage and PnL calculations")
# Also update trade_records list if it exists
if hasattr(self, 'trade_records') and self.trade_records:
logger.info("Updating trade_records list...")
for i, trade in enumerate(self.trade_records):
try:
# Get current leverage setting
leverage = self.get_leverage()
# Calculate position size in USD
position_size_usd = trade.entry_price * trade.quantity
# Calculate gross PnL (before fees) with leverage
if trade.side == 'LONG':
gross_pnl = (trade.exit_price - trade.entry_price) * trade.quantity * leverage
else: # SHORT
gross_pnl = (trade.entry_price - trade.exit_price) * trade.quantity * leverage
# Calculate fees (0.1% open + 0.1% close = 0.2% total)
entry_value = trade.entry_price * trade.quantity
exit_value = trade.exit_price * trade.quantity
fees = (entry_value + exit_value) * 0.001
# Calculate net PnL (after fees)
net_pnl = gross_pnl - fees
# Update trade record with corrected values
trade.leverage = leverage
trade.position_size_usd = position_size_usd
trade.gross_pnl = gross_pnl
trade.net_pnl = net_pnl
trade.pnl = net_pnl # Main PnL field
trade.fees = fees
except Exception as e:
logger.error(f"Error recalculating trade_records entry {i}: {e}")
continue
logger.info("Trade record recalculation completed")