integrating new CNN model
This commit is contained in:
253
web/dashboard_fix.py
Normal file
253
web/dashboard_fix.py
Normal file
@ -0,0 +1,253 @@
|
||||
"""
|
||||
Dashboard Fix
|
||||
|
||||
This module provides fixes for the trading dashboard to address:
|
||||
1. Trade display issues
|
||||
2. P&L calculation and display
|
||||
3. Position tracking and synchronization
|
||||
|
||||
Apply these fixes by importing and applying the patch in the dashboard initialization
|
||||
"""
|
||||
|
||||
import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, Any, List, Optional
|
||||
import time
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class DashboardFix:
|
||||
"""Fixes for the Dashboard class"""
|
||||
|
||||
@staticmethod
|
||||
def apply_fixes(dashboard):
|
||||
"""Apply all fixes to the dashboard"""
|
||||
logger.info("Applying Dashboard fixes...")
|
||||
|
||||
# Apply fixes
|
||||
DashboardFix._fix_trade_display(dashboard)
|
||||
DashboardFix._fix_position_sync(dashboard)
|
||||
DashboardFix._fix_pnl_calculation(dashboard)
|
||||
DashboardFix._add_trade_validation(dashboard)
|
||||
|
||||
logger.info("Dashboard fixes applied successfully")
|
||||
return dashboard
|
||||
|
||||
@staticmethod
|
||||
def _fix_trade_display(dashboard):
|
||||
"""Fix trade display to ensure accurate information"""
|
||||
# Store original format_closed_trades_table method
|
||||
if hasattr(dashboard.component_manager, 'format_closed_trades_table'):
|
||||
original_format_closed_trades = dashboard.component_manager.format_closed_trades_table
|
||||
|
||||
def format_closed_trades_table_fixed(self, closed_trades, trading_stats=None):
|
||||
"""Fixed closed trades table formatter with accurate P&L calculation"""
|
||||
# Recalculate P&L for each trade to ensure accuracy
|
||||
for trade in closed_trades:
|
||||
# Skip if already validated
|
||||
if getattr(trade, 'pnl_validated', False):
|
||||
continue
|
||||
|
||||
# Handle both trade objects and dictionary formats
|
||||
if hasattr(trade, 'entry_price'):
|
||||
# This is a trade object
|
||||
entry_price = getattr(trade, 'entry_price', 0)
|
||||
exit_price = getattr(trade, 'exit_price', 0)
|
||||
size = getattr(trade, 'size', 0)
|
||||
side = getattr(trade, 'side', 'UNKNOWN')
|
||||
fees = getattr(trade, 'fees', 0)
|
||||
else:
|
||||
# This is a dictionary format
|
||||
entry_price = trade.get('entry_price', 0)
|
||||
exit_price = trade.get('exit_price', 0)
|
||||
size = trade.get('size', trade.get('quantity', 0))
|
||||
side = trade.get('side', 'UNKNOWN')
|
||||
fees = trade.get('fees', 0)
|
||||
|
||||
# Recalculate P&L
|
||||
if side == 'LONG' or side == 'BUY':
|
||||
pnl = (exit_price - entry_price) * size
|
||||
else: # SHORT or SELL
|
||||
pnl = (entry_price - exit_price) * size
|
||||
|
||||
# Update P&L value
|
||||
if hasattr(trade, 'entry_price'):
|
||||
trade.pnl = pnl
|
||||
trade.net_pnl = pnl - fees
|
||||
trade.pnl_validated = True
|
||||
else:
|
||||
trade['pnl'] = pnl
|
||||
trade['net_pnl'] = pnl - fees
|
||||
trade['pnl_validated'] = True
|
||||
|
||||
# Call original method with validated trades
|
||||
return original_format_closed_trades(closed_trades, trading_stats)
|
||||
|
||||
# Apply the patch
|
||||
dashboard.component_manager.format_closed_trades_table = format_closed_trades_table_fixed.__get__(dashboard.component_manager)
|
||||
logger.info("Trade display fix applied")
|
||||
|
||||
@staticmethod
|
||||
def _fix_position_sync(dashboard):
|
||||
"""Fix position synchronization to ensure accurate position tracking"""
|
||||
# Store original _sync_position_from_executor method
|
||||
if hasattr(dashboard, '_sync_position_from_executor'):
|
||||
original_sync_position = dashboard._sync_position_from_executor
|
||||
|
||||
def sync_position_from_executor_fixed(self, symbol):
|
||||
"""Fixed position sync with validation and logging"""
|
||||
try:
|
||||
# Call original sync method
|
||||
result = original_sync_position(symbol)
|
||||
|
||||
# Add validation and logging
|
||||
if self.trading_executor and hasattr(self.trading_executor, 'positions'):
|
||||
if symbol in self.trading_executor.positions:
|
||||
position = self.trading_executor.positions[symbol]
|
||||
|
||||
# Log position details for debugging
|
||||
logger.debug(f"Position sync for {symbol}: "
|
||||
f"Side={position.side}, "
|
||||
f"Size={position.size}, "
|
||||
f"Entry=${position.entry_price:.2f}")
|
||||
|
||||
# Validate position data
|
||||
if position.entry_price <= 0:
|
||||
logger.warning(f"Invalid entry price for {symbol}: ${position.entry_price:.2f}")
|
||||
|
||||
# Store last sync time
|
||||
if not hasattr(self, 'last_position_sync'):
|
||||
self.last_position_sync = {}
|
||||
|
||||
self.last_position_sync[symbol] = time.time()
|
||||
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in sync_position_from_executor_fixed: {e}")
|
||||
return None
|
||||
|
||||
# Apply the patch
|
||||
dashboard._sync_position_from_executor = sync_position_from_executor_fixed.__get__(dashboard)
|
||||
logger.info("Position sync fix applied")
|
||||
|
||||
@staticmethod
|
||||
def _fix_pnl_calculation(dashboard):
|
||||
"""Fix P&L calculation to ensure accuracy"""
|
||||
# Add a method to recalculate P&L for all closed trades
|
||||
def recalculate_all_pnl(self):
|
||||
"""Recalculate P&L for all closed trades"""
|
||||
if not hasattr(self, 'closed_trades') or not self.closed_trades:
|
||||
return
|
||||
|
||||
for trade in self.closed_trades:
|
||||
# Handle both trade objects and dictionary formats
|
||||
if hasattr(trade, 'entry_price'):
|
||||
# This is a trade object
|
||||
entry_price = getattr(trade, 'entry_price', 0)
|
||||
exit_price = getattr(trade, 'exit_price', 0)
|
||||
size = getattr(trade, 'size', 0)
|
||||
side = getattr(trade, 'side', 'UNKNOWN')
|
||||
fees = getattr(trade, 'fees', 0)
|
||||
else:
|
||||
# This is a dictionary format
|
||||
entry_price = trade.get('entry_price', 0)
|
||||
exit_price = trade.get('exit_price', 0)
|
||||
size = trade.get('size', trade.get('quantity', 0))
|
||||
side = trade.get('side', 'UNKNOWN')
|
||||
fees = trade.get('fees', 0)
|
||||
|
||||
# Recalculate P&L
|
||||
if side == 'LONG' or side == 'BUY':
|
||||
pnl = (exit_price - entry_price) * size
|
||||
else: # SHORT or SELL
|
||||
pnl = (entry_price - exit_price) * size
|
||||
|
||||
# Update P&L value
|
||||
if hasattr(trade, 'entry_price'):
|
||||
trade.pnl = pnl
|
||||
trade.net_pnl = pnl - fees
|
||||
else:
|
||||
trade['pnl'] = pnl
|
||||
trade['net_pnl'] = pnl - fees
|
||||
|
||||
logger.info(f"Recalculated P&L for {len(self.closed_trades)} closed trades")
|
||||
|
||||
# Add the method
|
||||
dashboard.recalculate_all_pnl = recalculate_all_pnl.__get__(dashboard)
|
||||
|
||||
# Call it once to fix existing trades
|
||||
dashboard.recalculate_all_pnl()
|
||||
|
||||
logger.info("P&L calculation fix applied")
|
||||
|
||||
@staticmethod
|
||||
def _add_trade_validation(dashboard):
|
||||
"""Add trade validation to prevent invalid trades"""
|
||||
# Store original _on_trade_closed method if it exists
|
||||
original_on_trade_closed = getattr(dashboard, '_on_trade_closed', None)
|
||||
|
||||
if original_on_trade_closed:
|
||||
def on_trade_closed_fixed(self, trade_data):
|
||||
"""Fixed trade closed handler with validation"""
|
||||
try:
|
||||
# Validate trade data
|
||||
is_valid = True
|
||||
validation_errors = []
|
||||
|
||||
# Check for required fields
|
||||
required_fields = ['symbol', 'side', 'entry_price', 'exit_price', 'size']
|
||||
for field in required_fields:
|
||||
if field not in trade_data:
|
||||
is_valid = False
|
||||
validation_errors.append(f"Missing required field: {field}")
|
||||
|
||||
# Check for valid prices
|
||||
if 'entry_price' in trade_data and trade_data['entry_price'] <= 0:
|
||||
is_valid = False
|
||||
validation_errors.append(f"Invalid entry price: {trade_data['entry_price']}")
|
||||
|
||||
if 'exit_price' in trade_data and trade_data['exit_price'] <= 0:
|
||||
is_valid = False
|
||||
validation_errors.append(f"Invalid exit price: {trade_data['exit_price']}")
|
||||
|
||||
# Check for valid size
|
||||
if 'size' in trade_data and trade_data['size'] <= 0:
|
||||
is_valid = False
|
||||
validation_errors.append(f"Invalid size: {trade_data['size']}")
|
||||
|
||||
# If invalid, log errors and skip
|
||||
if not is_valid:
|
||||
logger.warning(f"Invalid trade data: {validation_errors}")
|
||||
return
|
||||
|
||||
# Calculate correct P&L
|
||||
if 'side' in trade_data and 'entry_price' in trade_data and 'exit_price' in trade_data and 'size' in trade_data:
|
||||
side = trade_data['side']
|
||||
entry_price = trade_data['entry_price']
|
||||
exit_price = trade_data['exit_price']
|
||||
size = trade_data['size']
|
||||
|
||||
if side == 'LONG' or side == 'BUY':
|
||||
pnl = (exit_price - entry_price) * size
|
||||
else: # SHORT or SELL
|
||||
pnl = (entry_price - exit_price) * size
|
||||
|
||||
# Update P&L in trade data
|
||||
trade_data['pnl'] = pnl
|
||||
|
||||
# Calculate net P&L (after fees)
|
||||
fees = trade_data.get('fees', 0)
|
||||
trade_data['net_pnl'] = pnl - fees
|
||||
|
||||
# Call original method with validated data
|
||||
return original_on_trade_closed(trade_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in on_trade_closed_fixed: {e}")
|
||||
|
||||
# Apply the patch
|
||||
dashboard._on_trade_closed = on_trade_closed_fixed.__get__(dashboard)
|
||||
logger.info("Trade validation fix applied")
|
||||
else:
|
||||
logger.warning("_on_trade_closed method not found, skipping trade validation fix")
|
Reference in New Issue
Block a user