File size: 6,079 Bytes
97a16e9
 
 
 
bf83c95
97a16e9
 
 
 
 
 
 
 
bf83c95
97a16e9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bf83c95
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# ν•„μš”ν•œ 라이브러리 μ„€μΉ˜ 및 μ—…λ°μ΄νŠΈ
!pip install --upgrade pip
!pip install --upgrade openai yfinance gradio matplotlib Pillow

# λͺ¨λ“  ν•„μš”ν•œ νŒ¨ν‚€μ§€κ°€ μ„€μΉ˜λœ ν›„ κ³„μ†ν•΄μ„œ μ‹€ν–‰λ˜λ„λ‘ 함.
import requests
import gradio as gr
import yfinance as yf
import matplotlib.pyplot as plt
import io
from PIL import Image
from datetime import datetime, timedelta
from openai import OpenAI
import os

# Perplexity AI API μ„€μ •
API_KEY = "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"  # 여기에 Perplexity AI API ν‚€λ₯Ό μž…λ ₯ν•˜μ„Έμš”.

def get_real_news_summary(company, date):
    # OpenAI ν΄λΌμ΄μ–ΈνŠΈ μ΄ˆκΈ°ν™”
    client = OpenAI(api_key=API_KEY, base_url="https://api.perplexity.ai")
    
    # API μš”μ²­μ„ μœ„ν•œ λ©”μ‹œμ§€ ꡬ성
    messages = [
        {"role": "system", "content": "You are a helpful assistant that summarizes stock news in Korean."},
        {"role": "user", "content": f"Summarize the latest stock news for {company} on {date} in Korean. If there's no specific news for that date, provide the most recent relevant information."}
    ]
    
    try:
        # API μš”μ²­
        response = client.chat.completions.create(
            model="llama-3.1-sonar-large-128k-online",
            messages=messages
        )
        
        # μ‘λ‹΅μ—μ„œ μš”μ•½ μΆ”μΆœ
        summary = response.choices[0].message.content
        return summary
    except Exception as e:
        return f"λ‰΄μŠ€ μš”μ•½ 쀑 μ—λŸ¬κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"

# λ‰΄μŠ€ μš”μ•½μ„ κ°€μ Έμ˜€λŠ” ν•¨μˆ˜
def handle_click(input_value, date_clicked):
    return get_real_news_summary(input_value, date_clicked)

# Gradioμ—μ„œ μ‚¬μš©ν•  ν•¨μˆ˜ (λ‰΄μŠ€ μš”μ•½ 포함)
def update_news(input_value, selected_date):
    if selected_date == "" or selected_date is None:
        return "λ‚ μ§œλ₯Ό μ„ νƒν•΄μ£Όμ„Έμš”."
    else:
        return handle_click(input_value, selected_date)

# μ’…λͺ©λͺ…κ³Ό 티컀λ₯Ό λ§€ν•‘ν•˜λŠ” λ”•μ…”λ„ˆλ¦¬
name_to_ticker = {
    "μ‚Όμ„±μ „μž": "005930.KS",
    "SKλ°”μ΄μ˜€νŒœ": "326030.KS",
    "Apple": "AAPL",
    # ν•„μš”ν•œ μ’…λͺ©λ“€μ„ μΆ”κ°€ν•˜μ„Έμš”
}

# μ£Όκ°€ 데이터λ₯Ό κ°€μ Έμ˜€κ³  쑰건에 λ§žλŠ” λ‚ μ§œμ™€ κ·Έλž˜ν”„λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜
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")  # 졜근 5λ…„ λ°μ΄ν„°λ‘œ μ œν•œ

        if stock_data.empty:
            return "μ£Όκ°€ 데이터λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.", []

        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", []

        dates = stock_data.index.to_numpy()
        closing_prices = stock_data['Close'].to_numpy()

        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=10, fontweight='bold', color=color, ha='right')
            plt.axvline(x=index, color=color, linestyle='--', linewidth=1)  # xμΆ•κ³Όμ˜ μ—°κ²°μ„  μ μ„ μœΌλ‘œ ν‘œμ‹œ

        plt.title(f'{input_value} μ£Όκ°€ 좔이 ({change_type} ν‘œμ‹œ)')
        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.update(choices=highlight_dates)
    except Exception as e:
        return f"Error processing data: {e}", gr.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.Textbox(label="λ‰΄μŠ€ μš”μ•½")

    # 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]
    )

# Gradio μ‹€ν–‰
demo.launch()