155 lines
4.8 KiB
Python
155 lines
4.8 KiB
Python
|
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()
|