Fix timezone handling and countdown messages

This commit is contained in:
justin committed 2026-01-29 17:56:44 -07:00
1 parent 9059843460
commit 45945da125
1 file changed
+34 -16
+34 -16
View File
@@ -12,6 +12,7 @@ import json
import pandas as pd import pandas as pd
import numpy as np import numpy as np
from datetime import datetime, timedelta from datetime import datetime, timedelta
import pytz
from pathlib import Path from pathlib import Path
from dotenv import load_dotenv from dotenv import load_dotenv
import alpaca_trade_api as tradeapi import alpaca_trade_api as tradeapi
@@ -128,6 +129,8 @@ REQUIRE_MACD_CONFIRMATION = bool(config["REQUIRE_MACD_CONFIRMATION"])
MIN_RISK_REWARD = float(config["MIN_RISK_REWARD"]) MIN_RISK_REWARD = float(config["MIN_RISK_REWARD"])
PULLBACK_PERCENTAGE = float(config["PULLBACK_PERCENTAGE"]) PULLBACK_PERCENTAGE = float(config["PULLBACK_PERCENTAGE"])
EASTERN = pytz.timezone('US/Eastern')
api = tradeapi.REST( api = tradeapi.REST(
os.getenv('APCA_API_KEY_ID'), os.getenv('APCA_API_KEY_ID'),
os.getenv('APCA_API_SECRET_KEY'), os.getenv('APCA_API_SECRET_KEY'),
@@ -493,7 +496,7 @@ def should_skip_trading_day():
return False return False
today = datetime.now().weekday() today = datetime.now().weekday()
day_name = datetime.now().strftime("%A") day_name = datetime.now(EASTERN).strftime("%A")
if today == 0 or today == 4: if today == 0 or today == 4:
debug_print(f"Skipping {day_name} (skip_mondays_fridays enabled)") debug_print(f"Skipping {day_name} (skip_mondays_fridays enabled)")
return True return True
@@ -520,9 +523,15 @@ def seconds_to_human_readable(seconds):
return " ".join(time_parts) if time_parts else "0 seconds" return " ".join(time_parts) if time_parts else "0 seconds"
def format_market_time(dt_obj): def format_market_time(dt_obj):
eastern_time = dt_obj.strftime("%Y-%m-%d %I:%M:%S %p %Z")
if hasattr(dt_obj, 'to_pydatetime'): if hasattr(dt_obj, 'to_pydatetime'):
dt_obj = dt_obj.to_pydatetime() dt_obj = dt_obj.to_pydatetime()
if dt_obj.tzinfo is None:
dt_obj = EASTERN.localize(dt_obj)
elif dt_obj.tzinfo != EASTERN:
dt_obj = dt_obj.astimezone(EASTERN)
eastern_time = dt_obj.strftime("%Y-%m-%d %I:%M:%S %p %Z")
local_time = dt_obj.astimezone().strftime("%I:%M%p").lstrip('0') local_time = dt_obj.astimezone().strftime("%I:%M%p").lstrip('0')
return f"{eastern_time} ({local_time} local)" return f"{eastern_time} ({local_time} local)"
@@ -1020,11 +1029,21 @@ def wait_until_market_open():
return return
now = clock.timestamp now = clock.timestamp
if now.tzinfo is None:
now = EASTERN.localize(now)
else:
now = now.astimezone(EASTERN)
next_open = clock.next_open next_open = clock.next_open
if next_open.tzinfo is None:
next_open = EASTERN.localize(next_open)
else:
next_open = next_open.astimezone(EASTERN)
if not clock.is_open: if not clock.is_open:
seconds_until_open = (next_open - now).total_seconds() seconds_until_open = (next_open - now).total_seconds()
debug_print(f"Market closed, {seconds_until_open:.0f} seconds until open") readable_time = seconds_to_human_readable(seconds_until_open)
debug_print(f"Market closed, {readable_time} until open")
if seconds_until_open > 0: if seconds_until_open > 0:
readable_time = seconds_to_human_readable(seconds_until_open) readable_time = seconds_to_human_readable(seconds_until_open)
logger.info(f"🕒 Market opens at {format_market_time(next_open)}") logger.info(f"🕒 Market opens at {format_market_time(next_open)}")
@@ -1035,7 +1054,7 @@ def wait_until_market_open():
time.sleep(sleep_time) time.sleep(sleep_time)
seconds_until_open -= sleep_time seconds_until_open -= sleep_time
if sleep_time >= 60: if sleep_time >= 60 and (seconds_until_open % 3600 < 60 or seconds_until_open < 3600):
remaining_readable = seconds_to_human_readable(seconds_until_open) remaining_readable = seconds_to_human_readable(seconds_until_open)
logger.info(f"⏱️ {remaining_readable} remaining...") logger.info(f"⏱️ {remaining_readable} remaining...")
debug_print(f"Waiting... {remaining_readable} remaining") debug_print(f"Waiting... {remaining_readable} remaining")
@@ -1368,19 +1387,19 @@ def should_trade_based_on_market_hours():
debug_print("Market hours filter disabled") debug_print("Market hours filter disabled")
return True return True
now = datetime.now().time() now_eastern = datetime.now(EASTERN).time()
open_buffer_end = datetime.strptime("10:00", "%H:%M").time() open_buffer_end = datetime.strptime("10:00", "%H:%M").time()
close_buffer_start = datetime.strptime("15:30", "%H:%M").time() close_buffer_start = datetime.strptime("15:30", "%H:%M").time()
debug_print(f"Current time: {now}") debug_print(f"Current time (ET): {now_eastern}")
if now < open_buffer_end: if now_eastern < open_buffer_end:
debug_print("Before 10:00 AM, outside trading hours") debug_print("Before 10:00 AM ET, outside trading hours")
return False return False
if now >= close_buffer_start: if now_eastern >= close_buffer_start:
debug_print("After 3:30 PM, outside trading hours") debug_print("After 3:30 PM ET, outside trading hours")
return False return False
debug_print("Within trading hours") debug_print("Within trading hours")
@@ -1593,7 +1612,7 @@ def main():
while True: while True:
debug_print("=== NEW MAIN LOOP ITERATION ===") debug_print("=== NEW MAIN LOOP ITERATION ===")
try: try:
current_date = datetime.now().date() current_date = datetime.now(EASTERN).date()
if last_reset_date != current_date: if last_reset_date != current_date:
trades_today = 0 trades_today = 0
last_reset_date = current_date last_reset_date = current_date
@@ -1608,7 +1627,7 @@ def main():
debug_print("Reset trailing_stop attribute") debug_print("Reset trailing_stop attribute")
if should_skip_trading_day(): if should_skip_trading_day():
day_name = datetime.now().strftime("%A") day_name = datetime.now(EASTERN).strftime("%A")
logger.info(f"📅 Skipping {day_name} - monitoring mode") logger.info(f"📅 Skipping {day_name} - monitoring mode")
debug_print(f"Skipping trading today ({day_name})") debug_print(f"Skipping trading today ({day_name})")
time.sleep(3600) time.sleep(3600)
@@ -1668,7 +1687,7 @@ def main():
time.sleep(60) time.sleep(60)
continue continue
if datetime.now().date() != current_date: if datetime.now(EASTERN).date() != current_date:
logger.info("📅 Day changed - resetting") logger.info("📅 Day changed - resetting")
debug_print("Day changed, exiting session loop") debug_print("Day changed, exiting session loop")
break break
@@ -1703,7 +1722,7 @@ def main():
debug_print(f"Managing active position: type={position_type}, entry=${entry_price:.2f}") debug_print(f"Managing active position: type={position_type}, entry=${entry_price:.2f}")
if entry_time: if entry_time:
time_in_trade = (datetime.now() - entry_time).total_seconds() time_in_trade = (datetime.now(EASTERN) - entry_time).total_seconds()
debug_print(f"Time in trade: {time_in_trade:.0f}s (max: {MAX_HOLD_TIME}s)") debug_print(f"Time in trade: {time_in_trade:.0f}s (max: {MAX_HOLD_TIME}s)")
if time_in_trade > MAX_HOLD_TIME: if time_in_trade > MAX_HOLD_TIME:
logger.info(f"⏰ Max hold time ({MAX_HOLD_TIME//60} min)") logger.info(f"⏰ Max hold time ({MAX_HOLD_TIME//60} min)")
@@ -1785,13 +1804,12 @@ def main():
trade_count += 1 trade_count += 1
trades_today += 1 trades_today += 1
entry_price = execution_price entry_price = execution_price
entry_time = datetime.now() entry_time = datetime.now(EASTERN)
stop_loss = signal_stop_loss stop_loss = signal_stop_loss
position_active = True position_active = True
position_type = 'long' if signal == 'buy' else 'short' position_type = 'long' if signal == 'buy' else 'short'
risk_amount = abs(entry_price - stop_loss) / entry_price risk_amount = abs(entry_price - stop_loss) / entry_price
logger.info(f"✅ {signal.upper()} executed")
logger.info(f" Entry=${entry_price:.2f}, Stop=${stop_loss:.2f}, Risk={risk_amount:.2%}") logger.info(f" Entry=${entry_price:.2f}, Stop=${stop_loss:.2f}, Risk={risk_amount:.2%}")
logger.info(f" Regime={regime}, Strength={strength:.2f}, Trade #{trade_count} ({trades_today}/{MAX_TRADES_PER_DAY})") logger.info(f" Regime={regime}, Strength={strength:.2f}, Trade #{trade_count} ({trades_today}/{MAX_TRADES_PER_DAY})")