Unosoftware commited on
Commit
27b5118
Β·
verified Β·
1 Parent(s): 2646ac5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +193 -383
app.py CHANGED
@@ -1,419 +1,229 @@
1
  import gradio as gr
2
- import MetaTrader5 as mt5
3
- import pandas as pd
4
- from datetime import datetime
5
- from smolagents import CodeAgent, HfApiModel, tool
6
- import json
7
- from typing import Dict, List, Optional
8
 
9
- # Custom MetaTrader Tools
10
- @tool
11
- def connect_mt5(login: int, password: str, server: str) -> str:
12
- """
13
- Connect to MetaTrader 5 terminal
14
-
15
- Args:
16
- login: MT5 account login number
17
- password: MT5 account password
18
- server: MT5 server name
19
-
20
- Returns:
21
- Connection status message
22
- """
23
- try:
24
- if not mt5.initialize():
25
- return f"Failed to initialize MT5: {mt5.last_error()}"
26
-
27
- if not mt5.login(login, password=password, server=server):
28
- return f"Failed to connect to account {login}: {mt5.last_error()}"
29
-
30
- return f"Successfully connected to MT5 account {login}"
31
- except Exception as e:
32
- return f"Error connecting to MT5: {str(e)}"
33
 
34
- @tool
35
- def get_account_info() -> str:
36
- """
37
- Get MetaTrader 5 account information
38
-
39
- Returns:
40
- Account information as formatted string
41
- """
42
- try:
43
- account_info = mt5.account_info()
44
- if account_info is None:
45
- return "Failed to get account info. Please ensure you're connected to MT5."
46
-
47
- info_dict = account_info._asdict()
48
- formatted_info = "=== ACCOUNT INFORMATION ===\n"
49
- formatted_info += f"Login: {info_dict['login']}\n"
50
- formatted_info += f"Server: {info_dict['server']}\n"
51
- formatted_info += f"Name: {info_dict['name']}\n"
52
- formatted_info += f"Company: {info_dict['company']}\n"
53
- formatted_info += f"Currency: {info_dict['currency']}\n"
54
- formatted_info += f"Balance: {info_dict['balance']:.2f}\n"
55
- formatted_info += f"Equity: {info_dict['equity']:.2f}\n"
56
- formatted_info += f"Margin: {info_dict['margin']:.2f}\n"
57
- formatted_info += f"Free Margin: {info_dict['margin_free']:.2f}\n"
58
- formatted_info += f"Margin Level: {info_dict['margin_level']:.2f}%\n"
59
- formatted_info += f"Profit: {info_dict['profit']:.2f}\n"
60
-
61
- return formatted_info
62
- except Exception as e:
63
- return f"Error getting account info: {str(e)}"
64
 
65
- @tool
66
- def get_closed_trades(days_back: int = 30) -> str:
67
  """
68
- Get closed trades from MetaTrader 5
69
 
70
  Args:
71
- days_back: Number of days to look back for trades (default: 30)
 
72
 
73
  Returns:
74
- Formatted string of closed trades
75
  """
76
  try:
77
- from datetime import datetime, timedelta
78
-
79
- # Calculate date range
80
- end_date = datetime.now()
81
- start_date = end_date - timedelta(days=days_back)
82
-
83
- # Get deals (closed trades)
84
- deals = mt5.history_deals_get(start_date, end_date)
85
-
86
- if deals is None or len(deals) == 0:
87
- return f"No closed trades found in the last {days_back} days."
88
-
89
- # Convert to DataFrame for easier handling
90
- df = pd.DataFrame(list(deals), columns=deals[0]._asdict().keys())
91
-
92
- # Filter only actual trades (exclude balance operations)
93
- trade_deals = df[df['type'].isin([0, 1])] # 0=buy, 1=sell
94
-
95
- if len(trade_deals) == 0:
96
- return f"No trading deals found in the last {days_back} days."
97
-
98
- formatted_trades = f"=== CLOSED TRADES (Last {days_back} days) ===\n"
99
- formatted_trades += f"Total deals: {len(trade_deals)}\n\n"
100
 
101
- for _, deal in trade_deals.iterrows():
102
- deal_type = "BUY" if deal['type'] == 0 else "SELL"
103
- deal_time = datetime.fromtimestamp(deal['time'])
 
 
 
 
 
 
 
 
 
104
 
105
- formatted_trades += f"Ticket: {deal['ticket']}\n"
106
- formatted_trades += f"Symbol: {deal['symbol']}\n"
107
- formatted_trades += f"Type: {deal_type}\n"
108
- formatted_trades += f"Volume: {deal['volume']:.2f}\n"
109
- formatted_trades += f"Price: {deal['price']:.5f}\n"
110
- formatted_trades += f"Profit: {deal['profit']:.2f}\n"
111
- formatted_trades += f"Commission: {deal['commission']:.2f}\n"
112
- formatted_trades += f"Swap: {deal['swap']:.2f}\n"
113
- formatted_trades += f"Time: {deal_time}\n"
114
- formatted_trades += f"Comment: {deal['comment']}\n"
115
- formatted_trades += "-" * 40 + "\n"
116
 
117
- return formatted_trades
 
 
118
 
119
  except Exception as e:
120
- return f"Error getting closed trades: {str(e)}"
 
 
121
 
122
- @tool
123
- def get_trade_statistics(days_back: int = 30) -> str:
124
- """
125
- Get trading statistics and analysis
126
-
127
- Args:
128
- days_back: Number of days to analyze (default: 30)
129
 
130
- Returns:
131
- Trading statistics as formatted string
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
  """
133
- try:
134
- from datetime import datetime, timedelta
135
-
136
- # Calculate date range
137
- end_date = datetime.now()
138
- start_date = end_date - timedelta(days=days_back)
139
-
140
- # Get deals
141
- deals = mt5.history_deals_get(start_date, end_date)
142
-
143
- if deals is None or len(deals) == 0:
144
- return f"No trades found for statistics in the last {days_back} days."
145
-
146
- # Convert to DataFrame
147
- df = pd.DataFrame(list(deals), columns=deals[0]._asdict().keys())
148
- trade_deals = df[df['type'].isin([0, 1])]
149
-
150
- if len(trade_deals) == 0:
151
- return f"No trading deals found for statistics."
152
-
153
- # Calculate statistics
154
- total_trades = len(trade_deals)
155
- total_profit = trade_deals['profit'].sum()
156
- total_commission = trade_deals['commission'].sum()
157
- total_swap = trade_deals['swap'].sum()
158
- net_profit = total_profit + total_commission + total_swap
159
-
160
- winning_trades = trade_deals[trade_deals['profit'] > 0]
161
- losing_trades = trade_deals[trade_deals['profit'] < 0]
162
-
163
- win_rate = (len(winning_trades) / total_trades * 100) if total_trades > 0 else 0
164
- avg_win = winning_trades['profit'].mean() if len(winning_trades) > 0 else 0
165
- avg_loss = losing_trades['profit'].mean() if len(losing_trades) > 0 else 0
166
-
167
- stats = f"=== TRADING STATISTICS (Last {days_back} days) ===\n"
168
- stats += f"Total Trades: {total_trades}\n"
169
- stats += f"Winning Trades: {len(winning_trades)}\n"
170
- stats += f"Losing Trades: {len(losing_trades)}\n"
171
- stats += f"Win Rate: {win_rate:.1f}%\n"
172
- stats += f"Average Win: {avg_win:.2f}\n"
173
- stats += f"Average Loss: {avg_loss:.2f}\n"
174
- stats += f"Total Profit: {total_profit:.2f}\n"
175
- stats += f"Total Commission: {total_commission:.2f}\n"
176
- stats += f"Total Swap: {total_swap:.2f}\n"
177
- stats += f"Net Profit: {net_profit:.2f}\n"
 
 
 
 
 
 
 
178
 
179
- # Most traded symbols
180
- symbol_counts = trade_deals['symbol'].value_counts()
181
- stats += f"\nMost Traded Symbols:\n"
182
- for symbol, count in symbol_counts.head(5).items():
183
- stats += f" {symbol}: {count} trades\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
 
185
- return stats
 
 
 
 
186
 
187
- except Exception as e:
188
- return f"Error calculating statistics: {str(e)}"
189
-
190
- @tool
191
- def disconnect_mt5() -> str:
192
- """
193
- Disconnect from MetaTrader 5
194
-
195
- Returns:
196
- Disconnection status message
197
- """
198
- try:
199
- mt5.shutdown()
200
- return "Successfully disconnected from MT5"
201
- except Exception as e:
202
- return f"Error disconnecting from MT5: {str(e)}"
203
-
204
- # Initialize the agent with Hugging Face model
205
- def create_agent():
206
- """Create and return the SmolagentsAI agent with MT5 tools"""
207
- try:
208
- # Use a free model from Hugging Face
209
- model = HfApiModel("microsoft/DialoGPT-medium")
210
 
211
- # Create agent with MetaTrader tools
212
- agent = CodeAgent(
213
- tools=[
214
- connect_mt5,
215
- get_account_info,
216
- get_closed_trades,
217
- get_trade_statistics,
218
- disconnect_mt5
219
- ],
220
- model=model,
221
- max_steps=10
222
  )
223
 
224
- return agent
225
- except Exception as e:
226
- return None, f"Error creating agent: {str(e)}"
227
-
228
- # Global variables
229
- agent = None
230
- is_connected = False
231
-
232
- def initialize_agent():
233
- """Initialize the agent"""
234
- global agent
235
- agent, error = create_agent()
236
- if agent is None:
237
- return f"Failed to initialize agent: {error}"
238
- return "Agent initialized successfully!"
239
-
240
- def connect_to_mt5(login, password, server):
241
- """Connect to MT5 with credentials"""
242
- global agent, is_connected
243
-
244
- if agent is None:
245
- return "Please initialize the agent first!"
246
-
247
- try:
248
- login_int = int(login)
249
- result = agent.run(f"Connect to MT5 with login {login_int}, password {password}, and server {server}")
250
 
251
- if "Successfully connected" in result:
252
- is_connected = True
253
- return result
254
- else:
255
- is_connected = False
256
- return result
257
-
258
- except ValueError:
259
- return "Login must be a valid number"
260
- except Exception as e:
261
- return f"Error: {str(e)}"
262
-
263
- def chat_with_agent(message, history):
264
- """Main chat function for the agent"""
265
- global agent, is_connected
266
-
267
- if agent is None:
268
- return history + [("Please initialize the agent first!", "")]
269
-
270
- if not is_connected:
271
- return history + [(message, "Please connect to MT5 first using your credentials in the connection tab.")]
272
-
273
- try:
274
- # Run the agent with the user's message
275
- response = agent.run(message)
276
- history.append((message, response))
277
- return history
278
- except Exception as e:
279
- error_msg = f"Error processing request: {str(e)}"
280
- history.append((message, error_msg))
281
- return history
282
-
283
- # Create Gradio interface
284
- def create_gradio_interface():
285
- """Create the Gradio interface"""
286
-
287
- with gr.Blocks(title="MetaTrader 5 AI Agent", theme=gr.themes.Soft()) as demo:
288
- gr.Markdown("# πŸ€– MetaTrader 5 AI Agent")
289
- gr.Markdown("An intelligent agent that can access your MT5 account and provide trading information.")
290
 
291
- with gr.Tabs():
292
- # Setup Tab
293
- with gr.TabItem("πŸ”§ Setup"):
294
- gr.Markdown("### Initialize Agent")
295
- init_btn = gr.Button("Initialize Agent", variant="primary")
296
- init_output = gr.Textbox(label="Initialization Status", interactive=False)
297
-
298
- init_btn.click(
299
- initialize_agent,
300
- outputs=init_output
301
- )
302
-
303
- gr.Markdown("### Connect to MetaTrader 5")
304
- with gr.Row():
305
- login_input = gr.Textbox(label="Login", placeholder="Your MT5 login number")
306
- password_input = gr.Textbox(label="Password", type="password", placeholder="Your MT5 password")
307
- server_input = gr.Textbox(label="Server", placeholder="Your MT5 server name")
308
-
309
- connect_btn = gr.Button("Connect to MT5", variant="primary")
310
- connection_output = gr.Textbox(label="Connection Status", interactive=False)
311
-
312
- connect_btn.click(
313
- connect_to_mt5,
314
- inputs=[login_input, password_input, server_input],
315
- outputs=connection_output
316
- )
317
-
318
- # Chat Tab
319
- with gr.TabItem("πŸ’¬ Chat with Agent"):
320
- gr.Markdown("### Ask the Agent About Your Trading Account")
321
- gr.Markdown("""
322
- **Example prompts you can try:**
323
- - "Show me my account information"
324
- - "Get my closed trades from the last 30 days"
325
- - "What are my trading statistics?"
326
- - "Show me trades from the last 7 days"
327
- - "Calculate my win rate and profit"
328
- """)
329
-
330
- chatbot = gr.Chatbot(
331
- label="MT5 Agent Chat",
332
- height=400,
333
- show_copy_button=True
334
- )
335
-
336
- msg = gr.Textbox(
337
- label="Your Message",
338
- placeholder="Ask about your account, trades, or statistics...",
339
- lines=2
340
- )
341
-
342
- with gr.Row():
343
- send_btn = gr.Button("Send", variant="primary")
344
- clear_btn = gr.Button("Clear Chat")
345
-
346
- # Event handlers
347
- def send_message(message, history):
348
- return chat_with_agent(message, history), ""
349
-
350
- def clear_chat():
351
- return []
352
-
353
- send_btn.click(
354
- send_message,
355
- inputs=[msg, chatbot],
356
- outputs=[chatbot, msg]
357
- )
358
-
359
- msg.submit(
360
- send_message,
361
- inputs=[msg, chatbot],
362
- outputs=[chatbot, msg]
363
- )
364
-
365
- clear_btn.click(
366
- clear_chat,
367
- outputs=chatbot
368
- )
369
-
370
- # Help Tab
371
- with gr.TabItem("❓ Help"):
372
- gr.Markdown("""
373
- ## How to Use This Application
374
-
375
- ### 1. Setup
376
- - First, click "Initialize Agent" in the Setup tab
377
- - Enter your MT5 credentials (login, password, server)
378
- - Click "Connect to MT5"
379
-
380
- ### 2. Chat with Agent
381
- - Go to the "Chat with Agent" tab
382
- - Ask questions about your trading account
383
- - The agent can provide account info, closed trades, and statistics
384
-
385
- ### Sample Questions:
386
- - "What's my account balance and equity?"
387
- - "Show me all closed trades from last week"
388
- - "Calculate my trading performance statistics"
389
- - "What symbols do I trade most?"
390
- - "What's my win rate?"
391
-
392
- ### Requirements:
393
- - MetaTrader 5 terminal must be installed and running
394
- - Valid MT5 account credentials
395
- - Internet connection for the AI model
396
-
397
- ### Troubleshooting:
398
- - Make sure MT5 terminal is running before connecting
399
- - Check your credentials are correct
400
- - Ensure your MT5 account allows API access
401
- - Try reinitializing the agent if you encounter errors
402
- """)
403
 
404
  # Footer
405
- gr.Markdown("---")
406
- gr.Markdown("*Powered by SmolagentsAI and MetaTrader 5 API*")
 
 
 
 
 
 
 
 
407
 
408
  return demo
409
 
410
- # Launch the application
411
  if __name__ == "__main__":
412
- # Create and launch the Gradio interface
413
- demo = create_gradio_interface()
414
  demo.launch(
415
  server_name="0.0.0.0",
416
  server_port=7860,
417
- share=True, # Creates a public link
418
- debug=True
419
- )
 
 
1
  import gradio as gr
2
+ from smolagents import CodeAgent, InferenceClientModel, Tool
3
+ import os
4
+ from PIL import Image
5
+ import tempfile
6
+ import base64
7
+ from io import BytesIO
8
 
9
+ # Initialize the image generation tool
10
+ image_generation_tool = Tool.from_space(
11
+ "black-forest-labs/FLUX.1-schnell",
12
+ name="image_generator",
13
+ description="Generate an image from a prompt"
14
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ # Initialize the model and agent
17
+ model = InferenceClientModel("Qwen/Qwen2.5-Coder-32B-Instruct")
18
+ agent = CodeAgent(tools=[image_generation_tool], model=model)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
 
20
+ def process_message(message, history):
 
21
  """
22
+ Process user message with the SmolagentsAI agent
23
 
24
  Args:
25
+ message: User input message
26
+ history: Chat history
27
 
28
  Returns:
29
+ Updated chat history
30
  """
31
  try:
32
+ # Run the agent with the user's message
33
+ response = agent.run(message)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
 
35
+ # Check if response contains image information
36
+ if hasattr(response, 'content') and isinstance(response.content, list):
37
+ # Handle multi-modal response (text + image)
38
+ text_parts = []
39
+ images = []
40
+
41
+ for item in response.content:
42
+ if hasattr(item, 'type'):
43
+ if item.type == 'text':
44
+ text_parts.append(item.text)
45
+ elif item.type == 'image':
46
+ images.append(item)
47
 
48
+ # Combine text parts
49
+ text_response = ' '.join(text_parts) if text_parts else str(response)
50
+
51
+ # Add images to the response if any
52
+ if images:
53
+ text_response += f"\n\nπŸ–ΌοΈ Generated {len(images)} image(s)"
54
+ else:
55
+ # Handle text-only response
56
+ text_response = str(response)
 
 
57
 
58
+ # Update chat history
59
+ history.append((message, text_response))
60
+ return history
61
 
62
  except Exception as e:
63
+ error_message = f"❌ Error: {str(e)}"
64
+ history.append((message, error_message))
65
+ return history
66
 
67
+ def clear_chat():
68
+ """Clear the chat history"""
69
+ return []
70
+
71
+ def create_interface():
72
+ """Create the Gradio interface"""
 
73
 
74
+ # Custom CSS for better styling
75
+ custom_css = """
76
+ .gradio-container {
77
+ max-width: 900px !important;
78
+ margin: auto !important;
79
+ }
80
+ .chat-message {
81
+ padding: 10px !important;
82
+ margin: 5px 0 !important;
83
+ border-radius: 10px !important;
84
+ }
85
+ .user-message {
86
+ background-color: #e3f2fd !important;
87
+ margin-left: 20% !important;
88
+ }
89
+ .bot-message {
90
+ background-color: #f5f5f5 !important;
91
+ margin-right: 20% !important;
92
+ }
93
  """
94
+
95
+ with gr.Blocks(
96
+ title="πŸ€– AI Agent with Image Generation",
97
+ theme=gr.themes.Soft(),
98
+ css=custom_css
99
+ ) as demo:
100
+
101
+ # Header
102
+ gr.Markdown("""
103
+ # πŸ€– AI Agent with Image Generation
104
+
105
+ This intelligent agent can help you with various tasks and generate images using FLUX.1-schnell!
106
+
107
+ **What you can do:**
108
+ - Ask questions and get intelligent responses
109
+ - Request image generation with detailed prompts
110
+ - Combine text and image requests in natural language
111
+
112
+ **Example prompts:**
113
+ - "Generate an image of a sunset over mountains"
114
+ - "Create a logo for a tech startup"
115
+ - "Show me a futuristic city"
116
+ - "Help me write code and create an illustration for it"
117
+ """)
118
+
119
+ # Chat interface
120
+ with gr.Row():
121
+ with gr.Column(scale=1):
122
+ # Chat history
123
+ chatbot = gr.Chatbot(
124
+ label="πŸ’¬ Chat with AI Agent",
125
+ height=500,
126
+ show_copy_button=True,
127
+ show_share_button=True,
128
+ avatar_images=("πŸ‘€", "πŸ€–"),
129
+ bubble_full_width=False
130
+ )
131
+
132
+ # Input area
133
+ with gr.Row():
134
+ msg_input = gr.Textbox(
135
+ label="Your Message",
136
+ placeholder="Ask me anything or request an image generation...",
137
+ lines=2,
138
+ scale=4
139
+ )
140
+ send_btn = gr.Button("Send πŸš€", variant="primary", scale=1)
141
+
142
+ # Control buttons
143
+ with gr.Row():
144
+ clear_btn = gr.Button("Clear Chat πŸ—‘οΈ", variant="secondary")
145
+ examples_btn = gr.Button("Show Examples πŸ’‘", variant="secondary")
146
 
147
+ # Examples section (initially hidden)
148
+ examples_section = gr.Markdown(
149
+ """
150
+ ### πŸ’‘ Example Prompts:
151
+
152
+ **Image Generation:**
153
+ - "Generate a realistic photo of a golden retriever playing in a park"
154
+ - "Create a minimalist logo design for a coffee shop"
155
+ - "Show me an abstract art piece with vibrant colors"
156
+ - "Generate a cyberpunk-style illustration of a neon city"
157
+
158
+ **Text + Image Combination:**
159
+ - "Explain quantum computing and create a visual representation"
160
+ - "Write a short story about space exploration and generate an accompanying image"
161
+ - "Help me design a website layout and show me a mockup"
162
+
163
+ **General AI Tasks:**
164
+ - "Help me write a Python function to sort a list"
165
+ - "Explain the concept of machine learning in simple terms"
166
+ - "Create a meal plan for the week"
167
+ """,
168
+ visible=False
169
+ )
170
 
171
+ # Event handlers
172
+ def send_message(message, history):
173
+ if not message.strip():
174
+ return history, ""
175
+ return process_message(message, history), ""
176
 
177
+ def toggle_examples(examples_visible):
178
+ return gr.update(visible=not examples_visible)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
179
 
180
+ # Wire up the events
181
+ send_btn.click(
182
+ send_message,
183
+ inputs=[msg_input, chatbot],
184
+ outputs=[chatbot, msg_input]
 
 
 
 
 
 
185
  )
186
 
187
+ msg_input.submit(
188
+ send_message,
189
+ inputs=[msg_input, chatbot],
190
+ outputs=[chatbot, msg_input]
191
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
 
193
+ clear_btn.click(
194
+ clear_chat,
195
+ outputs=chatbot
196
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
+ # Examples toggle
199
+ examples_visible = gr.State(False)
200
+ examples_btn.click(
201
+ lambda visible: (gr.update(visible=not visible), not visible),
202
+ inputs=examples_visible,
203
+ outputs=[examples_section, examples_visible]
204
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
  # Footer
207
+ gr.Markdown("""
208
+ ---
209
+ **Powered by:**
210
+ - 🧠 **Model**: Qwen2.5-Coder-32B-Instruct
211
+ - 🎨 **Image Generation**: FLUX.1-schnell
212
+ - πŸ€– **Framework**: SmolagentsAI
213
+ - 🌐 **Interface**: Gradio
214
+
215
+ *Built for Hugging Face Spaces*
216
+ """)
217
 
218
  return demo
219
 
220
+ # Launch the interface
221
  if __name__ == "__main__":
222
+ demo = create_interface()
 
223
  demo.launch(
224
  server_name="0.0.0.0",
225
  server_port=7860,
226
+ share=False, # Set to False for HF Spaces
227
+ show_error=True
228
+ )
229
+