position history with fees

This commit is contained in:
Dobromir Popov
2025-05-28 11:17:41 +03:00
parent f8681447e3
commit dd86d21854
11 changed files with 880 additions and 58 deletions

View File

@ -152,8 +152,8 @@ class TradingDashboard:
# Check if trading is enabled and not in dry run mode
if not self.trading_executor.trading_enabled:
logger.warning("MEXC: Trading not enabled - using default balance")
elif self.trading_executor.dry_run:
logger.warning("MEXC: Dry run mode enabled - using default balance")
elif self.trading_executor.simulation_mode:
logger.warning(f"MEXC: {self.trading_executor.trading_mode.upper()} mode enabled - using default balance")
else:
# Get USDT balance from MEXC
balance_info = self.trading_executor.get_account_balance()
@ -188,7 +188,7 @@ class TradingDashboard:
html.I(className="fas fa-chart-line me-2"),
"Live Trading Dashboard"
], className="text-white mb-1"),
html.P(f"Ultra-Fast Updates • Portfolio: ${self.starting_balance:,.0f}{'MEXC Live' if (self.trading_executor and self.trading_executor.trading_enabled and not self.trading_executor.dry_run) else 'Demo Mode'}",
html.P(f"Ultra-Fast Updates • Portfolio: ${self.starting_balance:,.0f}{'MEXC Live' if (self.trading_executor and self.trading_executor.trading_enabled and not self.trading_executor.simulation_mode) else 'Demo Mode'}",
className="text-light mb-0 opacity-75 small")
], className="bg-dark p-2 mb-2"),
@ -219,6 +219,13 @@ class TradingDashboard:
], className="card-body text-center p-2")
], className="card bg-light", style={"height": "60px"}),
html.Div([
html.Div([
html.H5(id="total-fees", className="text-warning mb-0 small"),
html.P("Total Fees", className="text-muted mb-0 tiny")
], className="card-body text-center p-2")
], className="card bg-light", style={"height": "60px"}),
html.Div([
html.Div([
html.H5(id="current-position", className="text-info mb-0 small"),
@ -246,7 +253,7 @@ class TradingDashboard:
html.P("MEXC API", className="text-muted mb-0 tiny")
], className="card-body text-center p-2")
], className="card bg-light", style={"height": "60px"}),
], style={"display": "grid", "gridTemplateColumns": "repeat(3, 1fr)", "gap": "8px", "width": "50%"}),
], style={"display": "grid", "gridTemplateColumns": "repeat(4, 1fr)", "gap": "8px", "width": "60%"}),
# Right side - Recent Signals & Executions
html.Div([
@ -350,6 +357,7 @@ class TradingDashboard:
Output('current-price', 'children'),
Output('session-pnl', 'children'),
Output('session-pnl', 'className'),
Output('total-fees', 'children'),
Output('current-position', 'children'),
Output('current-position', 'className'),
Output('trade-count', 'children'),
@ -511,6 +519,9 @@ class TradingDashboard:
pnl_text = f"${total_session_pnl:.2f}"
pnl_class = "text-success mb-0 small" if total_session_pnl >= 0 else "text-danger mb-0 small"
# Total fees formatting
fees_text = f"${self.total_fees:.2f}"
# Position info with real-time unrealized PnL and proper color coding
if self.current_position:
pos_side = self.current_position['side']
@ -540,8 +551,8 @@ class TradingDashboard:
# MEXC status with detailed information
if self.trading_executor and self.trading_executor.trading_enabled:
if self.trading_executor.dry_run:
mexc_status = "DRY RUN"
if self.trading_executor.simulation_mode:
mexc_status = f"{self.trading_executor.trading_mode.upper()} MODE"
else:
mexc_status = "LIVE"
else:
@ -597,7 +608,7 @@ class TradingDashboard:
closed_trades_table = [html.P("Closed trades data unavailable", className="text-muted")]
return (
price_text, pnl_text, pnl_class, position_text, position_class, trade_count_text, portfolio_text, mexc_status,
price_text, pnl_text, pnl_class, fees_text, position_text, position_class, trade_count_text, portfolio_text, mexc_status,
price_chart, training_metrics, decisions_list, session_perf, closed_trades_table,
system_status['icon_class'], system_status['title'], system_status['details']
)
@ -608,7 +619,7 @@ class TradingDashboard:
empty_fig = self._create_empty_chart("Error", "Dashboard error - check logs")
return (
"Error", "$0.00", "text-muted mb-0 small", "None", "text-muted", "0", "$10,000.00", "OFFLINE",
"Error", "$0.00", "text-muted mb-0 small", "$0.00", "None", "text-muted", "0", "$10,000.00", "OFFLINE",
empty_fig,
[html.P("Error loading training metrics", className="text-danger")],
[html.P("Error loading decisions", className="text-danger")],
@ -1414,6 +1425,7 @@ class TradingDashboard:
decision['mexc_executed'] = mexc_success
# Calculate position size based on confidence and configuration
current_price = decision.get('price', 0)
if current_price and current_price > 0:
# Get position sizing from trading executor configuration
if self.trading_executor:
@ -1756,9 +1768,12 @@ class TradingDashboard:
if not self.closed_trades:
return [html.P("No closed trades yet", className="text-muted text-center")]
# Create table rows for recent closed trades
# Create table rows for recent closed trades (newest first)
table_rows = []
for trade in self.closed_trades[-20:]: # Show last 20 trades
recent_trades = self.closed_trades[-20:] # Get last 20 trades
recent_trades.reverse() # Newest first
for trade in recent_trades:
# Determine row color based on P&L
row_class = "table-success" if trade['net_pnl'] >= 0 else "table-danger"
@ -1768,12 +1783,18 @@ class TradingDashboard:
# Format side color
side_color = "text-success" if trade['side'] == 'LONG' else "text-danger"
# Format position size
position_size = trade.get('size', 0)
size_display = f"{position_size:.4f}" if position_size < 1 else f"{position_size:.2f}"
table_rows.append(
html.Tr([
html.Td(f"#{trade['trade_id']}", className="small"),
html.Td(trade['side'], className=f"small fw-bold {side_color}"),
html.Td(size_display, className="small text-info"),
html.Td(f"${trade['entry_price']:.2f}", className="small"),
html.Td(f"${trade['exit_price']:.2f}", className="small"),
html.Td(f"${trade.get('fees', 0):.2f}", className="small text-warning"),
html.Td(f"${trade['net_pnl']:.2f}", className="small fw-bold"),
html.Td(duration_str, className="small"),
html.Td("" if trade.get('mexc_executed', False) else "SIM",
@ -1787,8 +1808,10 @@ class TradingDashboard:
html.Tr([
html.Th("ID", className="small"),
html.Th("Side", className="small"),
html.Th("Size", className="small"),
html.Th("Entry", className="small"),
html.Th("Exit", className="small"),
html.Th("Fees", className="small"),
html.Th("P&L", className="small"),
html.Th("Duration", className="small"),
html.Th("MEXC", className="small")
@ -1801,12 +1824,14 @@ class TradingDashboard:
total_trades = len(self.closed_trades)
winning_trades = len([t for t in self.closed_trades if t['net_pnl'] > 0])
total_pnl = sum(t['net_pnl'] for t in self.closed_trades)
total_fees_closed = sum(t.get('fees', 0) for t in self.closed_trades)
win_rate = (winning_trades / total_trades * 100) if total_trades > 0 else 0
summary = html.Div([
html.Small([
html.Strong(f"Total: {total_trades} | "),
html.Span(f"Win Rate: {win_rate:.1f}% | ", className="text-info"),
html.Span(f"Fees: ${total_fees_closed:.2f} | ", className="text-warning"),
html.Span(f"Total P&L: ${total_pnl:.2f}",
className="text-success" if total_pnl >= 0 else "text-danger")
], className="d-block mb-2")