FTSAAIMT5C 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: FTSAAIMT5C
3
+ Version: 0.1.0
4
+ Summary: FTSA AI MT5 Connector CLI
5
+ Author: Kelvin Mburu
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: Microsoft :: Windows :: Windows 10
10
+ Classifier: Intended Audience :: Financial and Insurance Industry
11
+ Classifier: Topic :: Office/Business :: Financial
12
+ Classifier: Development Status :: 4 - Beta
13
+ Requires-Python: >=3.10
14
+ Requires-Dist: pymongo>=4.3.3
15
+ Requires-Dist: python-dotenv>=1.0.0
16
+ Requires-Dist: MetaTrader5>=5.0.5640
17
+ Requires-Dist: click>=8.0.0
18
+ Requires-Dist: requests>=2.32.5
19
+ Dynamic: author
20
+ Dynamic: classifier
21
+ Dynamic: requires-dist
22
+ Dynamic: requires-python
23
+ Dynamic: summary
@@ -0,0 +1,12 @@
1
+ README.md
2
+ setup.py
3
+ FTSAAIMT5C.egg-info/PKG-INFO
4
+ FTSAAIMT5C.egg-info/SOURCES.txt
5
+ FTSAAIMT5C.egg-info/dependency_links.txt
6
+ FTSAAIMT5C.egg-info/entry_points.txt
7
+ FTSAAIMT5C.egg-info/requires.txt
8
+ FTSAAIMT5C.egg-info/top_level.txt
9
+ ftsaaipkg/__init__.py
10
+ ftsaaipkg/bridge.py
11
+ ftsaaipkg/cli.py
12
+ ftsaaipkg/exit_cli.py
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ exit-ftsaai = ftsaaipkg.exit_cli:main
3
+ ftsaai-run = ftsaaipkg.cli:run_cli
@@ -0,0 +1,5 @@
1
+ pymongo>=4.3.3
2
+ python-dotenv>=1.0.0
3
+ MetaTrader5>=5.0.5640
4
+ click>=8.0.0
5
+ requests>=2.32.5
@@ -0,0 +1 @@
1
+ ftsaaipkg
@@ -0,0 +1,23 @@
1
+ Metadata-Version: 2.4
2
+ Name: FTSAAIMT5C
3
+ Version: 0.1.0
4
+ Summary: FTSA AI MT5 Connector CLI
5
+ Author: Kelvin Mburu
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: Microsoft :: Windows :: Windows 10
10
+ Classifier: Intended Audience :: Financial and Insurance Industry
11
+ Classifier: Topic :: Office/Business :: Financial
12
+ Classifier: Development Status :: 4 - Beta
13
+ Requires-Python: >=3.10
14
+ Requires-Dist: pymongo>=4.3.3
15
+ Requires-Dist: python-dotenv>=1.0.0
16
+ Requires-Dist: MetaTrader5>=5.0.5640
17
+ Requires-Dist: click>=8.0.0
18
+ Requires-Dist: requests>=2.32.5
19
+ Dynamic: author
20
+ Dynamic: classifier
21
+ Dynamic: requires-dist
22
+ Dynamic: requires-python
23
+ Dynamic: summary
@@ -0,0 +1,9 @@
1
+ # FTSAAI MT5 CLI Tool
2
+
3
+ This is a local MT5 bridge for FTSA AI.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install -e .
9
+ ftsai-run
File without changes
@@ -0,0 +1,84 @@
1
+ # ftsaaipkg/bridge.py
2
+
3
+ import MetaTrader5 as mt5
4
+ from datetime import datetime
5
+
6
+
7
+ def connect_mt5(login: str, password: str, server: str, platform: str = "MT5") -> bool:
8
+ """
9
+ Connects to MT5 using the provided credentials.
10
+ Returns True if connection is successful, else False.
11
+ """
12
+ try:
13
+ login_int = int(login)
14
+ except ValueError:
15
+ print(f"Invalid login number: {login}")
16
+ return False
17
+
18
+ # If already initialized, shut it down cleanly
19
+ if mt5.initialize():
20
+ mt5.shutdown()
21
+
22
+ # Attempt to initialize MT5
23
+ if not mt5.initialize(login=login_int, password=password, server=server):
24
+ error_code, error_descr = mt5.last_error()
25
+ print(f"MT5 initialize failed, error code = {error_code}, description = {error_descr}")
26
+ return False
27
+
28
+ return True
29
+
30
+
31
+ def disconnect_mt5():
32
+ """
33
+ Shuts down MT5 terminal connection if initialized.
34
+ """
35
+ if mt5.initialize():
36
+ mt5.shutdown()
37
+
38
+
39
+ # šŸ”„ NEW: Account Summary Fetcher
40
+ def get_account_summary() -> dict:
41
+ """
42
+ Returns account summary data:
43
+ balance, equity, margin, free margin
44
+ """
45
+ info = mt5.account_info()
46
+
47
+ if info is None:
48
+ return {}
49
+
50
+ return {
51
+ "balance": info.balance,
52
+ "equity": info.equity,
53
+ "margin": info.margin,
54
+ "freeMargin": info.margin_free
55
+ }
56
+
57
+
58
+ # šŸ”„ NEW: Open Trades Fetcher
59
+ def get_open_trades() -> list:
60
+ """
61
+ Returns list of currently open positions
62
+ """
63
+ positions = mt5.positions_get()
64
+
65
+ if positions is None:
66
+ return []
67
+
68
+ trades = []
69
+
70
+ for p in positions:
71
+ trades.append({
72
+ "symbol": p.symbol,
73
+ "ticket": p.ticket,
74
+ "time": datetime.utcfromtimestamp(p.time).isoformat() + "Z",
75
+ "type": "buy" if p.type == 0 else "sell",
76
+ "volume": p.volume,
77
+ "open_price": p.price_open,
78
+ "current_price": p.price_current,
79
+ "sl": p.sl,
80
+ "tp": p.tp,
81
+ "profit": p.profit
82
+ })
83
+
84
+ return trades
@@ -0,0 +1,158 @@
1
+ # ftsaaipkg/cli.py
2
+
3
+ import os
4
+ import sys
5
+ import time
6
+ import requests
7
+ from pymongo import MongoClient
8
+ from dotenv import load_dotenv
9
+ from .bridge import connect_mt5, get_account_summary, get_open_trades
10
+
11
+ # Load environment variables
12
+ load_dotenv()
13
+
14
+ # Load Mongo URI from .env
15
+ MONGO_URI = os.getenv("MONGO_URI")
16
+ if not MONGO_URI:
17
+ print("MONGO_URI not set in .env. Exiting...")
18
+ sys.exit(1)
19
+
20
+ DB_NAME = "ftsa_ai"
21
+
22
+ BACKEND_URL = "https://ftsa-ai-backend.onrender.com/api/ftsaaicli/mt5trades"
23
+
24
+ # File to track live streaming status
25
+ RUN_FILE = os.path.join(os.path.expanduser("~"), "ftsaai_running.txt")
26
+
27
+
28
+ def get_user_by_email(email: str, client: MongoClient):
29
+ db = client[DB_NAME]
30
+ return db.users.find_one({"email": email.lower()})
31
+
32
+
33
+ def get_mt_accounts(user_id: str, client: MongoClient):
34
+ db = client[DB_NAME]
35
+ return list(db.mtaccounts.find({"userId": user_id}))
36
+
37
+
38
+ def get_prop_accounts(user_id: str, client: MongoClient):
39
+ db = client[DB_NAME]
40
+ return list(db.propaccounts.find({"userId": user_id}))
41
+
42
+
43
+ def run_cli():
44
+ print("=== FTSA AI MT5 Connector ===")
45
+ email = input("Enter your email: ").strip()
46
+
47
+ client = MongoClient(MONGO_URI)
48
+
49
+ try:
50
+ # Create running flag
51
+ with open(RUN_FILE, "w") as f:
52
+ f.write("running")
53
+
54
+ user = get_user_by_email(email, client)
55
+ if not user:
56
+ print(f"User with email '{email}' not found.")
57
+ print("Existing users in the database:")
58
+ for u in client[DB_NAME].users.find({}, {"email": 1}):
59
+ print(" -", u["email"])
60
+ sys.exit(1)
61
+
62
+ user_id = str(user["_id"])
63
+ print(f"Found user: {user.get('firstName', 'Unknown')} (ID: {user_id})")
64
+
65
+ mt_accounts = get_mt_accounts(user_id, client)
66
+ prop_accounts = get_prop_accounts(user_id, client)
67
+
68
+ # Prefer MT account first, fallback to Prop
69
+ account = mt_accounts[0] if mt_accounts else (
70
+ prop_accounts[0] if prop_accounts else None
71
+ )
72
+
73
+ if not account:
74
+ print("No MT or Prop accounts found for this user. Exiting...")
75
+ sys.exit(1)
76
+
77
+ broker = account.get("broker", "Unknown")
78
+ login = account.get("login")
79
+ password = account.get("password")
80
+ server = account.get("server")
81
+
82
+ if not all([login, password, server]):
83
+ print("Account credentials are incomplete. Cannot connect to MT5.")
84
+ sys.exit(1)
85
+
86
+ print(f"Using account from broker: {broker}")
87
+ print(f"Connecting to MT5 account {login} on {server}...")
88
+
89
+ # CONNECT TO MT5
90
+ if connect_mt5(login, password, server):
91
+ print("MT5 connection established successfully!")
92
+ print("Starting live trade streaming...\n")
93
+ else:
94
+ print("Failed to connect to MT5.")
95
+ sys.exit(1)
96
+
97
+ # šŸ”„ LIVE STREAM LOOP
98
+ last_trades = None # track last trades to send only if changed
99
+ first_sync_done = False # to print success message only once
100
+ spinner_chars = ['|', '/', '-', '\\'] # spinner animation
101
+ spinner_index = 0
102
+
103
+ while True:
104
+ try:
105
+ # Stop if exit command deleted the flag
106
+ if not os.path.exists(RUN_FILE):
107
+ print("\nšŸ›‘ Stop signal received. Exiting live streaming...")
108
+ break
109
+
110
+ summary = get_account_summary()
111
+ trades = get_open_trades()
112
+
113
+ # Only send if trades have changed
114
+ if trades != last_trades:
115
+ payload = {
116
+ "userId": user_id,
117
+ "broker": broker,
118
+ "login": int(login),
119
+ "summary": summary,
120
+ "trades": trades
121
+ }
122
+
123
+ try:
124
+ response = requests.post(BACKEND_URL, json=payload, timeout=10)
125
+ if response.status_code == 200 and not first_sync_done:
126
+ print("āœ… Trades synced successfully")
127
+ first_sync_done = True
128
+ elif response.status_code != 200:
129
+ print(f"āŒ Sync failed ({response.status_code})")
130
+ except Exception as e:
131
+ print(f"Error sending trades to backend: {e}")
132
+
133
+ last_trades = trades
134
+
135
+ # Animate spinner for live streaming
136
+ spinner_char = spinner_chars[spinner_index]
137
+ spinner_index = (spinner_index + 1) % len(spinner_chars)
138
+ print(f"\ršŸŸ¢šŸ“ˆāš” Live trades ongoing {spinner_char} ", end='', flush=True)
139
+
140
+ # Poll every 0.3 seconds for near real-time updates
141
+ time.sleep(0.3)
142
+
143
+ except KeyboardInterrupt:
144
+ print("\nStopping live streaming...")
145
+ break
146
+ except Exception as e:
147
+ print(f"\nError during streaming: {e}")
148
+ time.sleep(0.3)
149
+
150
+ finally:
151
+ # Remove running flag on exit
152
+ if os.path.exists(RUN_FILE):
153
+ os.remove(RUN_FILE)
154
+ client.close()
155
+
156
+
157
+ if __name__ == "__main__":
158
+ run_cli()
@@ -0,0 +1,16 @@
1
+ # ftsaaipkg/exit_cli.py
2
+
3
+ import os
4
+
5
+ def main():
6
+ """
7
+ Stops the live streaming of FTSA AI MT5 Connector
8
+ by deleting the running flag file.
9
+ """
10
+ RUN_FILE = os.path.join(os.path.expanduser("~"), "ftsaai_running.txt")
11
+
12
+ if os.path.exists(RUN_FILE):
13
+ os.remove(RUN_FILE)
14
+ print("āœ… Live streaming stopped successfully.")
15
+ else:
16
+ print("āš ļø No live streaming process found or already stopped.")
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,35 @@
1
+ # setup.py
2
+
3
+ from setuptools import setup, find_packages
4
+
5
+ setup(
6
+ name="FTSAAIMT5C", # updated name for global install
7
+ version="0.1.0",
8
+ packages=find_packages(),
9
+ install_requires=[
10
+ "pymongo>=4.3.3",
11
+ "python-dotenv>=1.0.0",
12
+ "MetaTrader5>=5.0.5640",
13
+ "click>=8.0.0",
14
+ "requests>=2.32.5"
15
+ ],
16
+ entry_points={
17
+ "console_scripts": [
18
+ "ftsaai-run = ftsaaipkg.cli:run_cli", # start live streaming
19
+ "exit-ftsaai = ftsaaipkg.exit_cli:main" # stop live streaming
20
+ ]
21
+ },
22
+ python_requires='>=3.10',
23
+ author="Kelvin Mburu",
24
+ description="FTSA AI MT5 Connector CLI",
25
+ include_package_data=True,
26
+ classifiers=[
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3.10",
29
+ "License :: OSI Approved :: MIT License",
30
+ "Operating System :: Microsoft :: Windows :: Windows 10",
31
+ "Intended Audience :: Financial and Insurance Industry",
32
+ "Topic :: Office/Business :: Financial",
33
+ "Development Status :: 4 - Beta"
34
+ ],
35
+ )