-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmt5_connector.py
More file actions
145 lines (124 loc) · 4.84 KB
/
Copy pathmt5_connector.py
File metadata and controls
145 lines (124 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
"""
mt5_connector.py
────────────────
Handles everything related to the MetaTrader 5 connection:
- Initialise / login / shutdown
- Fetch OHLCV data
- Fetch account information
- Fetch live tick prices
Usage:
from mt5_connector import MT5Connector
conn = MT5Connector()
conn.connect()
df = conn.fetch_ohlcv("XAUUSD", mt5.TIMEFRAME_H1, 500)
acct = conn.get_account_info()
conn.disconnect()
"""
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
import config
from logger import log
class MT5Connector:
"""Manages the MT5 session and all data retrieval."""
def __init__(self):
self.connected = False
# ── Connection ────────────────────────────────────────────────
def connect(self) -> bool:
"""Initialise MT5 and log in with credentials from config."""
if not mt5.initialize():
log.error(f"MT5 initialize() failed: {mt5.last_error()}")
return False
authorized = mt5.login(
config.MT5_LOGIN,
password=config.MT5_PASSWORD,
server=config.MT5_SERVER,
)
if not authorized:
log.error(f"MT5 login failed: {mt5.last_error()}")
mt5.shutdown()
return False
self.connected = True
info = mt5.account_info()
log.info(
f"MT5 connected | Account: {info.login} | "
f"Balance: {info.balance:.2f} {info.currency} | "
f"Server: {info.server}"
)
return True
def disconnect(self):
"""Cleanly shut down the MT5 connection."""
mt5.shutdown()
self.connected = False
log.info("MT5 disconnected.")
def ensure_connected(self) -> bool:
"""Reconnect if the session has dropped."""
if not mt5.terminal_info():
log.warning("MT5 session lost — attempting reconnect…")
return self.connect()
return True
# ── Account Info ─────────────────────────────────────────────
def get_account_info(self) -> dict:
"""Return a dict of key account metrics."""
info = mt5.account_info()
if info is None:
log.error(f"get_account_info() failed: {mt5.last_error()}")
return {}
return {
"login": info.login,
"name": info.name,
"balance": info.balance,
"equity": info.equity,
"margin": info.margin,
"free_margin": info.margin_free,
"margin_level": info.margin_level,
"profit": info.profit,
"currency": info.currency,
"leverage": info.leverage,
"server": info.server,
}
# ── Market Data ───────────────────────────────────────────────
def fetch_ohlcv(self, symbol: str, timeframe: int, bars: int) -> pd.DataFrame:
"""
Fetch OHLCV bars from MT5.
Returns a DataFrame indexed by datetime with columns:
open, high, low, price (close), tick_volume, returns
Returns an empty DataFrame on failure.
"""
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, bars)
if rates is None or len(rates) == 0:
log.error(f"fetch_ohlcv: no data for {symbol} — {mt5.last_error()}")
return pd.DataFrame()
df = pd.DataFrame(rates)
df["time"] = pd.to_datetime(df["time"], unit="s")
df.set_index("time", inplace=True)
df.rename(columns={"close": "price"}, inplace=True)
df["returns"] = np.log(df["price"] / df["price"].shift(1))
return df
def get_tick(self, symbol: str):
"""Return the latest tick for a symbol, or None."""
tick = mt5.symbol_info_tick(symbol)
if tick is None:
log.error(f"get_tick: no tick for {symbol} — {mt5.last_error()}")
return tick
def get_symbol_info(self, symbol: str):
"""Return MT5 symbol_info object, or None."""
info = mt5.symbol_info(symbol)
if info is None:
log.error(f"get_symbol_info: unknown symbol {symbol}")
return info
def pip_value(self, symbol: str) -> float:
"""
Return the pip size for a symbol.
Gold / Silver → 0.1
JPY pairs → 0.01
Everything else → point × 10
"""
if symbol in ("XAUUSD", "XAGUSD"):
return 0.1
if "JPY" in symbol:
return 0.01
info = mt5.symbol_info(symbol)
if info:
return info.point * 10
return 0.0001