This commit is contained in:
Dobromir Popov
2025-11-22 22:17:28 +02:00
parent 9a06288911
commit f38a924b0f
3 changed files with 254 additions and 7 deletions

View File

@@ -1962,6 +1962,16 @@ class CleanTradingDashboard:
def update_price_chart(n, pivots_value, relayout_data):
"""Update price chart every second, persisting user zoom/pan"""
try:
# Log transformer status on first update
if n == 1:
if self.orchestrator and hasattr(self.orchestrator, 'primary_transformer'):
if self.orchestrator.primary_transformer:
logger.info("TRANSFORMER MODEL LOADED - Ghost candles should be visible")
else:
logger.warning("TRANSFORMER MODEL IS NONE - Enable training to load model")
else:
logger.warning("NO TRANSFORMER AVAILABLE - Enable training first")
# Validate and train on predictions every update (once per second)
# This checks if any predictions can be validated against real candles
self._validate_and_train_on_predictions('ETH/USDT')
@@ -3365,6 +3375,7 @@ class CleanTradingDashboard:
self._add_dqn_predictions_to_chart(fig, symbol, df_main, row)
self._add_cnn_predictions_to_chart(fig, symbol, df_main, row)
self._add_transformer_predictions_to_chart(fig, symbol, df_main, row)
self._add_ghost_candles_to_chart(fig, symbol, df_main, row) # Add predicted future candles
self._add_cob_rl_predictions_to_chart(fig, symbol, df_main, row)
self._add_prediction_accuracy_feedback(fig, symbol, df_main, row)
self._add_williams_pivots_to_chart(fig, symbol, df_main, row)
@@ -3683,6 +3694,112 @@ class CleanTradingDashboard:
except Exception as e:
logger.debug(f"Error adding CNN predictions to chart: {e}")
def _add_ghost_candles_to_chart(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
"""Add predicted future candles (ghost candles) to the chart"""
try:
# Get latest live prediction with next_candles
prediction = self._get_live_transformer_prediction_with_next_candles(symbol)
if not prediction:
logger.debug("No transformer prediction available - is training enabled?")
return
if 'next_candles' not in prediction:
logger.debug("Prediction exists but has no next_candles data")
return
next_candles = prediction['next_candles']
if not next_candles:
return
# Get the chart timeframe from the dataframe (assume 1s or 1m based on df_main)
if df_main.empty:
return
# Detect timeframe from dataframe index
if len(df_main) >= 2:
time_diff = (df_main.index[-1] - df_main.index[-2]).total_seconds()
if time_diff <= 1.5:
chart_timeframe = '1s'
elif time_diff <= 65:
chart_timeframe = '1m'
elif time_diff <= 3900:
chart_timeframe = '1h'
else:
chart_timeframe = '1d'
else:
chart_timeframe = '1m' # Default
# Get prediction for this timeframe
if chart_timeframe not in next_candles:
logger.debug(f"No prediction for {chart_timeframe} timeframe")
return
predicted_ohlcv = next_candles[chart_timeframe]
if not predicted_ohlcv or len(predicted_ohlcv) < 5:
return
# Calculate timestamp for predicted candle
last_timestamp = df_main.index[-1]
timeframe_seconds = {'1s': 1, '1m': 60, '1h': 3600, '1d': 86400}
delta_seconds = timeframe_seconds.get(chart_timeframe, 60)
predicted_timestamp = last_timestamp + timedelta(seconds=delta_seconds)
# Extract OHLCV values
pred_open, pred_high, pred_low, pred_close, pred_volume = predicted_ohlcv
# Determine color based on direction
is_bullish = pred_close >= pred_open
# Add ghost candle as semi-transparent candlestick
fig.add_trace(
go.Candlestick(
x=[predicted_timestamp],
open=[pred_open],
high=[pred_high],
low=[pred_low],
close=[pred_close],
name='Predicted Candle',
increasing=dict(
line=dict(color='rgba(0, 255, 0, 0.4)', width=1),
fillcolor='rgba(0, 255, 0, 0.2)'
),
decreasing=dict(
line=dict(color='rgba(255, 0, 0, 0.4)', width=1),
fillcolor='rgba(255, 0, 0, 0.2)'
),
showlegend=True,
legendgroup='predictions',
opacity=0.5
),
row=row, col=1
)
# Add a marker at the predicted close price
fig.add_trace(
go.Scatter(
x=[predicted_timestamp],
y=[pred_close],
mode='markers',
marker=dict(
size=8,
color='rgba(255, 215, 0, 0.8)', # Gold color
symbol='star',
line=dict(color='white', width=1)
),
name='Prediction Target',
showlegend=True,
legendgroup='predictions',
hovertemplate=f'Predicted Close: ${pred_close:.2f}<br>Time: {predicted_timestamp.strftime("%H:%M:%S")}<extra></extra>'
),
row=row, col=1
)
logger.info(f"Added ghost candle for {chart_timeframe}: O={pred_open:.2f}, H={pred_high:.2f}, L={pred_low:.2f}, C={pred_close:.2f}")
except Exception as e:
logger.error(f"Error adding ghost candles to chart: {e}", exc_info=True)
def _add_transformer_predictions_to_chart(self, fig: go.Figure, symbol: str, df_main: pd.DataFrame, row: int = 1):
"""Add Transformer price predictions as trend lines with confidence bands"""
try:
@@ -4071,9 +4188,20 @@ class CleanTradingDashboard:
This makes a real-time prediction with the transformer model
"""
try:
if not self.orchestrator or not hasattr(self.orchestrator, 'primary_transformer') or not self.orchestrator.primary_transformer:
if not self.orchestrator:
logger.debug("No orchestrator available for predictions")
return None
if not hasattr(self.orchestrator, 'primary_transformer'):
logger.debug("Orchestrator has no primary_transformer attribute")
return None
if not self.orchestrator.primary_transformer:
logger.debug("primary_transformer is None - model not loaded")
return None
logger.debug(f"Making live transformer prediction for {symbol}...")
transformer = self.orchestrator.primary_transformer
transformer.eval()