# 필요한 라이브러리 설치 및 업데이트 import subprocess subprocess.run(["pip", "install", "--upgrade", "pip"]) subprocess.run(["pip", "install", "--upgrade", "yfinance", "gradio", "matplotlib", "Pillow"]) # 라이브러리 임포트 import yfinance as yf import gradio as gr import matplotlib.pyplot as plt import matplotlib.font_manager as fm import numpy as np import pandas as pd import re import io from PIL import Image from datetime import datetime, timedelta # 나눔고딕 폰트 설치 및 적용 def install_nanum_font(): try: subprocess.run(["apt-get", "update"], check=True) subprocess.run(["apt-get", "install", "-y", "fonts-nanum"], check=True) subprocess.run(["fc-cache", "-fv"], check=True) plt.rcParams['font.family'] = 'NanumGothic' except Exception as e: print(f"폰트 설치 중 오류가 발생했습니다: {e}") install_nanum_font() # 뉴스 요약 함수 (여기서는 간단히 예시로 처리) def get_real_news_summary(company, date): # 실제 API를 사용할 수 없는 환경이므로, 간단한 문자열로 대체합니다. return f"{company}의 {date} 주변 뉴스 요약입니다." def handle_click(company_name, date_clicked): return get_real_news_summary(company_name, date_clicked) def update_news(input_value, selected_date): if not selected_date: return "날짜를 선택해주세요." else: ticker = name_to_ticker.get(input_value, input_value) company_name = ticker_to_name.get(ticker, input_value) return handle_click(company_name, selected_date) # 종목명과 티커 매핑 딕셔너리 name_to_ticker = { "SK바이오팜": "326030.KS", "나스닥 시총 1위": "AAPL", "나스닥 바이오텍 시총 1위": "AMGN", "나스닥 헬스케어 시총 1위": "JNJ", "코스피 시총 1위": "005930.KS", "코스닥 시총 1위": "247540.KQ", # 에코프로비엠 } ticker_to_name = {v: k for k, v in name_to_ticker.items()} # 주가 데이터를 가져오고 그래프를 그리는 함수 def display_stock_with_highlight(input_value, change_type, percent_change): try: ticker = name_to_ticker.get(input_value, input_value) stock = yf.Ticker(ticker) stock_data = stock.history(period="5y") if stock_data.empty: return "주가 데이터를 찾을 수 없습니다.", gr.Dropdown.update(choices=[]) stock_data['Change'] = stock_data['Close'].pct_change() * 100 percent_change = float(percent_change) if change_type == "상승": highlight_data = stock_data[stock_data['Change'] >= percent_change] color = "darkorange" elif change_type == "하락": highlight_data = stock_data[stock_data['Change'] <= -percent_change] color = "purple" else: return "Invalid change type", gr.Dropdown.update(choices=[]) dates = stock_data.index closing_prices = stock_data['Close'] plt.figure(figsize=(10, 6)) plt.plot(dates, closing_prices, color='gray', label=input_value) plt.scatter(highlight_data.index, highlight_data['Close'], color=color, label=f'{change_type} 포인트') for index, row in highlight_data.iterrows(): plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=8, color=color, ha='right') plt.axvline(x=index, color=color, linestyle='--', linewidth=1) company_name = ticker_to_name.get(ticker, input_value) plt.title(f'{company_name} 주가 추이') plt.xlabel('날짜') plt.ylabel('종가') plt.legend() buf = io.BytesIO() plt.savefig(buf, format='png') plt.close() buf.seek(0) img = Image.open(buf) highlight_dates = highlight_data.index.strftime('%Y-%m-%d').tolist() return img, gr.Dropdown.update(choices=highlight_dates) except Exception as e: print(f"Error: {e}") return f"데이터 처리 중 오류가 발생했습니다: {e}", gr.Dropdown.update(choices=[]) # Gradio 인터페이스 생성 (3열 레이아웃) with gr.Blocks() as demo: gr.Markdown("## 주가 그래프와 뉴스 요약") with gr.Row(): with gr.Column(): input_value = gr.Textbox(label="종목명 또는 티커 입력", placeholder="예: SK바이오팜, AAPL") change_type = gr.Dropdown(choices=["상승", "하락"], label="상승 또는 하락 선택", value="상승") percent_change = gr.Textbox(label="변동 퍼센트 (%)", placeholder="예: 10", value="10") submit_btn = gr.Button("Submit") examples = [["SK바이오팜"], ["나스닥 시총 1위"], ["나스닥 바이오텍 시총 1위"], ["나스닥 헬스케어 시총 1위"], ["코스피 시총 1위"], ["코스닥 시총 1위"]] gr.Examples(examples=examples, inputs=[input_value]) with gr.Column(): plot = gr.Image(label="주가 그래프") date_dropdown = gr.Dropdown(label="조건에 해당하는 날짜 선택", choices=[]) with gr.Column(): news_output = gr.Markdown(label="뉴스 요약", value="") # 빈 칸으로 기본 표시 # Submit 버튼 클릭 시 그래프 및 날짜 드롭다운 업데이트 submit_btn.click( fn=display_stock_with_highlight, inputs=[input_value, change_type, percent_change], outputs=[plot, date_dropdown] ) # 날짜 선택 시 뉴스 요약 업데이트 date_dropdown.change( fn=update_news, inputs=[input_value, date_dropdown], outputs=[news_output] ) demo.launch()