diff --git a/config.yaml b/config.yaml index 43bd547..a7f2e5b 100644 --- a/config.yaml +++ b/config.yaml @@ -50,11 +50,12 @@ exchanges: bybit: enabled: true test_mode: false # Use mainnet (your credentials are for live trading) - trading_mode: "simulation" # simulation, testnet, live - SWITCHED TO SIMULATION FOR TRAINING + trading_mode: "live" # simulation, testnet, live - SWITCHED TO SIMULATION FOR TRAINING supported_symbols: ["BTCUSDT", "ETHUSDT"] # Bybit perpetual format base_position_percent: 5.0 max_position_percent: 20.0 leverage: 10.0 # Conservative leverage for safety + leverage_applied_by_exchange: true # Broker already applies leverage to P&L trading_fees: maker_fee: 0.0001 # 0.01% maker fee taker_fee: 0.0006 # 0.06% taker fee diff --git a/core/exchanges/bybit/debug/Order_history_sample.md b/core/exchanges/bybit/debug/Order_history_sample.md index e69de29..9e083ec 100644 --- a/core/exchanges/bybit/debug/Order_history_sample.md +++ b/core/exchanges/bybit/debug/Order_history_sample.md @@ -0,0 +1,20 @@ +ETHUSDT + 0.01 3,832.79 3,839.34 Close Short -0.1076 Loss 38.32 38.39 0.0210 0.0211 0.0000 2025-07-28 16:35:46 +ETHUSDT + 0.01 3,874.99 3,829.44 Close Short +0.4131 Win 38.74 38.29 0.0213 0.0210 0.0000 2025-07-28 16:33:52 +ETHUSDT + 0.11 3,874.41 3,863.37 Close Short +0.7473 Win 426.18 424.97 0.2344 0.2337 0.0000 2025-07-28 16:03:32 +ETHUSDT + 0.01 3,875.28 3,868.43 Close Short +0.0259 Win 38.75 38.68 0.0213 0.0212 0.0000 2025-07-28 16:01:40 +ETHUSDT + 0.01 3,875.70 3,871.28 Close Short +0.0016 Win 38.75 38.71 0.0213 0.0212 0.0000 2025-07-28 15:59:53 +ETHUSDT + 0.01 3,879.87 3,879.79 Close Short -0.0418 Loss 38.79 38.79 0.0213 0.0213 0.0000 2025-07-28 15:54:47 +ETHUSDT + -0.05 3,887.50 3,881.04 Close Long -0.5366 Loss 194.37 194.05 0.1069 0.1067 0.0000 2025-07-28 15:46:06 +ETHUSDT + -0.06 3,880.08 3,884.00 Close Long -0.0210 Loss 232.80 233.04 0.1280 0.1281 0.0000 2025-07-28 15:14:38 +ETHUSDT + 0.11 3,877.69 3,876.83 Close Short -0.3737 Loss 426.54 426.45 0.2346 0.2345 0.0000 2025-07-28 15:07:26 +ETHUSDT + 0.01 3,878.70 3,877.75 Close Short -0.0330 Loss 38.78 38.77 0.0213 0.0213 0.0000 2025-07-28 15:01:41 \ No newline at end of file diff --git a/core/trading_executor.py b/core/trading_executor.py index bb20c71..9ce0b9d 100644 --- a/core/trading_executor.py +++ b/core/trading_executor.py @@ -40,13 +40,14 @@ class Position: order_id: str unrealized_pnl: float = 0.0 - def calculate_pnl(self, current_price: float, leverage: float = 1.0, include_fees: bool = True) -> float: + def calculate_pnl(self, current_price: float, leverage: float = 1.0, include_fees: bool = True, leverage_applied_by_exchange: bool = False) -> float: """Calculate unrealized P&L for the position with leverage and fees Args: current_price: Current market price leverage: Leverage multiplier (default: 1.0) include_fees: Whether to subtract fees from PnL (default: True) + leverage_applied_by_exchange: Whether leverage is already applied by broker (default: False) Returns: float: Unrealized PnL including leverage and fees @@ -60,8 +61,13 @@ class Position: else: # SHORT base_pnl = (self.entry_price - current_price) * self.quantity - # Apply leverage - leveraged_pnl = base_pnl * leverage + # Apply leverage only if not already applied by exchange + if leverage_applied_by_exchange: + # Broker already applies leverage, so use base PnL + leveraged_pnl = base_pnl + else: + # Apply leverage locally + leveraged_pnl = base_pnl * leverage # Calculate fees (0.1% open + 0.1% close = 0.2% total) fees = 0.0 @@ -2074,7 +2080,21 @@ class TradingExecutor: """Update position P&L with current market price""" if symbol in self.positions: with self.lock: - self.positions[symbol].calculate_pnl(current_price) + # Get leverage configuration from primary exchange + leverage_applied_by_exchange = False + if hasattr(self, 'primary_config'): + leverage_applied_by_exchange = self.primary_config.get('leverage_applied_by_exchange', False) + + # Get configured leverage + leverage = 1.0 + if hasattr(self, 'primary_config'): + leverage = self.primary_config.get('leverage', 1.0) + + self.positions[symbol].calculate_pnl( + current_price, + leverage=leverage, + leverage_applied_by_exchange=leverage_applied_by_exchange + ) def get_positions(self) -> Dict[str, Position]: """Get current positions""" diff --git a/web/clean_dashboard.py b/web/clean_dashboard.py index 780f075..d78f207 100644 --- a/web/clean_dashboard.py +++ b/web/clean_dashboard.py @@ -824,37 +824,14 @@ class CleanTradingDashboard: else: # SHORT or SELL raw_pnl_per_unit = entry_price - current_price - # Apply current leverage to unrealized P&L - leveraged_unrealized_pnl = raw_pnl_per_unit * size * self.current_leverage - total_session_pnl += leveraged_unrealized_pnl - - side = self.current_position.get('side', 'UNKNOWN') - size = self.current_position.get('size', 0) - entry_price = self.current_position.get('price', 0) - - if entry_price and size > 0: - # Calculate unrealized P&L with current leverage - if side.upper() == 'LONG' or side.upper() == 'BUY': - raw_pnl_per_unit = current_price - entry_price - else: # SHORT or SELL - raw_pnl_per_unit = entry_price - current_price - - # Apply current leverage to unrealized P&L - leveraged_unrealized_pnl = raw_pnl_per_unit * size * self.current_leverage - total_session_pnl += leveraged_unrealized_pnl - side = self.current_position.get('side', 'UNKNOWN') - size = self.current_position.get('size', 0) - entry_price = self.current_position.get('price', 0) - - if entry_price and size > 0: - # Calculate unrealized P&L with current leverage - if side.upper() == 'LONG' or side.upper() == 'BUY': - raw_pnl_per_unit = current_price - entry_price - else: # SHORT or SELL - raw_pnl_per_unit = entry_price - current_price - - # Apply current leverage to unrealized P&L - leveraged_unrealized_pnl = raw_pnl_per_unit * size * self.current_leverage + # Apply leverage only if not already applied by exchange + leverage_applied_by_exchange = self._get_leverage_applied_by_exchange() + if leverage_applied_by_exchange: + # Broker already applies leverage, so use base P&L + leveraged_unrealized_pnl = raw_pnl_per_unit * size + else: + # Apply leverage locally + leveraged_unrealized_pnl = raw_pnl_per_unit * size * self.current_leverage total_session_pnl += leveraged_unrealized_pnl session_pnl_str = f"${total_session_pnl:.2f}" @@ -879,10 +856,15 @@ class CleanTradingDashboard: else: # SHORT or SELL raw_pnl_per_unit = entry_price - current_price - # Apply current leverage to P&L calculation - # With leverage, P&L is amplified by the leverage factor - leveraged_pnl_per_unit = raw_pnl_per_unit * self.current_leverage - unrealized_pnl = leveraged_pnl_per_unit * size + # Apply leverage only if not already applied by exchange + leverage_applied_by_exchange = self._get_leverage_applied_by_exchange() + if leverage_applied_by_exchange: + # Broker already applies leverage, so use base P&L + unrealized_pnl = raw_pnl_per_unit * size + else: + # Apply leverage locally + leveraged_pnl_per_unit = raw_pnl_per_unit * self.current_leverage + unrealized_pnl = leveraged_pnl_per_unit * size # Format P&L string with color if unrealized_pnl >= 0: @@ -1334,6 +1316,16 @@ class CleanTradingDashboard: # logger.error(f"Error updating cold start mode: {e}") # return "ERROR", "fw-bold text-danger" + def _get_leverage_applied_by_exchange(self) -> bool: + """Check if leverage is already applied by the exchange""" + try: + if self.trading_executor and hasattr(self.trading_executor, 'primary_config'): + return self.trading_executor.primary_config.get('leverage_applied_by_exchange', False) + return False + except Exception as e: + logger.debug(f"Error checking leverage_applied_by_exchange: {e}") + return False + def _get_current_price(self, symbol: str) -> Optional[float]: """Get current price for symbol - ONLY using our data providers""" try: @@ -4101,8 +4093,14 @@ class CleanTradingDashboard: else: # SHORT raw_pnl_per_unit = entry_price - current_price - # Apply current leverage to P&L calculation - leveraged_unrealized_pnl = raw_pnl_per_unit * size * self.current_leverage + # Apply leverage only if not already applied by exchange + leverage_applied_by_exchange = self._get_leverage_applied_by_exchange() + if leverage_applied_by_exchange: + # Broker already applies leverage, so use base P&L + leveraged_unrealized_pnl = raw_pnl_per_unit * size + else: + # Apply leverage locally + leveraged_unrealized_pnl = raw_pnl_per_unit * size * self.current_leverage # Calculate profit incentive - bigger profits create stronger incentive to close if leveraged_unrealized_pnl > 0: