import MetaTrader5 as mt5 import pytz import json import os import smtplib from datetime import datetime from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart import schedule import time import logging # ----------------------------------- # Logging Setup # ----------------------------------- logging.basicConfig( format="%(asctime)s | %(levelname)s | %(message)s", level=logging.INFO, datefmt="%Y-%m-%d %H:%M:%S" ) # ----------------------------------- # Load Configuration # ----------------------------------- def load_config(filepath="config.json"): if not os.path.exists(filepath): raise FileNotFoundError(f"Config file not found: {filepath}") with open(filepath, "r") as f: return json.load(f) config = load_config() EMAIL_CONFIG = config["email"] # ----------------------------------- # Initialize MT5 # ----------------------------------- def initialize_mt5(): logging.info("Initializing MT5 terminal...") if not mt5.initialize( path=config["mt5Pathway"], login=int(config["username"]), password=config["password"], server=config["server"] ): error = mt5.last_error() logging.error(f"MT5 initialize failed → Code {error[0]}: {error[1]}") raise RuntimeError(f"MT5 initialize failed: {error}") logging.info("MT5 successfully connected.") # ----------------------------------- # Send Email # ----------------------------------- def send_email(subject, body): msg = MIMEMultipart() msg['From'] = EMAIL_CONFIG["sender_email"] msg['To'] = EMAIL_CONFIG["recipient_email"] msg['Subject'] = subject msg.attach(MIMEText(body, "plain")) try: with smtplib.SMTP(EMAIL_CONFIG["smtp_server"], EMAIL_CONFIG["smtp_port"]) as server: server.starttls() server.login(EMAIL_CONFIG["sender_email"], EMAIL_CONFIG["sender_password"]) server.send_message(msg) logging.info(f"Email sent → {EMAIL_CONFIG['recipient_email']}") except Exception as e: logging.error(f"Email failed: {e}") # ----------------------------------- # Fetch Latest Candle # ----------------------------------- def get_latest_candle(symbol, timeframe=mt5.TIMEFRAME_M1): tz = pytz.timezone("America/New_York") utc_from = datetime.now(tz) rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, 1) if rates is None or len(rates) == 0: logging.warning(f"No data for {symbol}") return None return rates[0] # ----------------------------------- # Capture Data and Send # ----------------------------------- def capture_and_email(): logging.info("Capturing market data...") symbols = ["XAUUSD", "USTEC", "US30"] message_lines = [] for symbol in symbols: candle = get_latest_candle(symbol, mt5.TIMEFRAME_M1) if candle: time_str = datetime.fromtimestamp(candle['time']).strftime('%Y-%m-%d %H:%M:%S') message_lines.append( f"{symbol} @ {time_str}\nOpen: {candle['open']:.2f} | High: {candle['high']:.2f} | " f"Low: {candle['low']:.2f} | Close: {candle['close']:.2f}\n" ) else: message_lines.append(f"{symbol}: No data available\n") body = "\n".join(message_lines) send_email( subject="NY Session Market Levels Update", body=body ) # ----------------------------------- # NY Session Schedule # ----------------------------------- def schedule_tasks(): ny_tz = pytz.timezone("America/New_York") def is_ny_time(target_hour, target_minute): now = datetime.now(ny_tz) return now.hour == target_hour and now.minute == target_minute def task_runner(): if is_ny_time(0, 0): # 00:00 NY time logging.info("00:00 NY time → Daily Open") capture_and_email() if is_ny_time(8, 30): # 08:30 NY time logging.info("08:30 NY time → News Release") capture_and_email() if is_ny_time(9, 30): # 09:30 NY time logging.info("09:30 NY time → Market Open") capture_and_email() if is_ny_time(18, 0): # 18:00 NY time logging.info("18:00 NY time → Session Close") capture_and_email() schedule.every().minute.do(task_runner) # ----------------------------------- # Main # ----------------------------------- def main(): logging.info("===== Starting NY Session Levels Script =====") try: initialize_mt5() schedule_tasks() while True: schedule.run_pending() time.sleep(1) except Exception as e: logging.error(f"Fatal error in main(): {e}") finally: logging.info("Shutting down MetaTrader 5...") mt5.shutdown() logging.info("MT5 shutdown complete.") logging.info("===== Script Finished =====") if __name__ == "__main__": main()