import MetaTrader5 as mt5 import json import os import requests import logging from datetime import datetime, timedelta, timezone import smtplib from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart # =========================== # Logging Configuration # =========================== logging.basicConfig( level=logging.INFO, format="%(asctime)s | %(levelname)s | %(message)s", datefmt="%Y-%m-%d %H:%M:%S" ) log = logging.getLogger(__name__) # =========================== # Load Config # =========================== def load_config(config_path="config.json"): if not os.path.exists(config_path): raise FileNotFoundError(f"Config file not found at {config_path}") with open(config_path, "r") as f: config = json.load(f) log.info( f"Config loaded: Username={config['username']} | " f"Server={config['server']} | Path={config['mt5Pathway']}" ) return config # =========================== # Initialize MT5 # =========================== def initialize_mt5(config): log.info("Starting MetaTrader 5 initialization...") if mt5.initialize( path=config["mt5Pathway"], login=int(config["username"]), password=config["password"], server=config["server"] ): log.info("MT5 initialized successfully!") else: error_code, error_msg = mt5.last_error() log.error(f"MT5 initialization failed → Code {error_code}: {error_msg}") raise RuntimeError(f"MT5 initialize failed: {mt5.last_error()}") # =========================== # Fetch TradingView USD High Impact News # =========================== def fetch_tradingview_news(start_date, end_date, label="Events"): """ Pull ONLY high-impact USD economic news using TradingView's public API. """ try: url = "https://economic-calendar.tradingview.com/events" # Strict filter: USD + High Impact only params = { "from": start_date.strftime("%Y-%m-%d"), "to": end_date.strftime("%Y-%m-%d"), "currencies": "USD", # USD only "importance": 3 # 3 = High impact only } log.info(f"Fetching {label} for USD High Impact from {params['from']} to {params['to']}") response = requests.get(url, params=params, timeout=10) if response.status_code != 200: log.error(f"{label} API HTTP error: {response.status_code}") return [] try: data = response.json() except Exception as e: log.error(f"{label} JSON decode failed: {e}") log.error(f"Raw Response: {response.text}") return [] # Filter and format events events = [] for e in data.get("result", []): # Extra safety check to ensure it's USD and high impact if e.get("currency") != "USD" or e.get("importance") != 3: continue event_time = datetime.fromtimestamp(e["timestamp"], tz=timezone.utc) events.append( f"{event_time.strftime('%Y-%m-%d %H:%M UTC')} | {e['title']} | " f"Actual: {e.get('actual', 'N/A')} | Forecast: {e.get('forecast', 'N/A')}" ) return events except Exception as e: log.error(f"Error fetching {label}: {e}") return [] # =========================== # Get Past and Forward News # =========================== def get_past_month_news(): now = datetime.now(timezone.utc) last_month = now - timedelta(days=30) return fetch_tradingview_news(last_month, now, label="Past Month USD High Impact News") def get_forward_news(): now = datetime.now(timezone.utc) next_month = now + timedelta(days=30) return fetch_tradingview_news(now, next_month, label="Upcoming USD High Impact News") # =========================== # Email Sending # =========================== def send_email(subject, body, smtp_config): try: msg = MIMEMultipart() msg['From'] = smtp_config["sender_email"] msg['To'] = smtp_config["recipient_email"] msg['Subject'] = subject msg.attach(MIMEText(body, "plain")) with smtplib.SMTP(smtp_config["smtp_server"], smtp_config["smtp_port"]) as server: server.starttls() server.login(smtp_config["sender_email"], smtp_config["sender_password"]) server.send_message(msg) log.info(f"Email sent to {smtp_config['recipient_email']}") except Exception as e: log.error(f"Error sending email: {e}") # =========================== # Build Report # =========================== def build_report(past_news, forward_news): now_ny = datetime.now(timezone.utc) - timedelta(hours=4) # Convert to NY time (UTC-4 approx) report = f"Report generated at NY Time: {now_ny.strftime('%Y-%m-%d %H:%M:%S')}\n\n" report += "=== Past Month USD High Impact News ===\n" report += "\n".join(past_news) if past_news else "No data found for the past month." report += "\n\n" report += "=== Forward 30-Day USD High Impact News ===\n" report += "\n".join(forward_news) if forward_news else "No forward events found." return report # =========================== # Main Function # =========================== def main(): log.info("===== Starting USD High Impact News Script =====") try: # Load configuration config = load_config() # Initialize MT5 try: initialize_mt5(config) except RuntimeError as e: log.error(f"Fatal error in MT5 initialization: {e}") return # Fetch news past_news = get_past_month_news() forward_news = get_forward_news() # Build report report = build_report(past_news, forward_news) # Send email send_email( subject="USD High Impact Economic News Report", body=report, smtp_config=config["email"] ) except Exception as e: log.error(f"Fatal error in main(): {e}") finally: log.info("Shutting down MetaTrader 5...") mt5.shutdown() log.info("MT5 shutdown complete.") log.info("===== Script Finished =====") # =========================== # Run Script # =========================== if __name__ == "__main__": main()