Jeremy Live commited on
Commit
dcfac75
·
1 Parent(s): bc80b7a
Files changed (2) hide show
  1. app.py +54 -231
  2. stock_plot.py +0 -157
app.py CHANGED
@@ -175,250 +175,73 @@ def run_crewai_process(user_query, model, temperature):
175
  with open(temp_script_path, "w") as f:
176
  f.write(generated_code)
177
 
178
- # Create a debug script that will be executed in a subprocess
179
- debug_script = """
180
- import os
181
- import sys
182
  import traceback
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  try:
185
- print("\n" + "="*80)
186
- print("STOCK PLOT GENERATION")
187
- print("="*80)
 
 
 
 
 
188
 
189
- # Import the stock plot module
190
- try:
191
- import stock_plot
192
-
193
- # Generate the plot using the module
194
- plot_path = stock_plot.plot_stock_gain(["META"], "ytd")
195
-
196
- print("\n" + "="*80)
197
- print("PLOT GENERATION COMPLETE")
198
- print("="*80)
199
-
200
- if plot_path and os.path.exists(plot_path):
201
- file_size = os.path.getsize(plot_path)
202
- print(f"✓ Plot generated successfully: {os.path.abspath(plot_path)}")
203
- print(f"✓ File size: {file_size} bytes")
204
-
205
- # Also check for plot.png in the root directory
206
- if os.path.exists('plot.png'):
207
- print(f"✓ Main plot.png found: {os.path.abspath('plot.png')}")
208
- else:
209
- print("ℹ️ plot.png not found in root directory")
210
- else:
211
- print("❌ Failed to generate plot or plot file not found")
212
-
213
- except ImportError as e:
214
- print(f"❌ Error importing stock_plot module: {e}")
215
- print("Make sure the stock_plot.py file exists in the same directory.")
216
- raise
217
-
218
  print("\n" + "="*80)
219
- print("DIRECTORY CONTENTS")
220
  print("="*80)
 
221
 
222
- # List all files in the current directory
223
- for f in sorted(os.listdir('.')):
224
- try:
225
- fpath = os.path.join('.', f)
226
- if os.path.isfile(fpath):
227
- size = os.path.getsize(fpath)
228
- print(f" - {f} ({size} bytes)")
229
- else:
230
- print(f" - {f}/ (dir)")
231
- except Exception as e:
232
- print(f" - {f} (error: {e})")
233
-
234
- # Check for generated_plots directory
235
- plots_dir = 'generated_plots'
236
- if os.path.exists(plots_dir) and os.path.isdir(plots_dir):
237
- print(f"\nContents of {plots_dir}/:")
238
- try:
239
- for f in sorted(os.listdir(plots_dir)):
240
- try:
241
- fpath = os.path.join(plots_dir, f)
242
- if os.path.isfile(fpath):
243
- size = os.path.getsize(fpath)
244
- print(f" - {f} ({size} bytes)")
245
- except Exception as e:
246
- print(f" - {f} (error: {e})")
247
- except Exception as e:
248
- print(f" Error reading {plots_dir}: {e}")
249
-
250
- except Exception as e:
251
- print(f"\n❌ UNEXPECTED ERROR: {str(e)}")
252
- print("\nTraceback:")
253
- traceback.print_exc()
254
- sys.exit(1)
255
- """
256
-
257
- # Create a simple test plot
258
- try:
259
- # Create a new figure with a larger size
260
- fig, ax = plt.subplots(figsize=(10, 6))
261
-
262
- # Generate some sample data
263
- x = [1, 2, 3, 4, 5]
264
- y = [1, 4, 9, 16, 25]
265
-
266
- # Create the plot
267
- ax.plot(x, y, 'b-', linewidth=2, label='Sample Data')
268
-
269
- # Add labels and title
270
- ax.set_title('Test Plot - Matplotlib Verification', fontsize=14)
271
- ax.set_xlabel('X Axis', fontsize=12)
272
- ax.set_ylabel('Y Axis', fontsize=12)
273
-
274
- # Add grid and legend
275
- ax.grid(True, linestyle='--', alpha=0.7)
276
- ax.legend(fontsize=10)
277
-
278
- # Adjust layout to prevent label cutoff
279
- plt.tight_layout()
280
-
281
- # Save the test plot
282
- test_plot_path = 'test_plot.png'
283
- fig.savefig(test_plot_path, dpi=120, bbox_inches='tight')
284
- print(f"✓ Test plot saved to: {os.path.abspath(test_plot_path)}")
285
-
286
- # Close the figure to free memory
287
- plt.close(fig)
288
-
289
- except Exception as e:
290
- print(f"❌ Error creating test plot: {e}")
291
- print("Traceback:")
292
- traceback.print_exc()
293
-
294
- # Save with different formats and verify
295
- test_formats = [
296
- ('test_plot.png', 'PNG'),
297
- ('test_plot.jpg', 'JPEG'),
298
- ('test_plot.pdf', 'PDF')
299
- ]
300
 
301
- for filename, fmt in test_formats:
302
- try:
303
- test_fig.savefig(filename, bbox_inches='tight', dpi=100)
304
- abs_path = os.path.abspath(filename)
305
- file_size = os.path.getsize(filename)
306
- print(f"✓ Saved {{fmt}} to: {{abs_path}} ({{file_size}} bytes)")
307
-
308
- # Verify file is not empty
309
- if file_size == 0:
310
- print(f" ✗ WARNING: {{fmt}} file is empty!")
311
- elif file_size < 1024: # Very small file might be corrupted
312
- print(f" ⚠ WARNING: {{fmt}} file is unusually small ({{file_size}} bytes)")
313
-
314
- except Exception as e:
315
- print(f"✗ Failed to save {{fmt}}: {{str(e)}}")
316
-
317
- # Clean up
318
- plt.close(test_fig)
319
-
320
- # Test 2: Verify file system access
321
  print("\n" + "="*80)
322
- print("TEST 2: FILE SYSTEM VERIFICATION")
323
  print("="*80)
324
 
325
- # Check if files were created
326
- for filename, _ in test_formats:
327
- if os.path.exists(filename):
328
- try:
329
- file_size = os.path.getsize(filename)
330
- print(f"✓ Found {{filename}} ({{file_size}} bytes)")
331
- # Try to read the file
332
- with open(filename, 'rb') as f:
333
- header = f.read(4)
334
- print(f" File header: {{header[:20].hex()}}...")
335
- except Exception as e:
336
- print(f"✗ Error reading {{filename}}: {{str(e)}}")
337
- else:
338
- print(f"✗ File not found: {{filename}}")
339
-
340
- # Execute the original script with error handling
341
- print("\n" + "="*80)
342
- print("EXECUTING USER SCRIPT")
343
- print("="*80)
344
 
345
- # Create a safe execution environment
346
- try:
347
- # Execute the user's code
348
- exec_globals = {{'plt': plt, 'pd': __import__('pandas')}}
349
- exec_globals.update({{'__builtins__': __builtins__}})
350
-
351
- # Execute in a separate namespace to avoid polluting globals
352
- user_namespace = {{}}
353
- user_code = compile(
354
- {generated_code!r}.lstrip('\n').lstrip(' '),
355
- '<user_code>', 'exec',
356
- dont_inherit=True,
357
- optimize=2
358
- )
359
- exec(user_code, user_namespace, user_namespace)
360
 
361
- # Ensure any pending plots are drawn
362
- plt.ioff()
363
-
364
- # Save any open figures
365
- print("\n" + "="*80)
366
- print("SAVING PLOTS")
367
- print("="*80)
368
-
369
- # Get list of all figure numbers
370
- fig_nums = plt.get_fignums()
371
- print(f"Found {{len(fig_nums)}} open figures")
372
-
373
- if fig_nums:
374
- # Create plots directory if it doesn't exist
375
- plots_dir = 'generated_plots'
376
- os.makedirs(plots_dir, exist_ok=True)
377
-
378
- # Save all figures with unique names
379
- saved_plots = []
380
- for i, num in enumerate(fig_nums, 1):
381
- try:
382
- fig = plt.figure(num)
383
- plot_name = f'plot_{{i}}.png'
384
- plot_path = os.path.abspath(os.path.join(plots_dir, plot_name))
385
-
386
- # Save with high DPI and tight layout
387
- fig.savefig(
388
- plot_path,
389
- bbox_inches='tight',
390
- dpi=150,
391
- facecolor=fig.get_facecolor(),
392
- edgecolor='none',
393
- transparent=False
394
- )
395
-
396
- file_size = os.path.getsize(plot_path)
397
- print(f"✓ Saved plot {{i}} to: {{plot_path}} ({{file_size}} bytes)")
398
- saved_plots.append(plot_path)
399
-
400
- # If this is the last figure, also save as plot.png in root
401
- if i == len(fig_nums):
402
- root_plot_path = os.path.abspath('plot.png')
403
- fig.savefig(root_plot_path, bbox_inches='tight', dpi=150)
404
- print(f"✓ Saved main plot to: {{root_plot_path}}")
405
- saved_plots.append(root_plot_path)
406
-
407
- except Exception as e:
408
- print(f"✗ Error saving figure {{num}}: {{str(e)}}")
409
-
410
- if saved_plots:
411
- generated_plot_path = saved_plots[-1] # Use the last saved plot as the main plot
412
- print(f"\nSuccessfully saved {{len(saved_plots)}} plot(s)")
413
-
414
- else:
415
- print("ℹ️ No figures were created by the user script")
416
-
417
- except Exception as e:
418
- print(f"\n❌ Error executing user script: {{str(e)}}")
419
- print("\nTraceback:")
420
- traceback.print_exc()
421
- raise
422
 
423
  # Print final directory contents
424
  print("\n" + "="*80)
 
175
  with open(temp_script_path, "w") as f:
176
  f.write(generated_code)
177
 
178
+ # Execute the temporary script using subprocess
179
+ try:
180
+ # Add debug info and ensure plot is saved with absolute path
181
+ debug_script = f"""
182
  import traceback
183
+ import sys
184
+ import os
185
+ import matplotlib
186
+ # Use non-interactive backend to avoid display issues
187
+ matplotlib.use('Agg')
188
+ import matplotlib.pyplot as plt
189
+
190
+ # Debug info
191
+ print("="*80)
192
+ print("STARTING SCRIPT EXECUTION")
193
+ print("="*80)
194
+ print(f"[DEBUG] Python version: {{sys.version}}")
195
+ print(f"[DEBUG] Working directory: {{os.getcwd()}}")
196
+ print("[DEBUG] Directory contents:")
197
+ for f in os.listdir('.'):
198
+ print(f" - {{f}}{' (dir)' if os.path.isdir(f) else ''}")
199
+ print("\n" + "="*80 + "\n")
200
 
201
  try:
202
+ # Create a test plot first to verify matplotlib is working
203
+ test_fig, test_ax = plt.subplots()
204
+ test_ax.plot([1, 2, 3], [1, 4, 9])
205
+ test_ax.set_title('Test Plot - If you see this, matplotlib is working')
206
+ test_plot_path = 'test_plot.png'
207
+ test_fig.savefig(test_plot_path, bbox_inches='tight')
208
+ print(f"[DEBUG] Test plot saved to: {{os.path.abspath(test_plot_path)}}")
209
+ print(f"[DEBUG] Test plot size: {{os.path.getsize(test_plot_path)}} bytes")
210
 
211
+ # Execute the original script
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  print("\n" + "="*80)
213
+ print("EXECUTING USER SCRIPT")
214
  print("="*80)
215
+ {generated_code}
216
 
217
+ # Ensure any pending plots are drawn
218
+ plt.ioff()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
+ # Save any open figures
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
221
  print("\n" + "="*80)
222
+ print("SAVING PLOTS")
223
  print("="*80)
224
 
225
+ # Get list of all figure numbers
226
+ fig_nums = plt.get_fignums()
227
+ print(f"[DEBUG] Found {{len(fig_nums)}} open figures")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
 
229
+ if fig_nums:
230
+ # Save the last figure as plot.png
231
+ last_fig = plt.figure(fig_nums[-1])
232
+ plot_path = os.path.abspath('plot.png')
233
+ last_fig.savefig(plot_path, bbox_inches='tight', dpi=100)
234
+ print(f"[DEBUG] Saved plot to: {{plot_path}}")
235
+ print(f"[DEBUG] Plot file size: {{os.path.getsize(plot_path)}} bytes")
 
 
 
 
 
 
 
 
236
 
237
+ # Save all figures with unique names
238
+ for i, num in enumerate(fig_nums, 1):
239
+ fig = plt.figure(num)
240
+ fig_path = os.path.abspath(f'plot_{{i}}.png')
241
+ fig.savefig(fig_path, bbox_inches='tight', dpi=100)
242
+ print(f"[DEBUG] Saved additional plot to: {{fig_path}} ({{os.path.getsize(fig_path)}} bytes)")
243
+ else:
244
+ print("[WARNING] No figures were created in the script")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
245
 
246
  # Print final directory contents
247
  print("\n" + "="*80)
stock_plot.py DELETED
@@ -1,157 +0,0 @@
1
- """
2
- Stock Plot Generation Script
3
-
4
- This script generates stock gain plots using yfinance and matplotlib.
5
- It includes robust error handling and debugging information.
6
- """
7
-
8
- import os
9
- import sys
10
- import traceback
11
- import platform
12
- from datetime import datetime
13
-
14
- # Configure matplotlib before importing pyplot
15
- import matplotlib
16
- matplotlib.use('Agg') # Non-interactive backend
17
- import matplotlib.pyplot as plt
18
- import pandas as pd
19
- import yfinance as yf
20
-
21
-
22
- def setup_environment():
23
- """Print environment information and verify dependencies."""
24
- print("\n" + "=" * 80)
25
- print("ENVIRONMENT INFORMATION")
26
- print("=" * 80)
27
- print(f"Python: {sys.version}")
28
- print(f"Platform: {platform.platform()}")
29
- print(f"Current directory: {os.getcwd()}")
30
- print(f"Python executable: {sys.executable}")
31
- print(f"Current time: {datetime.now().isoformat()}")
32
-
33
- # Verify required packages
34
- print("\nChecking dependencies:")
35
- for pkg in [('pandas', pd), ('matplotlib', matplotlib), ('yfinance', yf)]:
36
- try:
37
- print(f" ✓ {pkg[0]}: {pkg[1].__version__}")
38
- except Exception as e:
39
- print(f" ✗ {pkg[0]}: Not available ({e})")
40
-
41
-
42
- def plot_stock_gain(symbols, timeframe="3mo"):
43
- """
44
- Generate and save stock gain plots.
45
-
46
- Args:
47
- symbols: List of stock symbols or a single symbol string
48
- timeframe: Time period to fetch data for (e.g., '1mo', '3mo', '1y')
49
-
50
- Returns:
51
- str: Path to the saved plot file, or None if failed
52
- """
53
- # Convert single symbol to list
54
- if isinstance(symbols, str):
55
- symbols = [symbols]
56
-
57
- print(f"\nProcessing symbols: {', '.join(symbols)} for timeframe: {timeframe}")
58
-
59
- # Create output directory if it doesn't exist
60
- output_dir = 'generated_plots'
61
- os.makedirs(output_dir, exist_ok=True)
62
-
63
- plot_paths = []
64
-
65
- for symbol in symbols:
66
- try:
67
- print(f"\n{'='*40}")
68
- print(f"Processing: {symbol}")
69
- print(f"{'='*40}")
70
-
71
- # Download stock data
72
- print(f"Downloading {timeframe} data for {symbol}...")
73
- ticker = yf.Ticker(symbol)
74
- stock_data = ticker.history(period=timeframe)
75
-
76
- if stock_data.empty:
77
- print(f"⚠ No data found for {symbol}")
78
- continue
79
-
80
- print(f"Retrieved {len(stock_data)} data points from {stock_data.index[0].date()} to {stock_data.index[-1].date()}")
81
-
82
- # Calculate percentage gain
83
- stock_data['Gain'] = stock_data['Close'].pct_change().fillna(0).cumsum()
84
-
85
- # Create plot
86
- plt.figure(figsize=(12, 6))
87
- plt.plot(stock_data.index, stock_data['Gain'],
88
- linewidth=2,
89
- label=f'{symbol} Gain')
90
-
91
- # Format plot
92
- plt.title(f'{symbol} Cumulative Gain - {timeframe.upper()}', fontsize=14)
93
- plt.xlabel('Date', fontsize=12)
94
- plt.ylabel('Cumulative Gain', fontsize=12)
95
- plt.legend()
96
- plt.grid(True, linestyle='--', alpha=0.7)
97
- plt.tight_layout()
98
-
99
- # Save plot
100
- timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
101
- plot_filename = f"{symbol}_{timeframe}_{timestamp}.png"
102
- plot_path = os.path.join(output_dir, plot_filename)
103
-
104
- plt.savefig(plot_path, dpi=120, bbox_inches='tight')
105
- plt.close() # Close the figure to free memory
106
-
107
- # Verify the file was created
108
- if os.path.exists(plot_path):
109
- file_size = os.path.getsize(plot_path)
110
- print(f"✓ Plot saved: {plot_path} ({file_size} bytes)")
111
- plot_paths.append(plot_path)
112
-
113
- # Also save as plot.png in root for compatibility
114
- if symbol == symbols[-1]: # Only for the last symbol
115
- main_plot_path = 'plot.png'
116
- plt.figure(plt.get_fignums()[-1]) # Get the last figure
117
- plt.savefig(main_plot_path, dpi=120, bbox_inches='tight')
118
- print(f"✓ Main plot saved as: {os.path.abspath(main_plot_path)}")
119
- else:
120
- print("❌ Failed to save plot")
121
-
122
- except Exception as e:
123
- print(f"❌ Error processing {symbol}: {str(e)}")
124
- print("Traceback:")
125
- traceback.print_exc()
126
-
127
- return plot_paths[0] if plot_paths else None
128
-
129
-
130
- def main():
131
- """Main execution function."""
132
- try:
133
- setup_environment()
134
-
135
- # Default symbols and timeframe
136
- symbols = ["META"]
137
- timeframe = "ytd"
138
-
139
- # Generate plots
140
- plot_path = plot_stock_gain(symbols, timeframe)
141
-
142
- if plot_path:
143
- print(f"\n✅ Successfully generated plot: {os.path.abspath(plot_path)}")
144
- return 0
145
- else:
146
- print("\n❌ Failed to generate any plots")
147
- return 1
148
-
149
- except Exception as e:
150
- print(f"\n❌ Fatal error: {str(e)}")
151
- print("Traceback:")
152
- traceback.print_exc()
153
- return 1
154
-
155
-
156
- if __name__ == "__main__":
157
- sys.exit(main())