fix Pnl, cob

This commit is contained in:
Dobromir Popov
2025-06-25 20:22:43 +03:00
parent 7d00a281ba
commit 2f712c9d6a
3 changed files with 446 additions and 83 deletions

View File

@ -239,9 +239,28 @@ class CleanTradingDashboard:
current_price = self._get_current_price('ETH/USDT')
price_str = f"${current_price:.2f}" if current_price else "Loading..."
# Calculate session P&L
session_pnl_str = f"${self.session_pnl:.2f}"
session_pnl_class = "text-success" if self.session_pnl >= 0 else "text-danger"
# Calculate session P&L including unrealized P&L from current position
total_session_pnl = self.session_pnl # Start with realized P&L
# Add unrealized P&L from current position (x50 leverage)
if self.current_position and current_price:
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 x50 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 x50 leverage to unrealized P&L
leveraged_unrealized_pnl = raw_pnl_per_unit * size * 50
total_session_pnl += leveraged_unrealized_pnl
session_pnl_str = f"${total_session_pnl:.2f}"
session_pnl_class = "text-success" if total_session_pnl >= 0 else "text-danger"
# Current position with unrealized P&L (x50 leverage)
position_str = "No Position"
@ -620,18 +639,18 @@ class CleanTradingDashboard:
"""Add model predictions to the chart - ONLY EXECUTED TRADES on main chart"""
try:
# Only show EXECUTED TRADES on the main 1m chart
executed_signals = [signal for signal in self.recent_decisions if signal.get('executed', False)]
executed_signals = [signal for signal in self.recent_decisions if self._get_signal_attribute(signal, 'executed', False)]
if executed_signals:
# Separate by prediction type
# Separate by prediction type
buy_trades = []
sell_trades = []
for signal in executed_signals[-20:]: # Last 20 executed trades
signal_time = signal.get('timestamp')
signal_price = signal.get('price', 0)
signal_action = signal.get('action', 'HOLD')
signal_confidence = signal.get('confidence', 0)
signal_time = self._get_signal_attribute(signal, 'timestamp')
signal_price = self._get_signal_attribute(signal, 'price', 0)
signal_action = self._get_signal_attribute(signal, 'action', 'HOLD')
signal_confidence = self._get_signal_attribute(signal, 'confidence', 0)
if signal_time and signal_price and signal_confidence > 0:
# Convert timestamp if needed
@ -657,51 +676,51 @@ class CleanTradingDashboard:
# Add EXECUTED BUY trades (large green circles)
if buy_trades:
fig.add_trace(
go.Scatter(
fig.add_trace(
go.Scatter(
x=[t['x'] for t in buy_trades],
y=[t['y'] for t in buy_trades],
mode='markers',
marker=dict(
mode='markers',
marker=dict(
symbol='circle',
size=15,
color='rgba(0, 255, 100, 0.9)',
line=dict(width=3, color='green')
),
name='EXECUTED BUY',
showlegend=True,
showlegend=True,
hovertemplate="<b>EXECUTED BUY TRADE</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata:.1%}<extra></extra>",
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata:.1%}<extra></extra>",
customdata=[t['confidence'] for t in buy_trades]
),
row=row, col=1
)
),
row=row, col=1
)
# Add EXECUTED SELL trades (large red circles)
if sell_trades:
fig.add_trace(
go.Scatter(
fig.add_trace(
go.Scatter(
x=[t['x'] for t in sell_trades],
y=[t['y'] for t in sell_trades],
mode='markers',
marker=dict(
mode='markers',
marker=dict(
symbol='circle',
size=15,
color='rgba(255, 100, 100, 0.9)',
line=dict(width=3, color='red')
),
name='EXECUTED SELL',
showlegend=True,
hovertemplate="<b>EXECUTED SELL TRADE</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata:.1%}<extra></extra>",
name='EXECUTED SELL',
showlegend=True,
hovertemplate="<b>EXECUTED SELL TRADE</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata:.1%}<extra></extra>",
customdata=[t['confidence'] for t in sell_trades]
),
row=row, col=1
)
),
row=row, col=1
)
except Exception as e:
logger.warning(f"Error adding executed trades to main chart: {e}")
@ -719,13 +738,13 @@ class CleanTradingDashboard:
sell_signals = []
for signal in all_signals:
signal_time = signal.get('timestamp')
signal_price = signal.get('price', 0)
signal_action = signal.get('action', 'HOLD')
signal_confidence = signal.get('confidence', 0)
is_executed = signal.get('executed', False)
signal_time = self._get_signal_attribute(signal, 'timestamp')
signal_price = self._get_signal_attribute(signal, 'price', 0)
signal_action = self._get_signal_attribute(signal, 'action', 'HOLD')
signal_confidence = self._get_signal_attribute(signal, 'confidence', 0)
is_executed = self._get_signal_attribute(signal, 'executed', False)
if signal_time and signal_price and signal_confidence > 0:
if signal_time and signal_price and signal_confidence and signal_confidence > 0:
# Convert timestamp if needed
if isinstance(signal_time, str):
try:
@ -762,36 +781,36 @@ class CleanTradingDashboard:
# Executed buy signals (solid green triangles)
if executed_buys:
fig.add_trace(
go.Scatter(
fig.add_trace(
go.Scatter(
x=[s['x'] for s in executed_buys],
y=[s['y'] for s in executed_buys],
mode='markers',
marker=dict(
mode='markers',
marker=dict(
symbol='triangle-up',
size=10,
size=10,
color='rgba(0, 255, 100, 1.0)',
line=dict(width=2, color='green')
),
name='BUY (Executed)',
showlegend=False,
hovertemplate="<b>BUY EXECUTED</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata:.1%}<extra></extra>",
customdata=[s['confidence'] for s in executed_buys]
),
row=row, col=1
)
),
row=row, col=1
)
# Pending/non-executed buy signals (hollow green triangles)
if pending_buys:
fig.add_trace(
go.Scatter(
fig.add_trace(
go.Scatter(
x=[s['x'] for s in pending_buys],
y=[s['y'] for s in pending_buys],
mode='markers',
marker=dict(
mode='markers',
marker=dict(
symbol='triangle-up',
size=8,
color='rgba(0, 255, 100, 0.5)',
@ -823,20 +842,20 @@ class CleanTradingDashboard:
mode='markers',
marker=dict(
symbol='triangle-down',
size=10,
size=10,
color='rgba(255, 100, 100, 1.0)',
line=dict(width=2, color='red')
),
name='SELL (Executed)',
showlegend=False,
hovertemplate="<b>SELL EXECUTED</b><br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Price: $%{y:.2f}<br>" +
"Time: %{x}<br>" +
"Confidence: %{customdata:.1%}<extra></extra>",
customdata=[s['confidence'] for s in executed_sells]
),
row=row, col=1
)
),
row=row, col=1
)
# Pending/non-executed sell signals (hollow red triangles)
if pending_sells:
@ -1869,6 +1888,20 @@ class CleanTradingDashboard:
except Exception as e:
logger.error(f"Error clearing session: {e}")
def _get_signal_attribute(self, signal, attr_name, default=None):
"""Safely get attribute from signal (handles both dict and dataclass objects)"""
try:
if hasattr(signal, attr_name):
# Dataclass or object with attribute
return getattr(signal, attr_name, default)
elif isinstance(signal, dict):
# Dictionary
return signal.get(attr_name, default)
else:
return default
except Exception:
return default
def _clear_old_signals_for_tick_range(self):
"""Clear old signals that are outside the current tick cache time range"""
try:
@ -1883,7 +1916,7 @@ class CleanTradingDashboard:
# Filter recent_decisions to only keep signals within the tick cache time range
filtered_decisions = []
for signal in self.recent_decisions:
signal_time = signal.get('timestamp')
signal_time = self._get_signal_attribute(signal, 'timestamp')
if signal_time:
# Convert signal timestamp to datetime for comparison
try: