Spaces:
Sleeping
Sleeping
Update app.py
Browse files
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, #
|
| 33 |
}
|
| 34 |
.main .block-container {
|
| 35 |
-
max-width: 95%;
|
| 36 |
padding-top: 2rem;
|
| 37 |
padding-bottom: 2rem;
|
| 38 |
}
|
| 39 |
h1, h2, h3 {
|
| 40 |
-
color: #
|
| 41 |
}
|
| 42 |
-
.stButton>button {
|
| 43 |
-
color:
|
| 44 |
-
background-color: #
|
| 45 |
border-radius: 5px;
|
| 46 |
border: none;
|
| 47 |
-
padding:
|
|
|
|
| 48 |
transition: all 0.3s ease 0s;
|
| 49 |
}
|
| 50 |
-
.stButton>button:hover {
|
| 51 |
-
background-color: #
|
| 52 |
-
}
|
| 53 |
-
.stTextInput>div>div>input {
|
| 54 |
-
color: #1e3c72;
|
| 55 |
}
|
| 56 |
-
.
|
| 57 |
-
|
|
|
|
|
|
|
|
|
|
| 58 |
}
|
| 59 |
.stPlotlyChart {
|
| 60 |
-
background-color:
|
| 61 |
border-radius: 5px;
|
| 62 |
padding: 10px;
|
| 63 |
}
|
| 64 |
.css-1d391kg {
|
| 65 |
-
background-color:
|
| 66 |
}
|
| 67 |
.stDataFrame {
|
| 68 |
-
background-color:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
|
|
|
|
|
|
|
|
|
| 445 |
|
| 446 |
-
|
| 447 |
-
st.error("No financial data available for processing.")
|
| 448 |
-
return
|
| 449 |
|
| 450 |
-
|
| 451 |
|
| 452 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 453 |
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 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("
|
| 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 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
|
| 527 |
-
|
| 528 |
-
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
|
| 538 |
-
|
| 539 |
-
|
| 540 |
-
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
|
| 546 |
-
|
| 547 |
-
|
| 548 |
-
st.subheader("
|
| 549 |
-
st.
|
| 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()
|