LIVE CHART WORKS ON ANNOTATE APP
This commit is contained in:
@@ -7,7 +7,7 @@ data quality and structure used by training and inference systems.
|
||||
|
||||
import logging
|
||||
from typing import Dict, List, Optional, Tuple
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
import pandas as pd
|
||||
from pathlib import Path
|
||||
import pickle
|
||||
@@ -73,7 +73,11 @@ class HistoricalDataLoader:
|
||||
elif timeframe == '1m':
|
||||
current_ttl = timedelta(seconds=5)
|
||||
|
||||
if cache_key in self.memory_cache and direction == 'latest':
|
||||
# For 'after' direction (incremental updates), we should force a refresh if cache is stale
|
||||
# or simply bypass cache for 1s/1m to ensure we get the absolute latest
|
||||
bypass_cache = (direction == 'after' and timeframe in ['1s', '1m'])
|
||||
|
||||
if cache_key in self.memory_cache and direction == 'latest' and not bypass_cache:
|
||||
cached_data, cached_time = self.memory_cache[cache_key]
|
||||
if datetime.now() - cached_time < current_ttl:
|
||||
# For 1s/1m, we want to return immediately if valid
|
||||
@@ -83,8 +87,8 @@ class HistoricalDataLoader:
|
||||
return cached_data
|
||||
|
||||
try:
|
||||
# FORCE refresh for 1s/1m if requesting latest data
|
||||
force_refresh = (timeframe in ['1s', '1m'] and not start_time and not end_time)
|
||||
# FORCE refresh for 1s/1m if requesting latest data OR incremental update
|
||||
force_refresh = (timeframe in ['1s', '1m'] and (bypass_cache or (not start_time and not end_time)))
|
||||
# Try to get data from DataProvider's cached data first (most efficient)
|
||||
if hasattr(self.data_provider, 'cached_data'):
|
||||
with self.data_provider.data_lock:
|
||||
@@ -403,27 +407,53 @@ class HistoricalDataLoader:
|
||||
Returns:
|
||||
Filtered DataFrame
|
||||
"""
|
||||
if direction == 'before' and end_time:
|
||||
# Get candles BEFORE end_time
|
||||
df = df[df.index < end_time]
|
||||
# Return the most recent N candles before end_time
|
||||
df = df.tail(limit)
|
||||
elif direction == 'after' and start_time:
|
||||
# Get candles AFTER start_time
|
||||
df = df[df.index > start_time]
|
||||
# Return the oldest N candles after start_time
|
||||
df = df.head(limit)
|
||||
else:
|
||||
# Default: filter by range
|
||||
if start_time:
|
||||
df = df[df.index >= start_time]
|
||||
if end_time:
|
||||
df = df[df.index <= end_time]
|
||||
# Return most recent candles
|
||||
if len(df) > limit:
|
||||
try:
|
||||
# Ensure df index is datetime and timezone-aware (UTC)
|
||||
if not isinstance(df.index, pd.DatetimeIndex):
|
||||
df.index = pd.to_datetime(df.index, utc=True)
|
||||
elif df.index.tz is None:
|
||||
df.index = df.index.tz_localize('UTC')
|
||||
else:
|
||||
# If already aware but not UTC, convert
|
||||
if str(df.index.tz) != 'UTC' and str(df.index.tz) != 'datetime.timezone.utc':
|
||||
df.index = df.index.tz_convert('UTC')
|
||||
|
||||
# Ensure start_time/end_time are UTC
|
||||
if start_time and start_time.tzinfo is None:
|
||||
start_time = start_time.replace(tzinfo=timezone.utc)
|
||||
elif start_time:
|
||||
start_time = start_time.astimezone(timezone.utc)
|
||||
|
||||
if end_time and end_time.tzinfo is None:
|
||||
end_time = end_time.replace(tzinfo=timezone.utc)
|
||||
elif end_time:
|
||||
end_time = end_time.astimezone(timezone.utc)
|
||||
|
||||
if direction == 'before' and end_time:
|
||||
# Get candles BEFORE end_time
|
||||
df = df[df.index < end_time]
|
||||
# Return the most recent N candles before end_time
|
||||
df = df.tail(limit)
|
||||
|
||||
return df
|
||||
elif direction == 'after' and start_time:
|
||||
# Get candles AFTER start_time
|
||||
df = df[df.index > start_time]
|
||||
# Return the oldest N candles after start_time
|
||||
df = df.head(limit)
|
||||
else:
|
||||
# Default: filter by range
|
||||
if start_time:
|
||||
df = df[df.index >= start_time]
|
||||
if end_time:
|
||||
df = df[df.index <= end_time]
|
||||
# Return most recent candles
|
||||
if len(df) > limit:
|
||||
df = df.tail(limit)
|
||||
|
||||
return df
|
||||
except Exception as e:
|
||||
logger.error(f"Error filtering data: {e}")
|
||||
# Fallback: return original or empty
|
||||
return df if not df.empty else pd.DataFrame()
|
||||
|
||||
def get_multi_timeframe_data(self, symbol: str,
|
||||
timeframes: List[str],
|
||||
|
||||
Reference in New Issue
Block a user