Commit
97a16e9
β€’
1 Parent(s): 1ccfa39

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +158 -0
app.py ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ν•„μš”ν•œ 라이브러리 μ„€μΉ˜ 및 μ—…λ°μ΄νŠΈ
2
+ !pip install --upgrade pip
3
+ !pip install --upgrade openai yfinance gradio matplotlib Pillow
4
+
5
+ # λŸ°νƒ€μž„ μž¬μ‹œμž‘μ„ μœ„ν•œ μ½”λ“œ (이 셀을 μ‹€ν–‰ν•œ ν›„ μ•„λž˜ 셀을 μ‹€ν–‰ν•˜μ„Έμš”)
6
+ import os
7
+ os.kill(os.getpid(), 9)
8
+
9
+ # μœ„ 셀을 μ‹€ν–‰ν•œ ν›„, λŸ°νƒ€μž„μ΄ μž¬μ‹œμž‘λ˜λ©΄ 이 μ…€λΆ€ν„° μ‹€ν–‰ν•˜μ„Έμš”
10
+ import requests
11
+ import gradio as gr
12
+ import yfinance as yf
13
+ import matplotlib.pyplot as plt
14
+ import io
15
+ from PIL import Image
16
+ from datetime import datetime, timedelta
17
+ from openai import OpenAI
18
+
19
+ # Perplexity AI API μ„€μ •
20
+ API_KEY = "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" # 여기에 Perplexity AI API ν‚€λ₯Ό μž…λ ₯ν•˜μ„Έμš”.
21
+
22
+ def get_real_news_summary(company, date):
23
+ # OpenAI ν΄λΌμ΄μ–ΈνŠΈ μ΄ˆκΈ°ν™”
24
+ client = OpenAI(api_key=API_KEY, base_url="https://api.perplexity.ai")
25
+
26
+ # API μš”μ²­μ„ μœ„ν•œ λ©”μ‹œμ§€ ꡬ성
27
+ messages = [
28
+ {"role": "system", "content": "You are a helpful assistant that summarizes stock news in Korean."},
29
+ {"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."}
30
+ ]
31
+
32
+ try:
33
+ # API μš”μ²­
34
+ response = client.chat.completions.create(
35
+ model="llama-3.1-sonar-large-128k-online",
36
+ messages=messages
37
+ )
38
+
39
+ # μ‘λ‹΅μ—μ„œ μš”μ•½ μΆ”μΆœ
40
+ summary = response.choices[0].message.content
41
+ return summary
42
+ except Exception as e:
43
+ return f"λ‰΄μŠ€ μš”μ•½ 쀑 μ—λŸ¬κ°€ λ°œμƒν–ˆμŠ΅λ‹ˆλ‹€: {str(e)}"
44
+
45
+ # λ‰΄μŠ€ μš”μ•½μ„ κ°€μ Έμ˜€λŠ” ν•¨μˆ˜
46
+ def handle_click(input_value, date_clicked):
47
+ return get_real_news_summary(input_value, date_clicked)
48
+
49
+ # Gradioμ—μ„œ μ‚¬μš©ν•  ν•¨μˆ˜ (λ‰΄μŠ€ μš”μ•½ 포함)
50
+ def update_news(input_value, selected_date):
51
+ if selected_date == "" or selected_date is None:
52
+ return "λ‚ μ§œλ₯Ό μ„ νƒν•΄μ£Όμ„Έμš”."
53
+ else:
54
+ return handle_click(input_value, selected_date)
55
+
56
+ # μ’…λͺ©λͺ…κ³Ό 티컀λ₯Ό λ§€ν•‘ν•˜λŠ” λ”•μ…”λ„ˆλ¦¬
57
+ name_to_ticker = {
58
+ "μ‚Όμ„±μ „μž": "005930.KS",
59
+ "SKλ°”μ΄μ˜€νŒœ": "326030.KS",
60
+ "Apple": "AAPL",
61
+ # ν•„μš”ν•œ μ’…λͺ©λ“€μ„ μΆ”κ°€ν•˜μ„Έμš”
62
+ }
63
+
64
+ # μ£Όκ°€ 데이터λ₯Ό κ°€μ Έμ˜€κ³  쑰건에 λ§žλŠ” λ‚ μ§œμ™€ κ·Έλž˜ν”„λ₯Ό λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜
65
+ def display_stock_with_highlight(input_value, change_type, percent_change):
66
+ try:
67
+ ticker = name_to_ticker.get(input_value, input_value)
68
+ stock = yf.Ticker(ticker)
69
+ stock_data = stock.history(period="5y") # 졜근 5λ…„ λ°μ΄ν„°λ‘œ μ œν•œ
70
+
71
+ if stock_data.empty:
72
+ return "μ£Όκ°€ 데이터λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.", []
73
+
74
+ stock_data['Change'] = stock_data['Close'].pct_change() * 100
75
+
76
+ percent_change = float(percent_change)
77
+
78
+ if change_type == "μƒμŠΉ":
79
+ highlight_data = stock_data[stock_data['Change'] >= percent_change]
80
+ color = "darkorange"
81
+ elif change_type == "ν•˜λ½":
82
+ highlight_data = stock_data[stock_data['Change'] <= -percent_change]
83
+ color = "purple"
84
+ else:
85
+ return "Invalid change type", []
86
+
87
+ dates = stock_data.index.to_numpy()
88
+ closing_prices = stock_data['Close'].to_numpy()
89
+
90
+ plt.figure(figsize=(10, 6))
91
+ plt.plot(dates, closing_prices, color='gray', label=input_value)
92
+ plt.scatter(highlight_data.index, highlight_data['Close'], color=color, label=f'{change_type} 포인트')
93
+
94
+ for index, row in highlight_data.iterrows():
95
+ plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=10, fontweight='bold', color=color, ha='right')
96
+ plt.axvline(x=index, color=color, linestyle='--', linewidth=1) # xμΆ•κ³Όμ˜ μ—°κ²°μ„  μ μ„ μœΌλ‘œ ν‘œμ‹œ
97
+
98
+ plt.title(f'{input_value} μ£Όκ°€ 좔이 ({change_type} ν‘œμ‹œ)')
99
+ plt.xlabel('λ‚ μ§œ')
100
+ plt.ylabel('μ’…κ°€')
101
+ plt.legend()
102
+
103
+ buf = io.BytesIO()
104
+ plt.savefig(buf, format='png')
105
+ plt.close()
106
+ buf.seek(0)
107
+ img = Image.open(buf)
108
+
109
+ highlight_dates = highlight_data.index.strftime('%Y-%m-%d').tolist()
110
+
111
+ return img, gr.update(choices=highlight_dates)
112
+ except Exception as e:
113
+ return f"Error processing data: {e}", gr.update(choices=[])
114
+
115
+ # Gradio μΈν„°νŽ˜μ΄μŠ€ 생성 (3μ—΄ λ ˆμ΄μ•„μ›ƒ)
116
+ with gr.Blocks() as demo:
117
+ gr.Markdown("## μ£Όκ°€ κ·Έλž˜ν”„μ™€ λ‰΄μŠ€ μš”μ•½")
118
+
119
+ with gr.Row():
120
+ with gr.Column(): # μž…λ ₯값을 담을 첫 번째 μ—΄
121
+ input_value = gr.Textbox(label="μ’…λͺ©λͺ… λ˜λŠ” 티컀 μž…λ ₯", placeholder="예: SKλ°”μ΄μ˜€νŒœ, AAPL")
122
+ change_type = gr.Dropdown(choices=["μƒμŠΉ", "ν•˜λ½"], label="μƒμŠΉ λ˜λŠ” ν•˜λ½ 선택", value="μƒμŠΉ")
123
+ percent_change = gr.Textbox(label="변동 νΌμ„ΌνŠΈ (%)", placeholder="예: 10", value="10")
124
+
125
+ submit_btn = gr.Button("Submit")
126
+
127
+ # 예제 (이�� λ ˆμ΄μ•„μ›ƒμœΌλ‘œ 볡원)
128
+ examples = [["SKλ°”μ΄μ˜€νŒœ"],
129
+ ["λ‚˜μŠ€λ‹₯ μ‹œμ΄ 1μœ„"],
130
+ ["λ‚˜μŠ€λ‹₯ μ œμ•½μ£Ό μ‹œμ΄ 1μœ„"],
131
+ ["λ‚˜μŠ€λ‹₯ λ°”μ΄μ˜€ν… μ‹œμ΄ 1μœ„"],
132
+ ["μ½”μŠ€ν”Ό μ‹œμ΄ 1μœ„"],
133
+ ["μ½”μŠ€λ‹₯ μ‹œμ΄ 1μœ„"]]
134
+ gr.Examples(examples=examples, inputs=[input_value])
135
+
136
+ with gr.Column(): # κ·Έλž˜ν”„λ₯Ό 좜λ ₯ν•  두 번째 μ—΄
137
+ plot = gr.Image(label="μ£Όκ°€ κ·Έλž˜ν”„")
138
+ date_dropdown = gr.Dropdown(label="쑰건에 ν•΄λ‹Ήν•˜λŠ” λ‚ μ§œ 선택", choices=[])
139
+
140
+ with gr.Column(): # λ‰΄μŠ€ μš”μ•½μ„ 좜λ ₯ν•  μ„Έ 번째 μ—΄
141
+ news_output = gr.Textbox(label="λ‰΄μŠ€ μš”μ•½")
142
+
143
+ # Submit λ²„νŠΌ 클릭 μ‹œ κ·Έλž˜ν”„ 및 λ‚ μ§œ λ“œλ‘­λ‹€μš΄ μ—…λ°μ΄νŠΈ
144
+ submit_btn.click(
145
+ fn=display_stock_with_highlight,
146
+ inputs=[input_value, change_type, percent_change],
147
+ outputs=[plot, date_dropdown]
148
+ )
149
+
150
+ # λ‚ μ§œ 선택 μ‹œ λ‰΄μŠ€ μš”μ•½ μ—…λ°μ΄νŠΈ
151
+ date_dropdown.change(
152
+ fn=update_news,
153
+ inputs=[input_value, date_dropdown],
154
+ outputs=[news_output]
155
+ )
156
+
157
+ # Gradio μ‹€ν–‰
158
+ demo.launch()