MacDash commited on
Commit
c95220d
·
verified ·
1 Parent(s): cd27a8e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +138 -343
app.py CHANGED
@@ -1,377 +1,172 @@
1
- # app.py
2
  import gradio as gr
3
  import pandas as pd
4
  import numpy as np
5
- from prophet import Prophet
6
- import plotly.graph_objs as go
7
- import math
8
- import requests
9
- from sklearn.ensemble import RandomForestClassifier
10
- from textblob import TextBlob
11
- import yfinance as yf # Import yfinance
12
 
13
- # --- Constants ---
14
- CRYPTO_SYMBOLS = ["BTC-USD", "ETH-USD"] # Use standardized symbols
15
- STOCK_SYMBOLS = ["AAPL", "MSFT"]
16
- INTERVAL_OPTIONS = ["1h", "1d"] # 1h not available for yfinance for stocks; use 1d for stocks.
17
 
18
- # --- Data Fetching Functions (Revised) ---
19
- def fetch_crypto_data(symbol, interval="1h", limit=100):
20
- """Fetch crypto market data using yfinance (Yahoo Finance)."""
21
- try:
22
- # yfinance uses standardized symbols (e.g., BTC-USD)
23
- ticker = yf.Ticker(symbol)
24
- # Handle different intervals. Yahoo Finance has limitations.
25
- if interval == "1h":
26
- period = "1d" # yfinance doesn't support 1h for historical data, so we'll use 1d and resample.
27
- df = ticker.history(period=period, interval="1h")
28
- elif interval == "1d":
29
- df = ticker.history(period="1y", interval=interval) # Get 1 year of data
30
- else:
31
- raise ValueError("Invalid interval for yfinance.")
32
- if df.empty:
33
- raise Exception("No data returned from yfinance.")
34
-
35
- df.reset_index(inplace=True)
36
- df.rename(columns={"Datetime": "timestamp", "Open": "open", "High": "high", "Low": "low", "Close": "close", "Volume": "volume"}, inplace=True)
37
- df = df[["timestamp", "open", "high", "low", "close", "volume"]] # Select and order columns
38
- return df.dropna()
39
- except Exception as e:
40
- raise Exception(f"Error fetching crypto data from yfinance: {e}")
41
 
42
- def fetch_stock_data(symbol, interval="1d"): # Simplified for yfinance
43
- """Fetch stock market data using yfinance."""
44
  try:
45
- ticker = yf.Ticker(symbol)
46
- df = ticker.history(period="1y", interval=interval) # Get 1 year of daily data
47
-
48
- if df.empty:
49
- raise Exception("No data returned from yfinance.")
50
-
51
- df.reset_index(inplace=True)
52
- df.rename(columns={"Date": "timestamp", "Open": "open", "High": "high", "Low": "low", "Close": "close", "Volume": "volume"}, inplace=True)
53
- df = df[["timestamp", "open", "high", "low", "close", "volume"]]
54
- return df.dropna()
55
  except Exception as e:
56
- raise Exception(f"Error fetching stock data from yfinance: {e}")
57
 
58
-
59
- def fetch_sentiment_data(keyword): # Placeholder - replace with a real sentiment analysis method
60
- """Analyze sentiment from social media (placeholder)."""
61
  try:
62
- tweets = [
63
- f"{keyword} is going to moon!",
64
- f"I hate {keyword}, it's trash!",
65
- f"{keyword} is amazing!"
66
- ]
67
- sentiments = [TextBlob(tweet).sentiment.polarity for tweet in tweets]
68
- return sum(sentiments) / len(sentiments) if sentiments else 0 # Avoid ZeroDivisionError
 
 
 
 
69
  except Exception as e:
70
- print(f"Sentiment analysis error: {e}")
71
- return 0
72
-
73
- # --- Technical Analysis Functions ---
74
- def calculate_technical_indicators(df):
75
- """Calculates RSI, MACD, and Bollinger Bands."""
76
- if df.empty:
77
- return df
78
-
79
- # RSI Calculation
80
- delta = df['close'].diff()
81
- gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
82
- loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
83
- rs = gain / loss
84
- df['RSI'] = 100 - (100 / (1 + rs))
85
 
86
- # MACD Calculation
87
- exp1 = df['close'].ewm(span=12, adjust=False).mean()
88
- exp2 = df['close'].ewm(span=26, adjust=False).mean()
89
- df['MACD'] = exp1 - exp2
90
- df['Signal_Line'] = df['MACD'].ewm(span=9, adjust=False).mean()
91
-
92
- # Bollinger Bands Calculation
93
- df['MA20'] = df['close'].rolling(window=20).mean()
94
- df['BB_upper'] = df['MA20'] + 2 * df['close'].rolling(window=20).std()
95
- df['BB_lower'] = df['MA20'] - 2 * df['close'].rolling(window=20).std()
96
-
97
- return df
98
-
99
- def create_technical_charts(df):
100
- """Creates technical analysis charts (Price, RSI, MACD)."""
101
- if df.empty:
102
- return None, None, None
103
-
104
- fig1 = go.Figure()
105
- fig1.add_trace(go.Candlestick(
106
- x=df['timestamp'],
107
- open=df['open'],
108
- high=df['high'],
109
- low=df['low'],
110
- close=df['close'],
111
- name='Price'
112
- ))
113
- fig1.add_trace(go.Scatter(x=df['timestamp'], y=df['BB_upper'], name='Upper BB', line=dict(color='gray', dash='dash')))
114
- fig1.add_trace(go.Scatter(x=df['timestamp'], y=df['BB_lower'], name='Lower BB', line=dict(color='gray', dash='dash')))
115
- fig1.update_layout(title='Price and Bollinger Bands', xaxis_title='Date', yaxis_title='Price')
116
-
117
- fig2 = go.Figure()
118
- fig2.add_trace(go.Scatter(x=df['timestamp'], y=df['RSI'], name='RSI'))
119
- fig2.add_hline(y=70, line_dash="dash", line_color="red")
120
- fig2.add_hline(y=30, line_dash="dash", line_color="green")
121
- fig2.update_layout(title='RSI Indicator', xaxis_title='Date', yaxis_title='RSI')
122
-
123
- fig3 = go.Figure()
124
- fig3.add_trace(go.Scatter(x=df['timestamp'], y=df['MACD'], name='MACD'))
125
- fig3.add_trace(go.Scatter(x=df['timestamp'], y=df['Signal_Line'], name='Signal Line'))
126
- fig3.update_layout(title='MACD', xaxis_title='Date', yaxis_title='Value')
127
-
128
- return fig1, fig2, fig3
129
-
130
- # --- Prophet Forecasting Functions ---
131
- def prepare_data_for_prophet(df):
132
- """Prepares data for Prophet."""
133
- if df.empty:
134
- return pd.DataFrame(columns=["ds", "y"])
135
- df_prophet = df.rename(columns={"timestamp": "ds", "close": "y"})
136
- return df_prophet[["ds", "y"]]
137
-
138
- def prophet_forecast(df_prophet, periods=10, freq="h", daily_seasonality=False, weekly_seasonality=False, yearly_seasonality=False, seasonality_mode="additive", changepoint_prior_scale=0.05):
139
- """Performs Prophet forecasting."""
140
- if df_prophet.empty:
141
- return pd.DataFrame(), "No data for Prophet."
142
 
 
 
143
  try:
144
- model = Prophet(
145
- daily_seasonality=daily_seasonality,
146
- weekly_seasonality=weekly_seasonality,
147
- yearly_seasonality=yearly_seasonality,
148
- seasonality_mode=seasonality_mode,
149
- changepoint_prior_scale=changepoint_prior_scale,
150
- )
151
- model.fit(df_prophet)
152
- future = model.make_future_dataframe(periods=periods, freq=freq)
153
- forecast = model.predict(future)
154
- return forecast, ""
155
  except Exception as e:
156
- return pd.DataFrame(), f"Forecast error: {e}"
157
-
158
- def prophet_wrapper(df_prophet, forecast_steps, freq, daily_seasonality, weekly_seasonality, yearly_seasonality, seasonality_mode, changepoint_prior_scale):
159
- """Wrapper for Prophet forecasting."""
160
- if len(df_prophet) < 10:
161
- return pd.DataFrame(), "Not enough data for forecasting (need >=10 rows)."
162
-
163
- full_forecast, err = prophet_forecast(
164
- df_prophet,
165
- periods=forecast_steps,
166
- freq=freq,
167
- daily_seasonality=daily_seasonality,
168
- weekly_seasonality=weekly_seasonality,
169
- yearly_seasonality=yearly_seasonality,
170
- seasonality_mode=seasonality_mode,
171
- changepoint_prior_scale=changepoint_prior_scale,
172
- )
173
- if err:
174
- return pd.DataFrame(), err
175
-
176
- future_only = full_forecast.loc[len(df_prophet):, ["ds", "yhat", "yhat_lower", "yhat_upper"]]
177
- return future_only, ""
178
-
179
- def create_forecast_plot(forecast_df):
180
- """Creates the forecast plot."""
181
- if forecast_df.empty:
182
- return go.Figure()
183
-
184
- fig = go.Figure()
185
- fig.add_trace(go.Scatter(
186
- x=forecast_df["ds"],
187
- y=forecast_df["yhat"],
188
- mode="lines",
189
- name="Forecast",
190
- line=dict(color="blue", width=2)
191
- ))
192
-
193
- fig.add_trace(go.Scatter(
194
- x=forecast_df["ds"],
195
- y=forecast_df["yhat_lower"],
196
- fill=None,
197
- mode="lines",
198
- line=dict(width=0),
199
- showlegend=True,
200
- name="Lower Bound"
201
- ))
202
-
203
- fig.add_trace(go.Scatter(
204
- x=forecast_df["ds"],
205
- y=forecast_df["yhat_upper"],
206
- fill="tonexty",
207
- mode="lines",
208
- line=dict(width=0),
209
- name="Upper Bound"
210
- ))
211
-
212
- fig.update_layout(
213
- title="Price Forecast",
214
- xaxis_title="Time",
215
- yaxis_title="Price",
216
- hovermode="x unified",
217
- template="plotly_white",
218
- )
219
- return fig
220
-
221
- # --- Model Training and Prediction ---
222
- model = RandomForestClassifier() # Moved here
223
-
224
- def train_model(df):
225
- """Train the AI model."""
226
- if df.empty:
227
- return # Or raise an exception, or return a default model.
228
- df["target"] = (df["close"].pct_change() > 0.05).astype(int) # Target: 1 if price increased by >5%
229
- features = df[["close", "volume"]].dropna()
230
- target = df["target"].dropna()
231
- if not features.empty and not target.empty: #check data is available
232
- model.fit(features, target)
233
- else:
234
- print("Not enough data for model training.")
235
-
236
- def predict_growth(latest_data):
237
- """Predict explosive growth."""
238
- if not hasattr(model, 'estimators_') or len(model.estimators_) == 0: # Check if model is trained
239
- return [0] # Or return an error message, or a default value
240
 
 
 
 
 
241
  try:
242
- prediction = model.predict(latest_data.reshape(1, -1))
243
- return prediction
 
244
  except Exception as e:
245
- print(f"Prediction error: {e}")
246
- return [0]
247
 
248
- # --- Main Prediction and Display Function ---
249
- def analyze_market(market_type, symbol, interval, forecast_steps, daily_seasonality, weekly_seasonality, yearly_seasonality, seasonality_mode, changepoint_prior_scale, sentiment_keyword=""):
250
- """Main function to orchestrate data fetching, analysis, and prediction."""
251
- df = pd.DataFrame()
252
- error_message = ""
253
- sentiment_score = 0 # Initialize sentiment score
254
- # 1. Data Fetching
255
- try:
256
- if market_type == "Crypto":
257
- df = fetch_crypto_data(symbol, interval=interval)
258
- elif market_type == "Stock":
259
- df = fetch_stock_data(symbol, interval=interval)
260
- else:
261
- error_message = "Invalid market type selected."
262
- return None, None, None, None, None, "", error_message, 0 # Also return sentiment
263
 
264
- if sentiment_keyword: # If a keyword for sentiment is entered:
265
- sentiment_score = fetch_sentiment_data(sentiment_keyword)
 
 
 
 
 
 
266
  except Exception as e:
267
- error_message = f"Data Fetching Error: {e}"
268
- return None, None, None, None, None, "", error_message, 0 #Return error + sentiment
269
-
270
- if df.empty:
271
- error_message = "No data fetched."
272
- return None, None, None, None, None, "", error_message, 0 # Return empty + sentiment
273
- # 2. Preprocessing & Technical Analysis
274
- df["timestamp"] = pd.to_datetime(df["timestamp"])
275
- numeric_cols = ["open", "high", "low", "close", "volume"]
276
- df[numeric_cols] = df[numeric_cols].astype(float)
277
- df = calculate_technical_indicators(df)
278
-
279
- # 3. Prophet Forecasting
280
- df_prophet = prepare_data_for_prophet(df)
281
- freq = "h" if interval == "1h" or interval == "60min" else "d" #dynamic freq
282
- forecast_df, prophet_error = prophet_wrapper(
283
- df_prophet,
284
- forecast_steps,
285
- freq,
286
- daily_seasonality,
287
- weekly_seasonality,
288
- yearly_seasonality,
289
- seasonality_mode,
290
- changepoint_prior_scale,
291
- )
292
-
293
- if prophet_error:
294
- error_message = f"Prophet Error: {prophet_error}"
295
- return None, None, None, None, None, "", error_message, sentiment_score #Return prophet error
296
 
297
- forecast_plot = create_forecast_plot(forecast_df)
 
 
298
 
299
- # 4. Create the Charts
300
- tech_plot, rsi_plot, macd_plot = create_technical_charts(df)
 
301
 
302
- # 5. Model Training and Prediction (simplified)
 
 
303
  try:
304
- train_model(df.copy()) # Train on a copy to avoid modifying original df.
305
- if not df.empty: #Check if dataframe is empty or not.
306
- latest_data = df[["close", "volume"]].iloc[-1].values # Get the last row for prediction.
307
- growth_prediction = predict_growth(latest_data)
308
- growth_label = "Yes" if growth_prediction[0] == 1 else "No"
309
- else:
310
- growth_label = "N/A: Insufficient Data" # If there is no data to predict the growth.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
 
312
- except Exception as e:
313
- error_message = f"Model Error: {e}"
314
- growth_label = "N/A"
315
 
316
- # Prepare forecast data for the Dataframe output
317
- forecast_df_display = forecast_df.loc[:, ["ds", "yhat", "yhat_lower", "yhat_upper"]].copy()
318
- forecast_df_display.rename(columns={"ds": "Date", "yhat": "Forecast", "yhat_lower": "Lower Bound", "yhat_upper": "Upper Bound"}, inplace=True)
319
- return forecast_plot, tech_plot, rsi_plot, macd_plot, forecast_df_display, growth_label, error_message, sentiment_score
320
 
321
- # --- Gradio Interface ---
322
- with gr.Blocks(theme=gr.themes.Base()) as demo:
323
- gr.Markdown("# Market Analysis and Prediction")
324
 
325
- with gr.Row():
326
- with gr.Column():
327
- market_type_dd = gr.Radio(label="Market Type", choices=["Crypto", "Stock"], value="Crypto")
328
- symbol_dd = gr.Dropdown(label="Symbol", choices=CRYPTO_SYMBOLS, value="BTC-USD") # Use standardized symbols
329
- interval_dd = gr.Dropdown(label="Interval", choices=INTERVAL_OPTIONS, value="1h")
330
- forecast_steps_slider = gr.Slider(label="Forecast Steps", minimum=1, maximum=100, value=24, step=1)
331
- daily_box = gr.Checkbox(label="Daily Seasonality", value=True)
332
- weekly_box = gr.Checkbox(label="Weekly Seasonality", value=True)
333
- yearly_box = gr.Checkbox(label="Yearly Seasonality", value=False)
334
- seasonality_mode_dd = gr.Dropdown(label="Seasonality Mode", choices=["additive", "multiplicative"], value="additive")
335
- changepoint_scale_slider = gr.Slider(label="Changepoint Prior Scale", minimum=0.01, maximum=1.0, step=0.01, value=0.05)
336
- sentiment_keyword_txt = gr.Textbox(label="Sentiment Keyword (optional)") #Add Sentiment input
337
 
338
- with gr.Column():
339
- forecast_plot = gr.Plot(label="Price Forecast")
340
- with gr.Row():
341
- tech_plot = gr.Plot(label="Technical Analysis")
342
- rsi_plot = gr.Plot(label="RSI Indicator")
343
- with gr.Row():
344
- macd_plot = gr.Plot(label="MACD")
345
- forecast_df = gr.Dataframe(label="Forecast Data", headers=["Date", "Forecast", "Lower Bound", "Upper Bound"])
346
- growth_label_output = gr.Label(label="Explosive Growth Prediction") # Added for prediction.
347
- sentiment_label_output = gr.Number(label="Sentiment Score") # Added for sentiment output
348
 
349
- # Event Listener to update symbol dropdown based on market type
350
- def update_symbol_choices(market_type):
351
- if market_type == "Crypto":
352
- return gr.Dropdown(choices=CRYPTO_SYMBOLS, value="BTC-USD")
353
- elif market_type == "Stock":
354
- return gr.Dropdown(choices=STOCK_SYMBOLS, value="AAPL") # Default to AAPL for stock
355
- return gr.Dropdown(choices=[], value=None) # Shouldn't happen, but safety check
356
- market_type_dd.change(fn=update_symbol_choices, inputs=[market_type_dd], outputs=[symbol_dd])
357
 
358
- analyze_button = gr.Button("Analyze Market", variant="primary")
359
- analyze_button.click(
360
- fn=analyze_market,
361
- inputs=[
362
- market_type_dd,
363
- symbol_dd,
364
- interval_dd,
365
- forecast_steps_slider,
366
- daily_box,
367
- weekly_box,
368
- yearly_box,
369
- seasonality_mode_dd,
370
- changepoint_scale_slider,
371
- sentiment_keyword_txt, # Add sentiment keyword to the input
372
- ],
373
- outputs=[forecast_plot, tech_plot, rsi_plot, macd_plot, forecast_df, growth_label_output, gr.Label(label="Error Message"), sentiment_label_output] # Add sentiment score to the output
374
- )
 
 
 
 
 
 
 
375
 
376
  if __name__ == "__main__":
377
- demo.launch()
 
 
1
  import gradio as gr
2
  import pandas as pd
3
  import numpy as np
4
+ from transformers import pipeline # For sentiment analysis
5
+ from sklearn.ensemble import IsolationForest # For anomaly detection
6
+ import yfinance as yf # For stock market data
7
+ import requests # For API calls
 
 
 
8
 
9
+ # Replace with your actual API keys
10
+ NEWS_API_KEY = "YOUR_NEWS_API_KEY" # Get from https://newsapi.org/
11
+ TWITTER_BEARER_TOKEN = "YOUR_TWITTER_BEARER_TOKEN" # Get from https://developer.twitter.com/
 
12
 
13
+ # Initialize pre-trained sentiment analysis model from Hugging Face Transformers
14
+ sentiment_analyzer = pipeline("sentiment-analysis")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ def fetch_news(keyword):
17
+ """Fetches news articles using the NewsAPI."""
18
  try:
19
+ url = f"https://newsapi.org/v2/everything?q={keyword}&apiKey={NEWS_API_KEY}"
20
+ response = requests.get(url)
21
+ response.raise_for_status() # Raise an exception for HTTP errors
22
+ articles = response.json().get("articles", [])
23
+ return pd.DataFrame([{"title": article["title"], "description": article["description"]} for article in articles])
24
+ except requests.exceptions.RequestException as e:
25
+ raise Exception(f"Failed to fetch news: {e}")
 
 
 
26
  except Exception as e:
27
+ raise Exception(f"Error processing news data: {e}")
28
 
29
+ def fetch_social_media_data(keyword):
30
+ """Fetches social media data using Twitter API."""
 
31
  try:
32
+ url = f"https://api.twitter.com/2/tweets/search/recent?query={keyword}&tweet.fields=text&max_results=10"
33
+ headers = {"Authorization": f"Bearer {TWITTER_BEARER_TOKEN}"}
34
+ response = requests.get(url, headers=headers)
35
+ response.raise_for_status() # Raise an exception for HTTP errors
36
+ tweets = response.json().get("data", [])
37
+ if tweets: # Handle case when no tweets are found
38
+ return pd.DataFrame([{"text": tweet["text"]} for tweet in tweets])
39
+ else:
40
+ return pd.DataFrame({"text": []}) # Return empty DataFrame if no tweets found
41
+ except requests.exceptions.RequestException as e:
42
+ raise Exception(f"Failed to fetch social media data: {e}")
43
  except Exception as e:
44
+ raise Exception(f"Error processing social media data: {e}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
+ def fetch_market_data(ticker, timeframe):
48
+ """Fetches stock/crypto market data using yfinance."""
49
  try:
50
+ data = yf.download(ticker, period=timeframe, interval="1d")
51
+ if data.empty:
52
+ raise Exception(f"No market data found for ticker: {ticker}")
53
+ return data.reset_index()
 
 
 
 
 
 
 
54
  except Exception as e:
55
+ raise Exception(f"Failed to fetch market data for {ticker}: {str(e)}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ def analyze_sentiment(text_list):
58
+ """Performs sentiment analysis on a list of texts."""
59
+ if not text_list: # Handle empty text list
60
+ return []
61
  try:
62
+ sentiments = sentiment_analyzer(text_list)
63
+ scores = [item['score'] if item['label'] == 'POSITIVE' else -item['score'] for item in sentiments]
64
+ return scores
65
  except Exception as e:
66
+ raise Exception(f"Sentiment analysis error: {e}")
 
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
69
+ def detect_anomalies(data):
70
+ """Detects anomalies in time series data using Isolation Forest."""
71
+ if len(data) <= 1: # Need at least 2 data points for diff and anomaly detection
72
+ return []
73
+ try:
74
+ model = IsolationForest(contamination=0.1, random_state=42)
75
+ anomalies = model.fit_predict(data.reshape(-1, 1))
76
+ return [i for i, val in enumerate(anomalies) if val == -1]
77
  except Exception as e:
78
+ raise Exception(f"Anomaly detection error: {e}")
79
+
80
+ def identify_opportunities(ticker, news_sentiment, social_sentiment, anomalies, market_data):
81
+ """Identifies potential explosive growth opportunities."""
82
+ if np.mean(news_sentiment) > 0.3 and np.mean(social_sentiment) > 0.3 and len(anomalies) > 0: # Reduced sentiment threshold slightly
83
+ return [
84
+ {
85
+ "ticker": ticker,
86
+ "potential_gain": np.random.randint(10, 50), # Simulated gain percentage
87
+ "risk_level": "High",
88
+ "disclaimer": "This is a speculative opportunity. Conduct thorough research."
89
+ }
90
+ ]
91
+ return []
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
+ def analyze_market(ticker_or_keyword, timeframe="1d"):
94
+ """
95
+ Analyzes news, social media, and market data for a given ticker or keyword.
96
 
97
+ Args:
98
+ ticker_or_keyword (str): The stock ticker symbol (e.g., "AAPL") or keyword (e.g., "AI").
99
+ timeframe (str): The time frame for analysis (e.g., "1d", "1w", "1m").
100
 
101
+ Returns:
102
+ dict: A dictionary containing analysis results for Gradio display.
103
+ """
104
  try:
105
+ # Data Collection
106
+ news_df = fetch_news(ticker_or_keyword)
107
+ social_media_df = fetch_social_media_data(ticker_or_keyword)
108
+ market_df = fetch_market_data(ticker_or_keyword, timeframe)
109
+
110
+ # Sentiment Analysis
111
+ news_sentiment = analyze_sentiment(news_df["description"].fillna("").tolist()) if not news_df.empty else []
112
+ social_sentiment = analyze_sentiment(social_media_df["text"].tolist()) if not social_media_df.empty else []
113
+
114
+ # Anomaly Detection
115
+ price_changes = market_df["Close"].pct_change().dropna().values if not market_df.empty else np.array([])
116
+ anomalies = detect_anomalies(price_changes)
117
+
118
+ # Opportunity Identification
119
+ opportunities = identify_opportunities(
120
+ ticker_or_keyword,
121
+ news_sentiment,
122
+ social_sentiment,
123
+ anomalies,
124
+ market_df
125
+ )
126
 
127
+ # Results Formatting for Gradio
128
+ results_md = f"## Analysis Results for: {ticker_or_keyword}\n\n"
 
129
 
130
+ results_md += f"**Average News Sentiment:** {np.mean(news_sentiment):.2f} \n" if news_sentiment else "**Average News Sentiment:** N/A (No news found) \n"
131
+ results_md += f"**Average Social Sentiment:** {np.mean(social_sentiment):.2f} \n" if social_sentiment else "**Average Social Sentiment:** N/A (No social media data found) \n"
132
+ results_md += f"**Anomalies Detected in Price Changes:** {len(anomalies)} \n\n" if price_changes.size > 0 else "**Anomalies Detected in Price Changes:** N/A (Insufficient market data) \n\n"
 
133
 
 
 
 
134
 
135
+ if opportunities:
136
+ results_md += "### Potential Explosive Growth Opportunities:\n"
137
+ opportunities_df = pd.DataFrame(opportunities)
138
+ results_md += opportunities_df.to_markdown(index=False) + "\n\n"
139
+ else:
140
+ results_md += "**No Explosive Growth Opportunities Identified based on current analysis.**\n\n"
 
 
 
 
 
 
141
 
142
+ results_md += "---\n**Disclaimer:** This analysis is for informational purposes only and not financial advice. Investing in financial markets involves risk. Conduct thorough research and consult with a financial advisor before making investment decisions."
 
 
 
 
 
 
 
 
 
143
 
144
+ return results_md
 
 
 
 
 
 
 
145
 
146
+ except Exception as e:
147
+ error_md = f"## Analysis Error for: {ticker_or_keyword}\n\n"
148
+ error_md += f"**Error Details:** {str(e)}\n\n"
149
+ error_md += "---\n**Disclaimer:** This analysis is for informational purposes only and not financial advice. Investing in financial markets involves risk. Conduct thorough research and consult with a financial advisor before making investment decisions."
150
+ return error_md
151
+
152
+
153
+ # Gradio Interface
154
+ iface = gr.Interface(
155
+ fn=analyze_market,
156
+ inputs=[
157
+ gr.Textbox(label="Stock Ticker or Keyword (e.g., AAPL, BTC-USD, AI)"),
158
+ gr.Dropdown(["1d", "1w", "1m"], label="Timeframe", value="1d"),
159
+ ],
160
+ outputs=gr.Markdown(label="Analysis Results"),
161
+ title="Explosive Growth Opportunity Finder",
162
+ description=(
163
+ "This tool leverages AI to analyze news sentiment, social media trends, and market data to identify potential investment opportunities. "
164
+ "Enter a stock ticker (e.g., AAPL), crypto symbol (e.g., BTC-USD), or a general keyword (e.g., AI) to analyze. "
165
+ "**Disclaimer:** This is a highly speculative tool for educational purposes. "
166
+ "It is not financial advice. Investing in financial markets involves significant risk. "
167
+ "Always conduct your own thorough research and consult with a financial advisor before making any investment decisions."
168
+ ),
169
+ )
170
 
171
  if __name__ == "__main__":
172
+ iface.launch()