Dooratre commited on
Commit
8e56885
·
verified ·
1 Parent(s): d05d6ed

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +250 -0
app.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import time
3
+ import logging
4
+ from datetime import datetime
5
+ import requests
6
+ from flask import Flask, jsonify
7
+ from apscheduler.schedulers.background import BackgroundScheduler
8
+ from db import paires, deeper
9
+ import ai
10
+
11
+ # Configure logging
12
+ logging.basicConfig(
13
+ level=logging.INFO,
14
+ format='%(asctime)s - %(levelname)s - %(message)s'
15
+ )
16
+ logger = logging.getLogger(__name__)
17
+
18
+ # Initialize Flask app
19
+ app = Flask(__name__)
20
+
21
+ def fetch_pairs_configuration():
22
+ """Fetch the current pairs configuration from GitHub"""
23
+ result = paires.fetch_json_from_github()
24
+
25
+ if result["success"]:
26
+ config = result["data"]
27
+ if not config: # If the JSON is empty
28
+ config = {"status": False, "GROUPS": {}}
29
+ return config
30
+ else:
31
+ logger.error(f"Error fetching pairs configuration: {result['message']}")
32
+ return {"status": False, "GROUPS": {}}
33
+
34
+ def fetch_deeper_configuration():
35
+ """Fetch the current deeper analysis configuration from GitHub"""
36
+ result = deeper.fetch_json_from_github()
37
+
38
+ if result["success"]:
39
+ config = result["data"]
40
+ if not config: # If the JSON is empty
41
+ config = {"status": True, "forwards": {}}
42
+ return config
43
+ else:
44
+ logger.error(f"Error fetching deeper configuration: {result['message']}")
45
+ return {"status": True, "forwards": {}}
46
+
47
+ def save_deeper_configuration(config):
48
+ """Save the deeper configuration to GitHub"""
49
+ # Format the JSON as a single line with no indentation or whitespace
50
+ formatted_json = json.dumps(config, separators=(',', ':'))
51
+
52
+ # Get authentication token and commit ID
53
+ auth_token, commit_oid = deeper.fetch_authenticity_token_and_commit_oid()
54
+
55
+ if auth_token and commit_oid:
56
+ # Update the GitHub file
57
+ result = deeper.update_user_json_file(auth_token, commit_oid, formatted_json)
58
+ if result["success"]:
59
+ logger.info("Deeper analysis saved successfully!")
60
+ return True
61
+ else:
62
+ logger.error(f"Error saving deeper analysis: {result['message']}")
63
+ return False
64
+ else:
65
+ logger.error("Failed to get authentication token or commit ID. Deeper analysis not saved.")
66
+ return False
67
+
68
+ def extract_forward_content(analysis_text):
69
+ """Extract content between <Forward> and </Forward> tags"""
70
+ start_tag = "<Forward>"
71
+ end_tag = "</Forward>"
72
+
73
+ start_index = analysis_text.find(start_tag)
74
+ if start_index == -1:
75
+ return None
76
+
77
+ start_index += len(start_tag)
78
+ end_index = analysis_text.find(end_tag, start_index)
79
+
80
+ if end_index == -1:
81
+ return None
82
+
83
+ return analysis_text[start_index:end_index].strip()
84
+
85
+ def analyze_forex_groups():
86
+ """Main function to analyze forex groups and update deeper analysis"""
87
+ logger.info("Starting forex group analysis...")
88
+
89
+ try:
90
+ # Fetch current configurations
91
+ pairs_config = fetch_pairs_configuration()
92
+
93
+ # Check if trading is enabled
94
+ if not pairs_config.get("status", False):
95
+ logger.info("Trading is currently disabled. No analysis will be performed.")
96
+ return
97
+
98
+ # Process each group
99
+ groups = pairs_config.get("GROUPS", {})
100
+ if not groups:
101
+ logger.info("No groups configured for analysis.")
102
+ return
103
+
104
+ # Create a new forwards dictionary to replace the existing one
105
+ new_forwards = {}
106
+
107
+ for group_id, group_data in groups.items():
108
+ logger.info(f"Analyzing group {group_id}...")
109
+ try:
110
+ # Extract group information
111
+ pairs = group_data.get("pairs", [])
112
+ description = group_data.get("description", "")
113
+ relationships = group_data.get("relationships", "")
114
+
115
+ if not pairs:
116
+ logger.warning(f"No pairs defined for group {group_id}, skipping.")
117
+ continue
118
+
119
+ # Get AI analysis for the group
120
+ analysis = ai.analyze_forex_group(pairs, description, relationships)
121
+ logger.info(f"Analysis received for group {group_id}")
122
+
123
+ # Extract forward-looking content if present
124
+ forward_content = extract_forward_content(analysis)
125
+
126
+ if forward_content:
127
+ logger.info(f"Forward-looking analysis found for group {group_id}")
128
+ # Add to the new forwards dictionary with group ID as key
129
+ new_forwards[group_id] = {
130
+ "pairs": pairs,
131
+ "message": forward_content
132
+ }
133
+ else:
134
+ logger.info(f"No forward-looking analysis for group {group_id}")
135
+
136
+ except Exception as e:
137
+ logger.error(f"Error analyzing group {group_id}: {str(e)}", exc_info=True)
138
+ # Continue with next group instead of stopping the entire process
139
+ continue
140
+
141
+ # After collecting all analyses, update the deeper configuration in a single operation
142
+ if new_forwards:
143
+ logger.info(f"Saving forward analysis for {len(new_forwards)} groups...")
144
+
145
+ # Fetch the latest deeper configuration
146
+ deeper_config = fetch_deeper_configuration()
147
+
148
+ # Ensure deeper config has the correct structure
149
+ if "status" not in deeper_config:
150
+ deeper_config["status"] = True
151
+
152
+ # Replace the entire forwards section with our new data
153
+ deeper_config["forwards"] = new_forwards
154
+
155
+ # Save the configuration
156
+ save_deeper_configuration(deeper_config)
157
+ logger.info("All forward analyses saved successfully")
158
+ else:
159
+ logger.info("No forward-looking analyses found for any groups")
160
+
161
+ logger.info("Analysis cycle completed successfully")
162
+
163
+ except Exception as e:
164
+ logger.error(f"Unexpected error in analyze_forex_groups: {str(e)}", exc_info=True)
165
+
166
+ # Flask routes
167
+ @app.route('/')
168
+ def health_check():
169
+ """Health check endpoint to verify the service is running"""
170
+ return jsonify({
171
+ "status": "running",
172
+ "message": "Forex Analysis System is active",
173
+ "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
174
+ })
175
+
176
+ @app.route('/analyze/now')
177
+ def trigger_analysis():
178
+ """Endpoint to manually trigger analysis"""
179
+ try:
180
+ analyze_forex_groups()
181
+ return jsonify({
182
+ "status": "success",
183
+ "message": "Analysis triggered successfully",
184
+ "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
185
+ })
186
+ except Exception as e:
187
+ logger.error(f"Error triggering analysis: {e}", exc_info=True)
188
+ return jsonify({
189
+ "status": "error",
190
+ "message": f"Error triggering analysis: {str(e)}"
191
+ }), 500
192
+
193
+ @app.route('/status')
194
+ def get_status():
195
+ """Endpoint to get system status"""
196
+ try:
197
+ pairs_config = fetch_pairs_configuration()
198
+ deeper_config = fetch_deeper_configuration()
199
+
200
+ # Count all pairs across all groups
201
+ total_pairs = 0
202
+ for group_data in pairs_config.get("GROUPS", {}).values():
203
+ total_pairs += len(group_data.get("pairs", []))
204
+
205
+ return jsonify({
206
+ "service_status": "running",
207
+ "trading_enabled": pairs_config.get("status", False),
208
+ "groups_count": len(pairs_config.get("GROUPS", {})),
209
+ "total_pairs_count": total_pairs,
210
+ "deeper_analysis_enabled": deeper_config.get("status", True),
211
+ "forwards_count": len(deeper_config.get("forwards", {})),
212
+ "time": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
213
+ })
214
+ except Exception as e:
215
+ logger.error(f"Error getting status: {e}", exc_info=True)
216
+ return jsonify({
217
+ "service_status": "running",
218
+ "error": str(e)
219
+ })
220
+
221
+ # Initialize scheduler
222
+ scheduler = BackgroundScheduler(daemon=True)
223
+
224
+ def start_scheduler():
225
+ """Start the scheduler with the analysis job"""
226
+ logger.info("Starting scheduler for forex analysis")
227
+
228
+ # Schedule the analysis function to run every hour
229
+ scheduler.add_job(
230
+ analyze_forex_groups, # Changed from analyze_forex_pairs to analyze_forex_groups
231
+ 'interval',
232
+ hours=1,
233
+ id='forex_analysis',
234
+ replace_existing=True,
235
+ next_run_time=datetime.now() # Run immediately on startup
236
+ )
237
+
238
+ # Start the scheduler if it's not already running
239
+ if not scheduler.running:
240
+ scheduler.start()
241
+ logger.info("Scheduler started successfully")
242
+
243
+ if __name__ == "__main__":
244
+ logger.info("Starting Forex Analysis System...")
245
+
246
+ # Start the scheduler
247
+ start_scheduler()
248
+
249
+ # Start the Flask application
250
+ app.run(host='0.0.0.0', port=7860, debug=False)