|
""" |
|
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 |
|
|
|
|
|
import matplotlib |
|
matplotlib.use('Agg') |
|
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()}") |
|
|
|
|
|
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 |
|
""" |
|
|
|
if isinstance(symbols, str): |
|
symbols = [symbols] |
|
|
|
print(f"\nProcessing symbols: {', '.join(symbols)} for timeframe: {timeframe}") |
|
|
|
|
|
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}") |
|
|
|
|
|
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()}") |
|
|
|
|
|
stock_data['Gain'] = stock_data['Close'].pct_change().fillna(0).cumsum() |
|
|
|
|
|
plt.figure(figsize=(12, 6)) |
|
plt.plot(stock_data.index, stock_data['Gain'], |
|
linewidth=2, |
|
label=f'{symbol} Gain') |
|
|
|
|
|
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() |
|
|
|
|
|
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() |
|
|
|
|
|
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) |
|
|
|
|
|
if symbol == symbols[-1]: |
|
main_plot_path = 'plot.png' |
|
plt.figure(plt.get_fignums()[-1]) |
|
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() |
|
|
|
|
|
symbols = ["META"] |
|
timeframe = "ytd" |
|
|
|
|
|
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()) |
|
|