Commit
5e70a47
ยท
verified ยท
1 Parent(s): af28bec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +24 -127
app.py CHANGED
@@ -1,142 +1,43 @@
 
1
  import subprocess
2
-
3
- # ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐ ์—…๋ฐ์ดํŠธ
4
- subprocess.run(["pip", "install", "--upgrade", "pip"])
5
- subprocess.run(["pip", "install", "--upgrade", "openai", "yfinance", "gradio", "matplotlib", "Pillow"])
6
-
7
- import os
8
  import matplotlib.font_manager as fm
9
  import matplotlib.pyplot as plt
10
- import yfinance as yf
11
- import numpy as np
12
- import re # ํ•œ๊ธ€, ์ˆซ์ž, ๊ธฐํ˜ธ๋ฅผ ๋‚จ๊ธฐ๊ธฐ ์œ„ํ•œ ์ •๊ทœ ํ‘œํ˜„์‹์— ์‚ฌ์šฉ
13
  import gradio as gr
14
  import io
15
  from PIL import Image
16
  from datetime import datetime, timedelta
17
- from openai import OpenAI
18
-
19
- # 1. ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ์„ค์น˜ ๋ฐ ์ ์šฉ
20
- def install_nanum_font():
21
- try:
22
- subprocess.run(["apt-get", "update"], check=True)
23
- subprocess.run(["apt-get", "install", "-y", "fonts-nanum"], check=True)
24
- subprocess.run(["fc-cache", "-fv"], check=True)
25
- except Exception as e:
26
- print(f"ํฐํŠธ ์„ค์น˜ ์ค‘ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {e}")
27
-
28
- install_nanum_font()
29
-
30
- # ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ๊ฒฝ๋กœ ์„ค์ • ๋ฐ ๊ฐ•์ œ ์ ์šฉ
31
- font_path = '/usr/share/fonts/truetype/nanum/NanumGothic.ttf'
32
-
33
- if os.path.exists(font_path):
34
- fm.fontManager.addfont(font_path)
35
- else:
36
- print("ํฐํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
37
-
38
- # ๋‚˜๋ˆ”๊ณ ๋”• ํฐํŠธ ๊ฐ•์ œ ์ ์šฉ
39
- font_prop = fm.FontProperties(fname=font_path)
40
- plt.rcParams['font.family'] = font_prop.get_name()
41
- plt.rcParams['axes.unicode_minus'] = False # ๋งˆ์ด๋„ˆ์Šค ๋ถ€ํ˜ธ ๊นจ์ง ๋ฐฉ์ง€
42
-
43
- # 2. yfinance๋กœ ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ (์‚ผ์„ฑ์ „์ž ์˜ˆ์‹œ)
44
- ticker = '005930.KS' # ์‚ผ์„ฑ์ „์ž ํ‹ฐ์ปค
45
- stock = yf.Ticker(ticker)
46
- stock_data = stock.history(period="max")
47
-
48
- # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ ์ถœ๋ ฅ ํ™•์ธ
49
- print(stock_data.head()) # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ ์ผ๋ถ€ ํ™•์ธ
50
-
51
- # 3. ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™” (pandas ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์„ numpy ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ฒ˜๋ฆฌ)
52
- plt.figure(figsize=(10, 6))
53
-
54
- # ์ธ๋ฑ์Šค์™€ ์ข…๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ numpy ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜
55
- dates = stock_data.index.to_numpy()
56
- closing_prices = stock_data['Close'].to_numpy()
57
-
58
- # ์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ ์‹œ๊ฐํ™”
59
- plt.plot(dates, closing_prices, label='์‚ผ์„ฑ์ „์ž ์ข…๊ฐ€')
60
-
61
- # ๊ทธ๋ž˜ํ”„ ์ œ๋ชฉ, ์ถ• ๋ผ๋ฒจ์„ ํ•œ๊ธ€๋กœ ์„ค์ •
62
- plt.title('์‚ผ์„ฑ์ „์ž ์ฃผ๊ฐ€ ์ถ”์ด', fontproperties=font_prop)
63
- plt.xlabel('๋‚ ์งœ', fontproperties=font_prop)
64
- plt.ylabel('์ข…๊ฐ€', fontproperties=font_prop)
65
- plt.legend(prop=font_prop)
66
 
67
- # B ์ฝ”๋“œ
 
 
68
 
69
  # Perplexity AI API ์„ค์ •
70
  API_KEY = "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" # ์—ฌ๊ธฐ์— Perplexity AI API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.
71
 
72
- # ๋‰ด์Šค ์š”์•ฝ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
73
- def get_real_news_summary(company, date):
74
- # OpenAI ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
75
- client = OpenAI(api_key=API_KEY, base_url="https://api.perplexity.ai")
76
-
77
- # ๋‚ ์งœ ํ˜•์‹์„ ๋งž์ถฐ์ฃผ๊ธฐ ์œ„ํ•œ ์ฒ˜๋ฆฌ
78
- target_date = datetime.strptime(date, '%Y-%m-%d')
79
- start_date = (target_date - timedelta(days=1)).strftime('%Y-%m-%d')
80
- end_date = (target_date + timedelta(days=1)).strftime('%Y-%m-%d')
81
-
82
- # API ์š”์ฒญ์„ ์œ„ํ•œ ๋ฉ”์‹œ์ง€ ๊ตฌ์„ฑ - ํ•œ๊ตญ์–ด๋กœ๋งŒ ์‘๋‹ต์„ ๋ฐ›๋„๋ก ์ง€์‹œ
83
- messages = [
84
- {"role": "system", "content": "You are a helpful assistant that summarizes stock news strictly in Korean."},
85
- {"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."}
86
- ]
87
-
88
- try:
89
- # API ์š”์ฒญ
90
- response = client.chat.completions.create(
91
- model="llama-3.1-sonar-large-128k-online",
92
- messages=messages
93
- )
94
-
95
- # ์‘๋‹ต์—์„œ ์š”์•ฝ ์ถ”์ถœ
96
- summary = response.choices[0].message.content
97
 
98
- # ํ•œ๊ธ€, ์ˆซ์ž, ๊ณต๋ฐฑ, ํŠน์ˆ˜ ๊ธฐํ˜ธ๋งŒ ๋‚จ๊ธฐ๋Š” ์ •๊ทœ ํ‘œํ˜„์‹
99
- korean_only_summary = re.sub(r'[^\w\s#.,!%()\-\[\]]', '', summary)
 
 
100
 
101
- # ##๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ถ€๋ถ„์„ **์œผ๋กœ ๊ฐ์‹ธ์„œ Bold ์ฒ˜๋ฆฌ
102
- formatted_summary = re.sub(r'##\s*(.+)', r'**\1**', korean_only_summary)
 
103
 
104
- return formatted_summary
105
- except Exception as e:
106
- return f"๋‰ด์Šค ์š”์•ฝ ์ค‘ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค: {str(e)}"
107
-
108
- # ๋‰ด์Šค ์š”์•ฝ์„ ๊ฐ€์ ธ์˜ค๋Š” ํ•จ์ˆ˜
109
- def handle_click(company_name, date_clicked):
110
- return get_real_news_summary(company_name, date_clicked)
111
-
112
- # Gradio์—์„œ ์‚ฌ์šฉํ•  ํ•จ์ˆ˜ (๋‰ด์Šค ์š”์•ฝ ํฌํ•จ)
113
- def update_news(input_value, selected_date):
114
- if selected_date == "" or selected_date is None:
115
- return "๋‚ ์งœ๋ฅผ ์„ ํƒํ•ด์ฃผ์„ธ์š”."
116
- else:
117
- # ์ข…๋ชฉ๋ช…์„ ๊ฐ€์ ธ์™€์„œ Perplexity๋กœ ๊ฒ€์ƒ‰
118
- ticker = name_to_ticker.get(input_value, input_value)
119
- company_name = input_value if ticker == input_value else list(name_to_ticker.keys())[list(name_to_ticker.values()).index(ticker)]
120
- return handle_click(company_name, selected_date)
121
 
122
  # ์ข…๋ชฉ๋ช…๊ณผ ํ‹ฐ์ปค๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ ํ™•์žฅ ๋ฐ ์กฐ๊ฑด๋ณ„ ์ข…๋ชฉ ๋งคํ•‘
123
  name_to_ticker = {
124
- "์‚ผ์„ฑ์ „์ž": "005930.KS",
125
- "SK๋ฐ”์ด์˜คํŒœ": "326030.KS",
126
- "Apple": "AAPL",
127
- "Nvidia": "NVDA",
128
- "Vertex": "VRTX",
129
- "ํ˜„๋Œ€์ฐจ": "005380.KS",
130
- "์นด์นด์˜ค": "035720.KS",
131
- "LGํ™”ํ•™": "051910.KS",
132
- "์…€ํŠธ๋ฆฌ์˜จ": "068270.KS",
133
- "๋„ค์ด๋ฒ„": "035420.KS",
134
- "์—์ฝ”ํ”„๋กœ๋น„์— ": "247540.KS",
135
- "์•Œํ…Œ์˜ค์  ": "196170.KQ",
136
- # ์ตœ์‹  ์‹œ๊ฐ€์ด์•ก ์ƒ์œ„ ์ข…๋ชฉ์„ ๋ฐ˜์˜ํ•˜์—ฌ ์—…๋ฐ์ดํŠธ
137
  "๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„": "AAPL", # Apple
138
  "๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„": "VRTX", # Vertex Pharmaceuticals
139
- "๋‚˜์Šค๋‹ฅ ์ œ์•ฝ์ฃผ ์‹œ์ด 1์œ„": "VRTX", # Vertex Pharmaceuticals
140
  "์ฝ”์Šคํ”ผ ์‹œ์ด 1์œ„": "005930.KS", # ์‚ผ์„ฑ์ „์ž
141
  "์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„": "196170.KQ", # ์•Œํ…Œ์˜ค์  
142
  }
@@ -153,7 +54,6 @@ def display_stock_with_highlight(input_value, change_type, percent_change):
153
  return "์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", []
154
 
155
  stock_data['Change'] = stock_data['Close'].pct_change() * 100
156
-
157
  percent_change = float(percent_change)
158
 
159
  if change_type == "์ƒ์Šน":
@@ -176,11 +76,9 @@ def display_stock_with_highlight(input_value, change_type, percent_change):
176
  plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=10, fontweight='bold', color=color, ha='right')
177
  plt.axvline(x=index, color=color, linestyle='--', linewidth=1) # x์ถ•๊ณผ์˜ ์—ฐ๊ฒฐ์„  ์ ์„ ์œผ๋กœ ํ‘œ์‹œ
178
 
179
- # ์ข…๋ชฉ๋ช… + '์ฃผ๊ฐ€ ์ถ”์ด'๋กœ ์ œ๋ชฉ ์„ค์ • (์ข…๋ชฉ๋ช… ๊ธฐ๋ฐ˜)
180
- company_name = list(name_to_ticker.keys())[list(name_to_ticker.values()).index(ticker)]
181
- plt.title(f'{company_name} ์ฃผ๊ฐ€ ์ถ”์ด', fontproperties=font_prop)
182
- plt.xlabel('๋‚ ์งœ', fontproperties=font_prop)
183
- plt.ylabel('์ข…๊ฐ€', fontproperties=font_prop)
184
  plt.legend()
185
 
186
  buf = io.BytesIO()
@@ -210,8 +108,8 @@ with gr.Blocks() as demo:
210
  # ์˜ˆ์ œ (์ด์ „ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ๋ณต์›)
211
  examples = [["SK๋ฐ”์ด์˜คํŒœ"],
212
  ["๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„"],
213
- ["๋‚˜์Šค๋‹ฅ ์ œ์•ฝ์ฃผ ์‹œ์ด 1์œ„"],
214
  ["๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„"],
 
215
  ["์ฝ”์Šคํ”ผ ์‹œ์ด 1์œ„"],
216
  ["์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„"]]
217
  gr.Examples(examples=examples, inputs=[input_value])
@@ -221,7 +119,6 @@ with gr.Blocks() as demo:
221
  date_dropdown = gr.Dropdown(label="์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ ์„ ํƒ", choices=[])
222
 
223
  with gr.Column(): # ๋‰ด์Šค ์š”์•ฝ์„ ์ถœ๋ ฅํ•  ์„ธ ๋ฒˆ์งธ ์—ด
224
- # news_output์„ gr.Markdown์œผ๋กœ ๋ณ€๊ฒฝ
225
  news_output = gr.Markdown(label="๋‰ด์Šค ์š”์•ฝ", value="") # ๋นˆ ์นธ์œผ๋กœ ๊ธฐ๋ณธ ํ‘œ์‹œ
226
 
227
  # Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๊ทธ๋ž˜ํ”„ ๋ฐ ๋‚ ์งœ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ
 
1
+ import yfinance as yf
2
  import subprocess
 
 
 
 
 
 
3
  import matplotlib.font_manager as fm
4
  import matplotlib.pyplot as plt
 
 
 
5
  import gradio as gr
6
  import io
7
  from PIL import Image
8
  from datetime import datetime, timedelta
9
+ import os
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ # ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ๋ฐ ์—…๋ฐ์ดํŠธ
12
+ subprocess.run(["pip", "install", "--upgrade", "pip"])
13
+ subprocess.run(["pip", "install", "--upgrade", "openai", "yfinance", "gradio", "matplotlib", "Pillow"])
14
 
15
  # Perplexity AI API ์„ค์ •
16
  API_KEY = "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" # ์—ฌ๊ธฐ์— Perplexity AI API ํ‚ค๋ฅผ ์ž…๋ ฅํ•˜์„ธ์š”.
17
 
18
+ # yfinance๋กœ ๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„ ์ข…๋ชฉ ๊ฐ€์ ธ์˜ค๊ธฐ
19
+ def get_nasdaq_healthcare_leader():
20
+ # ํ—ฌ์Šค์ผ€์–ด ์„นํ„ฐ ์ƒ์œ„ ๊ธฐ์—…๋“ค์„ ๊ฐ€์ ธ์˜ด
21
+ healthcare_tickers = ["JNJ", "PFE", "MRNA", "VRTX", "AMGN"] # ์˜ˆ์‹œ๋กœ ๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์ƒ์œ„ ํ‹ฐ์ปค๋“ค
22
+ largest_market_cap = 0
23
+ leader_ticker = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
 
25
+ for ticker in healthcare_tickers:
26
+ stock = yf.Ticker(ticker)
27
+ stock_data = stock.history(period="1d") # ์ „์ผ ์ข…๊ฐ€ ๊ธฐ์ค€
28
+ market_cap = stock.info.get('marketCap', 0)
29
 
30
+ if market_cap > largest_market_cap:
31
+ largest_market_cap = market_cap
32
+ leader_ticker = ticker
33
 
34
+ return leader_ticker
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
 
36
  # ์ข…๋ชฉ๋ช…๊ณผ ํ‹ฐ์ปค๋ฅผ ๋งคํ•‘ํ•˜๋Š” ๋”•์…”๋„ˆ๋ฆฌ ํ™•์žฅ ๋ฐ ์กฐ๊ฑด๋ณ„ ์ข…๋ชฉ ๋งคํ•‘
37
  name_to_ticker = {
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  "๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„": "AAPL", # Apple
39
  "๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„": "VRTX", # Vertex Pharmaceuticals
40
+ "๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„": get_nasdaq_healthcare_leader(), # yfinance๋กœ ๋™์ ์œผ๋กœ ์„ค์ •
41
  "์ฝ”์Šคํ”ผ ์‹œ์ด 1์œ„": "005930.KS", # ์‚ผ์„ฑ์ „์ž
42
  "์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„": "196170.KQ", # ์•Œํ…Œ์˜ค์  
43
  }
 
54
  return "์ฃผ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", []
55
 
56
  stock_data['Change'] = stock_data['Close'].pct_change() * 100
 
57
  percent_change = float(percent_change)
58
 
59
  if change_type == "์ƒ์Šน":
 
76
  plt.text(index, row['Close'], index.strftime('%Y-%m-%d'), fontsize=10, fontweight='bold', color=color, ha='right')
77
  plt.axvline(x=index, color=color, linestyle='--', linewidth=1) # x์ถ•๊ณผ์˜ ์—ฐ๊ฒฐ์„  ์ ์„ ์œผ๋กœ ํ‘œ์‹œ
78
 
79
+ plt.title(f'{input_value} ์ฃผ๊ฐ€ ์ถ”์ด')
80
+ plt.xlabel('๋‚ ์งœ')
81
+ plt.ylabel('์ข…๊ฐ€')
 
 
82
  plt.legend()
83
 
84
  buf = io.BytesIO()
 
108
  # ์˜ˆ์ œ (์ด์ „ ๋ ˆ์ด์•„์›ƒ์œผ๋กœ ๋ณต์›)
109
  examples = [["SK๋ฐ”์ด์˜คํŒœ"],
110
  ["๋‚˜์Šค๋‹ฅ ์‹œ์ด 1์œ„"],
 
111
  ["๋‚˜์Šค๋‹ฅ ๋ฐ”์ด์˜คํ… ์‹œ์ด 1์œ„"],
112
+ ["๋‚˜์Šค๋‹ฅ ํ—ฌ์Šค์ผ€์–ด ์‹œ์ด 1์œ„"], # ์ˆ˜์ •๋œ ์˜ˆ์ œ
113
  ["์ฝ”์Šคํ”ผ ์‹œ์ด 1์œ„"],
114
  ["์ฝ”์Šค๋‹ฅ ์‹œ์ด 1์œ„"]]
115
  gr.Examples(examples=examples, inputs=[input_value])
 
119
  date_dropdown = gr.Dropdown(label="์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๋‚ ์งœ ์„ ํƒ", choices=[])
120
 
121
  with gr.Column(): # ๋‰ด์Šค ์š”์•ฝ์„ ์ถœ๋ ฅํ•  ์„ธ ๋ฒˆ์งธ ์—ด
 
122
  news_output = gr.Markdown(label="๋‰ด์Šค ์š”์•ฝ", value="") # ๋นˆ ์นธ์œผ๋กœ ๊ธฐ๋ณธ ํ‘œ์‹œ
123
 
124
  # Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๊ทธ๋ž˜ํ”„ ๋ฐ ๋‚ ์งœ ๋“œ๋กญ๋‹ค์šด ์—…๋ฐ์ดํŠธ