Method314 commited on
Commit
8d93a7c
·
verified ·
1 Parent(s): 27ec6d9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +147 -144
app.py CHANGED
@@ -25,55 +25,62 @@ openai.api_key = OPENAI_API_KEY
25
  # Alpha Vantage API key
26
  ALPHA_VANTAGE_API_KEY = "JK0DVDNTEYBTBP5L"
27
 
 
 
 
28
  # Custom CSS
29
  st.markdown("""
30
  <style>
31
  .reportview-container {
32
- background: linear-gradient(to right, #1e3c72, #2a5298);
33
  }
34
  .main .block-container {
35
- max-width: 95%;
36
  padding-top: 2rem;
37
  padding-bottom: 2rem;
38
  }
39
  h1, h2, h3 {
40
- color: #f0f2f6;
41
  }
42
- .stButton>button {
43
- color: #ffffff;
44
- background-color: #4CAF50;
45
  border-radius: 5px;
46
  border: none;
47
- padding: 10px 24px;
 
48
  transition: all 0.3s ease 0s;
49
  }
50
- .stButton>button:hover {
51
- background-color: #45a049;
52
- }
53
- .stTextInput>div>div>input {
54
- color: #1e3c72;
55
  }
56
- .stDateInput>div>div>input {
57
- color: #1e3c72;
 
 
 
58
  }
59
  .stPlotlyChart {
60
- background-color: rgba(255, 255, 255, 0.1);
61
  border-radius: 5px;
62
  padding: 10px;
63
  }
64
  .css-1d391kg {
65
- background-color: rgba(255, 255, 255, 0.05);
66
  }
67
  .stDataFrame {
68
- background-color: rgba(255, 255, 255, 0.1);
 
 
 
 
 
 
 
69
  border-radius: 5px;
70
- padding: 10px;
71
  }
72
  </style>
73
-
74
  """, unsafe_allow_html=True)
75
 
76
- @st.cache_data
77
  def get_financial_data(ticker, end_date):
78
  base_url = "https://www.alphavantage.co/query"
79
  functions = ['INCOME_STATEMENT', 'BALANCE_SHEET', 'CASH_FLOW']
@@ -105,7 +112,6 @@ def get_financial_data(ticker, end_date):
105
 
106
  return data
107
 
108
- @st.cache_data
109
  def get_earnings_dates(ticker):
110
  url = f"https://www.alphavantage.co/query?function=EARNINGS&symbol={ticker}&apikey={ALPHA_VANTAGE_API_KEY}"
111
  response = requests.get(url)
@@ -119,7 +125,6 @@ def get_earnings_dates(ticker):
119
 
120
  return earnings_dates
121
 
122
- @st.cache_data
123
  def get_earnings_data(ticker):
124
  url = f"https://www.alphavantage.co/query?function=EARNINGS&symbol={ticker}&apikey={ALPHA_VANTAGE_API_KEY}"
125
  response = requests.get(url)
@@ -137,7 +142,6 @@ def get_earnings_data(ticker):
137
 
138
  return df
139
 
140
- @st.cache_data
141
  def process_financial_data(data, earnings_dates, earnings_data):
142
  quarterly_data = {}
143
 
@@ -161,7 +165,6 @@ def process_financial_data(data, earnings_dates, earnings_data):
161
 
162
  return df
163
 
164
- @st.cache_data
165
  def get_stock_data(ticker, start_date, end_date):
166
  df = yf.download(ticker, start=start_date, end=end_date)
167
 
@@ -295,7 +298,6 @@ def plot_results(dates, y, fair_values, lower_bound, upper_bound, scaler_y):
295
 
296
  return fig
297
 
298
- @st.cache_data
299
  def get_monthly_seasonality(ticker, start_date, end_date):
300
  data = yf.download(ticker, start=start_date, end=end_date)
301
  monthly_data = data['Adj Close'].resample('M').last()
@@ -435,77 +437,104 @@ def plot_interactive_logarithmic_stock_chart(ticker, start_date, end_date):
435
  return fig
436
 
437
  def analyze_stock(ticker, start_date, end_date, use_ai_assistant):
438
- with st.spinner('Analyzing stock data...'):
439
- try:
440
- financial_data = get_financial_data(ticker, end_date)
441
- earnings_dates = get_earnings_dates(ticker)
442
- earnings_data = get_earnings_data(ticker)
443
- quarterly_df = process_financial_data(financial_data, earnings_dates, earnings_data)
444
- stock_df = get_stock_data(ticker, start_date, end_date)
 
 
 
445
 
446
- if quarterly_df.empty:
447
- st.error("No financial data available for processing.")
448
- return
449
 
450
- X_scaled, y_scaled, dates, scaler_X, scaler_y = prepare_data(quarterly_df, stock_df, end_date)
451
 
452
- X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_scaled, test_size=0.2, random_state=42)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
 
454
- model = train_catboost_model(X_train, X_test, y_train, y_test)
455
-
456
- r2 = evaluate_model(model, X_test, y_test, scaler_y)
457
-
458
- if r2 < 0.5:
459
- st.warning("Model performance is poor. Results may not be reliable.")
460
-
461
- fair_values, lower_bound, upper_bound = conformal_prediction(model, X_train, y_train, X_scaled, scaler_y)
462
-
463
- fig = plot_results(dates, y_scaled, fair_values, lower_bound, upper_bound, scaler_y)
464
-
465
- feature_importance = model.feature_importances_
466
- feature_importance_df = pd.DataFrame({'feature': X_scaled.columns, 'importance': feature_importance})
467
- feature_importance_df = feature_importance_df.sort_values('importance', ascending=False)
468
-
469
- explainer = shap.TreeExplainer(model)
470
- shap_values = explainer.shap_values(X_scaled)
471
-
472
- shap_fig, ax = plt.subplots(figsize=(10, 6))
473
- shap.summary_plot(shap_values, X_scaled, plot_type="bar", show=False)
474
- plt.title("SHAP Feature Importance")
475
- plt.tight_layout()
476
-
477
- seasonality = get_monthly_seasonality(ticker, start_date, end_date)
478
- seasonality_fig = plot_monthly_seasonality(seasonality, ticker, start_date, end_date)
479
-
480
- log_chart = plot_interactive_logarithmic_stock_chart(ticker, start_date, end_date)
481
-
482
- gpt_analysis = get_gpt_analysis(ticker, financial_data) if use_ai_assistant else "AI assistant analysis not requested."
483
-
484
- return {
485
- 'ticker': ticker,
486
- 'fair_values': fair_values,
487
- 'lower_bound': lower_bound,
488
- 'upper_bound': upper_bound,
489
- 'r2': r2,
490
- 'fig': fig,
491
- 'feature_importance_df': feature_importance_df,
492
- 'shap_fig': shap_fig,
493
- 'seasonality': seasonality,
494
- 'seasonality_fig': seasonality_fig,
495
- 'gpt_analysis': gpt_analysis,
496
- 'log_chart': log_chart,
497
- 'latest_close': stock_df['Close'].iloc[-1],
498
- 'latest_fair_value': fair_values[-1],
499
- 'latest_lower_bound': lower_bound[-1],
500
- 'latest_upper_bound': upper_bound[-1],
501
- }
502
-
503
- except Exception as e:
504
- st.error(f"An error occurred: {str(e)}")
505
- return None
506
 
507
  def main():
508
- st.title("🚀 Advanced Stock Analysis App")
509
  st.markdown("Enter a stock ticker and date range to perform comprehensive stock analysis.")
510
 
511
  col1, col2, col3, col4 = st.columns([2,2,2,1])
@@ -519,60 +548,34 @@ def main():
519
  use_ai_assistant = st.checkbox("Use AI Assistant")
520
 
521
  if st.button("Analyze Stock", key="analyze_button"):
522
- results = analyze_stock(ticker, start_date, end_date, use_ai_assistant)
523
-
524
- if results:
525
- st.header("📊 Fair Price Analysis")
526
- col1, col2, col3 = st.columns(3)
527
- with col1:
528
- st.metric("Current Price", f"${results['latest_close']:.2f}")
529
- with col2:
530
- change_pct = ((results['latest_fair_value'] - results['latest_close']) / results['latest_close'] * 100)
531
- st.metric("Estimated Fair Value", f"${results['latest_fair_value']:.2f}",
532
- f"{change_pct:+.2f}%",
533
- delta_color="normal" if change_pct >= 0 else "inverse")
534
- with col3:
535
- st.metric("R-squared Score", f"{results['r2']:.4f}")
536
-
537
- st.metric("Price Prediction Range",
538
- f"${results['latest_lower_bound']:.2f} to ${results['latest_upper_bound']:.2f}")
539
-
540
- st.subheader("📈 Fair Price Prediction")
541
- st.plotly_chart(results['fig'], use_container_width=True)
542
-
543
- col1, col2 = st.columns(2)
544
- with col1:
545
- st.subheader("🔍 SHAP Feature Importance")
546
- st.pyplot(results['shap_fig'])
547
- with col2:
548
- st.subheader("🏆 Top 10 Important Features")
549
- st.dataframe(results['feature_importance_df'].head(10), height=400)
550
-
551
- st.subheader("📅 Monthly Seasonality")
552
- st.plotly_chart(results['seasonality_fig'], use_container_width=True)
553
-
554
- current_month = datetime.now().month
555
- next_month = (current_month % 12) + 1
556
- col1, col2 = st.columns(2)
557
- with col1:
558
- current_change = results['seasonality'].loc[current_month, 'Mean Change%']*100
559
- st.metric(f"Current month ({datetime.now().strftime('%B')})",
560
- f"{current_change:.2f}%",
561
- f"{results['seasonality'].loc[current_month, 'Positive Periods']*100:.1f}% probability of positive return",
562
- delta_color="normal" if current_change >= 0 else "inverse")
563
- with col2:
564
- next_change = results['seasonality'].loc[next_month, 'Mean Change%']*100
565
- st.metric(f"Next month ({(datetime.now() + timedelta(days=31)).strftime('%B')})",
566
- f"{next_change:.2f}%",
567
- f"{results['seasonality'].loc[next_month, 'Positive Periods']*100:.1f}% probability of positive return",
568
- delta_color="normal" if next_change >= 0 else "inverse")
569
-
570
- if results['gpt_analysis'] != "AI assistant analysis not requested.":
571
- st.subheader("🤖 AI Assistant Analysis")
572
- st.text_area("Analysis", value=results['gpt_analysis'], height=300)
573
-
574
- st.subheader("📉 Logarithmic Stock Chart")
575
- st.plotly_chart(results['log_chart'], use_container_width=True)
576
 
577
  if __name__ == "__main__":
578
  main()
 
25
  # Alpha Vantage API key
26
  ALPHA_VANTAGE_API_KEY = "JK0DVDNTEYBTBP5L"
27
 
28
+ # GPT Assistant ID
29
+ ASSISTANT_ID = "asst_Fl3rRrRijb8FJDpqjBexfUBp"
30
+
31
  # Custom CSS
32
  st.markdown("""
33
  <style>
34
  .reportview-container {
35
+ background: linear-gradient(to bottom right, #10161e, #1f2937);
36
  }
37
  .main .block-container {
 
38
  padding-top: 2rem;
39
  padding-bottom: 2rem;
40
  }
41
  h1, h2, h3 {
42
+ color: #3db892;
43
  }
44
+ .stButton > button {
45
+ color: white;
46
+ background-color: #3db892;
47
  border-radius: 5px;
48
  border: none;
49
+ padding: 0.5rem 1rem;
50
+ font-weight: bold;
51
  transition: all 0.3s ease 0s;
52
  }
53
+ .stButton > button:hover {
54
+ background-color: #2c8d6f;
 
 
 
55
  }
56
+ .stTextInput > div > div > input,
57
+ .stDateInput > div > div > input {
58
+ background-color: #1f2937;
59
+ color: white;
60
+ border: 1px solid #3db892;
61
  }
62
  .stPlotlyChart {
63
+ background-color: #1f2937;
64
  border-radius: 5px;
65
  padding: 10px;
66
  }
67
  .css-1d391kg {
68
+ background-color: #1f2937;
69
  }
70
  .stDataFrame {
71
+ background-color: #1f2937;
72
+ }
73
+ .stTable {
74
+ background-color: #1f2937;
75
+ }
76
+ .css-1s0xp3b {
77
+ background-color: #1f2937;
78
+ border: 1px solid #3db892;
79
  border-radius: 5px;
 
80
  }
81
  </style>
 
82
  """, unsafe_allow_html=True)
83
 
 
84
  def get_financial_data(ticker, end_date):
85
  base_url = "https://www.alphavantage.co/query"
86
  functions = ['INCOME_STATEMENT', 'BALANCE_SHEET', 'CASH_FLOW']
 
112
 
113
  return data
114
 
 
115
  def get_earnings_dates(ticker):
116
  url = f"https://www.alphavantage.co/query?function=EARNINGS&symbol={ticker}&apikey={ALPHA_VANTAGE_API_KEY}"
117
  response = requests.get(url)
 
125
 
126
  return earnings_dates
127
 
 
128
  def get_earnings_data(ticker):
129
  url = f"https://www.alphavantage.co/query?function=EARNINGS&symbol={ticker}&apikey={ALPHA_VANTAGE_API_KEY}"
130
  response = requests.get(url)
 
142
 
143
  return df
144
 
 
145
  def process_financial_data(data, earnings_dates, earnings_data):
146
  quarterly_data = {}
147
 
 
165
 
166
  return df
167
 
 
168
  def get_stock_data(ticker, start_date, end_date):
169
  df = yf.download(ticker, start=start_date, end=end_date)
170
 
 
298
 
299
  return fig
300
 
 
301
  def get_monthly_seasonality(ticker, start_date, end_date):
302
  data = yf.download(ticker, start=start_date, end=end_date)
303
  monthly_data = data['Adj Close'].resample('M').last()
 
437
  return fig
438
 
439
  def analyze_stock(ticker, start_date, end_date, use_ai_assistant):
440
+ try:
441
+ financial_data = get_financial_data(ticker, end_date)
442
+ earnings_dates = get_earnings_dates(ticker)
443
+ earnings_data = get_earnings_data(ticker)
444
+ quarterly_df = process_financial_data(financial_data, earnings_dates, earnings_data)
445
+ stock_df = get_stock_data(ticker, start_date, end_date)
446
+
447
+ if quarterly_df.empty:
448
+ st.error("No financial data available for processing.")
449
+ return None
450
 
451
+ X_scaled, y_scaled, dates, scaler_X, scaler_y = prepare_data(quarterly_df, stock_df, end_date)
 
 
452
 
453
+ X_train, X_test, y_train, y_test = train_test_split(X_scaled, y_scaled, test_size=0.2, random_state=42)
454
 
455
+ model = train_catboost_model(X_train, X_test, y_train, y_test)
456
+
457
+ r2 = evaluate_model(model, X_test, y_test, scaler_y)
458
+
459
+ if r2 < 0.5:
460
+ st.warning("Model performance is poor. Results may not be reliable.")
461
+
462
+ fair_values, lower_bound, upper_bound = conformal_prediction(model, X_train, y_train, X_scaled, scaler_y)
463
+
464
+ fig = plot_results(dates, y_scaled, fair_values, lower_bound, upper_bound, scaler_y)
465
+
466
+ feature_importance = model.feature_importances_
467
+ feature_importance_df = pd.DataFrame({'feature': X_scaled.columns, 'importance': feature_importance})
468
+ feature_importance_df = feature_importance_df.sort_values('importance', ascending=False)
469
+
470
+ explainer = shap.TreeExplainer(model)
471
+ shap_values = explainer.shap_values(X_scaled)
472
+
473
+ shap_fig, ax = plt.subplots(figsize=(10, 6))
474
+ shap.summary_plot(shap_values, X_scaled, plot_type="bar", show=False)
475
+ plt.title("SHAP Feature Importance")
476
+ plt.tight_layout()
477
+
478
+ seasonality = get_monthly_seasonality(ticker, start_date, end_date)
479
+ seasonality_fig = plot_monthly_seasonality(seasonality, ticker, start_date, end_date)
480
+
481
+ log_chart = plot_interactive_logarithmic_stock_chart(ticker, start_date, end_date)
482
+
483
+ gpt_analysis = get_gpt_analysis(ticker, financial_data) if use_ai_assistant else "AI assistant analysis not requested."
484
+
485
+ latest_close = stock_df['Close'].iloc[-1]
486
+ latest_fair_value = fair_values[-1]
487
+ latest_lower_bound = lower_bound[-1]
488
+ latest_upper_bound = upper_bound[-1]
489
+
490
+ percentage_change = ((latest_fair_value - latest_close) / latest_close) * 100
491
+
492
+ fair_price_html = f"""
493
+ <h2 style="margin-bottom: 15px;">Fair Price Analysis</h2>
494
+ <p><strong>Current Price:</strong> ${latest_close:.2f}</p>
495
+ <p><strong>Estimated Fair Value:</strong> ${latest_fair_value:.2f}</p>
496
+ <p><strong>Price Prediction Range:</strong> ${latest_lower_bound:.2f} to ${latest_upper_bound:.2f}</p>
497
+ <p><strong>R-squared Score:</strong> {r2:.4f}</p>
498
+ <h3 style="margin-top: 20px;">Top 10 most important features for fair value prediction:</h3>
499
+ <pre>{feature_importance_df.head(10).to_string(index=False)}</pre>
500
+ """
501
+
502
+ current_month = datetime.now().month
503
+ next_month = (current_month % 12) + 1
504
+
505
+ current_month_return = seasonality.loc[current_month, 'Mean Change%'] * 100
506
+ next_month_return = seasonality.loc[next_month, 'Mean Change%'] * 100
507
+ current_month_win_rate = seasonality.loc[current_month, 'Positive Periods'] * 100
508
+ next_month_win_rate = seasonality.loc[next_month, 'Positive Periods'] * 100
509
+
510
+ seasonality_html = f"""
511
+ <h2 style="margin-bottom: 15px;">Seasonality Analysis ({start_date} to {end_date})</h2>
512
+ <h3>Current month ({datetime.now().strftime('%B')}):</h3>
513
+ <p>Average return: {current_month_return:.2f}%</p>
514
+ <p>Probability of positive return: {current_month_win_rate:.1f}%</p>
515
+ <h3>Next month ({(datetime.now() + timedelta(days=31)).strftime('%B')}):</h3>
516
+ <p>Average return: {next_month_return:.2f}%</p>
517
+ <p>Probability of positive return: {next_month_win_rate:.1f}%</p>
518
+ """
519
+
520
+ return {
521
+ 'fair_price_html': fair_price_html,
522
+ 'fig': fig,
523
+ 'shap_fig': shap_fig,
524
+ 'seasonality_fig': seasonality_fig,
525
+ 'seasonality_html': seasonality_html,
526
+ 'gpt_analysis': gpt_analysis,
527
+ 'log_chart': log_chart,
528
+ 'feature_importance_df': feature_importance_df.head(10),
529
+ 'percentage_change': percentage_change
530
+ }
531
 
532
+ except Exception as e:
533
+ st.error(f"An error occurred: {str(e)}")
534
+ return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
 
536
  def main():
537
+ st.title("Advanced Stock Analysis App")
538
  st.markdown("Enter a stock ticker and date range to perform comprehensive stock analysis.")
539
 
540
  col1, col2, col3, col4 = st.columns([2,2,2,1])
 
548
  use_ai_assistant = st.checkbox("Use AI Assistant")
549
 
550
  if st.button("Analyze Stock", key="analyze_button"):
551
+ with st.spinner('Analyzing stock data...'):
552
+ results = analyze_stock(ticker, start_date, end_date, use_ai_assistant)
553
+
554
+ if results:
555
+ st.header("Fair Price Analysis")
556
+ st.markdown(results['fair_price_html'], unsafe_allow_html=True)
557
+
558
+ st.subheader("Fair Price Prediction")
559
+ st.plotly_chart(results['fig'], use_container_width=True)
560
+
561
+ col1, col2 = st.columns(2)
562
+ with col1:
563
+ st.subheader("SHAP Feature Importance")
564
+ st.pyplot(results['shap_fig'])
565
+ with col2:
566
+ st.subheader("Top 10 Important Features")
567
+ st.dataframe(results['feature_importance_df'], height=400)
568
+
569
+ st.subheader("Monthly Seasonality")
570
+ st.plotly_chart(results['seasonality_fig'], use_container_width=True)
571
+ st.markdown(results['seasonality_html'], unsafe_allow_html=True)
572
+
573
+ if results['gpt_analysis'] != "AI assistant analysis not requested.":
574
+ st.subheader("AI Assistant Analysis")
575
+ st.text_area("Analysis", value=results['gpt_analysis'], height=300)
576
+
577
+ st.subheader("Logarithmic Stock Chart")
578
+ st.plotly_chart(results['log_chart'], use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
579
 
580
  if __name__ == "__main__":
581
  main()