wip misc; cleaup launch
This commit is contained in:
@@ -1183,16 +1183,21 @@ class DataProvider:
|
||||
price = tick.get('price')
|
||||
if not price:
|
||||
price = tick.get('mid_price') or stats.get('mid_price', 0)
|
||||
# Derive a volume proxy if not provided (use bid+ask volume from stats)
|
||||
# Strict: if still falsy or non-finite, skip
|
||||
try:
|
||||
price = float(price)
|
||||
except Exception:
|
||||
price = 0.0
|
||||
# Volume: do not synthesize from other stats; use provided value or 0.0
|
||||
volume = tick.get('volume')
|
||||
if volume is None:
|
||||
bid_vol = stats.get('bid_volume', 0) or 0
|
||||
ask_vol = stats.get('ask_volume', 0) or 0
|
||||
volume = float(bid_vol) + float(ask_vol)
|
||||
# Do not create synthetic volume; keep zero if not available
|
||||
try:
|
||||
volume = float(volume) if volume is not None else 0.0
|
||||
except Exception:
|
||||
volume = 0.0
|
||||
else:
|
||||
continue
|
||||
|
||||
# Normalize timestamp; support seconds or milliseconds since epoch and tz-aware datetimes
|
||||
if not timestamp or not price or price <= 0:
|
||||
continue
|
||||
|
||||
@@ -1200,7 +1205,16 @@ class DataProvider:
|
||||
if isinstance(timestamp, (int, float)):
|
||||
import pytz
|
||||
utc = pytz.UTC
|
||||
tick_time = datetime.fromtimestamp(timestamp, tz=utc)
|
||||
# Handle ms epoch inputs by thresholding reasonable ranges
|
||||
try:
|
||||
# If timestamp looks like milliseconds (e.g., > 10^12), convert to seconds
|
||||
if timestamp > 1e12:
|
||||
tick_time = datetime.fromtimestamp(timestamp / 1000.0, tz=utc)
|
||||
else:
|
||||
tick_time = datetime.fromtimestamp(timestamp, tz=utc)
|
||||
except Exception:
|
||||
# Skip bad timestamps cleanly on Windows
|
||||
continue
|
||||
# Keep in UTC to match COB WebSocket data
|
||||
elif isinstance(timestamp, datetime):
|
||||
import pytz
|
||||
@@ -1208,7 +1222,14 @@ class DataProvider:
|
||||
tick_time = timestamp
|
||||
# If no timezone info, assume UTC and keep in UTC
|
||||
if tick_time.tzinfo is None:
|
||||
tick_time = utc.localize(tick_time)
|
||||
try:
|
||||
tick_time = utc.localize(tick_time)
|
||||
except Exception:
|
||||
# Fallback: coerce via fromtimestamp using naive seconds
|
||||
try:
|
||||
tick_time = datetime.fromtimestamp(tick_time.timestamp(), tz=utc)
|
||||
except Exception:
|
||||
continue
|
||||
# Keep in UTC (no timezone conversion)
|
||||
else:
|
||||
continue
|
||||
@@ -1265,25 +1286,26 @@ class DataProvider:
|
||||
|
||||
# logger.info(f"Generated {len(df)} 1s candles from {len(recent_ticks)} ticks for {symbol}")
|
||||
return df
|
||||
|
||||
|
||||
except Exception as e:
|
||||
# Handle Windows-specific invalid argument (e.g., bad timestamps) gracefully
|
||||
# Handle invalid argument or bad timestamps gracefully (Windows-safe)
|
||||
try:
|
||||
import errno
|
||||
if hasattr(e, 'errno') and e.errno == errno.EINVAL:
|
||||
logger.warning(f"Invalid argument while generating 1s candles for {symbol}; trimming tick buffer and falling back")
|
||||
try:
|
||||
if hasattr(self, 'cob_raw_ticks') and symbol in getattr(self, 'cob_raw_ticks', {}):
|
||||
buf = self.cob_raw_ticks[symbol]
|
||||
drop = max(1, len(buf)//2)
|
||||
for _ in range(drop):
|
||||
buf.popleft()
|
||||
except Exception:
|
||||
pass
|
||||
else:
|
||||
logger.error(f"Error generating 1s candles from ticks for {symbol}: {e}")
|
||||
except Exception:
|
||||
logger.error(f"Error generating 1s candles from ticks for {symbol}: {e}")
|
||||
# Always trim a small portion of tick buffer to recover from corrupt front entries
|
||||
try:
|
||||
if hasattr(self, 'cob_raw_ticks') and symbol in getattr(self, 'cob_raw_ticks', {}):
|
||||
buf = self.cob_raw_ticks[symbol]
|
||||
drop = max(1, min(50, len(buf)//10)) # drop up to 10% or 50 entries
|
||||
for _ in range(drop):
|
||||
buf.popleft()
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def _fetch_from_binance(self, symbol: str, timeframe: str, limit: int) -> Optional[pd.DataFrame]:
|
||||
|
||||
Reference in New Issue
Block a user