multicandle chart

This commit is contained in:
Dobromir Popov 2025-03-18 23:35:00 +02:00
parent 7ea193d70f
commit 3347ecb494

View File

@ -524,6 +524,68 @@ class ExchangeWebSocket:
"""Check if the WebSocket is running"""
return self.ws.running if self.ws else False
class CandleCache:
def __init__(self, max_candles: int = 2000):
self.candles = {
'1s': deque(maxlen=max_candles),
'1m': deque(maxlen=max_candles),
'1h': deque(maxlen=max_candles),
'1d': deque(maxlen=max_candles)
}
logger.info("Initialized CandleCache with max candles: {}".format(max_candles))
def add_candles(self, interval: str, new_candles: pd.DataFrame):
if interval in self.candles and not new_candles.empty:
for _, row in new_candles.iterrows():
self.candles[interval].append(row)
logger.debug(f"Added {len(new_candles)} candles to {interval} cache")
def get_recent_candles(self, interval: str, count: int = 500) -> pd.DataFrame:
if interval in self.candles and self.candles[interval]:
recent_candles = list(self.candles[interval])[-count:]
return pd.DataFrame(recent_candles)
return pd.DataFrame()
def update_cache(self, interval: str, new_candles: pd.DataFrame):
if interval not in self.candles:
logger.warning(f"Invalid interval {interval} for cache update")
return
if new_candles.empty:
logger.debug(f"No new candles to update {interval} cache")
return
# Check if timestamp column exists
if 'timestamp' not in new_candles.columns:
logger.warning(f"No timestamp column in new candles for {interval}")
return
last_cached_time = None
if self.candles[interval]:
try:
# Get the timestamp from the last cached candle
last_cached_candle = self.candles[interval][-1]
if isinstance(last_cached_candle, dict) and 'timestamp' in last_cached_candle:
last_cached_time = last_cached_candle['timestamp']
logger.debug(f"Last cached timestamp for {interval}: {last_cached_time}")
except (IndexError, KeyError) as e:
logger.error(f"Error accessing timestamp from last cached candle: {e}")
try:
# Only filter if we have a valid last_cached_time
if last_cached_time is not None:
filtered_candles = new_candles[new_candles['timestamp'] > last_cached_time]
logger.debug(f"Filtered {len(filtered_candles)} new candles for {interval}")
self.add_candles(interval, filtered_candles)
else:
# If no previous candles, add all
logger.debug(f"No previous candles, adding all {len(new_candles)} candles to {interval} cache")
self.add_candles(interval, new_candles)
except Exception as e:
logger.error(f"Error updating cache for {interval}: {str(e)}")
import traceback
logger.error(traceback.format_exc())
class RealTimeChart:
def __init__(self, symbol: str):
self.symbol = symbol
@ -536,8 +598,13 @@ class RealTimeChart:
'1h': None,
'1d': None
}
self.candle_cache = CandleCache() # Initialize local candle cache
logger.info(f"Initializing RealTimeChart for {symbol}")
# We'll populate the cache as data comes in rather than trying to load on startup
# when there might not be any ticks available yet
logger.info(f"Cache will be populated as data becomes available for {symbol}")
# Button style
button_style = {
'background-color': '#4CAF50',
@ -794,8 +861,16 @@ class RealTimeChart:
# Fetch and cache OHLCV data for different intervals
for interval_key in self.ohlcv_cache.keys():
if self.ohlcv_cache[interval_key] is None:
self.ohlcv_cache[interval_key] = self.tick_storage.get_candles(interval_seconds=self._interval_to_seconds(interval_key))
try:
new_candles = self.tick_storage.get_candles(interval_seconds=self._interval_to_seconds(interval_key))
if not new_candles.empty:
# Update the cache with new candles
self.candle_cache.update_cache(interval_key, new_candles)
# Get the updated candles from cache for display
self.ohlcv_cache[interval_key] = self.candle_cache.get_recent_candles(interval_key)
logger.debug(f"Updated cache for {interval_key}, now has {len(self.ohlcv_cache[interval_key])} candles")
except Exception as e:
logger.error(f"Error updating cache for {interval_key}: {str(e)}")
# Add OHLCV subcharts
for i, (interval_key, ohlcv_df) in enumerate(self.ohlcv_cache.items(), start=3):