multicandle chart
This commit is contained in:
parent
7ea193d70f
commit
3347ecb494
81
realtime.py
81
realtime.py
@ -524,6 +524,68 @@ class ExchangeWebSocket:
|
|||||||
"""Check if the WebSocket is running"""
|
"""Check if the WebSocket is running"""
|
||||||
return self.ws.running if self.ws else False
|
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:
|
class RealTimeChart:
|
||||||
def __init__(self, symbol: str):
|
def __init__(self, symbol: str):
|
||||||
self.symbol = symbol
|
self.symbol = symbol
|
||||||
@ -536,8 +598,13 @@ class RealTimeChart:
|
|||||||
'1h': None,
|
'1h': None,
|
||||||
'1d': None
|
'1d': None
|
||||||
}
|
}
|
||||||
|
self.candle_cache = CandleCache() # Initialize local candle cache
|
||||||
logger.info(f"Initializing RealTimeChart for {symbol}")
|
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
|
||||||
button_style = {
|
button_style = {
|
||||||
'background-color': '#4CAF50',
|
'background-color': '#4CAF50',
|
||||||
@ -794,8 +861,16 @@ class RealTimeChart:
|
|||||||
|
|
||||||
# Fetch and cache OHLCV data for different intervals
|
# Fetch and cache OHLCV data for different intervals
|
||||||
for interval_key in self.ohlcv_cache.keys():
|
for interval_key in self.ohlcv_cache.keys():
|
||||||
if self.ohlcv_cache[interval_key] is None:
|
try:
|
||||||
self.ohlcv_cache[interval_key] = self.tick_storage.get_candles(interval_seconds=self._interval_to_seconds(interval_key))
|
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
|
# Add OHLCV subcharts
|
||||||
for i, (interval_key, ohlcv_df) in enumerate(self.ohlcv_cache.items(), start=3):
|
for i, (interval_key, ohlcv_df) in enumerate(self.ohlcv_cache.items(), start=3):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user