Toymakerftw commited on
Commit
e69a18d
·
1 Parent(s): 99c5ed6

initial readme

Browse files
Files changed (4) hide show
  1. .gitattributes +35 -0
  2. README.md +13 -0
  3. app.py +118 -159
  4. requirements.txt +6 -6
.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Trading Analyst
3
+ emoji: 📈
4
+ colorFrom: green
5
+ colorTo: red
6
+ sdk: gradio
7
+ sdk_version: 4.39.0
8
+ app_file: app.py
9
+ pinned: false
10
+ license: mit
11
+ ---
12
+
13
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -1,173 +1,132 @@
 
 
1
  import gradio as gr
2
- from yfinance import Ticker
3
  import pandas as pd
4
- import numpy as np
5
- import matplotlib.pyplot as plt
6
- import talib
7
- from datetime import datetime, timedelta
8
 
9
- def fetch_stock_data(symbol):
10
- """Fetch historical data for the given stock symbol."""
11
- try:
12
- ticker = Ticker(symbol)
13
- historical_data = ticker.history(period="1mo")
14
- return historical_data
15
- except Exception as e:
16
- return None
17
-
18
- def calculate_indicators(data):
19
- """Calculate technical indicators like RSI, MACD, etc."""
20
- if data is None:
21
- return None
22
-
23
- # Calculate RSI
24
- data['RSI'] = talib.RSI(data['Close'], timeperiod=14)
25
-
26
- # Calculate MACD
27
- macd, macd_signal, macd_hist = talib.MACD(data['Close'])
28
- data['MACD'] = macd
29
- data['MACD_Signal'] = macd_signal
30
-
31
- return data
32
-
33
- def generate_recommendation(data):
34
- """Generate buy/sell recommendations based on indicators."""
35
- if data is None:
36
- return "Insufficient data"
37
-
38
- rsi = data['RSI'].iloc[-1]
39
- macd = data['MACD'].iloc[-1]
40
- macd_signal = data['MACD_Signal'].iloc[-1]
41
-
42
- if rsi < 30 and macd > macd_signal:
43
- return " BUY RECOMMENDATION: Stock is oversold and trending upward."
44
- elif rsi > 70 and macd < macd_signal:
45
- return " SELL RECOMMENDATION: Stock is overbought and trending downward."
46
- else:
47
- return "HOLD: No strong signal at this time."
48
-
49
- def plot_stock_data(data):
50
- """Plot stock price and indicators."""
51
- plt.figure(figsize=(10, 6))
52
-
53
- # Plot closing prices
54
- plt.plot(data['Close'], label='Close Price')
55
-
56
- # Plot RSI
57
- ax = plt.twinx()
58
- ax.plot(data['RSI'], color='red', label='RSI')
59
- ax.axhline(30, color='r', linestyle='--')
60
- ax.axhline(70, color='r', linestyle='--')
61
-
62
- # Add MACD
63
- plt.figure(figsize=(10, 6))
64
- plt.plot(data['MACD'], label='MACD')
65
- plt.plot(data['MACD_Signal'], label='MACD Signal')
66
- plt.fill_between(data.index, data['MACD_hist'], color='gray', alpha=0.2, label='MACD Histogram')
67
- plt.legend()
68
-
69
- plt.title(f"Stock Analysis for {symbol}")
70
- plt.xlabel("Date")
71
- plt.ylabel("Price")
72
- plt.legend()
73
- plt.grid(True)
74
-
75
- return plt
76
-
77
- def news_updates(symbol):
78
- """Fetch recent news articles for the stock."""
79
- try:
80
- news = Ticker(symbol).news
81
- articles = []
82
- for article in news:
83
- articles.append({
84
- 'Title': article['title'],
85
- 'Publish Date': article['publishDate'],
86
- 'URL': article['url']
87
- })
88
- return pd.DataFrame(articles)
89
- except Exception as e:
90
- return pd.DataFrame(columns=['Title', 'Publish Date', 'URL'])
91
-
92
- def main(symbol):
93
- """Main function to process stock symbol and generate output."""
94
- # Fetch real-time price and historical data
95
- real_time = Ticker(symbol).info
96
- price = real_time['regularMarketPrice']
97
- change = real_time['regularMarketChangePercent']
98
-
99
- # Fetch and process historical data
100
- historical_data = fetch_stock_data(symbol)
101
- if historical_data is None:
102
- return "Error: Could not fetch data for the symbol."
103
-
104
- data = calculate_indicators(historical_data)
105
-
106
- # Generate analysis
107
- analysis = generate_recommendation(data)
108
-
109
- # Plot visualization
110
- fig = plot_stock_data(data)
111
-
112
- # Fetch news
113
- news_df = news_updates(symbol)
114
-
115
- return {
116
- 'Price Analysis': pd.DataFrame([{
117
- 'Current Price': f'${price:.2f}',
118
- '24h Change': f'{change:.2f}%',
119
- 'Recommendation': analysis
120
- }]),
121
- 'Historical Data': data[['Close', 'RSI', 'MACD', 'MACD_Signal']],
122
- 'Visualizations': fig,
123
- 'Latest News': news_df
124
- }
125
-
126
- def interface(symbol):
127
- """Gradio interface implementation."""
128
  try:
129
- analysis = main(symbol.strip())
130
-
131
- with gr.Blocks():
132
- gr.Markdown(f"### Stock Analysis for {symbol}")
133
- gr.Dataframe(analysis['Price Analysis'])
134
- gr.Plot(analysis['Visualizations'])
135
- if not analysis['Latest News'].empty:
136
- gr.Markdown("#### Latest News Updates")
137
- gr.Dataframe(analysis['Latest News'], max_rows=5)
138
  except Exception as e:
139
- return f"Error: {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
- # Gradio Interface Setup
142
  with gr.Blocks() as iface:
143
- gr.Markdown("# Stock Analysis Tool")
144
- gr.Markdown("Enter a stock symbol (e.g., TSLA, AAPL, etc.)")
145
-
 
 
146
  with gr.Row():
147
- stock_input = gr.Textbox(
148
- label="Stock Symbol",
149
  lines=1,
150
- placeholder="Enter stock symbol..."
151
  )
152
- analyze_button = gr.Button("Analyze", variant="primary")
153
-
154
  with gr.Row():
155
- gr.Examples(
156
- examples=[
157
- "TSLA", "AAPL", "MSFT", "GOOGL", "AMZN"
158
- ],
159
- inputs=stock_input
160
- )
161
-
162
- analysis_output = gr.Textbox(label="Analysis")
163
-
164
- # Connect the button to the interface function
 
 
 
 
 
 
 
 
 
 
 
 
165
  analyze_button.click(
166
- fn=interface,
167
- inputs=[stock_input],
168
- outputs=[analysis_output]
169
  )
170
 
171
- # Launch the Gradio interface
172
- if __name__ == "__main__":
173
- iface.launch()
 
1
+ import logging
2
+
3
  import gradio as gr
 
4
  import pandas as pd
5
+ import torch
6
+ from GoogleNews import GoogleNews
7
+ from transformers import pipeline
 
8
 
9
+ # Set up logging
10
+ logging.basicConfig(
11
+ level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
12
+ )
13
+
14
+ SENTIMENT_ANALYSIS_MODEL = (
15
+ "mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis"
16
+ )
17
+
18
+ DEVICE = "cuda" if torch.cuda.is_available() else "cpu"
19
+ logging.info(f"Using device: {DEVICE}")
20
+
21
+ logging.info("Initializing sentiment analysis model...")
22
+ sentiment_analyzer = pipeline(
23
+ "sentiment-analysis", model=SENTIMENT_ANALYSIS_MODEL, device=DEVICE
24
+ )
25
+ logging.info("Model initialized successfully")
26
+
27
+
28
+ def fetch_articles(query):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  try:
30
+ logging.info(f"Fetching articles for query: '{query}'")
31
+ googlenews = GoogleNews(lang="en")
32
+ googlenews.search(query)
33
+ articles = googlenews.result()
34
+ logging.info(f"Fetched {len(articles)} articles")
35
+ return articles
 
 
 
36
  except Exception as e:
37
+ logging.error(
38
+ f"Error while searching articles for query: '{query}'. Error: {e}"
39
+ )
40
+ raise gr.Error(
41
+ f"Unable to search articles for query: '{query}'. Try again later...",
42
+ duration=5,
43
+ )
44
+
45
+
46
+ def analyze_article_sentiment(article):
47
+ logging.info(f"Analyzing sentiment for article: {article['title']}")
48
+ sentiment = sentiment_analyzer(article["desc"])[0]
49
+ article["sentiment"] = sentiment
50
+ return article
51
+
52
+
53
+ def analyze_asset_sentiment(asset_name):
54
+ logging.info(f"Starting sentiment analysis for asset: {asset_name}")
55
+
56
+ logging.info("Fetching articles")
57
+ articles = fetch_articles(asset_name)
58
+
59
+ logging.info("Analyzing sentiment of each article")
60
+ analyzed_articles = [analyze_article_sentiment(article) for article in articles]
61
+
62
+ logging.info("Sentiment analysis completed")
63
+
64
+ return convert_to_dataframe(analyzed_articles)
65
+
66
+
67
+ def convert_to_dataframe(analyzed_articles):
68
+ df = pd.DataFrame(analyzed_articles)
69
+ df["Title"] = df.apply(
70
+ lambda row: f'<a href="{row["link"]}" target="_blank">{row["title"]}</a>',
71
+ axis=1,
72
+ )
73
+ df["Description"] = df["desc"]
74
+ df["Date"] = df["date"]
75
+
76
+ def sentiment_badge(sentiment):
77
+ colors = {
78
+ "negative": "red",
79
+ "neutral": "gray",
80
+ "positive": "green",
81
+ }
82
+ color = colors.get(sentiment, "grey")
83
+ return f'<span style="background-color: {color}; color: white; padding: 2px 6px; border-radius: 4px;">{sentiment}</span>'
84
+
85
+ df["Sentiment"] = df["sentiment"].apply(lambda x: sentiment_badge(x["label"]))
86
+ return df[["Sentiment", "Title", "Description", "Date"]]
87
+
88
 
 
89
  with gr.Blocks() as iface:
90
+ gr.Markdown("# Trading Asset Sentiment Analysis")
91
+ gr.Markdown(
92
+ "Enter the name of a trading asset, and I'll fetch recent articles and analyze their sentiment!"
93
+ )
94
+
95
  with gr.Row():
96
+ input_asset = gr.Textbox(
97
+ label="Asset Name",
98
  lines=1,
99
+ placeholder="Enter the name of the trading asset...",
100
  )
101
+
 
102
  with gr.Row():
103
+ analyze_button = gr.Button("Analyze Sentiment", size="sm")
104
+
105
+ gr.Examples(
106
+ examples=[
107
+ "Bitcoin",
108
+ "Tesla",
109
+ "Apple",
110
+ "Amazon",
111
+ ],
112
+ inputs=input_asset,
113
+ )
114
+
115
+ with gr.Row():
116
+ with gr.Column():
117
+ with gr.Blocks():
118
+ gr.Markdown("## Articles and Sentiment Analysis")
119
+ articles_output = gr.Dataframe(
120
+ headers=["Sentiment", "Title", "Description", "Date"],
121
+ datatype=["markdown", "html", "markdown", "markdown"],
122
+ wrap=False,
123
+ )
124
+
125
  analyze_button.click(
126
+ analyze_asset_sentiment,
127
+ inputs=[input_asset],
128
+ outputs=[articles_output],
129
  )
130
 
131
+ logging.info("Launching Gradio interface")
132
+ iface.queue().launch()
 
requirements.txt CHANGED
@@ -1,6 +1,6 @@
1
- gradio==3.33.0
2
- yfinance==0.2.16
3
- pandas==2.1.2
4
- numpy==1.25.1
5
- matplotlib==3.7.1
6
- ta-lib==0.4.21
 
1
+ gradio==4.39.0
2
+ transformers==4.43.2
3
+ diffusers==0.29.2
4
+ accelerate==0.33.0
5
+ sentencepiece==0.2.0
6
+ GoogleNews==1.6.14