dash closed trades history
This commit is contained in:
@ -19,6 +19,7 @@ import pytz
|
||||
from datetime import datetime, timedelta
|
||||
from threading import Thread, Lock
|
||||
from typing import Dict, List, Optional, Any
|
||||
from collections import deque
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import requests
|
||||
@ -32,16 +33,17 @@ import dash_bootstrap_components as dbc
|
||||
from core.config import get_config
|
||||
from core.data_provider import DataProvider, MarketTick
|
||||
from core.enhanced_orchestrator import EnhancedTradingOrchestrator, TradingAction
|
||||
from core.trading_executor import TradingExecutor, Position, TradeRecord
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class TradingSession:
|
||||
"""
|
||||
Session-based trading with $100 starting balance
|
||||
Session-based trading with MEXC integration
|
||||
Tracks P&L for each session but resets between sessions
|
||||
"""
|
||||
|
||||
def __init__(self, session_id: str = None):
|
||||
def __init__(self, session_id: str = None, trading_executor: TradingExecutor = None):
|
||||
self.session_id = session_id or str(uuid.uuid4())[:8]
|
||||
self.start_time = datetime.now()
|
||||
self.starting_balance = 100.0 # $100 USD starting balance
|
||||
@ -53,17 +55,36 @@ class TradingSession:
|
||||
self.positions = {} # symbol -> {'size': float, 'entry_price': float, 'side': str}
|
||||
self.trade_history = []
|
||||
self.last_action = None
|
||||
self.trading_executor = trading_executor
|
||||
|
||||
logger.info(f"NEW TRADING SESSION STARTED")
|
||||
logger.info(f"NEW TRADING SESSION STARTED WITH MEXC INTEGRATION")
|
||||
logger.info(f"Session ID: {self.session_id}")
|
||||
logger.info(f"Starting Balance: ${self.starting_balance:.2f}")
|
||||
logger.info(f"MEXC Trading: {'ENABLED' if trading_executor and trading_executor.trading_enabled else 'DISABLED'}")
|
||||
logger.info(f"Start Time: {self.start_time.strftime('%Y-%m-%d %H:%M:%S')}")
|
||||
|
||||
def execute_trade(self, action: TradingAction, current_price: float):
|
||||
"""Execute a trading action and update P&L"""
|
||||
"""Execute a trading action through MEXC and update P&L"""
|
||||
try:
|
||||
symbol = action.symbol
|
||||
|
||||
# Execute trade through MEXC if available
|
||||
mexc_success = False
|
||||
if self.trading_executor and action.action != 'HOLD':
|
||||
try:
|
||||
mexc_success = self.trading_executor.execute_signal(
|
||||
symbol=symbol,
|
||||
action=action.action,
|
||||
confidence=action.confidence,
|
||||
current_price=current_price
|
||||
)
|
||||
if mexc_success:
|
||||
logger.info(f"MEXC: Trade executed successfully: {action.action} {symbol}")
|
||||
else:
|
||||
logger.warning(f"MEXC: Trade execution failed: {action.action} {symbol}")
|
||||
except Exception as e:
|
||||
logger.error(f"MEXC: Error executing trade: {e}")
|
||||
|
||||
# Calculate position size based on confidence and leverage
|
||||
leverage = 500 # 500x leverage
|
||||
risk_per_trade = 0.02 # 2% risk per trade
|
||||
@ -77,7 +98,8 @@ class TradingSession:
|
||||
'price': current_price,
|
||||
'size': position_size,
|
||||
'value': position_value,
|
||||
'confidence': action.confidence
|
||||
'confidence': action.confidence,
|
||||
'mexc_executed': mexc_success
|
||||
}
|
||||
|
||||
if action.action == 'BUY':
|
||||
@ -121,6 +143,7 @@ class TradingSession:
|
||||
self.current_balance = self.starting_balance + self.total_pnl
|
||||
|
||||
logger.info(f"TRADING: TRADE EXECUTED: {action.action} {symbol} @ ${current_price:.2f}")
|
||||
logger.info(f"MEXC: {'SUCCESS' if mexc_success else 'SIMULATION'}")
|
||||
logger.info(f"CHART: Position Size: {position_size:.6f} (${position_value:.2f})")
|
||||
logger.info(f"MONEY: Session P&L: ${self.total_pnl:+.2f} | Balance: ${self.current_balance:.2f}")
|
||||
|
||||
@ -191,11 +214,12 @@ class TradingSession:
|
||||
class RealTimeScalpingDashboard:
|
||||
"""Real-time scalping dashboard with WebSocket streaming and ultra-low latency"""
|
||||
|
||||
def __init__(self, data_provider: DataProvider = None, orchestrator: EnhancedTradingOrchestrator = None):
|
||||
"""Initialize the real-time dashboard with WebSocket streaming"""
|
||||
def __init__(self, data_provider: DataProvider = None, orchestrator: EnhancedTradingOrchestrator = None, trading_executor: TradingExecutor = None):
|
||||
"""Initialize the real-time dashboard with WebSocket streaming and MEXC integration"""
|
||||
self.config = get_config()
|
||||
self.data_provider = data_provider or DataProvider()
|
||||
self.orchestrator = orchestrator or EnhancedTradingOrchestrator(self.data_provider)
|
||||
self.trading_executor = trading_executor or TradingExecutor()
|
||||
|
||||
# Verify universal data format compliance
|
||||
logger.info("UNIVERSAL DATA FORMAT VERIFICATION:")
|
||||
@ -213,8 +237,8 @@ class RealTimeScalpingDashboard:
|
||||
# Log preload results
|
||||
for symbol, timeframe_results in preload_results.items():
|
||||
for timeframe, success in timeframe_results.items():
|
||||
status = "✅" if success else "❌"
|
||||
logger.info(f" {status} {symbol} {timeframe}")
|
||||
status = "OK" if success else "FAIL"
|
||||
logger.info(f" {status} {symbol} {timeframe}")
|
||||
|
||||
# Test universal data adapter
|
||||
try:
|
||||
@ -230,14 +254,14 @@ class RealTimeScalpingDashboard:
|
||||
logger.info(f" BTC reference: {len(universal_stream.btc_ticks)} samples")
|
||||
logger.info(f" Data quality: {universal_stream.metadata['data_quality']['overall_score']:.2f}")
|
||||
else:
|
||||
logger.warning(f"✗ Universal data format validation FAILED: {issues}")
|
||||
logger.warning(f"FAIL: Universal data format validation FAILED: {issues}")
|
||||
else:
|
||||
logger.warning("✗ Failed to get universal data stream")
|
||||
logger.warning("FAIL: Failed to get universal data stream")
|
||||
except Exception as e:
|
||||
logger.error(f"✗ Universal data format test failed: {e}")
|
||||
logger.error(f"FAIL: Universal data format test failed: {e}")
|
||||
|
||||
# Initialize new trading session with $100 starting balance
|
||||
self.trading_session = TradingSession()
|
||||
# Initialize new trading session with MEXC integration
|
||||
self.trading_session = TradingSession(trading_executor=self.trading_executor)
|
||||
|
||||
# Timezone setup
|
||||
self.timezone = pytz.timezone('Europe/Sofia')
|
||||
@ -549,7 +573,8 @@ class RealTimeScalpingDashboard:
|
||||
|
||||
html.Div([
|
||||
html.H4(id="current-balance", className="text-success"),
|
||||
html.P("Current Balance", className="text-white")
|
||||
html.P("Current Balance", className="text-white"),
|
||||
html.Small(id="account-details", className="text-muted")
|
||||
], className="col-md-3 text-center"), # Increased from col-md-2
|
||||
|
||||
html.Div([
|
||||
@ -565,40 +590,57 @@ class RealTimeScalpingDashboard:
|
||||
html.Div([
|
||||
html.H4("500x", className="text-danger"),
|
||||
html.P("Leverage", className="text-white")
|
||||
], className="col-md-3 text-center") # Increased from col-md-2
|
||||
], className="col-md-2 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H4(id="mexc-status", className="text-info"),
|
||||
html.P("MEXC API", className="text-white")
|
||||
], className="col-md-2 text-center")
|
||||
], className="row mb-3"),
|
||||
|
||||
# Live metrics row
|
||||
# Live metrics row (split layout)
|
||||
html.Div([
|
||||
# Left side - Key metrics (4 columns, 8/12 width)
|
||||
html.Div([
|
||||
html.H3(id="live-pnl", className="text-success"),
|
||||
html.P("Session P&L", className="text-white")
|
||||
], className="col-md-2 text-center"),
|
||||
html.Div([
|
||||
html.H3(id="live-pnl", className="text-success"),
|
||||
html.P("Session P&L", className="text-white")
|
||||
], className="col-md-3 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="win-rate", className="text-info"),
|
||||
html.P("Win Rate", className="text-white")
|
||||
], className="col-md-3 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="total-trades", className="text-primary"),
|
||||
html.P("Total Trades", className="text-white")
|
||||
], className="col-md-3 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="last-action", className="text-warning"),
|
||||
html.P("Last Action", className="text-white")
|
||||
], className="col-md-3 text-center")
|
||||
], className="col-md-4"),
|
||||
|
||||
# Middle - Price displays (2 columns, 2/12 width)
|
||||
html.Div([
|
||||
html.H3(id="win-rate", className="text-info"),
|
||||
html.P("Win Rate", className="text-white")
|
||||
], className="col-md-2 text-center"),
|
||||
html.Div([
|
||||
html.H3(id="eth-price", className="text-success"),
|
||||
html.P("ETH/USDT LIVE", className="text-white")
|
||||
], className="col-md-6 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="btc-price", className="text-success"),
|
||||
html.P("BTC/USDT LIVE", className="text-white")
|
||||
], className="col-md-6 text-center")
|
||||
], className="col-md-2"),
|
||||
|
||||
# Right side - Recent Trading Actions (6/12 width)
|
||||
html.Div([
|
||||
html.H3(id="total-trades", className="text-primary"),
|
||||
html.P("Total Trades", className="text-white")
|
||||
], className="col-md-2 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="last-action", className="text-warning"),
|
||||
html.P("Last Action", className="text-white")
|
||||
], className="col-md-2 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="eth-price", className="text-success"),
|
||||
html.P("ETH/USDT LIVE", className="text-white")
|
||||
], className="col-md-2 text-center"),
|
||||
|
||||
html.Div([
|
||||
html.H3(id="btc-price", className="text-success"),
|
||||
html.P("BTC/USDT LIVE", className="text-white")
|
||||
], className="col-md-2 text-center")
|
||||
html.H5("Recent Trading Signals & Executions", className="text-center mb-2 text-warning"),
|
||||
html.Div(id="actions-log", style={"height": "120px", "overflowY": "auto", "backgroundColor": "rgba(0,0,0,0.3)", "padding": "10px", "borderRadius": "5px"})
|
||||
], className="col-md-6")
|
||||
], className="row mb-4")
|
||||
], className="bg-dark p-3 mb-3"),
|
||||
|
||||
@ -651,11 +693,7 @@ class RealTimeScalpingDashboard:
|
||||
html.Div(id="training-events-log")
|
||||
], className="mb-4"),
|
||||
|
||||
# Live actions log
|
||||
html.Div([
|
||||
html.H5("Live Session Trading Actions (Real-Time Stream)", className="text-center mb-3"),
|
||||
html.Div(id="actions-log")
|
||||
], className="mb-4"),
|
||||
|
||||
|
||||
# Dynamic interval - adjusts based on system performance
|
||||
dcc.Interval(
|
||||
@ -690,6 +728,7 @@ class RealTimeScalpingDashboard:
|
||||
@self.app.callback(
|
||||
[
|
||||
Output('current-balance', 'children'),
|
||||
Output('account-details', 'children'),
|
||||
Output('session-duration', 'children'),
|
||||
Output('open-positions', 'children'),
|
||||
Output('live-pnl', 'children'),
|
||||
@ -698,6 +737,7 @@ class RealTimeScalpingDashboard:
|
||||
Output('last-action', 'children'),
|
||||
Output('eth-price', 'children'),
|
||||
Output('btc-price', 'children'),
|
||||
Output('mexc-status', 'children'),
|
||||
Output('main-eth-1s-chart', 'figure'),
|
||||
Output('eth-1m-chart', 'figure'),
|
||||
Output('eth-1h-chart', 'figure'),
|
||||
@ -739,6 +779,11 @@ class RealTimeScalpingDashboard:
|
||||
# Update session metrics
|
||||
current_balance = f"${dashboard_instance.trading_session.current_balance:.2f}"
|
||||
|
||||
# Account details
|
||||
balance_change = dashboard_instance.trading_session.current_balance - dashboard_instance.trading_session.starting_balance
|
||||
balance_change_pct = (balance_change / dashboard_instance.trading_session.starting_balance) * 100
|
||||
account_details = f"Change: ${balance_change:+.2f} ({balance_change_pct:+.1f}%)"
|
||||
|
||||
# Create color-coded position display
|
||||
positions = dashboard_instance.trading_session.positions
|
||||
if positions:
|
||||
@ -775,6 +820,14 @@ class RealTimeScalpingDashboard:
|
||||
eth_price = f"${dashboard_instance.live_prices['ETH/USDT']:.2f}" if dashboard_instance.live_prices['ETH/USDT'] > 0 else "Loading..."
|
||||
btc_price = f"${dashboard_instance.live_prices['BTC/USDT']:.2f}" if dashboard_instance.live_prices['BTC/USDT'] > 0 else "Loading..."
|
||||
|
||||
# MEXC status
|
||||
if dashboard_instance.trading_executor and dashboard_instance.trading_executor.trading_enabled:
|
||||
mexc_status = "LIVE"
|
||||
elif dashboard_instance.trading_executor and dashboard_instance.trading_executor.dry_run:
|
||||
mexc_status = "DRY RUN"
|
||||
else:
|
||||
mexc_status = "OFFLINE"
|
||||
|
||||
# Create real-time charts - use WebSocket tick buffer for main chart and BTC
|
||||
try:
|
||||
main_eth_chart = dashboard_instance._create_main_tick_chart('ETH/USDT')
|
||||
@ -840,7 +893,7 @@ class RealTimeScalpingDashboard:
|
||||
|
||||
# Store last known state for throttling
|
||||
result = (
|
||||
current_balance, duration_str, open_positions, pnl, win_rate, total_trades, last_action, eth_price, btc_price,
|
||||
current_balance, account_details, duration_str, open_positions, pnl, win_rate, total_trades, last_action, eth_price, btc_price, mexc_status,
|
||||
main_eth_chart, eth_1m_chart, eth_1h_chart, eth_1d_chart, btc_1s_chart,
|
||||
model_training_status, orchestrator_status, training_events_log, actions_log, debug_status
|
||||
)
|
||||
@ -876,7 +929,7 @@ class RealTimeScalpingDashboard:
|
||||
])
|
||||
|
||||
error_result = (
|
||||
"$100.00", "00:00:00", "0", "$0.00", "0%", "0", "ERROR", "Loading...", "Loading...",
|
||||
"$100.00", "Change: $0.00 (0.0%)", "00:00:00", "0", "$0.00", "0%", "0", "ERROR", "Loading...", "Loading...", "OFFLINE",
|
||||
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
||||
"Loading model status...", "Loading orchestrator status...", "Loading training events...",
|
||||
"Loading real-time data...", error_debug
|
||||
@ -928,7 +981,7 @@ class RealTimeScalpingDashboard:
|
||||
}
|
||||
|
||||
return (
|
||||
"$100.00", "00:00:00", "0", "$0.00", "0%", "0", "INIT", "Loading...", "Loading...",
|
||||
"$100.00", "Change: $0.00 (0.0%)", "00:00:00", "0", "$0.00", "0%", "0", "INIT", "Loading...", "Loading...", "OFFLINE",
|
||||
empty_fig, empty_fig, empty_fig, empty_fig, empty_fig,
|
||||
"Initializing models...", "Starting orchestrator...", "Loading events...",
|
||||
"Waiting for data...", html.P("Initializing dashboard...", className="text-info")
|
||||
@ -1108,11 +1161,11 @@ class RealTimeScalpingDashboard:
|
||||
# Update live prices
|
||||
self.live_prices[symbol] = current_price
|
||||
|
||||
# Add to tick buffer for charts (simulate tick data from HTTP)
|
||||
# Add to tick buffer for charts (HTTP polling data)
|
||||
tick_entry = {
|
||||
'timestamp': timestamp,
|
||||
'price': current_price,
|
||||
'volume': 100.0, # Mock volume for HTTP data
|
||||
'volume': 0.0, # No volume data from HTTP polling
|
||||
'open': current_price,
|
||||
'high': current_price,
|
||||
'low': current_price,
|
||||
@ -1248,26 +1301,20 @@ class RealTimeScalpingDashboard:
|
||||
self.chart_data[symbol][timeframe] = cached_data
|
||||
logger.info(f"CACHE: Using cached data for {symbol} {timeframe} ({len(cached_data)} candles)")
|
||||
else:
|
||||
# Final fallback to mock data
|
||||
logger.warning(f"MOCK: Generating mock data for {symbol} {timeframe}")
|
||||
mock_data = self._generate_mock_data(symbol, timeframe, 50)
|
||||
# No data available - use empty DataFrame
|
||||
logger.warning(f"NO DATA: No data available for {symbol} {timeframe}")
|
||||
with self.data_lock:
|
||||
if symbol not in self.chart_data:
|
||||
self.chart_data[symbol] = {}
|
||||
self.chart_data[symbol][timeframe] = mock_data
|
||||
self.chart_data[symbol][timeframe] = pd.DataFrame()
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"ERROR: Failed to refresh {symbol} {timeframe}: {e}")
|
||||
# Generate mock data as final fallback
|
||||
try:
|
||||
mock_data = self._generate_mock_data(symbol, timeframe, 50)
|
||||
with self.data_lock:
|
||||
if symbol not in self.chart_data:
|
||||
self.chart_data[symbol] = {}
|
||||
self.chart_data[symbol][timeframe] = mock_data
|
||||
logger.warning(f"FALLBACK: Using mock data for {symbol} {timeframe}")
|
||||
except Exception as mock_error:
|
||||
logger.error(f"CRITICAL: Failed to generate mock data: {mock_error}")
|
||||
# Use empty DataFrame as fallback
|
||||
with self.data_lock:
|
||||
if symbol not in self.chart_data:
|
||||
self.chart_data[symbol] = {}
|
||||
self.chart_data[symbol][timeframe] = pd.DataFrame()
|
||||
|
||||
logger.info("REFRESH: LIVE data refresh complete")
|
||||
|
||||
@ -1291,83 +1338,7 @@ class RealTimeScalpingDashboard:
|
||||
logger.error(f"Error fetching fresh candles for {symbol} {timeframe}: {e}")
|
||||
return pd.DataFrame()
|
||||
|
||||
def _generate_mock_data(self, symbol: str, timeframe: str, num_candles: int = 100) -> pd.DataFrame:
|
||||
"""Generate realistic mock data as fallback when API fails"""
|
||||
try:
|
||||
import random
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
# Base prices for different symbols
|
||||
base_prices = {
|
||||
'ETH/USDT': 3500.0,
|
||||
'BTC/USDT': 65000.0
|
||||
}
|
||||
|
||||
base_price = base_prices.get(symbol, 3500.0)
|
||||
|
||||
# Timeframe intervals in seconds
|
||||
intervals = {
|
||||
'1s': 1,
|
||||
'1m': 60,
|
||||
'1h': 3600,
|
||||
'1d': 86400
|
||||
}
|
||||
|
||||
interval_seconds = intervals.get(timeframe, 60)
|
||||
|
||||
# Generate timestamps
|
||||
end_time = datetime.now()
|
||||
timestamps = []
|
||||
for i in range(num_candles):
|
||||
timestamp = end_time - timedelta(seconds=interval_seconds * (num_candles - i - 1))
|
||||
timestamps.append(timestamp)
|
||||
|
||||
# Generate realistic price data with trend and volatility
|
||||
data = []
|
||||
current_price = base_price
|
||||
|
||||
for i, timestamp in enumerate(timestamps):
|
||||
# Add some trend and random walk
|
||||
trend = 0.0001 * random.uniform(-1, 1) # Small trend
|
||||
volatility = 0.002 * random.uniform(0.5, 2.0) # Variable volatility
|
||||
|
||||
# Price movement
|
||||
price_change = current_price * (trend + volatility * random.uniform(-1, 1))
|
||||
current_price += price_change
|
||||
|
||||
# Ensure price doesn't go negative
|
||||
current_price = max(current_price, base_price * 0.5)
|
||||
|
||||
# Generate OHLC from current price
|
||||
high_offset = abs(random.uniform(0, 0.005)) * current_price
|
||||
low_offset = abs(random.uniform(0, 0.005)) * current_price
|
||||
|
||||
open_price = current_price + random.uniform(-0.002, 0.002) * current_price
|
||||
high_price = max(open_price, current_price) + high_offset
|
||||
low_price = min(open_price, current_price) - low_offset
|
||||
close_price = current_price
|
||||
|
||||
# Generate volume
|
||||
base_volume = 1000 if symbol == 'ETH/USDT' else 50
|
||||
volume = base_volume * random.uniform(0.5, 2.0)
|
||||
|
||||
data.append({
|
||||
'timestamp': timestamp,
|
||||
'open': round(open_price, 2),
|
||||
'high': round(high_price, 2),
|
||||
'low': round(low_price, 2),
|
||||
'close': round(close_price, 2),
|
||||
'volume': round(volume, 4)
|
||||
})
|
||||
|
||||
df = pd.DataFrame(data)
|
||||
logger.info(f"Generated {len(df)} mock candles for {symbol} {timeframe}")
|
||||
return df
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating mock data: {e}")
|
||||
# Return minimal empty dataframe
|
||||
return pd.DataFrame(columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
||||
|
||||
|
||||
def _create_live_chart(self, symbol: str, timeframe: str, main_chart: bool = False):
|
||||
"""Create charts with real-time streaming data using proven working method"""
|
||||
@ -1385,10 +1356,10 @@ class RealTimeScalpingDashboard:
|
||||
except Exception as e:
|
||||
logger.warning(f"[ERROR] Error getting cached data: {e}")
|
||||
|
||||
# If no cached data, generate mock data immediately
|
||||
# If no cached data, return empty chart
|
||||
if data is None or data.empty:
|
||||
logger.debug(f"[MOCK] Generating mock data for {symbol} {timeframe}")
|
||||
data = self._generate_mock_data(symbol, timeframe, 50)
|
||||
logger.debug(f"NO DATA: No data available for {symbol} {timeframe}")
|
||||
return self._create_empty_chart(f"{symbol} {timeframe} - No Data Available")
|
||||
|
||||
# Ensure we have valid data
|
||||
if data is None or data.empty:
|
||||
@ -1562,10 +1533,10 @@ class RealTimeScalpingDashboard:
|
||||
except Exception as e:
|
||||
logger.warning(f"Error getting cached data: {e}")
|
||||
|
||||
# If no cached data, generate mock data
|
||||
# If no cached data, return empty chart
|
||||
if data is None or data.empty:
|
||||
logger.debug(f"Generating mock data for {symbol} {timeframe}")
|
||||
data = self._generate_mock_data(symbol, timeframe, 50)
|
||||
logger.debug(f"NO DATA: No data available for {symbol} {timeframe}")
|
||||
return self._create_empty_chart(f"{symbol} {timeframe} - No Data Available")
|
||||
|
||||
# Ensure we have valid data
|
||||
if data is None or data.empty:
|
||||
@ -2175,17 +2146,17 @@ class RealTimeScalpingDashboard:
|
||||
'confidence': confidence_gap,
|
||||
'color': 'text-info',
|
||||
'priority': 2
|
||||
})
|
||||
})
|
||||
|
||||
# Add RL training events based on queue activity
|
||||
# Add RL training events based on queue activity
|
||||
if hasattr(self.orchestrator, 'rl_evaluation_queue') and self.orchestrator.rl_evaluation_queue:
|
||||
queue_size = len(self.orchestrator.rl_evaluation_queue)
|
||||
current_time = datetime.now()
|
||||
current_time = datetime.now()
|
||||
|
||||
if queue_size > 0:
|
||||
events.append({
|
||||
'time': current_time.strftime('%H:%M:%S'),
|
||||
'type': 'RL',
|
||||
'type': 'RL',
|
||||
'event': f'Experience replay active (queue: {queue_size} actions)',
|
||||
'confidence': min(1.0, queue_size / 10),
|
||||
'color': 'text-success',
|
||||
@ -2200,7 +2171,7 @@ class RealTimeScalpingDashboard:
|
||||
if patterns_detected > 0:
|
||||
events.append({
|
||||
'time': datetime.now().strftime('%H:%M:%S'),
|
||||
'type': 'TICK',
|
||||
'type': 'TICK',
|
||||
'event': f'Violent move patterns detected: {patterns_detected}',
|
||||
'confidence': min(1.0, patterns_detected / 5),
|
||||
'color': 'text-info',
|
||||
@ -2529,49 +2500,48 @@ class RealTimeScalpingDashboard:
|
||||
logger.info("Training data collection thread started")
|
||||
|
||||
def _collect_training_ticks(self):
|
||||
"""Collect tick data for training cache"""
|
||||
"""Collect real tick data for training cache from data provider"""
|
||||
try:
|
||||
# Get current prices and create mock ticks for training
|
||||
# Get real tick data from data provider subscribers
|
||||
for symbol in ['ETH/USDT', 'BTC/USDT']:
|
||||
try:
|
||||
# Get latest price data
|
||||
latest_data = self.data_provider.get_historical_data(symbol, '1m', limit=1)
|
||||
if latest_data is not None and len(latest_data) > 0:
|
||||
latest_price = latest_data['close'].iloc[-1]
|
||||
|
||||
# Create tick data
|
||||
# Get recent ticks from data provider
|
||||
recent_ticks = self.data_provider.get_recent_ticks(symbol, count=10)
|
||||
|
||||
for tick in recent_ticks:
|
||||
# Create tick data from real market data
|
||||
tick_data = {
|
||||
'symbol': symbol,
|
||||
'price': latest_price,
|
||||
'timestamp': datetime.now(),
|
||||
'volume': latest_data['volume'].iloc[-1] if 'volume' in latest_data.columns else 1000
|
||||
'symbol': tick.symbol,
|
||||
'price': tick.price,
|
||||
'timestamp': tick.timestamp,
|
||||
'volume': tick.volume
|
||||
}
|
||||
|
||||
# Add to tick cache
|
||||
self.tick_cache.append(tick_data)
|
||||
|
||||
# Create 1s bar data
|
||||
# Create 1s bar data from real tick
|
||||
bar_data = {
|
||||
'symbol': symbol,
|
||||
'open': latest_price,
|
||||
'high': latest_price * 1.001,
|
||||
'low': latest_price * 0.999,
|
||||
'close': latest_price,
|
||||
'volume': tick_data['volume'],
|
||||
'timestamp': datetime.now()
|
||||
'symbol': tick.symbol,
|
||||
'open': tick.price,
|
||||
'high': tick.price,
|
||||
'low': tick.price,
|
||||
'close': tick.price,
|
||||
'volume': tick.volume,
|
||||
'timestamp': tick.timestamp
|
||||
}
|
||||
|
||||
# Add to 1s bars cache
|
||||
self.one_second_bars.append(bar_data)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error collecting tick data for {symbol}: {e}")
|
||||
logger.error(f"Error collecting real tick data for {symbol}: {e}")
|
||||
|
||||
# Set streaming status
|
||||
# Set streaming status based on real data availability
|
||||
self.is_streaming = len(self.tick_cache) > 0
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error in tick data collection: {e}")
|
||||
logger.error(f"Error in real tick data collection: {e}")
|
||||
|
||||
def _send_training_data_to_models(self):
|
||||
"""Send training data to models for actual training"""
|
||||
@ -2604,9 +2574,9 @@ class RealTimeScalpingDashboard:
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending training data to models: {e}")
|
||||
|
||||
def create_scalping_dashboard(data_provider=None, orchestrator=None):
|
||||
"""Create real-time dashboard instance"""
|
||||
return RealTimeScalpingDashboard(data_provider, orchestrator)
|
||||
def create_scalping_dashboard(data_provider=None, orchestrator=None, trading_executor=None):
|
||||
"""Create real-time dashboard instance with MEXC integration"""
|
||||
return RealTimeScalpingDashboard(data_provider, orchestrator, trading_executor)
|
||||
|
||||
# For backward compatibility
|
||||
ScalpingDashboard = RealTimeScalpingDashboard
|
Reference in New Issue
Block a user