Gr8/economiccalender.py

193 lines
6.2 KiB
Python
Raw Permalink Normal View History

2025-09-10 15:02:31 +03:00
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()