""" Stock Plot Generation Script This script generates stock gain plots using yfinance and matplotlib. It includes robust error handling and debugging information. """ import os import sys import traceback import platform from datetime import datetime # Configure matplotlib before importing pyplot import matplotlib matplotlib.use('Agg') # Non-interactive backend import matplotlib.pyplot as plt import pandas as pd import yfinance as yf def setup_environment(): """Print environment information and verify dependencies.""" print("\n" + "=" * 80) print("ENVIRONMENT INFORMATION") print("=" * 80) print(f"Python: {sys.version}") print(f"Platform: {platform.platform()}") print(f"Current directory: {os.getcwd()}") print(f"Python executable: {sys.executable}") print(f"Current time: {datetime.now().isoformat()}") # Verify required packages print("\nChecking dependencies:") for pkg in [('pandas', pd), ('matplotlib', matplotlib), ('yfinance', yf)]: try: print(f" ✓ {pkg[0]}: {pkg[1].__version__}") except Exception as e: print(f" ✗ {pkg[0]}: Not available ({e})") def plot_stock_gain(symbols, timeframe="3mo"): """ Generate and save stock gain plots. Args: symbols: List of stock symbols or a single symbol string timeframe: Time period to fetch data for (e.g., '1mo', '3mo', '1y') Returns: str: Path to the saved plot file, or None if failed """ # Convert single symbol to list if isinstance(symbols, str): symbols = [symbols] print(f"\nProcessing symbols: {', '.join(symbols)} for timeframe: {timeframe}") # Create output directory if it doesn't exist output_dir = 'generated_plots' os.makedirs(output_dir, exist_ok=True) plot_paths = [] for symbol in symbols: try: print(f"\n{'='*40}") print(f"Processing: {symbol}") print(f"{'='*40}") # Download stock data print(f"Downloading {timeframe} data for {symbol}...") ticker = yf.Ticker(symbol) stock_data = ticker.history(period=timeframe) if stock_data.empty: print(f"⚠ No data found for {symbol}") continue print(f"Retrieved {len(stock_data)} data points from {stock_data.index[0].date()} to {stock_data.index[-1].date()}") # Calculate percentage gain stock_data['Gain'] = stock_data['Close'].pct_change().fillna(0).cumsum() # Create plot plt.figure(figsize=(12, 6)) plt.plot(stock_data.index, stock_data['Gain'], linewidth=2, label=f'{symbol} Gain') # Format plot plt.title(f'{symbol} Cumulative Gain - {timeframe.upper()}', fontsize=14) plt.xlabel('Date', fontsize=12) plt.ylabel('Cumulative Gain', fontsize=12) plt.legend() plt.grid(True, linestyle='--', alpha=0.7) plt.tight_layout() # Save plot timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') plot_filename = f"{symbol}_{timeframe}_{timestamp}.png" plot_path = os.path.join(output_dir, plot_filename) plt.savefig(plot_path, dpi=120, bbox_inches='tight') plt.close() # Close the figure to free memory # Verify the file was created if os.path.exists(plot_path): file_size = os.path.getsize(plot_path) print(f"✓ Plot saved: {plot_path} ({file_size} bytes)") plot_paths.append(plot_path) # Also save as plot.png in root for compatibility if symbol == symbols[-1]: # Only for the last symbol main_plot_path = 'plot.png' plt.figure(plt.get_fignums()[-1]) # Get the last figure plt.savefig(main_plot_path, dpi=120, bbox_inches='tight') print(f"✓ Main plot saved as: {os.path.abspath(main_plot_path)}") else: print("❌ Failed to save plot") except Exception as e: print(f"❌ Error processing {symbol}: {str(e)}") print("Traceback:") traceback.print_exc() return plot_paths[0] if plot_paths else None def main(): """Main execution function.""" try: setup_environment() # Default symbols and timeframe symbols = ["META"] timeframe = "ytd" # Generate plots plot_path = plot_stock_gain(symbols, timeframe) if plot_path: print(f"\n✅ Successfully generated plot: {os.path.abspath(plot_path)}") return 0 else: print("\n❌ Failed to generate any plots") return 1 except Exception as e: print(f"\n❌ Fatal error: {str(e)}") print("Traceback:") traceback.print_exc() return 1 if __name__ == "__main__": sys.exit(main())