1+ """MetaTrader5 headless initialization test with advanced configurations."""
2+
3+ import os
4+ import sys
5+ import time
6+ import shutil
7+ import subprocess
8+ import MetaTrader5 as mt5
9+
10+ def prepare_mt5_environment ():
11+ """Prepare necessary files and environment for headless MT5 operation."""
12+ print (f"MetaTrader5 package version: { mt5 .__version__ } " )
13+
14+ # Constants
15+ mt5_install_dir = "C:\\ Program Files\\ MetaTrader 5"
16+ mt5_exe = os .path .join (mt5_install_dir , "terminal64.exe" )
17+
18+ if not os .path .exists (mt5_exe ):
19+ print (f"ERROR: MetaTrader5 not found at { mt5_exe } " )
20+ return False
21+
22+ # Create data directories that MT5 expects
23+ user_dir = os .path .expanduser ("~" )
24+ mt5_data_dir = os .path .join (user_dir , "AppData" , "Roaming" , "MetaQuotes" , "Terminal" , "Headless" )
25+ mt5_config_dir = os .path .join (mt5_data_dir , "config" )
26+
27+ # Create directories
28+ os .makedirs (mt5_config_dir , exist_ok = True )
29+ print (f"Created MT5 config directory: { mt5_config_dir } " )
30+
31+ # Create minimal config files needed
32+ with open (os .path .join (mt5_config_dir , "startup.ini" ), "w" ) as f :
33+ f .write ("""[Common]
34+ Login=0
35+ EnableNews=0
36+ EnablePush=0
37+ AutoUpdate=0
38+ DisableOpenGL=1
39+ """ )
40+
41+ print ("Created minimal startup.ini configuration file" )
42+
43+ # Copy potential config files from installation directory if they exist
44+ install_config = os .path .join (mt5_install_dir , "Config" )
45+ if os .path .exists (install_config ):
46+ for file in ["servers.dat" , "groups.ini" ]:
47+ src = os .path .join (install_config , file )
48+ dst = os .path .join (mt5_config_dir , file )
49+ if os .path .exists (src ):
50+ shutil .copy2 (src , dst )
51+ print (f"Copied { file } to config directory" )
52+
53+ return mt5_data_dir
54+
55+ def test_mt5_initialization ():
56+ """Test MetaTrader5 initialization with special headless handling."""
57+
58+ # Set up environment
59+ config_dir = prepare_mt5_environment ()
60+ if not config_dir :
61+ return False
62+
63+ # Kill any existing MT5 processes
64+ try :
65+ subprocess .run (["taskkill" , "/F" , "/IM" , "terminal64.exe" ],
66+ stdout = subprocess .PIPE , stderr = subprocess .PIPE )
67+ print ("Killed any existing MetaTrader 5 processes" )
68+ time .sleep (5 )
69+ except Exception :
70+ pass # Ignore if no processes found
71+
72+ # Start MT5 with the prepared config directory
73+ mt_path = "C:\\ Program Files\\ MetaTrader 5\\ terminal64.exe"
74+
75+ try :
76+ cmd = [
77+ mt_path ,
78+ f"/config:{ os .path .basename (config_dir )} " , # Use our headless config
79+ "/portable" , # Portable mode to avoid login
80+ "/skipupdate" , # Skip updates
81+ "/autoclose" # Allow auto-closing (may help with headless operation)
82+ ]
83+ print (f"Starting MT5 with command: { ' ' .join (cmd )} " )
84+
85+ process = subprocess .Popen (cmd ,
86+ stdout = subprocess .PIPE ,
87+ stderr = subprocess .PIPE )
88+ print (f"Started MetaTrader 5 with PID: { process .pid } " )
89+ except Exception as e :
90+ print (f"Error starting MetaTrader 5: { e } " )
91+ return False
92+
93+ # Give extra time for initialization in CI
94+ print ("Waiting for MT5 process to initialize (30 seconds)..." )
95+ time .sleep (30 )
96+
97+ # Verify if process is still running
98+ try :
99+ if process .poll () is not None :
100+ print (f"WARNING: MetaTrader 5 process exited prematurely with code { process .poll ()} " )
101+ stdout , stderr = process .communicate ()
102+ print (f"STDOUT: { stdout .decode ('utf-8' , errors = 'ignore' )} " )
103+ print (f"STDERR: { stderr .decode ('utf-8' , errors = 'ignore' )} " )
104+ except Exception :
105+ pass
106+
107+ # Try various initialization approaches
108+ print ("\n Attempting MT5 initialization with various methods..." )
109+
110+ # Define all methods to try (path with increasing timeouts)
111+ methods = [
112+ {"name" : "Default config path" , "params" : {"path" : mt_path , "timeout" : 30000 }},
113+ {"name" : "With longer timeout" , "params" : {"path" : mt_path , "timeout" : 60000 }},
114+ {"name" : "With login=0" , "params" : {"path" : mt_path , "login" : 0 , "timeout" : 30000 }},
115+ {"name" : "With config path" , "params" : {"path" : mt_path , "config" : config_dir , "timeout" : 30000 }}
116+ ]
117+
118+ # Try each method in sequence
119+ for method in methods :
120+ print (f"\n Trying method: { method ['name' ]} " )
121+ try :
122+ # Ensure we're not already initialized
123+ mt5 .shutdown ()
124+ time .sleep (2 )
125+
126+ # Try initialization with this method's params
127+ result = mt5 .initialize (** method ['params' ])
128+ error = mt5 .last_error ()
129+ print (f"Result: { result } , Error: { error } " )
130+
131+ if result :
132+ print (f"SUCCESS with method: { method ['name' ]} " )
133+
134+ # Print terminal info
135+ try :
136+ terminal_info = mt5 .terminal_info ()
137+ if terminal_info :
138+ print (f"Terminal path: { terminal_info .path } " )
139+ print (f"Connection: { getattr (terminal_info , 'connected' , 'N/A' )} " )
140+ print (f"Community: { getattr (terminal_info , 'community_account' , 'N/A' )} " )
141+ except Exception as e :
142+ print (f"Error getting terminal info: { e } " )
143+
144+ mt5 .shutdown ()
145+ return True
146+ except Exception as e :
147+ print (f"Exception: { e } " )
148+
149+ # If we get here, all methods failed
150+ print ("\n All initialization methods failed" )
151+ return False
152+
153+ if __name__ == "__main__" :
154+ success = test_mt5_initialization ()
155+ print (f"\n Test { 'PASSED' if success else 'FAILED' } : MetaTrader5 initialization" )
156+ sys .exit (0 if success else 1 )
0 commit comments