Gr8/economiccalender.py
2025-09-10 15:02:31 +03:00

192 lines
6.2 KiB
Python

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()