Commit
0170c23
ยท
verified ยท
1 Parent(s): 7628d13

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +32 -82
app.py CHANGED
@@ -1,32 +1,23 @@
1
- import subprocess
2
  import os
3
  import matplotlib.font_manager as fm
4
  import matplotlib.pyplot as plt
5
  import yfinance as yf
6
  import numpy as np
7
- import re # ํ•œ๊ธ€, ์ˆซ์ž, ๊ธฐํ˜ธ๋ฅผ ๋‚จ๊ธฐ๊ธฐ ์œ„ํ•œ ์ •๊ทœ ํ‘œํ˜„์‹์— ์‚ฌ์šฉ
8
  import gradio as gr
9
  import io
10
  from PIL import Image
11
  from datetime import datetime, timedelta
12
- from openai import OpenAI
13
 
14
- # 1. ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐ ์—…๋ฐ์ดํŠธ
15
- def install_libraries():
16
- try:
17
- subprocess.run(["pip", "install", "--upgrade", "pip"])
18
- subprocess.run(["pip", "install", "--upgrade", "openai", "yfinance", "gradio", "matplotlib", "Pillow"])
19
- except Exception as e:
20
- print(f"๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
21
-
22
- install_libraries()
23
-
24
- # 2. ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ์„ค์น˜ ๋ฐ ์ ์šฉ
25
  def install_nanum_font():
26
  try:
27
- subprocess.run(["apt-get", "update"], check=True)
28
- subprocess.run(["apt-get", "install", "-y", "fonts-nanum"], check=True)
29
- subprocess.run(["fc-cache", "-fv"], check=True)
 
 
30
  except Exception as e:
31
  print(f"ํฐํŠธ ์„ค์น˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
32
 
@@ -43,60 +34,24 @@ font_prop = fm.FontProperties(fname=font_path)
43
  plt.rcParams['font.family'] = font_prop.get_name()
44
  plt.rcParams['axes.unicode_minus'] = False # ๋งˆ์ด๋„ˆ์Šค ๋ถ€ํ˜ธ ๊นจ์ง ๋ฐฉ์ง€
45
 
46
- # 3. Perplexity AI API ์„ค์ •
47
- API_KEY = "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"
48
-
49
- # ๋‰ด์Šค ์š”์•ฝ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
50
  def get_real_news_summary(company, date):
51
- # OpenAI ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
52
- client = OpenAI(api_key=API_KEY, base_url="https://api.perplexity.ai")
53
-
54
- # ๋‚ ์งœ ํ˜•์‹์„ ๋งž์ถฐ์ฃผ๊ธฐ ์œ„ํ•œ ์ฒ˜๋ฆฌ
55
- target_date = datetime.strptime(date, '%Y-%m-%d')
56
- start_date = (target_date - timedelta(days=1)).strftime('%Y-%m-%d')
57
- end_date = (target_date + timedelta(days=1)).strftime('%Y-%m-%d')
58
-
59
- # API ์š”์ฒญ์„ ์œ„ํ•œ ๋ฉ”์‹œ์ง€ ๊ตฌ์„ฑ
60
- messages = [
61
- {"role": "system", "content": "You are a helpful assistant that summarizes stock news strictly in Korean."},
62
- {"role": "user", "content": f"Summarize the stock news for {company} between {start_date} and {end_date} in Korean. Only focus on news within this date range."}
63
- ]
64
-
65
- try:
66
- # API ์š”์ฒญ
67
- response = client.chat.completions.create(
68
- model="llama-3.1-sonar-large-128k-online",
69
- messages=messages
70
- )
71
 
72
- # ์‘๋‹ต์—์„œ ์š”์•ฝ ์ถ”์ถœ
73
- summary = response.choices[0].message.content
74
-
75
- # ํ•œ๊ธ€, ์ˆซ์ž, ๊ณต๋ฐฑ, ํŠน์ˆ˜ ๊ธฐํ˜ธ๋งŒ ๋‚จ๊ธฐ๋Š” ์ •๊ทœ ํ‘œํ˜„์‹
76
- korean_only_summary = re.sub(r'[^\w\s#.,!%()\-\[\]]', '', summary)
77
-
78
- # ##๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ถ€๋ถ„์„ **์œผ๋กœ ๊ฐ์‹ธ์„œ Bold ์ฒ˜๋ฆฌ
79
- formatted_summary = re.sub(r'##\s*(.+)', r'**\1**', korean_only_summary)
80
-
81
- return formatted_summary
82
- except Exception as e:
83
- return f"๋‰ด์Šค ์š”์•ฝ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
84
-
85
- # ๋‰ด์Šค ์š”์•ฝ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
86
  def handle_click(company_name, date_clicked):
87
  return get_real_news_summary(company_name, date_clicked)
88
 
89
- # Gradio์—์„œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜ (๋‰ด์Šค ์š”์•ฝ ํฌํ•จ)
90
  def update_news(input_value, selected_date):
91
- if selected_date == "" or selected_date is None:
92
  return "๋‚ ์งœ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."
93
  else:
94
- # ์ข…๋ชฉ๋ช…์„ ๊ฐ€์ ธ์™€์„œ Perplexity๋กœ ๊ฒ€์ƒ‰
95
  ticker = name_to_ticker.get(input_value, input_value)
96
  company_name = input_value if ticker == input_value else list(name_to_ticker.keys())[list(name_to_ticker.values()).index(ticker)]
97
  return handle_click(company_name, selected_date)
98
 
99
- # ์ข…๋ชฉ๋ช…๊ณผ ํ‹ฐ์ปค๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ ํ™•์žฅ ๋ฐ ์กฐ๊ฑด๋ณ„ ์ข…๋ชฉ ๋งคํ•‘
100
  name_to_ticker = {
101
  "์‚ผ์„ฑ์ „์ž": "005930.KS",
102
  "SK๋ฐ”์ด์˜คํŒœ": "326030.KS",
@@ -110,7 +65,6 @@ name_to_ticker = {
110
  "๋„ค์ด๋ฒ„": "035420.KS",
111
  "์—์ฝ”ํ”„๋กœ๋น„์— ": "247540.KS",
112
  "์•Œํ…Œ์˜ค์  ": "196170.KQ",
113
- # ์ตœ์‹  ์‹œ๊ฐ€์ด์•ก ์ƒ์œ„ ์ข…๋ชฉ์„ ๋ฐ˜์˜ํ•˜์—ฌ ์—…๋ฐ์ดํŠธ
114
  "๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„": "AAPL", # Apple
115
  "๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„": "VRTX", # Vertex Pharmaceuticals
116
  "๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„": "LLY", # Eli Lilly
@@ -118,19 +72,17 @@ name_to_ticker = {
118
  "์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„": "196170.KQ", # ๏ฟฝ๏ฟฝํ…Œ์˜ค์  
119
  }
120
 
121
- # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ์กฐ๊ฑด์— ๋งž๋Š” ๋‚ ์งœ์™€ ๊ทธ๋ž˜ํ”„๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜
122
  def display_stock_with_highlight(input_value, change_type, percent_change):
123
  try:
124
- # ์ž…๋ ฅ๊ฐ’์„ ํ‹ฐ์ปค๋กœ ๋ณ€ํ™˜
125
  ticker = name_to_ticker.get(input_value, input_value)
126
  stock = yf.Ticker(ticker)
127
- stock_data = stock.history(period="5y") # ์ตœ๊ทผ 5๋…„ ๋ฐ์ดํ„ฐ๋กœ ์ œํ•œ
128
 
129
  if stock_data.empty:
130
- return "์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", []
131
 
132
  stock_data['Change'] = stock_data['Close'].pct_change() * 100
133
-
134
  percent_change = float(percent_change)
135
 
136
  if change_type == "์ƒ์Šน":
@@ -140,20 +92,19 @@ def display_stock_with_highlight(input_value, change_type, percent_change):
140
  highlight_data = stock_data[stock_data['Change'] <= -percent_change]
141
  color = "purple"
142
  else:
143
- return "Invalid change type", []
144
 
145
- dates = stock_data.index.to_numpy()
146
- closing_prices = stock_data['Close'].to_numpy()
147
 
148
  plt.figure(figsize=(10, 6))
149
  plt.plot(dates, closing_prices, color='gray', label=input_value)
150
  plt.scatter(highlight_data.index, highlight_data['Close'], color=color, label=f'{change_type} ํฌ์ธํŠธ')
151
 
152
  for index, row in highlight_data.iterrows():
153
- plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=10, fontweight='bold', color=color, ha='right')
154
- plt.axvline(x=index, color=color, linestyle='--', linewidth=1) # x์ถ•๊ณผ์˜ ์—ฐ๊ฒฐ์„  ์ ์„ ์œผ๋กœ ํ‘œ์‹œ
155
 
156
- # ์ข…๋ชฉ๋ช… + '์ฃผ๊ฐ€ ์ถ”์ด'๋กœ ์ œ๋ชฉ ์„ค์ • (์ข…๋ชฉ๋ช… ๊ธฐ๋ฐ˜)
157
  company_name = list(name_to_ticker.keys())[list(name_to_ticker.values()).index(ticker)]
158
  plt.title(f'{company_name} ์ฃผ๊ฐ€ ์ถ”์ด', fontproperties=font_prop)
159
  plt.xlabel('๋‚ ์งœ', fontproperties=font_prop)
@@ -168,25 +119,25 @@ def display_stock_with_highlight(input_value, change_type, percent_change):
168
 
169
  highlight_dates = highlight_data.index.strftime('%Y-%m-%d').tolist()
170
 
171
- return img, gr.update(choices=highlight_dates)
172
  except Exception as e:
173
- return f"Error processing data: {e}", gr.update(choices=[])
 
174
 
175
- # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ (3์—ด ๋ ˆ์ด์•„์›ƒ)
176
  with gr.Blocks() as demo:
177
  gr.Markdown("## ์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„์™€ ๋‰ด์Šค ์š”์•ฝ")
178
 
 
179
  demo.css("#news_output_box { background-color: #f0f0f0; padding: 20px; }")
180
 
181
  with gr.Row():
182
- with gr.Column(): # ์ž…๋ ฅ๊ฐ’์„ ๋‹ด์„ ์ฒซ ๋ฒˆ์งธ ์—ด
183
  input_value = gr.Textbox(label="์ข…๋ชฉ๋ช… ๋˜๋Š” ํ‹ฐ์ปค ์ž…๋ ฅ", placeholder="์˜ˆ: SK๋ฐ”์ด์˜คํŒœ, AAPL")
184
  change_type = gr.Dropdown(choices=["์ƒ์Šน", "ํ•˜๋ฝ"], label="์ƒ์Šน ๋˜๋Š” ํ•˜๋ฝ ์„ ํƒ", value="์ƒ์Šน")
185
  percent_change = gr.Textbox(label="๋ณ€๋™ ํผ์„ผํŠธ (%)", placeholder="์˜ˆ: 10", value="10")
186
-
187
  submit_btn = gr.Button("Submit")
188
 
189
- # ์˜ˆ์ œ
190
  examples = [["SK๋ฐ”์ด์˜คํŒœ"],
191
  ["๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„"],
192
  ["๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„"],
@@ -195,26 +146,25 @@ with gr.Blocks() as demo:
195
  ["์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„"]]
196
  gr.Examples(examples=examples, inputs=[input_value])
197
 
198
- with gr.Column(): # ๊ทธ๋ž˜ํ”„๋ฅผ ์ถœ๋ ฅํ•  ๋‘ ๋ฒˆ์งธ ์—ด
199
  plot = gr.Image(label="์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„")
200
  date_dropdown = gr.Dropdown(label="์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ ์„ ํƒ", choices=[])
201
 
202
- with gr.Column(): # ๋‰ด์Šค ์š”์•ฝ์„ ์ถœ๋ ฅํ•  ์„ธ ๋ฒˆ์งธ ์—ด
203
  news_output = gr.Markdown(label="๋‰ด์Šค ์š”์•ฝ", value="", elem_id="news_output_box")
204
 
205
- # Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๊ทธ๋ž˜ํ”„ ๋ฐ ๋‚ ์งœ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ
206
  submit_btn.click(
207
  fn=display_stock_with_highlight,
208
  inputs=[input_value, change_type, percent_change],
209
  outputs=[plot, date_dropdown]
210
  )
211
 
212
- # ๋‚ ์งœ ์„ ํƒ ์‹œ ๋‰ด์Šค ์š”์•ฝ ์—…๋ฐ์ดํŠธ
213
  date_dropdown.change(
214
  fn=update_news,
215
  inputs=[input_value, date_dropdown],
216
  outputs=[news_output]
217
  )
218
 
219
- # Gradio ์‹คํ–‰
220
  demo.launch()
 
 
1
  import os
2
  import matplotlib.font_manager as fm
3
  import matplotlib.pyplot as plt
4
  import yfinance as yf
5
  import numpy as np
6
+ import re
7
  import gradio as gr
8
  import io
9
  from PIL import Image
10
  from datetime import datetime, timedelta
11
+ # from openai import OpenAI # ์‹ค์ œ API ํ‚ค๊ฐ€ ์žˆ๊ณ  ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ฃผ์„์„ ํ•ด์ œํ•˜์„ธ์š”.
12
 
13
+ # 1. ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ์„ค์น˜ ๋ฐ ์ ์šฉ
 
 
 
 
 
 
 
 
 
 
14
  def install_nanum_font():
15
  try:
16
+ # ์‹œ์Šคํ…œ์— ๋”ฐ๋ผ ํฐํŠธ ์„ค์น˜ ๋ฐฉ๋ฒ•์ด ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
17
+ # ์—ฌ๊ธฐ์„œ๋Š” Ubuntu ๊ธฐ๋ฐ˜ ์‹œ์Šคํ…œ์—์„œ์˜ ์˜ˆ์‹œ์ž…๋‹ˆ๋‹ค.
18
+ os.system('apt-get update')
19
+ os.system('apt-get install -y fonts-nanum')
20
+ fm._rebuild()
21
  except Exception as e:
22
  print(f"ํฐํŠธ ์„ค์น˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
23
 
 
34
  plt.rcParams['font.family'] = font_prop.get_name()
35
  plt.rcParams['axes.unicode_minus'] = False # ๋งˆ์ด๋„ˆ์Šค ๋ถ€ํ˜ธ ๊นจ์ง ๋ฐฉ์ง€
36
 
37
+ # 3. ๋‰ด์Šค ์š”์•ฝ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜ (์‹ค์ œ API ํ˜ธ์ถœ์€ ๊ตฌํ˜„ ํ•„์š”)
 
 
 
38
  def get_real_news_summary(company, date):
39
+ # ์‹ค์ œ API ํ˜ธ์ถœ ์ฝ”๋“œ๋ฅผ ์—ฌ๊ธฐ์— ๊ตฌํ˜„ํ•˜์„ธ์š”.
40
+ # ์˜ˆ์‹œ๋กœ ๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
41
+ return f"{company}์˜ {date} ์ฃผ๋ณ€ ๋‰ด์Šค ์š”์•ฝ์ž…๋‹ˆ๋‹ค."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  def handle_click(company_name, date_clicked):
44
  return get_real_news_summary(company_name, date_clicked)
45
 
 
46
  def update_news(input_value, selected_date):
47
+ if not selected_date:
48
  return "๋‚ ์งœ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."
49
  else:
 
50
  ticker = name_to_ticker.get(input_value, input_value)
51
  company_name = input_value if ticker == input_value else list(name_to_ticker.keys())[list(name_to_ticker.values()).index(ticker)]
52
  return handle_click(company_name, selected_date)
53
 
54
+ # ์ข…๋ชฉ๋ช…๊ณผ ํ‹ฐ์ปค๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ
55
  name_to_ticker = {
56
  "์‚ผ์„ฑ์ „์ž": "005930.KS",
57
  "SK๋ฐ”์ด์˜คํŒœ": "326030.KS",
 
65
  "๋„ค์ด๋ฒ„": "035420.KS",
66
  "์—์ฝ”ํ”„๋กœ๋น„์— ": "247540.KS",
67
  "์•Œํ…Œ์˜ค์  ": "196170.KQ",
 
68
  "๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„": "AAPL", # Apple
69
  "๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„": "VRTX", # Vertex Pharmaceuticals
70
  "๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„": "LLY", # Eli Lilly
 
72
  "์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„": "196170.KQ", # ๏ฟฝ๏ฟฝํ…Œ์˜ค์  
73
  }
74
 
75
+ # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๊ณ  ๊ทธ๋ž˜ํ”„๋ฅผ ๊ทธ๋ฆฌ๋Š” ํ•จ์ˆ˜
76
  def display_stock_with_highlight(input_value, change_type, percent_change):
77
  try:
 
78
  ticker = name_to_ticker.get(input_value, input_value)
79
  stock = yf.Ticker(ticker)
80
+ stock_data = stock.history(period="5y")
81
 
82
  if stock_data.empty:
83
+ return "์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", gr.Dropdown.update(choices=[])
84
 
85
  stock_data['Change'] = stock_data['Close'].pct_change() * 100
 
86
  percent_change = float(percent_change)
87
 
88
  if change_type == "์ƒ์Šน":
 
92
  highlight_data = stock_data[stock_data['Change'] <= -percent_change]
93
  color = "purple"
94
  else:
95
+ return "Invalid change type", gr.Dropdown.update(choices=[])
96
 
97
+ dates = stock_data.index
98
+ closing_prices = stock_data['Close']
99
 
100
  plt.figure(figsize=(10, 6))
101
  plt.plot(dates, closing_prices, color='gray', label=input_value)
102
  plt.scatter(highlight_data.index, highlight_data['Close'], color=color, label=f'{change_type} ํฌ์ธํŠธ')
103
 
104
  for index, row in highlight_data.iterrows():
105
+ plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=8, color=color, ha='right')
106
+ plt.axvline(x=index, color=color, linestyle='--', linewidth=1)
107
 
 
108
  company_name = list(name_to_ticker.keys())[list(name_to_ticker.values()).index(ticker)]
109
  plt.title(f'{company_name} ์ฃผ๊ฐ€ ์ถ”์ด', fontproperties=font_prop)
110
  plt.xlabel('๋‚ ์งœ', fontproperties=font_prop)
 
119
 
120
  highlight_dates = highlight_data.index.strftime('%Y-%m-%d').tolist()
121
 
122
+ return img, gr.Dropdown.update(choices=highlight_dates)
123
  except Exception as e:
124
+ print(f"Error: {e}")
125
+ return f"๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}", gr.Dropdown.update(choices=[])
126
 
127
+ # Gradio ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ
128
  with gr.Blocks() as demo:
129
  gr.Markdown("## ์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„์™€ ๋‰ด์Šค ์š”์•ฝ")
130
 
131
+ # CSS ์ ์šฉ
132
  demo.css("#news_output_box { background-color: #f0f0f0; padding: 20px; }")
133
 
134
  with gr.Row():
135
+ with gr.Column():
136
  input_value = gr.Textbox(label="์ข…๋ชฉ๋ช… ๋˜๋Š” ํ‹ฐ์ปค ์ž…๋ ฅ", placeholder="์˜ˆ: SK๋ฐ”์ด์˜คํŒœ, AAPL")
137
  change_type = gr.Dropdown(choices=["์ƒ์Šน", "ํ•˜๋ฝ"], label="์ƒ์Šน ๋˜๋Š” ํ•˜๋ฝ ์„ ํƒ", value="์ƒ์Šน")
138
  percent_change = gr.Textbox(label="๋ณ€๋™ ํผ์„ผํŠธ (%)", placeholder="์˜ˆ: 10", value="10")
 
139
  submit_btn = gr.Button("Submit")
140
 
 
141
  examples = [["SK๋ฐ”์ด์˜คํŒœ"],
142
  ["๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„"],
143
  ["๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„"],
 
146
  ["์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„"]]
147
  gr.Examples(examples=examples, inputs=[input_value])
148
 
149
+ with gr.Column():
150
  plot = gr.Image(label="์ฃผ๊ฐ€ ๊ทธ๋ž˜ํ”„")
151
  date_dropdown = gr.Dropdown(label="์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ ์„ ํƒ", choices=[])
152
 
153
+ with gr.Column():
154
  news_output = gr.Markdown(label="๋‰ด์Šค ์š”์•ฝ", value="", elem_id="news_output_box")
155
 
156
+ # ์ด๋ฒคํŠธ ์—ฐ๊ฒฐ
157
  submit_btn.click(
158
  fn=display_stock_with_highlight,
159
  inputs=[input_value, change_type, percent_change],
160
  outputs=[plot, date_dropdown]
161
  )
162
 
 
163
  date_dropdown.change(
164
  fn=update_news,
165
  inputs=[input_value, date_dropdown],
166
  outputs=[news_output]
167
  )
168
 
169
+ # Gradio ์•ฑ ์‹คํ–‰
170
  demo.launch()