Update app.py
Browse files
app.py
CHANGED
@@ -8,6 +8,7 @@ from GoogleNews import GoogleNews
|
|
8 |
from transformers import pipeline
|
9 |
from datetime import datetime, timedelta
|
10 |
import matplotlib
|
|
|
11 |
matplotlib.use('Agg')
|
12 |
|
13 |
# Set up logging
|
@@ -26,6 +27,24 @@ sentiment_analyzer = pipeline(
|
|
26 |
)
|
27 |
logging.info("Model initialized successfully")
|
28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
def fetch_articles(query, max_articles=30):
|
30 |
try:
|
31 |
logging.info(f"Fetching up to {max_articles} articles for query: '{query}'")
|
@@ -144,6 +163,84 @@ def calculate_sentiment_score(sentiment_label, time_weight):
|
|
144 |
|
145 |
return base_score, weighted_addition
|
146 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
147 |
def analyze_asset_sentiment(asset_name):
|
148 |
logging.info(f"Starting sentiment analysis for asset: {asset_name}")
|
149 |
logging.info("Fetching up to 30 articles")
|
@@ -168,7 +265,14 @@ def analyze_asset_sentiment(asset_name):
|
|
168 |
# ์ข
ํฉ ์ ์ ๊ณ์ฐ ๋ฐ ๊ทธ๋ํ ์์ฑ
|
169 |
sentiment_summary = create_sentiment_summary(analyzed_articles, asset_name)
|
170 |
|
171 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
172 |
|
173 |
def create_sentiment_summary(analyzed_articles, asset_name):
|
174 |
"""
|
@@ -293,6 +397,15 @@ with gr.Blocks() as iface:
|
|
293 |
inputs=input_asset,
|
294 |
)
|
295 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
296 |
with gr.Row():
|
297 |
with gr.Column():
|
298 |
with gr.Blocks():
|
@@ -312,7 +425,7 @@ with gr.Blocks() as iface:
|
|
312 |
analyze_button.click(
|
313 |
analyze_asset_sentiment,
|
314 |
inputs=[input_asset],
|
315 |
-
outputs=[articles_output, sentiment_summary],
|
316 |
)
|
317 |
|
318 |
logging.info("Launching Gradio interface")
|
|
|
8 |
from transformers import pipeline
|
9 |
from datetime import datetime, timedelta
|
10 |
import matplotlib
|
11 |
+
import yfinance as yf
|
12 |
matplotlib.use('Agg')
|
13 |
|
14 |
# Set up logging
|
|
|
27 |
)
|
28 |
logging.info("Model initialized successfully")
|
29 |
|
30 |
+
# ์์ฅ ์ข
๋ชฉ ์ฌ๋ณผ ๋งคํ์ ์ํ ์ผ๋ฐ์ ์ธ ์ข
๋ชฉ๋ช
์ฌ์ (ํ์์ ๋ฐ๋ผ ํ์ฅ)
|
31 |
+
COMMON_TICKERS = {
|
32 |
+
"apple": "AAPL",
|
33 |
+
"microsoft": "MSFT",
|
34 |
+
"amazon": "AMZN",
|
35 |
+
"google": "GOOGL",
|
36 |
+
"alphabet": "GOOGL",
|
37 |
+
"facebook": "META",
|
38 |
+
"meta": "META",
|
39 |
+
"tesla": "TSLA",
|
40 |
+
"nvidia": "NVDA",
|
41 |
+
"bitcoin": "BTC-USD",
|
42 |
+
"ethereum": "ETH-USD",
|
43 |
+
"samsung": "005930.KS", # ํ๊ตญ ์ผ์ฑ์ ์
|
44 |
+
"hyundai": "005380.KS", # ํ๋์๋์ฐจ
|
45 |
+
"sk hynix": "000660.KS", # SKํ์ด๋์ค
|
46 |
+
}
|
47 |
+
|
48 |
def fetch_articles(query, max_articles=30):
|
49 |
try:
|
50 |
logging.info(f"Fetching up to {max_articles} articles for query: '{query}'")
|
|
|
163 |
|
164 |
return base_score, weighted_addition
|
165 |
|
166 |
+
def get_stock_ticker(asset_name):
|
167 |
+
"""
|
168 |
+
์์ฐ๋ช
์ผ๋ก๋ถํฐ ์ฃผ์ ํฐ์ปค ์ฌ๋ณผ์ ์ถ์ถ
|
169 |
+
"""
|
170 |
+
# ์๋ฌธ์๋ก ๋ณํํ์ฌ ๋งคํ ํ์ธ
|
171 |
+
asset_lower = asset_name.lower()
|
172 |
+
|
173 |
+
# ์ง์ ํฐ์ปค๋ก ์
๋ ฅํ ๊ฒฝ์ฐ (๋๋ฌธ์ 3-5์ ํํ)
|
174 |
+
if asset_name.isupper() and 3 <= len(asset_name) <= 5:
|
175 |
+
return asset_name
|
176 |
+
|
177 |
+
# ์ผ๋ฐ์ ์ธ ์ข
๋ชฉ๋ช
๋งคํ ํ์ธ
|
178 |
+
if asset_lower in COMMON_TICKERS:
|
179 |
+
return COMMON_TICKERS[asset_lower]
|
180 |
+
|
181 |
+
# ๊ทธ ์ธ์ ๊ฒฝ์ฐ yfinance๋ก ๊ฒ์ ์๋
|
182 |
+
try:
|
183 |
+
ticker_search = yf.Ticker(asset_name)
|
184 |
+
# ๊ธฐ๋ณธ ์ ๋ณด ๊ฐ์ ธ์์ ์ ํจํ ํฐ์ปค์ธ์ง ํ์ธ
|
185 |
+
info = ticker_search.info
|
186 |
+
if 'symbol' in info:
|
187 |
+
return info['symbol']
|
188 |
+
except:
|
189 |
+
pass
|
190 |
+
|
191 |
+
return None
|
192 |
+
|
193 |
+
def create_stock_chart(ticker, period="1mo"):
|
194 |
+
"""
|
195 |
+
์ฃผ์ ํฐ์ปค์ ๋ํ ์ฐจํธ ์์ฑ
|
196 |
+
"""
|
197 |
+
try:
|
198 |
+
logging.info(f"Fetching stock data for {ticker}")
|
199 |
+
stock_data = yf.download(ticker, period=period)
|
200 |
+
|
201 |
+
if stock_data.empty:
|
202 |
+
logging.warning(f"No stock data found for ticker: {ticker}")
|
203 |
+
return None
|
204 |
+
|
205 |
+
fig, ax = plt.subplots(figsize=(10, 6))
|
206 |
+
|
207 |
+
# ์ข
๊ฐ ๊ทธ๋ํ
|
208 |
+
ax.plot(stock_data.index, stock_data['Close'], label='Close Price', color='blue')
|
209 |
+
|
210 |
+
# ์ด๋ํ๊ท ์ ์ถ๊ฐ (20์ผ)
|
211 |
+
if len(stock_data) > 20:
|
212 |
+
stock_data['MA20'] = stock_data['Close'].rolling(window=20).mean()
|
213 |
+
ax.plot(stock_data.index, stock_data['MA20'], label='20-day MA', color='orange')
|
214 |
+
|
215 |
+
# ๊ฑฐ๋๋ ์๋ธํ๋กฏ ์ถ๊ฐ
|
216 |
+
ax2 = ax.twinx()
|
217 |
+
ax2.bar(stock_data.index, stock_data['Volume'], alpha=0.3, color='gray', label='Volume')
|
218 |
+
ax2.set_ylabel('Volume')
|
219 |
+
|
220 |
+
# ์ฐจํธ ์คํ์ผ๋ง
|
221 |
+
ax.set_title(f"{ticker} Stock Price")
|
222 |
+
ax.set_xlabel('Date')
|
223 |
+
ax.set_ylabel('Price')
|
224 |
+
ax.grid(True, alpha=0.3)
|
225 |
+
|
226 |
+
# ๋ฒ๋ก ์ถ๊ฐ
|
227 |
+
lines, labels = ax.get_legend_handles_labels()
|
228 |
+
lines2, labels2 = ax2.get_legend_handles_labels()
|
229 |
+
ax.legend(lines + lines2, labels + labels2, loc='upper left')
|
230 |
+
|
231 |
+
plt.tight_layout()
|
232 |
+
|
233 |
+
# ์ด๋ฏธ์ง ์ ์ฅ
|
234 |
+
chart_path = f"stock_chart_{ticker.replace('-', '_')}.png"
|
235 |
+
plt.savefig(chart_path)
|
236 |
+
plt.close()
|
237 |
+
|
238 |
+
logging.info(f"Stock chart created: {chart_path}")
|
239 |
+
return chart_path
|
240 |
+
except Exception as e:
|
241 |
+
logging.error(f"Error creating stock chart for {ticker}: {e}")
|
242 |
+
return None
|
243 |
+
|
244 |
def analyze_asset_sentiment(asset_name):
|
245 |
logging.info(f"Starting sentiment analysis for asset: {asset_name}")
|
246 |
logging.info("Fetching up to 30 articles")
|
|
|
265 |
# ์ข
ํฉ ์ ์ ๊ณ์ฐ ๋ฐ ๊ทธ๋ํ ์์ฑ
|
266 |
sentiment_summary = create_sentiment_summary(analyzed_articles, asset_name)
|
267 |
|
268 |
+
# ์ฃผ์ ํฐ์ปค ํ์ธ ๋ฐ ์ฐจํธ ์์ฑ
|
269 |
+
stock_chart = None
|
270 |
+
ticker = get_stock_ticker(asset_name)
|
271 |
+
if ticker:
|
272 |
+
logging.info(f"Found ticker {ticker} for asset {asset_name}")
|
273 |
+
stock_chart = create_stock_chart(ticker)
|
274 |
+
|
275 |
+
return convert_to_dataframe(analyzed_articles), sentiment_summary, stock_chart, ticker
|
276 |
|
277 |
def create_sentiment_summary(analyzed_articles, asset_name):
|
278 |
"""
|
|
|
397 |
inputs=input_asset,
|
398 |
)
|
399 |
|
400 |
+
# ์ฃผ์ ์ฐจํธ ์์ญ ์ถ๊ฐ
|
401 |
+
with gr.Row():
|
402 |
+
with gr.Column():
|
403 |
+
with gr.Blocks():
|
404 |
+
gr.Markdown("## Stock Chart")
|
405 |
+
with gr.Row():
|
406 |
+
stock_chart = gr.Image(type="filepath", label="Stock Price Chart")
|
407 |
+
ticker_info = gr.Textbox(label="Ticker Symbol")
|
408 |
+
|
409 |
with gr.Row():
|
410 |
with gr.Column():
|
411 |
with gr.Blocks():
|
|
|
425 |
analyze_button.click(
|
426 |
analyze_asset_sentiment,
|
427 |
inputs=[input_asset],
|
428 |
+
outputs=[articles_output, sentiment_summary, stock_chart, ticker_info],
|
429 |
)
|
430 |
|
431 |
logging.info("Launching Gradio interface")
|