Gr8/yearly.py

169 lines
5.8 KiB
Python
Raw Permalink Normal View History

2025-09-10 15:02:31 +03:00
import MetaTrader5 as mt5
import logging
import json
from datetime import datetime
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
# ================================
# Logging
# ================================
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(message)s"
)
log = logging.getLogger()
# ================================
# Load Config
# ================================
def load_config(filepath="config.json"):
log.info(f"Loading configuration file: {filepath}")
with open(filepath, "r") as f:
config = json.load(f)
log.info("Configuration loaded successfully")
return config
# ================================
# Send Email (Multiple Recipients)
# ================================
def send_email(subject, body, smtp_config):
recipients = smtp_config["recipient_email"]
if isinstance(recipients, str):
recipients = [recipients]
msg = MIMEMultipart()
msg["From"] = smtp_config["sender_email"]
msg["To"] = ", ".join(recipients)
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
try:
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: {', '.join(recipients)}")
except Exception as e:
log.error(f"Error sending email: {e}")
# ================================
# Fetch Yearly Data
# ================================
def get_yearly_data(symbol):
log.info(f"Fetching yearly data for {symbol}")
# Ensure symbol is selected in Market Watch
if not mt5.symbol_select(symbol, True):
log.warning(f"Could not select symbol {symbol}")
return None
now = datetime.now()
year_start = datetime(now.year, 1, 1)
rates = mt5.copy_rates_range(symbol, mt5.TIMEFRAME_D1, year_start, now)
if rates is None or len(rates) == 0:
log.warning(f"No historical data for {symbol}")
return None
# OHLC
open_price = rates[0]['open']
high_price = max(r['high'] for r in rates)
low_price = min(r['low'] for r in rates)
close_price = rates[-1]['close']
range_points = high_price - low_price
# Current price
tick = mt5.symbol_info_tick(symbol)
if tick is None:
log.warning(f"No tick data for {symbol}")
current_price = None
rel_open = rel_high = rel_low = rel_close = None
else:
# Use last price, fallback to bid if last is zero
current_price = tick.last if tick.last != 0 else tick.bid
multiplier = 100 if symbol.lower().startswith("xau") else 1
rel_open = (current_price - open_price) * multiplier
rel_high = (current_price - high_price) * multiplier
rel_low = (current_price - low_price) * multiplier
rel_close = (current_price - close_price) * multiplier
range_pips = range_points * (100 if symbol.lower().startswith("xau") else 1)
log.info(f"{symbol} → Open: {open_price}, High: {high_price}, Low: {low_price}, Close: {close_price}, Current: {current_price}")
return {
"Open": open_price,
"High": high_price,
"Low": low_price,
"Close": close_price,
"RangePoints": range_points,
"RangePips": range_pips,
"Current": current_price,
"RelOpen": rel_open,
"RelHigh": rel_high,
"RelLow": rel_low,
"RelClose": rel_close
}
# ================================
# Main Function
# ================================
def main():
log.info("===== Yearly Data Script Started =====")
config = load_config()
# Connect to running MT5 (do not reinitialize)
if not mt5.initialize():
log.warning(f"MT5 not running or cannot connect: {mt5.last_error()}")
else:
log.info("Connected to running MT5 terminal")
symbols = ["XAUUSD", "USTEC", "US30"]
report_lines = ["Yearly Data Report\n"]
for sym in symbols:
log.info(f"Processing symbol: {sym}")
data = get_yearly_data(sym)
if data:
report_lines.append(f"--- {sym} ---")
report_lines.append(f"Yearly Open: {data['Open']}")
report_lines.append(f"Yearly High: {data['High']}")
report_lines.append(f"Yearly Low: {data['Low']}")
report_lines.append(f"Yearly Close: {data['Close']}")
report_lines.append(f"Range (Points): {data['RangePoints']}")
report_lines.append(f"Range (Pips): {data['RangePips']}")
report_lines.append(f"Current Price: {data['Current'] if data['Current'] is not None else 'N/A'}")
if data['Current'] is not None:
if data['RelOpen'] is not None:
report_lines.append(f"Relative to Open: {data['RelOpen']:.2f}")
if data['RelHigh'] is not None:
report_lines.append(f"Relative to High: {data['RelHigh']:.2f}")
if data['RelLow'] is not None:
report_lines.append(f"Relative to Low: {data['RelLow']:.2f}")
if data['RelClose'] is not None:
report_lines.append(f"Relative to Close: {data['RelClose']:.2f}")
else:
report_lines.append("Current price not available")
report_lines.append("\n")
else:
report_lines.append(f"{sym}: No data available\n")
# Send email
send_email(
subject="Yearly OHLC + Current Position Report",
body="\n".join(report_lines),
smtp_config=config["email"]
)
mt5.shutdown()
log.info("===== Yearly Data Script Finished =====")
# ================================
# Run Script
# ================================
if __name__ == "__main__":
main()