llllllllllllllllllllllllllleeeeeeeeeeeeee
commited on
Commit
β’
97a16e9
1
Parent(s):
1ccfa39
Create app.py
Browse files
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()
|