training fixes
This commit is contained in:
@ -40,6 +40,7 @@ from threading import Lock
|
||||
import warnings
|
||||
from dataclasses import asdict
|
||||
import math
|
||||
import subprocess
|
||||
|
||||
# Setup logger
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -258,18 +259,19 @@ class CleanTradingDashboard:
|
||||
def _setup_callbacks(self):
|
||||
"""Setup dashboard callbacks"""
|
||||
|
||||
# Callbacks setup - no process killing needed
|
||||
|
||||
@self.app.callback(
|
||||
[Output('current-price', 'children'),
|
||||
Output('session-pnl', 'children'),
|
||||
Output('current-position', 'children'),
|
||||
# Output('leverage-info', 'children'),
|
||||
Output('trade-count', 'children'),
|
||||
Output('portfolio-value', 'children'),
|
||||
Output('mexc-status', 'children')],
|
||||
[Input('interval-component', 'n_intervals')]
|
||||
)
|
||||
def update_metrics(n):
|
||||
"""Update key metrics"""
|
||||
"""Update key metrics - FIXED callback mismatch"""
|
||||
try:
|
||||
# Sync position from trading executor first
|
||||
symbol = 'ETH/USDT'
|
||||
@ -712,27 +714,44 @@ class CleanTradingDashboard:
|
||||
buy_trades = []
|
||||
sell_trades = []
|
||||
|
||||
for signal in executed_signals[-20:]: # Last 20 executed trades
|
||||
signal_time = self._get_signal_attribute(signal, 'timestamp')
|
||||
for signal in executed_signals[-50:]: # Last 50 executed trades (increased from 20)
|
||||
# Try to get full timestamp first, fall back to string timestamp
|
||||
signal_time = self._get_signal_attribute(signal, 'full_timestamp')
|
||||
if not signal_time:
|
||||
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
|
||||
# FIXED: Better timestamp conversion to prevent race conditions
|
||||
if isinstance(signal_time, str):
|
||||
try:
|
||||
# Handle time-only format
|
||||
# Handle time-only format with current date
|
||||
if ':' in signal_time and len(signal_time.split(':')) == 3:
|
||||
signal_time = datetime.now().replace(
|
||||
hour=int(signal_time.split(':')[0]),
|
||||
minute=int(signal_time.split(':')[1]),
|
||||
second=int(signal_time.split(':')[2]),
|
||||
now = datetime.now()
|
||||
time_parts = signal_time.split(':')
|
||||
signal_time = now.replace(
|
||||
hour=int(time_parts[0]),
|
||||
minute=int(time_parts[1]),
|
||||
second=int(time_parts[2]),
|
||||
microsecond=0
|
||||
)
|
||||
# Handle day boundary issues - if signal seems from future, subtract a day
|
||||
if signal_time > now + timedelta(minutes=5):
|
||||
signal_time -= timedelta(days=1)
|
||||
else:
|
||||
signal_time = pd.to_datetime(signal_time)
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.debug(f"Error parsing timestamp {signal_time}: {e}")
|
||||
continue
|
||||
elif not isinstance(signal_time, datetime):
|
||||
# Convert other timestamp formats to datetime
|
||||
try:
|
||||
signal_time = pd.to_datetime(signal_time)
|
||||
except Exception as e:
|
||||
logger.debug(f"Error converting timestamp to datetime: {e}")
|
||||
continue
|
||||
|
||||
if signal_action == 'BUY':
|
||||
@ -797,34 +816,51 @@ class CleanTradingDashboard:
|
||||
if not self.recent_decisions:
|
||||
return
|
||||
|
||||
# Show ALL signals on the mini chart
|
||||
all_signals = self.recent_decisions[-50:] # Last 50 signals
|
||||
# Show ALL signals on the mini chart - MORE SIGNALS for better visibility
|
||||
all_signals = self.recent_decisions[-100:] # Last 100 signals (increased from 50)
|
||||
|
||||
buy_signals = []
|
||||
sell_signals = []
|
||||
|
||||
for signal in all_signals:
|
||||
signal_time = self._get_signal_attribute(signal, 'timestamp')
|
||||
# Try to get full timestamp first, fall back to string timestamp
|
||||
signal_time = self._get_signal_attribute(signal, 'full_timestamp')
|
||||
if not signal_time:
|
||||
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 and signal_confidence > 0:
|
||||
# Convert timestamp if needed
|
||||
# FIXED: Same timestamp conversion as main chart
|
||||
if isinstance(signal_time, str):
|
||||
try:
|
||||
# Handle time-only format
|
||||
# Handle time-only format with current date
|
||||
if ':' in signal_time and len(signal_time.split(':')) == 3:
|
||||
signal_time = datetime.now().replace(
|
||||
hour=int(signal_time.split(':')[0]),
|
||||
minute=int(signal_time.split(':')[1]),
|
||||
second=int(signal_time.split(':')[2]),
|
||||
now = datetime.now()
|
||||
time_parts = signal_time.split(':')
|
||||
signal_time = now.replace(
|
||||
hour=int(time_parts[0]),
|
||||
minute=int(time_parts[1]),
|
||||
second=int(time_parts[2]),
|
||||
microsecond=0
|
||||
)
|
||||
# Handle day boundary issues
|
||||
if signal_time > now + timedelta(minutes=5):
|
||||
signal_time -= timedelta(days=1)
|
||||
else:
|
||||
signal_time = pd.to_datetime(signal_time)
|
||||
except:
|
||||
except Exception as e:
|
||||
logger.debug(f"Error parsing mini chart timestamp {signal_time}: {e}")
|
||||
continue
|
||||
elif not isinstance(signal_time, datetime):
|
||||
# Convert other timestamp formats to datetime
|
||||
try:
|
||||
signal_time = pd.to_datetime(signal_time)
|
||||
except Exception as e:
|
||||
logger.debug(f"Error converting mini chart timestamp to datetime: {e}")
|
||||
continue
|
||||
|
||||
signal_data = {
|
||||
@ -1543,7 +1579,7 @@ class CleanTradingDashboard:
|
||||
next_pivot_price = recent_low + (price_range * 0.5) # Mid-range target
|
||||
confidence = base_confidence + cob_confidence_boost
|
||||
|
||||
# Calculate time prediction (in minutes)
|
||||
# Calculate time prediction (in minutes)
|
||||
try:
|
||||
recent_closes = [float(x) for x in closes[-20:]]
|
||||
if len(recent_closes) > 1:
|
||||
@ -1659,12 +1695,14 @@ class CleanTradingDashboard:
|
||||
# Don't generate HOLD signals - return None instead
|
||||
return None
|
||||
|
||||
now = datetime.now()
|
||||
return {
|
||||
'action': action,
|
||||
'symbol': symbol,
|
||||
'price': current_price,
|
||||
'confidence': confidence,
|
||||
'timestamp': datetime.now().strftime('%H:%M:%S'),
|
||||
'timestamp': now.strftime('%H:%M:%S'),
|
||||
'full_timestamp': now, # Add full timestamp for chart persistence
|
||||
'size': 0.005,
|
||||
'reason': f'Momentum signal (s={short_momentum:.4f}, m={medium_momentum:.4f})',
|
||||
'model': 'Momentum'
|
||||
@ -1937,9 +1975,11 @@ class CleanTradingDashboard:
|
||||
logger.warning(f"Failed to capture model inputs with COB data: {e}")
|
||||
model_inputs = {}
|
||||
|
||||
# Create manual trading decision
|
||||
# Create manual trading decision with FULL TIMESTAMP for chart persistence
|
||||
now = datetime.now()
|
||||
decision = {
|
||||
'timestamp': datetime.now().strftime('%H:%M:%S'),
|
||||
'timestamp': now.strftime('%H:%M:%S'),
|
||||
'full_timestamp': now, # Store full datetime for better chart positioning
|
||||
'action': action,
|
||||
'confidence': 1.0, # Manual trades have 100% confidence
|
||||
'price': current_price,
|
||||
@ -3124,12 +3164,14 @@ class CleanTradingDashboard:
|
||||
logger.debug(f"Ignoring BTC signal: {symbol}")
|
||||
return
|
||||
|
||||
# Convert orchestrator decision to dashboard format
|
||||
# Convert orchestrator decision to dashboard format with FULL TIMESTAMP
|
||||
# Handle both TradingDecision objects and dictionary formats
|
||||
now = datetime.now()
|
||||
if hasattr(decision, 'action'):
|
||||
# This is a TradingDecision object (dataclass)
|
||||
dashboard_decision = {
|
||||
'timestamp': datetime.now().strftime('%H:%M:%S'),
|
||||
'timestamp': now.strftime('%H:%M:%S'),
|
||||
'full_timestamp': now, # Add full timestamp for chart persistence
|
||||
'action': decision.action,
|
||||
'confidence': decision.confidence,
|
||||
'price': decision.price,
|
||||
@ -3141,7 +3183,8 @@ class CleanTradingDashboard:
|
||||
else:
|
||||
# This is a dictionary format
|
||||
dashboard_decision = {
|
||||
'timestamp': datetime.now().strftime('%H:%M:%S'),
|
||||
'timestamp': now.strftime('%H:%M:%S'),
|
||||
'full_timestamp': now, # Add full timestamp for chart persistence
|
||||
'action': decision.get('action', 'UNKNOWN'),
|
||||
'confidence': decision.get('confidence', 0),
|
||||
'price': decision.get('price', 0),
|
||||
@ -3359,7 +3402,7 @@ class CleanTradingDashboard:
|
||||
if not self.orchestrator:
|
||||
logger.warning("No orchestrator available for training")
|
||||
return
|
||||
|
||||
|
||||
# Check if DQN needs training
|
||||
dqn_status = self._is_model_actually_training('dqn')
|
||||
if not dqn_status['is_training'] and hasattr(self.orchestrator, 'rl_agent') and self.orchestrator.rl_agent:
|
||||
|
Reference in New Issue
Block a user