display time in current TZ
This commit is contained in:
parent
058816ddcd
commit
05f61b5663
181
realtime.py
181
realtime.py
@ -17,6 +17,8 @@ from threading import Thread
|
|||||||
import requests
|
import requests
|
||||||
import os
|
import os
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
import pytz
|
||||||
|
import tzlocal
|
||||||
|
|
||||||
# Configure logging with more detailed format
|
# Configure logging with more detailed format
|
||||||
logging.basicConfig(
|
logging.basicConfig(
|
||||||
@ -29,6 +31,50 @@ logging.basicConfig(
|
|||||||
)
|
)
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Try to get local timezone, default to Sofia/EET if not available
|
||||||
|
try:
|
||||||
|
local_timezone = tzlocal.get_localzone()
|
||||||
|
# Get timezone name safely
|
||||||
|
try:
|
||||||
|
tz_name = str(local_timezone)
|
||||||
|
# Handle case where it might be zoneinfo.ZoneInfo object instead of pytz timezone
|
||||||
|
if hasattr(local_timezone, 'zone'):
|
||||||
|
tz_name = local_timezone.zone
|
||||||
|
elif hasattr(local_timezone, 'key'):
|
||||||
|
tz_name = local_timezone.key
|
||||||
|
else:
|
||||||
|
tz_name = str(local_timezone)
|
||||||
|
except:
|
||||||
|
tz_name = "Local"
|
||||||
|
logger.info(f"Detected local timezone: {local_timezone} ({tz_name})")
|
||||||
|
except Exception as e:
|
||||||
|
logger.warning(f"Could not detect local timezone: {str(e)}. Defaulting to Sofia/EET")
|
||||||
|
local_timezone = pytz.timezone('Europe/Sofia')
|
||||||
|
tz_name = "Europe/Sofia"
|
||||||
|
|
||||||
|
def convert_to_local_time(timestamp):
|
||||||
|
"""Convert timestamp to local timezone"""
|
||||||
|
try:
|
||||||
|
if isinstance(timestamp, pd.Timestamp):
|
||||||
|
dt = timestamp.to_pydatetime()
|
||||||
|
elif isinstance(timestamp, np.datetime64):
|
||||||
|
dt = pd.Timestamp(timestamp).to_pydatetime()
|
||||||
|
elif isinstance(timestamp, str):
|
||||||
|
dt = pd.to_datetime(timestamp).to_pydatetime()
|
||||||
|
else:
|
||||||
|
dt = timestamp
|
||||||
|
|
||||||
|
# If datetime is naive (no timezone), assume it's UTC
|
||||||
|
if dt.tzinfo is None:
|
||||||
|
dt = dt.replace(tzinfo=pytz.UTC)
|
||||||
|
|
||||||
|
# Convert to local timezone
|
||||||
|
local_dt = dt.astimezone(local_timezone)
|
||||||
|
return local_dt
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error converting timestamp to local time: {str(e)}")
|
||||||
|
return timestamp
|
||||||
|
|
||||||
class TradeTickStorage:
|
class TradeTickStorage:
|
||||||
"""Store and manage raw trade ticks for display and candle formation"""
|
"""Store and manage raw trade ticks for display and candle formation"""
|
||||||
def __init__(self, max_age_seconds: int = 1800): # 30 minutes by default
|
def __init__(self, max_age_seconds: int = 1800): # 30 minutes by default
|
||||||
@ -1110,10 +1156,19 @@ class RealTimeChart:
|
|||||||
|
|
||||||
logger.debug(f"Displaying {len(display_df)} candles in main chart")
|
logger.debug(f"Displaying {len(display_df)} candles in main chart")
|
||||||
|
|
||||||
|
# Convert timestamps to local time for display
|
||||||
|
display_df = display_df.copy()
|
||||||
|
try:
|
||||||
|
display_df['local_time'] = display_df['timestamp'].apply(convert_to_local_time)
|
||||||
|
logger.debug(f"Converted timestamps to local time ({local_timezone})")
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error converting timestamps to local time: {str(e)}")
|
||||||
|
display_df['local_time'] = display_df['timestamp']
|
||||||
|
|
||||||
# Add candlestick chart
|
# Add candlestick chart
|
||||||
fig.add_trace(
|
fig.add_trace(
|
||||||
go.Candlestick(
|
go.Candlestick(
|
||||||
x=display_df['timestamp'],
|
x=display_df['local_time'], # Use local time for display
|
||||||
open=display_df['open'],
|
open=display_df['open'],
|
||||||
high=display_df['high'],
|
high=display_df['high'],
|
||||||
low=display_df['low'],
|
low=display_df['low'],
|
||||||
@ -1131,7 +1186,7 @@ class RealTimeChart:
|
|||||||
|
|
||||||
fig.add_trace(
|
fig.add_trace(
|
||||||
go.Bar(
|
go.Bar(
|
||||||
x=display_df['timestamp'],
|
x=display_df['local_time'], # Use local time for display
|
||||||
y=display_df['volume'],
|
y=display_df['volume'],
|
||||||
name='Volume',
|
name='Volume',
|
||||||
marker_color=colors
|
marker_color=colors
|
||||||
@ -1141,21 +1196,30 @@ class RealTimeChart:
|
|||||||
|
|
||||||
# Add latest price line from the candlestick data
|
# Add latest price line from the candlestick data
|
||||||
latest_price = display_df['close'].iloc[-1]
|
latest_price = display_df['close'].iloc[-1]
|
||||||
|
latest_time = display_df['local_time'].iloc[-1]
|
||||||
|
earliest_time = display_df['local_time'].iloc[0]
|
||||||
|
|
||||||
fig.add_shape(
|
fig.add_shape(
|
||||||
type="line",
|
type="line",
|
||||||
x0=display_df['timestamp'].min(),
|
x0=earliest_time,
|
||||||
y0=latest_price,
|
y0=latest_price,
|
||||||
x1=display_df['timestamp'].max(),
|
x1=latest_time,
|
||||||
y1=latest_price,
|
y1=latest_price,
|
||||||
line=dict(color="yellow", width=1, dash="dash"),
|
line=dict(color="yellow", width=1, dash="dash"),
|
||||||
row=1, col=1
|
row=1, col=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Format the last update time in local timezone
|
||||||
|
try:
|
||||||
|
last_update_time = latest_time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
except:
|
||||||
|
last_update_time = datetime.now().astimezone(local_timezone).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
# Annotation for last candle close price
|
# Annotation for last candle close price
|
||||||
fig.add_annotation(
|
fig.add_annotation(
|
||||||
x=display_df['timestamp'].max(),
|
x=latest_time,
|
||||||
y=latest_price,
|
y=latest_price,
|
||||||
text=f"{latest_price:.2f}",
|
text=f"{latest_price:.2f} ({last_update_time})",
|
||||||
showarrow=False,
|
showarrow=False,
|
||||||
font=dict(size=14, color="yellow"),
|
font=dict(size=14, color="yellow"),
|
||||||
xshift=50,
|
xshift=50,
|
||||||
@ -1167,19 +1231,22 @@ class RealTimeChart:
|
|||||||
# Add current price line
|
# Add current price line
|
||||||
fig.add_shape(
|
fig.add_shape(
|
||||||
type="line",
|
type="line",
|
||||||
x0=display_df['timestamp'].min(),
|
x0=earliest_time,
|
||||||
y0=current_price,
|
y0=current_price,
|
||||||
x1=display_df['timestamp'].max(),
|
x1=latest_time,
|
||||||
y1=current_price,
|
y1=current_price,
|
||||||
line=dict(color="cyan", width=1, dash="dot"),
|
line=dict(color="cyan", width=1, dash="dot"),
|
||||||
row=1, col=1
|
row=1, col=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Format current time in local timezone
|
||||||
|
current_time_str = datetime.now().astimezone(local_timezone).strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
# Add current price annotation
|
# Add current price annotation
|
||||||
fig.add_annotation(
|
fig.add_annotation(
|
||||||
x=display_df['timestamp'].max(),
|
x=latest_time,
|
||||||
y=current_price,
|
y=current_price,
|
||||||
text=f"Current: {current_price:.2f}",
|
text=f"Current: {current_price:.2f} ({current_time_str})",
|
||||||
showarrow=False,
|
showarrow=False,
|
||||||
font=dict(size=14, color="cyan"),
|
font=dict(size=14, color="cyan"),
|
||||||
xshift=50,
|
xshift=50,
|
||||||
@ -1221,13 +1288,21 @@ class RealTimeChart:
|
|||||||
if len(ohlcv_df) > 100:
|
if len(ohlcv_df) > 100:
|
||||||
ohlcv_df = ohlcv_df.tail(100)
|
ohlcv_df = ohlcv_df.tail(100)
|
||||||
|
|
||||||
|
# Convert to local time
|
||||||
|
ohlcv_display_df = ohlcv_df.copy()
|
||||||
|
try:
|
||||||
|
ohlcv_display_df['local_time'] = ohlcv_df['timestamp'].apply(convert_to_local_time)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error converting {interval_key} timestamps to local time: {str(e)}")
|
||||||
|
ohlcv_display_df['local_time'] = ohlcv_df['timestamp']
|
||||||
|
|
||||||
fig.add_trace(
|
fig.add_trace(
|
||||||
go.Candlestick(
|
go.Candlestick(
|
||||||
x=ohlcv_df['timestamp'],
|
x=ohlcv_display_df['local_time'],
|
||||||
open=ohlcv_df['open'],
|
open=ohlcv_display_df['open'],
|
||||||
high=ohlcv_df['high'],
|
high=ohlcv_display_df['high'],
|
||||||
low=ohlcv_df['low'],
|
low=ohlcv_display_df['low'],
|
||||||
close=ohlcv_df['close'],
|
close=ohlcv_display_df['close'],
|
||||||
name=f'{label}',
|
name=f'{label}',
|
||||||
increasing_line_color='#33CC33',
|
increasing_line_color='#33CC33',
|
||||||
decreasing_line_color='#FF4136',
|
decreasing_line_color='#FF4136',
|
||||||
@ -1237,23 +1312,33 @@ class RealTimeChart:
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Add latest price line
|
# Add latest price line
|
||||||
latest_timeframe_price = ohlcv_df['close'].iloc[-1] if len(ohlcv_df) > 0 else None
|
latest_timeframe_price = ohlcv_display_df['close'].iloc[-1] if len(ohlcv_display_df) > 0 else None
|
||||||
if latest_timeframe_price:
|
if latest_timeframe_price:
|
||||||
|
# Get first and last timestamps
|
||||||
|
earliest_tf_time = ohlcv_display_df['local_time'].iloc[0]
|
||||||
|
latest_tf_time = ohlcv_display_df['local_time'].iloc[-1]
|
||||||
|
|
||||||
fig.add_shape(
|
fig.add_shape(
|
||||||
type="line",
|
type="line",
|
||||||
x0=ohlcv_df['timestamp'].min(),
|
x0=earliest_tf_time,
|
||||||
y0=latest_timeframe_price,
|
y0=latest_timeframe_price,
|
||||||
x1=ohlcv_df['timestamp'].max(),
|
x1=latest_tf_time,
|
||||||
y1=latest_timeframe_price,
|
y1=latest_timeframe_price,
|
||||||
line=dict(color="yellow", width=1, dash="dash"),
|
line=dict(color="yellow", width=1, dash="dash"),
|
||||||
row=row_idx, col=1
|
row=row_idx, col=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Get formatted time
|
||||||
|
try:
|
||||||
|
update_time = latest_tf_time.strftime('%Y-%m-%d %H:%M')
|
||||||
|
except:
|
||||||
|
update_time = ""
|
||||||
|
|
||||||
# Add price annotation
|
# Add price annotation
|
||||||
fig.add_annotation(
|
fig.add_annotation(
|
||||||
x=ohlcv_df['timestamp'].max(),
|
x=latest_tf_time,
|
||||||
y=latest_timeframe_price,
|
y=latest_timeframe_price,
|
||||||
text=f"{latest_timeframe_price:.2f}",
|
text=f"{latest_timeframe_price:.2f} ({update_time})",
|
||||||
showarrow=False,
|
showarrow=False,
|
||||||
font=dict(size=12, color="yellow"),
|
font=dict(size=12, color="yellow"),
|
||||||
xshift=50,
|
xshift=50,
|
||||||
@ -1279,13 +1364,21 @@ class RealTimeChart:
|
|||||||
if len(ohlcv_df) > 100:
|
if len(ohlcv_df) > 100:
|
||||||
ohlcv_df = ohlcv_df.tail(100)
|
ohlcv_df = ohlcv_df.tail(100)
|
||||||
|
|
||||||
|
# Convert to local time
|
||||||
|
ohlcv_display_df = ohlcv_df.copy()
|
||||||
|
try:
|
||||||
|
ohlcv_display_df['local_time'] = ohlcv_df['timestamp'].apply(convert_to_local_time)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error converting {interval_key} timestamps to local time: {str(e)}")
|
||||||
|
ohlcv_display_df['local_time'] = ohlcv_df['timestamp']
|
||||||
|
|
||||||
fig.add_trace(
|
fig.add_trace(
|
||||||
go.Candlestick(
|
go.Candlestick(
|
||||||
x=ohlcv_df['timestamp'],
|
x=ohlcv_display_df['local_time'],
|
||||||
open=ohlcv_df['open'],
|
open=ohlcv_display_df['open'],
|
||||||
high=ohlcv_df['high'],
|
high=ohlcv_display_df['high'],
|
||||||
low=ohlcv_df['low'],
|
low=ohlcv_display_df['low'],
|
||||||
close=ohlcv_df['close'],
|
close=ohlcv_display_df['close'],
|
||||||
name=f'{label}',
|
name=f'{label}',
|
||||||
increasing_line_color='#33CC33',
|
increasing_line_color='#33CC33',
|
||||||
decreasing_line_color='#FF4136',
|
decreasing_line_color='#FF4136',
|
||||||
@ -1293,6 +1386,40 @@ class RealTimeChart:
|
|||||||
),
|
),
|
||||||
row=row_idx, col=1
|
row=row_idx, col=1
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Add latest price line
|
||||||
|
latest_timeframe_price = ohlcv_display_df['close'].iloc[-1] if len(ohlcv_display_df) > 0 else None
|
||||||
|
if latest_timeframe_price:
|
||||||
|
# Get first and last timestamps
|
||||||
|
earliest_tf_time = ohlcv_display_df['local_time'].iloc[0]
|
||||||
|
latest_tf_time = ohlcv_display_df['local_time'].iloc[-1]
|
||||||
|
|
||||||
|
fig.add_shape(
|
||||||
|
type="line",
|
||||||
|
x0=earliest_tf_time,
|
||||||
|
y0=latest_timeframe_price,
|
||||||
|
x1=latest_tf_time,
|
||||||
|
y1=latest_timeframe_price,
|
||||||
|
line=dict(color="yellow", width=1, dash="dash"),
|
||||||
|
row=row_idx, col=1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get formatted time
|
||||||
|
try:
|
||||||
|
update_time = latest_tf_time.strftime('%Y-%m-%d %H:%M')
|
||||||
|
except:
|
||||||
|
update_time = ""
|
||||||
|
|
||||||
|
# Add price annotation
|
||||||
|
fig.add_annotation(
|
||||||
|
x=latest_tf_time,
|
||||||
|
y=latest_timeframe_price,
|
||||||
|
text=f"{latest_timeframe_price:.2f} ({update_time})",
|
||||||
|
showarrow=False,
|
||||||
|
font=dict(size=12, color="yellow"),
|
||||||
|
xshift=50,
|
||||||
|
row=row_idx, col=1
|
||||||
|
)
|
||||||
|
|
||||||
# Add a message to the empty main chart
|
# Add a message to the empty main chart
|
||||||
fig.add_annotation(
|
fig.add_annotation(
|
||||||
@ -1317,6 +1444,10 @@ class RealTimeChart:
|
|||||||
# Build info box text with all the statistics
|
# Build info box text with all the statistics
|
||||||
info_lines = [f"<b>{self.symbol}</b>"]
|
info_lines = [f"<b>{self.symbol}</b>"]
|
||||||
|
|
||||||
|
# Add current time in local timezone
|
||||||
|
current_local_time = datetime.now().astimezone(local_timezone)
|
||||||
|
info_lines.append(f"Time: {current_local_time.strftime('%Y-%m-%d %H:%M:%S')} ({tz_name})")
|
||||||
|
|
||||||
# Add current price if available
|
# Add current price if available
|
||||||
if current_price:
|
if current_price:
|
||||||
info_lines.append(f"Current: <b>{current_price:.2f}</b> USDT")
|
info_lines.append(f"Current: <b>{current_price:.2f}</b> USDT")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user