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")
|